diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 39d208eac59a535c5ad6e5af38cd7e6b97998e98..a63bccf5405485de1cbb5ce5b6ee2269298b15fc 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -72,6 +72,7 @@ libes2panda_sources = [ "checker/types/ets/etsFunctionType.cpp", "checker/types/ets/etsObjectType.cpp", "checker/types/ets/etsStringType.cpp", + "checker/types/ets/etsTupleType.cpp", "checker/types/ets/etsTypeParameter.cpp", "checker/types/ets/etsUnionType.cpp", "checker/types/ets/etsVoidType.cpp", @@ -155,7 +156,9 @@ libes2panda_sources = [ "compiler/function/generatorFunctionBuilder.cpp", "compiler/lowering/checkerPhase.cpp", "compiler/lowering/ets/generateDeclarations.cpp", + "compiler/lowering/ets/lambdaLowering.cpp", "compiler/lowering/ets/opAssignment.cpp", + "compiler/lowering/ets/tupleLowering.cpp", "compiler/lowering/ets/unionLowering.cpp", "compiler/lowering/phase.cpp", "compiler/lowering/plugin_phase.cpp", @@ -193,6 +196,7 @@ libes2panda_sources = [ "ir/ets/etsPrimitiveType.cpp", "ir/ets/etsScript.cpp", "ir/ets/etsStructDeclaration.cpp", + "ir/ets/etsTuple.cpp", "ir/ets/etsTypeReference.cpp", "ir/ets/etsTypeReferencePart.cpp", "ir/ets/etsUnionType.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 45978a26fe5155df778a079e034531ca39d33477..d63126df9f7e3149cf008a4248153b414878ed73 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -137,8 +137,10 @@ set(ES2PANDA_LIB_SRC compiler/lowering/phase.cpp compiler/lowering/plugin_phase.cpp compiler/lowering/util.cpp + compiler/lowering/ets/lambdaLowering.cpp compiler/lowering/ets/generateDeclarations.cpp compiler/lowering/ets/opAssignment.cpp + compiler/lowering/ets/tupleLowering.cpp compiler/lowering/ets/unionLowering.cpp ir/astDump.cpp ir/astNode.cpp @@ -243,6 +245,7 @@ set(ES2PANDA_LIB_SRC ir/ets/etsParameterExpression.cpp ir/ets/etsPrimitiveType.cpp ir/ets/etsScript.cpp + ir/ets/etsTuple.cpp ir/ets/etsTypeReference.cpp ir/ets/etsTypeReferencePart.cpp ir/ets/etsUnionType.cpp @@ -373,6 +376,7 @@ set(ES2PANDA_LIB_SRC checker/types/ets/etsFunctionType.cpp checker/types/ets/etsObjectType.cpp checker/types/ets/etsStringType.cpp + checker/types/ets/etsTupleType.cpp checker/types/ets/etsTypeParameter.cpp checker/types/ets/etsUnionType.cpp checker/types/ets/etsVoidType.cpp diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index c26e12302dfa23fe17414210e3865726446af043..631c7cdae5b4e7bbb4278540dbeffc065a05d2dd 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -338,9 +338,8 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ScriptFunction *node) con UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::SpreadElement *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::SpreadElement *expr) const { - (void)expr; UNREACHABLE(); } @@ -366,58 +365,215 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSPropertySignature *node UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSSignatureDeclaration *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSSignatureDeclaration *node) const { - (void)node; UNREACHABLE(); } // from ets folder checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker->ThrowTypeError("Class literal is not yet supported.", expr->expr_->Start()); + + expr->expr_->Check(checker); + auto *expr_type = expr->expr_->GetType(checker); + + if (expr_type->IsETSVoidType()) { + checker->ThrowTypeError("Invalid .class reference", expr->expr_->Start()); + } + + ArenaVector type_arg_types(checker->Allocator()->Adapter()); + type_arg_types.push_back(expr_type); // NOTE: Box it if it's a primitive type + + checker::InstantiationContext ctx(checker, checker->GlobalBuiltinTypeType(), type_arg_types, expr->range_.start); + expr->SetTsType(ctx.Result()); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker->CreateFunctionalInterfaceForFunctionType(node); + auto *interface_type = + checker->CreateETSObjectType(node->FunctionalInterface()->Id()->Name(), node->FunctionalInterface(), + checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); + interface_type->SetSuperType(checker->GlobalETSObjectType()); + + auto *invoke_func = node->FunctionalInterface()->Body()->Body()[0]->AsMethodDefinition()->Function(); + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + + for (auto *it : invoke_func->Params()) { + auto *const param = it->AsETSParameterExpression(); + if (param->IsRestParameter()) { + auto *rest_ident = param->Ident(); + + ASSERT(rest_ident->Variable()); + signature_info->rest_var = rest_ident->Variable()->AsLocalVariable(); + + ASSERT(param->TypeAnnotation()); + signature_info->rest_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); + + auto array_type = signature_info->rest_var->TsType()->AsETSArrayType(); + checker->CreateBuiltinArraySignature(array_type, array_type->Rank()); + } else { + auto *param_ident = param->Ident(); + + ASSERT(param_ident->Variable()); + varbinder::Variable *param_var = param_ident->Variable(); + + ASSERT(param->TypeAnnotation()); + param_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); + signature_info->params.push_back(param_var->AsLocalVariable()); + ++signature_info->min_arg_count; + } + } + + invoke_func->ReturnTypeAnnotation()->Check(checker); + auto *signature = checker->Allocator()->New(signature_info, + node->ReturnType()->GetType(checker), invoke_func); + signature->SetOwnerVar(invoke_func->Id()->Variable()->AsLocalVariable()); + signature->AddSignatureFlag(checker::SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); + signature->SetOwner(interface_type); + + auto *func_type = checker->CreateETSFunctionType(signature); + invoke_func->SetSignature(signature); + invoke_func->Id()->Variable()->SetTsType(func_type); + interface_type->AddProperty( + invoke_func->Id()->Variable()->AsLocalVariable()); + node->FunctionalInterface()->SetTsType(interface_type); + + auto *this_var = invoke_func->Scope()->ParamScope()->Params().front(); + this_var->SetTsType(interface_type); + checker->BuildFunctionalInterfaceName(node); + + node->SetTsType(interface_type); + return interface_type; } -checker::Type *ETSAnalyzer::Check(ir::ETSImportDeclaration *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::ETSLaunchExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + expr->expr_->Check(checker); + auto *const launch_promise_type = + checker->GlobalBuiltinPromiseType() + ->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()) + ->AsETSObjectType(); + launch_promise_type->AddTypeFlag(checker::TypeFlag::GENERIC); + + // Launch expression returns a Promise type, so we need to insert the expression's type + // as type parameter for the Promise class. + + auto *expr_type = + expr->expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && !expr->expr_->TsType()->IsETSVoidType() + ? checker->PrimitiveTypeAsETSBuiltinType(expr->expr_->TsType()) + : expr->expr_->TsType(); + checker::Substitution *substitution = checker->NewSubstitution(); + ASSERT(launch_promise_type->TypeArguments().size() == 1); + substitution->emplace(checker->GetOriginalBaseType(launch_promise_type->TypeArguments()[0]), expr_type); + + expr->SetTsType(launch_promise_type->Substitute(checker->Relation(), substitution)); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + + auto *element_type = expr->type_reference_->GetType(checker); + checker->ValidateArrayIndex(expr->dimension_); + + expr->SetTsType(checker->CreateETSArrayType(element_type)); + checker->CreateBuiltinArraySignature(expr->TsType()->AsETSArrayType(), 1); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::Type *callee_type = expr->GetTypeRef()->Check(checker); + + if (!callee_type->IsETSObjectType()) { + checker->ThrowTypeError("This expression is not constructible.", expr->Start()); + } + + auto *callee_obj = callee_type->AsETSObjectType(); + expr->SetTsType(callee_obj); + + if (expr->ClassDefinition() != nullptr) { + if (!callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT) && callee_obj->GetDeclNode()->IsFinal()) { + checker->ThrowTypeError({"Class ", callee_obj->Name(), " cannot be both 'abstract' and 'final'."}, + callee_obj->GetDeclNode()->Start()); + } + + bool from_interface = callee_obj->HasObjectFlag(checker::ETSObjectFlags::INTERFACE); + auto *class_type = checker->BuildAnonymousClassProperties( + expr->ClassDefinition(), from_interface ? checker->GlobalETSObjectType() : callee_obj); + if (from_interface) { + class_type->AddInterface(callee_obj); + callee_obj = checker->GlobalETSObjectType(); + } + expr->ClassDefinition()->SetTsType(class_type); + checker->CheckClassDefinition(expr->ClassDefinition()); + checker->CheckInnerClassMembers(class_type); + expr->SetTsType(class_type); + } else if (callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) { + checker->ThrowTypeError({callee_obj->Name(), " is abstract therefore cannot be instantiated."}, expr->Start()); + } + + if (callee_type->IsETSDynamicType() && !callee_type->AsETSDynamicType()->HasDecl()) { + auto lang = callee_type->AsETSDynamicType()->Language(); + expr->SetSignature(checker->ResolveDynamicCallExpression(expr->GetTypeRef(), expr->GetArguments(), lang, true)); + } else { + auto *signature = checker->ResolveConstructExpression(callee_obj, expr->GetArguments(), expr->Start()); + + checker->CheckObjectLiteralArguments(signature, expr->GetArguments()); + checker->AddUndefinedParamsForDefaultParams(signature, expr->arguments_, checker); + + checker->ValidateSignatureAccessibility(callee_obj, signature, expr->Start()); + + ASSERT(signature->Function() != nullptr); + + if (signature->Function()->IsThrowing() || signature->Function()->IsRethrowing()) { + checker->CheckThrowingStatements(expr); + } + + if (callee_type->IsETSDynamicType()) { + ASSERT(signature->Function()->IsDynamic()); + auto lang = callee_type->AsETSDynamicType()->Language(); + expr->SetSignature( + checker->ResolveDynamicCallExpression(expr->GetTypeRef(), signature->Params(), lang, true)); + } else { + ASSERT(!signature->Function()->IsDynamic()); + expr->SetSignature(signature); + } + } + + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + auto *element_type = expr->type_reference_->GetType(checker); + + for (auto *dim : expr->dimensions_) { + checker->ValidateArrayIndex(dim); + element_type = checker->CreateETSArrayType(element_type); + } + + expr->SetTsType(element_type); + expr->signature_ = checker->CreateBuiltinArraySignature(element_type->AsETSArrayType(), expr->dimensions_.size()); + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::ETSPackageDeclaration *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const { - (void)st; - UNREACHABLE(); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::ETSParameterExpression *expr) const @@ -453,6 +609,12 @@ checker::Type *ETSAnalyzer::Check(ir::ETSStructDeclaration *node) const return nullptr; } +checker::Type *ETSAnalyzer::Check(ir::ETSTuple *node) const +{ + (void)node; + UNREACHABLE(); +} + checker::Type *ETSAnalyzer::Check(ir::ETSTypeReference *node) const { ETSChecker *checker = GetETSChecker(); @@ -475,11 +637,86 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ETSWildcardType *node) co { UNREACHABLE(); } + // compile methods for EXPRESSIONS in alphabetical order + +checker::Type *ETSAnalyzer::GetPreferredType(ir::ArrayExpression *expr) const +{ + return expr->preferred_type_; +} + checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + const bool is_array = (expr->preferred_type_ != nullptr) && expr->preferred_type_->IsETSArrayType() && + !expr->preferred_type_->IsETSTupleType(); + + if (is_array) { + expr->preferred_type_ = expr->preferred_type_->AsETSArrayType()->ElementType(); + } + + if (!expr->Elements().empty()) { + if (expr->preferred_type_ == nullptr) { + expr->preferred_type_ = expr->Elements()[0]->Check(checker); + } + + const bool is_preferred_tuple = expr->preferred_type_->IsETSTupleType(); + auto *const target_element_type = is_preferred_tuple && !is_array + ? expr->preferred_type_->AsETSTupleType()->ElementType() + : expr->preferred_type_; + + for (std::size_t idx = 0; idx < expr->elements_.size(); ++idx) { + auto *const current_element = expr->elements_[idx]; + + if (current_element->IsArrayExpression()) { + expr->HandleNestedArrayExpression(checker, current_element->AsArrayExpression(), is_array, + is_preferred_tuple, idx); + } + + if (current_element->IsObjectExpression()) { + current_element->AsObjectExpression()->SetPreferredType(expr->preferred_type_); + } + + checker::Type *element_type = current_element->Check(checker); + + if (!element_type->IsETSArrayType() && is_preferred_tuple) { + auto *const compare_type = expr->preferred_type_->AsETSTupleType()->GetTypeAtIndex(idx); + + if (compare_type == nullptr) { + checker->ThrowTypeError( + {"Too many elements in array initializer for tuple with size of ", + static_cast(expr->preferred_type_->AsETSTupleType()->GetTupleSize())}, + current_element->Start()); + } + + const checker::CastingContext cast( + checker->Relation(), current_element, element_type, compare_type, current_element->Start(), + {"Array initializer's type is not assignable to tuple type at index: ", idx}); + + element_type = compare_type; + } + + checker::AssignmentContext(checker->Relation(), current_element, element_type, target_element_type, + current_element->Start(), + {"Array element type '", element_type, "' is not assignable to explicit type '", + expr->GetPreferredType(), "'"}); + } + + expr->SetPreferredType(target_element_type); + } + + if (expr->preferred_type_ == nullptr) { + checker->ThrowTypeError("Can't resolve array type", expr->Start()); + } + + expr->SetTsType(checker->CreateETSArrayType(expr->preferred_type_)); + auto *const array_type = expr->TsType()->AsETSArrayType(); + checker->CreateBuiltinArraySignature(array_type, array_type->Rank()); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const @@ -524,19 +761,7 @@ checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const checker->AddStatus(checker::CheckerStatus::IN_LAMBDA); checker->Context().SetContainingSignature(func_type->CallSignatures()[0]); - auto *body_type = expr->Function()->Body()->Check(checker); - - if (expr->Function()->Body()->IsExpression()) { - if (expr->Function()->ReturnTypeAnnotation() == nullptr) { - func_type->CallSignatures()[0]->SetReturnType(body_type); - } - - checker::AssignmentContext( - checker->Relation(), expr->Function()->Body()->AsExpression(), body_type, - func_type->CallSignatures()[0]->ReturnType(), expr->Function()->Start(), - {"Return statements return type is not compatible with the containing functions return type"}, - checker::TypeRelationFlag::DIRECT_RETURN); - } + expr->Function()->Body()->Check(checker); checker->Context().SetContainingSignature(nullptr); checker->CheckCapturedVariables(); @@ -552,8 +777,77 @@ checker::Type *ETSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::AssignmentExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + auto *left_type = expr->Left()->Check(checker); + if (expr->Left()->IsMemberExpression() && + expr->Left()->AsMemberExpression()->Object()->TsType()->IsETSArrayType() && + expr->Left()->AsMemberExpression()->Property()->IsIdentifier() && + expr->Left()->AsMemberExpression()->Property()->AsIdentifier()->Name().Is("length")) { + checker->ThrowTypeError("Setting the length of an array is not permitted", expr->Left()->Start()); + } + + if (expr->Left()->IsIdentifier()) { + expr->target_ = expr->Left()->AsIdentifier()->Variable(); + } else { + expr->target_ = expr->Left()->AsMemberExpression()->PropVar(); + } + + if (expr->target_ != nullptr) { + checker->ValidateUnaryOperatorOperand(expr->target_); + } + + checker::Type *source_type {}; + ir::Expression *relation_node = expr->Right(); + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: + case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: + case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: + case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: + case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: + case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: + case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: + case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: + case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: + case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: + case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { + std::tie(std::ignore, expr->operation_type_) = checker->CheckBinaryOperator( + expr->Left(), expr->Right(), expr, expr->OperatorType(), expr->Start(), true); + + auto unboxed_left = checker->ETSBuiltinTypeAsPrimitiveType(left_type); + source_type = unboxed_left == nullptr ? left_type : unboxed_left; + + relation_node = expr; + break; + } + case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { + if (left_type->IsETSArrayType() && expr->Right()->IsArrayExpression()) { + checker->ModifyPreferredType(expr->Right()->AsArrayExpression(), left_type); + } + + if (expr->Right()->IsObjectExpression()) { + expr->Right()->AsObjectExpression()->SetPreferredType(left_type); + } + + source_type = expr->Right()->Check(checker); + break; + } + default: { + UNREACHABLE(); + break; + } + } + + checker::AssignmentContext(checker->Relation(), relation_node, source_type, left_type, expr->Right()->Start(), + {"Initializers type is not assignable to the target type"}); + + expr->SetTsType(expr->Left()->TsType()); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::AwaitExpression *expr) const @@ -866,110 +1160,565 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::FunctionExpression *expr) checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + expr->SetTsType(checker->ResolveIdentifier(expr)); + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::ImportExpression *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ImportExpression *expr) const { - (void)expr; UNREACHABLE(); } +static std::pair ResolveEnumMember(checker::ETSChecker *checker, + checker::Type *type, + ir::MemberExpression *expr) +{ + auto const *const enum_interface = [type]() -> checker::ETSEnumInterface const * { + if (type->IsETSEnumType()) { + return type->AsETSEnumType(); + } + return type->AsETSStringEnumType(); + }(); + + if (expr->Parent()->Type() == ir::AstNodeType::CALL_EXPRESSION && + expr->Parent()->AsCallExpression()->Callee() == expr) { + return {enum_interface->LookupMethod(checker, expr->Object(), expr->Property()->AsIdentifier()), nullptr}; + } + + auto *const literal_type = + enum_interface->LookupConstant(checker, expr->Object(), expr->Property()->AsIdentifier()); + return {literal_type, literal_type->GetMemberVar()}; +} + +static std::pair ResolveObjectMember(checker::ETSChecker *checker, + ir::MemberExpression *expr) +{ + auto resolve_res = checker->ResolveMemberReference(expr, expr->ObjType()); + switch (resolve_res.size()) { + case 1U: { + if (resolve_res[0]->Kind() == checker::ResolvedKind::PROPERTY) { + auto var = resolve_res[0]->Variable()->AsLocalVariable(); + checker->ValidatePropertyAccess(var, expr->ObjType(), expr->Property()->Start()); + return {checker->GetTypeOfVariable(var), var}; + } + return {checker->GetTypeOfVariable(resolve_res[0]->Variable()), nullptr}; + } + case 2U: { + // ETSExtensionFuncHelperType(class_method_type, extension_method_type) + auto *resolved_type = checker->CreateETSExtensionFuncHelperType( + checker->GetTypeOfVariable(resolve_res[1]->Variable())->AsETSFunctionType(), + checker->GetTypeOfVariable(resolve_res[0]->Variable())->AsETSFunctionType()); + return {resolved_type, nullptr}; + } + default: { + UNREACHABLE(); + } + } +} + +static checker::Type *CheckUnionMember(checker::ETSChecker *checker, checker::Type *base_type, + ir::MemberExpression *expr) +{ + auto *const union_type = base_type->AsETSUnionType(); + checker::Type *common_prop_type = nullptr; + auto const add_prop_type = [expr, checker, &common_prop_type](checker::Type *member_type) { + if (common_prop_type != nullptr && common_prop_type != member_type) { + checker->ThrowTypeError("Member type must be the same for all union objects.", expr->Start()); + } + common_prop_type = member_type; + }; + for (auto *const type : union_type->ConstituentTypes()) { + if (type->IsETSObjectType()) { + expr->SetObjectType(type->AsETSObjectType()); + add_prop_type(ResolveObjectMember(checker, expr).first); + } else if (type->IsETSEnumType() || base_type->IsETSStringEnumType()) { + add_prop_type(ResolveEnumMember(checker, type, expr).first); + } else { + UNREACHABLE(); + } + } + expr->SetObjectType(union_type->GetLeastUpperBoundType(checker)->AsETSObjectType()); + return common_prop_type; +} + +static checker::Type *CheckComputed(checker::ETSChecker *checker, checker::Type *base_type, ir::MemberExpression *expr) +{ + if (!base_type->IsETSArrayType() && !base_type->IsETSDynamicType()) { + checker->ThrowTypeError("Indexed access expression can only be used in array type.", expr->Object()->Start()); + } + + checker->ValidateArrayIndex(expr->Property()); + + if (base_type->IsETSTupleType()) { + checker->ValidateTupleIndex(base_type->AsETSTupleType(), expr); + } + + if (expr->Property()->IsIdentifier()) { + expr->SetPropVar(expr->Property()->AsIdentifier()->Variable()->AsLocalVariable()); + } else if (auto var = expr->Property()->Variable(); (var != nullptr) && var->IsLocalVariable()) { + expr->SetPropVar(var->AsLocalVariable()); + } + + // NOTE: apply capture conversion on this type + if (base_type->IsETSArrayType()) { + if (!base_type->IsETSTupleType()) { + return base_type->AsETSArrayType()->ElementType(); + } + + auto *const tuple_type_at_idx = base_type->AsETSTupleType()->GetTypeAtIndex( + checker->GetTupleElementAccessValue(expr->Property()->TsType())); + + if ((!expr->Parent()->IsAssignmentExpression() || expr->Parent()->AsAssignmentExpression()->Left() != expr) && + (!expr->Parent()->IsUpdateExpression())) { + // Error never should be thrown by this call, because LUB of types can be converted to any type which LUB + // was calculated by casting + const checker::CastingContext cast(checker->Relation(), expr, base_type->AsETSArrayType()->ElementType(), + tuple_type_at_idx, expr->Start(), {"Tuple type couldn't be converted "}); + + // TODO(mmartin): this can be replaced with the general type mapper, once implemented + if ((expr->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U) { + auto *const saved_node = checker->Relation()->GetNode(); + if (saved_node == nullptr) { + checker->Relation()->SetNode(expr); + } + + expr->SetTupleConvertedType(checker->PrimitiveTypeAsETSBuiltinType(tuple_type_at_idx)); + + checker->Relation()->SetNode(saved_node); + } + + if (tuple_type_at_idx->IsETSObjectType() && base_type->AsETSArrayType()->ElementType()->IsETSObjectType()) { + expr->SetTupleConvertedType(tuple_type_at_idx); + } + } + + return tuple_type_at_idx; + } + + // Dynamic + return checker->GlobalBuiltinDynamicType(base_type->AsETSDynamicType()->Language()); +} + +static checker::Type *AdjustOptional(checker::ETSChecker *checker, checker::Type *type, ir::MemberExpression *expr) +{ + expr->SetOptionalType(type); + if (expr->IsOptional() && expr->Object()->TsType()->IsNullishOrNullLike()) { + checker->Relation()->SetNode(expr); + type = checker->CreateOptionalResultType(type); + checker->Relation()->SetNode(nullptr); + } + expr->SetTsType(type); + return expr->TsType(); +} + checker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const { - (void)expr; + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + auto *const left_type = expr->Object()->Check(checker); + auto *const base_type = expr->IsOptional() ? checker->GetNonNullishType(left_type) : left_type; + if (!expr->IsOptional()) { + checker->CheckNonNullishType(left_type, expr->Object()->Start()); + } + + if (expr->IsComputed()) { + return AdjustOptional(checker, CheckComputed(checker, base_type, expr), expr); + } + + if (base_type->IsETSArrayType() && expr->Property()->AsIdentifier()->Name().Is("length")) { + return AdjustOptional(checker, checker->GlobalIntType(), expr); + } + + if (base_type->IsETSObjectType()) { + expr->SetObjectType(base_type->AsETSObjectType()); + auto [res_type, res_var] = ResolveObjectMember(checker, expr); + expr->SetPropVar(res_var); + return AdjustOptional(checker, res_type, expr); + } + + if (base_type->IsETSEnumType() || base_type->IsETSStringEnumType()) { + auto [member_type, member_var] = ResolveEnumMember(checker, base_type, expr); + expr->SetPropVar(member_var); + return AdjustOptional(checker, member_type, expr); + } + + if (base_type->IsETSUnionType()) { + return AdjustOptional(checker, CheckUnionMember(checker, base_type, expr), expr); + } + + if (base_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + checker->Relation()->SetNode(expr); + expr->SetObjectType(checker->PrimitiveTypeAsETSBuiltinType(base_type)->AsETSObjectType()); + checker->AddBoxingUnboxingFlagToNode(expr, expr->ObjType()); + auto [res_type, res_var] = ResolveObjectMember(checker, expr); + expr->SetPropVar(res_var); + return AdjustOptional(checker, res_type, expr); + } + + checker->ThrowTypeError({"Cannot access property of non-object or non-enum type"}, expr->Object()->Start()); +} + +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::NewExpression *expr) const +{ UNREACHABLE(); } +checker::Type *ETSAnalyzer::PreferredType(ir::ObjectExpression *expr) const +{ + return expr->preferred_type_; +} + +checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const +{ + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + if (expr->PreferredType() == nullptr) { + checker->ThrowTypeError({"need to specify target type for class composite"}, expr->Start()); + } + if (!expr->PreferredType()->IsETSObjectType()) { + checker->ThrowTypeError({"target type for class composite needs to be an object type"}, expr->Start()); + } + + if (expr->PreferredType()->IsETSDynamicType()) { + for (ir::Expression *prop_expr : expr->Properties()) { + ASSERT(prop_expr->IsProperty()); + ir::Property *prop = prop_expr->AsProperty(); + ir::Expression *value = prop->Value(); + value->Check(checker); + ASSERT(value->TsType()); + } + + expr->SetTsType(expr->PreferredType()); + return expr->PreferredType(); + } + + checker::ETSObjectType *obj_type = expr->PreferredType()->AsETSObjectType(); + if (obj_type->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT | checker::ETSObjectFlags::INTERFACE)) { + checker->ThrowTypeError({"target type for class composite ", obj_type->Name(), " is not instantiable"}, + expr->Start()); + } + + bool have_empty_constructor = false; + for (checker::Signature *sig : obj_type->ConstructSignatures()) { + if (sig->Params().empty()) { + have_empty_constructor = true; + checker->ValidateSignatureAccessibility(obj_type, sig, expr->Start()); + break; + } + } + if (!have_empty_constructor) { + checker->ThrowTypeError({"type ", obj_type->Name(), " has no parameterless constructor"}, expr->Start()); + } + + for (ir::Expression *prop_expr : expr->Properties()) { + ASSERT(prop_expr->IsProperty()); + ir::Property *prop = prop_expr->AsProperty(); + ir::Expression *key = prop->Key(); + ir::Expression *value = prop->Value(); + + util::StringView pname; + if (key->IsStringLiteral()) { + pname = key->AsStringLiteral()->Str(); + } else if (key->IsIdentifier()) { + pname = key->AsIdentifier()->Name(); + } else { + checker->ThrowTypeError({"key in class composite should be either identifier or string literal"}, + expr->Start()); + } + varbinder::LocalVariable *lv = obj_type->GetProperty( + pname, checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | checker::PropertySearchFlags::SEARCH_IN_BASE); + if (lv == nullptr) { + checker->ThrowTypeError({"type ", obj_type->Name(), " has no property named ", pname}, prop_expr->Start()); + } + checker->ValidatePropertyAccess(lv, obj_type, prop_expr->Start()); + if (lv->HasFlag(varbinder::VariableFlags::READONLY)) { + checker->ThrowTypeError({"cannot assign to readonly property ", pname}, prop_expr->Start()); + } + + auto *prop_type = checker->GetTypeOfVariable(lv); + key->SetTsType(prop_type); + + if (value->IsObjectExpression()) { + value->AsObjectExpression()->SetPreferredType(prop_type); + } + value->SetTsType(value->Check(checker)); + checker::AssignmentContext(checker->Relation(), value, value->TsType(), prop_type, value->Start(), + {"value type is not assignable to the property type"}); + } + + expr->SetTsType(obj_type); + return obj_type; +} + +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::OmittedExpression *expr) const +{ + UNREACHABLE(); +} + +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::OpaqueTypeNode *expr) const +{ + UNREACHABLE(); +} + +checker::Type *ETSAnalyzer::Check(ir::SequenceExpression *expr) const +{ + 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 +{ + 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([[maybe_unused]] ir::TaggedTemplateExpression *expr) const +{ + UNREACHABLE(); +} + +checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const +{ + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + if (expr->Quasis().size() != expr->Expressions().size() + 1U) { + checker->ThrowTypeError("Invalid string template expression", expr->Start()); + } + + for (auto *it : expr->Expressions()) { + it->Check(checker); + } + + for (auto *it : expr->Quasis()) { + it->Check(checker); + } + + expr->SetTsType(checker->GlobalBuiltinETSStringType()); + return expr->TsType(); +} + +checker::Type *ETSAnalyzer::Check(ir::ThisExpression *expr) const +{ + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + + /* + example code: + ``` + class A { + prop + } + function A.method() { + let a = () => { + console.println(this.prop) + } + } + is identical to + function method(this: A) { + let a = () => { + console.println(this.prop) + } + } + ``` + here when "this" is used inside an extension function, we need to bind "this" to the first + parameter(MANDATORY_PARAM_THIS), and capture the paramter's variable other than containing class's variable + */ + auto *variable = checker->AsETSChecker()->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable; + if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) { + ASSERT(variable != nullptr); + expr->SetTsType(variable->TsType()); + } else { + expr->SetTsType(checker->CheckThisOrSuperAccess(expr, checker->Context().ContainingClass(), "this")); + } + + if (checker->HasStatus(checker::CheckerStatus::IN_LAMBDA)) { + if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) { + checker->Context().AddCapturedVar(variable, expr->Start()); + } else { + checker->Context().AddCapturedVar(checker->Context().ContainingClass()->Variable(), expr->Start()); + } + } -checker::Type *ETSAnalyzer::Check(ir::NewExpression *expr) const -{ - (void)expr; - UNREACHABLE(); + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const +checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const { - (void)expr; - UNREACHABLE(); -} + ETSChecker *checker = GetETSChecker(); -checker::Type *ETSAnalyzer::Check(ir::OmittedExpression *expr) const -{ - (void)expr; - UNREACHABLE(); -} + if (expr->TsType() != nullptr) { + return expr->TsType(); + } -checker::Type *ETSAnalyzer::Check(ir::OpaqueTypeNode *expr) const -{ - (void)expr; - UNREACHABLE(); -} + auto arg_type = expr->argument_->Check(checker); + const auto is_cond_expr = expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK; + checker::Type *operand_type = checker->ApplyUnaryOperatorPromotion(arg_type, true, true, is_cond_expr); + auto unboxed_operand_type = is_cond_expr ? checker->ETSBuiltinTypeAsConditionalType(arg_type) + : checker->ETSBuiltinTypeAsPrimitiveType(arg_type); -checker::Type *ETSAnalyzer::Check(ir::SequenceExpression *expr) const -{ - (void)expr; - UNREACHABLE(); -} + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MINUS: + case lexer::TokenType::PUNCTUATOR_PLUS: { + if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", + expr->Argument()->Start()); + } -checker::Type *ETSAnalyzer::Check(ir::SuperExpression *expr) const -{ - (void)expr; - UNREACHABLE(); -} + if (operand_type->HasTypeFlag(checker::TypeFlag::CONSTANT) && + expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { + expr->SetTsType(checker->NegateNumericType(operand_type, expr)); + break; + } -checker::Type *ETSAnalyzer::Check(ir::TaggedTemplateExpression *expr) const -{ - (void)expr; - UNREACHABLE(); -} + expr->SetTsType(operand_type); + break; + } + case lexer::TokenType::PUNCTUATOR_TILDE: { + if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be integral type.", + expr->Argument()->Start()); + } -checker::Type *ETSAnalyzer::Check(ir::TemplateLiteral *expr) const -{ - (void)expr; - UNREACHABLE(); -} + if (operand_type->HasTypeFlag(checker::TypeFlag::CONSTANT)) { + expr->SetTsType(checker->BitwiseNegateIntegralType(operand_type, expr)); + break; + } -checker::Type *ETSAnalyzer::Check(ir::ThisExpression *expr) const -{ - (void)expr; - UNREACHABLE(); -} + expr->SetTsType(operand_type); + break; + } + case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { + if (checker->IsNullLikeOrVoidExpression(expr->Argument())) { + auto ts_type = checker->CreateETSBooleanType(true); + ts_type->AddTypeFlag(checker::TypeFlag::CONSTANT); + expr->SetTsType(ts_type); + break; + } -checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const -{ - (void)expr; - UNREACHABLE(); + if (operand_type == nullptr || !operand_type->IsConditionalExprType()) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be boolean type.", + expr->Argument()->Start()); + } + + auto expr_res = operand_type->ResolveConditionExpr(); + if (std::get<0>(expr_res)) { + auto ts_type = checker->CreateETSBooleanType(!std::get<1>(expr_res)); + ts_type->AddTypeFlag(checker::TypeFlag::CONSTANT); + expr->SetTsType(ts_type); + break; + } + + expr->SetTsType(checker->GlobalETSBooleanType()); + break; + } + case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR: { + expr->SetTsType(arg_type); + break; + } + default: { + UNREACHABLE(); + break; + } + } + + if (arg_type->IsETSObjectType() && (unboxed_operand_type != nullptr) && + unboxed_operand_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + expr->Argument()->AddBoxingUnboxingFlag(checker->GetUnboxingFlag(unboxed_operand_type)); + } + + return expr->TsType(); } 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 if (expr->Argument()->IsTSAsExpression()) { + if (auto *const as_expr_var = expr->Argument()->AsTSAsExpression()->Variable(); as_expr_var != nullptr) { + checker->ValidateUnaryOperatorOperand(as_expr_var); + } + } 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 +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::YieldExpression *expr) const { - (void)expr; 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(); } checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() == nullptr) { + expr->SetTsType(checker->CreateETSBooleanType(expr->Value())); + } + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + if (expr->TsType() == nullptr) { + expr->SetTsType(checker->Allocator()->New(expr->Char())); + } + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const @@ -1146,20 +1895,44 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::ImportSpecifier *st) cons // compile methods for STATEMENTS in alphabetical order checker::Type *ETSAnalyzer::Check(ir::AssertStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker->CheckTruthinessOfType(st->test_); + + if (st->Second() != nullptr) { + auto *msg_type = st->second_->Check(checker); + + if (!msg_type->IsETSStringType()) { + checker->ThrowTypeError("Assert message must be string", st->Second()->Start()); + } + } + + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::ScopeContext scope_ctx(checker, st->Scope()); + + for (auto *it : st->Statements()) { + it->Check(checker); + } + + for (auto [stmt, trailing_block] : st->trailing_blocks_) { + auto iterator = std::find(st->Statements().begin(), st->Statements().end(), stmt); + ASSERT(iterator != st->Statements().end()); + st->Statements().insert(iterator + 1, trailing_block); + trailing_block->Check(checker); + } + + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + st->target_ = checker->FindJumpTarget(st->Type(), st, st->Ident()); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::ClassDeclaration *st) const @@ -1545,8 +2318,8 @@ checker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const } if ((st->argument_ != nullptr) && st->argument_->IsArrayExpression()) { - st->argument_->AsArrayExpression()->SetPreferredType( - func_return_type->IsETSArrayType() ? func_return_type->AsETSArrayType()->ElementType() : func_return_type); + checker->ModifyPreferredType(st->argument_->AsArrayExpression(), func_return_type); + st->argument_->Check(checker); } st->return_type_ = func_return_type; @@ -1615,32 +2388,92 @@ checker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const checker::Type *ETSAnalyzer::Check(ir::ThrowStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + auto *arg_type = st->argument_->Check(checker); + checker->CheckExceptionOrErrorType(arg_type, st->Start()); + + if (checker->Relation()->IsAssignableTo(arg_type, checker->GlobalBuiltinExceptionType())) { + checker->CheckThrowingStatements(st); + } + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::TryStatement *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + std::vector exceptions; + st->Block()->Check(checker); + + for (auto *catch_clause : st->CatchClauses()) { + auto exception_type = catch_clause->Check(checker); + + if ((exception_type != nullptr) && (catch_clause->Param() != nullptr)) { + auto *clause_type = exception_type->AsETSObjectType(); + + for (auto *exception : exceptions) { + checker->Relation()->IsIdenticalTo(clause_type, exception); + if (checker->Relation()->IsTrue()) { + checker->ThrowTypeError("Redeclaration of exception type", catch_clause->Start()); + } + } + + exceptions.push_back(clause_type); + } + } + + bool default_catch_found = false; + + for (auto *catch_clause : st->CatchClauses()) { + if (default_catch_found) { + checker->ThrowTypeError("Default catch clause should be the last in the try statement", + catch_clause->Start()); + } + + default_catch_found = catch_clause->IsDefaultCatchClause(); + } + + if (st->HasFinalizer()) { + st->finalizer_->Check(checker); + } + + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + ASSERT(st->Id()->IsIdentifier()); + ir::ModifierFlags flags = ir::ModifierFlags::NONE; + + if (st->Id()->Parent()->Parent()->AsVariableDeclaration()->Kind() == + ir::VariableDeclaration::VariableDeclarationKind::CONST) { + flags |= ir::ModifierFlags::CONST; + } + + st->SetTsType(checker->CheckVariableDeclaration(st->Id()->AsIdentifier(), + st->Id()->AsIdentifier()->TypeAnnotation(), st->Init(), flags)); + return st->TsType(); } 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 { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::ScopeContext scope_ctx(checker, st->Scope()); + + checker->CheckTruthinessOfType(st->Test()); + + st->Body()->Check(checker); + return nullptr; } // from ts folder checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSAnyKeyword *node) const @@ -1650,19 +2483,48 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSAnyKeyword *node) const checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + node->element_type_->Check(checker); + return nullptr; } 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 +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSBigintKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1671,21 +2533,18 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSBooleanKeyword *node) c UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSClassImplements *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSConditionalType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSConditionalType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSConstructorType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSConstructorType *node) const { - (void)node; UNREACHABLE(); } @@ -1724,105 +2583,116 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSExternalModuleReference UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSFunctionType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSFunctionType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSImportEqualsDeclaration *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSImportEqualsDeclaration *st) const { - (void)st; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSImportType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSImportType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSIndexedAccessType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSIndexedAccessType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSInferType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSInferType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSInterfaceBody *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSInterfaceBody *expr) const { - (void)expr; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + + checker::ETSObjectType *interface_type {}; + + if (st->TsType() == nullptr) { + interface_type = checker->BuildInterfaceProperties(st); + ASSERT(interface_type != nullptr); + interface_type->SetSuperType(checker->GlobalETSObjectType()); + checker->CheckInvokeMethodsLegitimacy(interface_type); + st->SetTsType(interface_type); + } + + checker::ScopeContext scope_ctx(checker, st->Scope()); + auto saved_context = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, interface_type); + + for (auto *it : st->Body()->Body()) { + it->Check(checker); + } + + return nullptr; } -checker::Type *ETSAnalyzer::Check(ir::TSInterfaceHeritage *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSIntersectionType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSIntersectionType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSLiteralType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSLiteralType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSMappedType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSMappedType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSModuleBlock *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSModuleBlock *st) const { - (void)st; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSModuleDeclaration *st) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSModuleDeclaration *st) const { - (void)st; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSNamedTupleMember *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSNamedTupleMember *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSNeverKeyword *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSNeverKeyword *node) const { - (void)node; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + auto expr_type = expr->expr_->Check(checker); + + if (!expr_type->IsNullish()) { + checker->ThrowTypeError("Bad operand type, the operand of the non-null expression must be a nullable type", + expr->Expr()->Start()); + } + + expr->SetTsType(expr_type->IsNullish() ? checker->GetNonNullishType(expr_type) : expr_type); + return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::TSNullKeyword *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSNullKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1836,22 +2706,30 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSObjectKeyword *node) co UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSParameterProperty *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSParameterProperty *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSParenthesizedType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSParenthesizedType *node) const { - (void)node; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + checker::Type *base_type = expr->Left()->Check(checker); + if (base_type->IsETSObjectType()) { + varbinder::Variable *prop = + base_type->AsETSObjectType()->GetProperty(expr->Right()->Name(), checker::PropertySearchFlags::SEARCH_DECL); + + if (prop != nullptr) { + return checker->GetTypeOfVariable(prop); + } + } + + checker->ThrowTypeError({"'", expr->Right()->Name(), "' type does not exist."}, expr->Right()->Start()); } checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSStringKeyword *node) const @@ -1859,75 +2737,65 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSStringKeyword *node) co UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSThisType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSThisType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTupleType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTupleType *node) const { - (void)node; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + st->TypeAnnotation()->Check(checker); + return nullptr; } -checker::Type *ETSAnalyzer::Check(ir::TSTypeAssertion *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeLiteral *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeLiteral *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeOperator *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeOperator *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeParameter *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeParameter *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeParameterDeclaration *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeParameterDeclaration *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeParameterInstantiation *expr) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeParameterInstantiation *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypePredicate *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypePredicate *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeQuery *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeQuery *node) const { - (void)node; UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeReference *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeReference *node) const { - (void)node; UNREACHABLE(); } @@ -1936,9 +2804,8 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSUndefinedKeyword *node) UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSUnionType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSUnionType *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/checker/ETSAnalyzer.h b/ets2panda/checker/ETSAnalyzer.h index ba76d31adaced2bab7242650536707b4db6e1c2e..92725e2ed242839f887cb33eb3473d4d708e5a92 100644 --- a/ets2panda/checker/ETSAnalyzer.h +++ b/ets2panda/checker/ETSAnalyzer.h @@ -34,6 +34,8 @@ public: virtual checker::Type *Check(ir::nodeType *node) const override; AST_NODE_REINTERPRET_MAPPING(DECLARE_ETSANALYZER_CHECK_METHOD) #undef DECLARE_ETSANALYZER_CHECK_METHOD + checker::Type *PreferredType(ir::ObjectExpression *expr) const; + checker::Type *GetPreferredType(ir::ArrayExpression *expr) const; private: ETSChecker *GetETSChecker() const; diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 0a35bc556a69d48ce367f9ae596ee7d2b0347680..1696ec817cac39508ea0d007438c078ea06240b8 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -17,20 +17,20 @@ #define ES2PANDA_CHECKER_ETS_CHECKER_H #include "checker/checkerContext.h" -#include "checker/types/ets/etsObjectType.h" -#include "checker/checker.h" #include "varbinder/enumMemberResult.h" +#include "varbinder/scope.h" +#include "checker/checker.h" +#include "checker/ets/primitiveWrappers.h" +#include "checker/ets/typeConverter.h" +#include "checker/types/ets/etsObjectType.h" +#include "checker/types/ets/etsTupleType.h" +#include "checker/types/ets/types.h" +#include "checker/types/globalTypesHolder.h" #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterInstantiation.h" #include "util/enumbitops.h" #include "util/ustring.h" #include "checker/resolveResult.h" -#include "checker/types/ets/types.h" -#include "checker/ets/typeConverter.h" -#include "checker/ets/primitiveWrappers.h" -#include "checker/types/globalTypesHolder.h" -#include "varbinder/scope.h" - #include "macros.h" #include @@ -140,7 +140,9 @@ public: void ValidateImplementedInterface(ETSObjectType *type, Type *interface, std::unordered_set *extends_set, const lexer::SourcePosition &pos); void ResolveDeclaredMembersOfObject(ETSObjectType *type); + int32_t GetTupleElementAccessValue(const Type *type) const; Type *ValidateArrayIndex(ir::Expression *expr); + void ValidateTupleIndex(const ETSTupleType *tuple, const ir::MemberExpression *expr); ETSObjectType *CheckThisOrSuperAccess(ir::Expression *node, ETSObjectType *class_type, std::string_view msg); void CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type); void SetTypeParameterType(ir::TSTypeParameter *type_param, Type *type_param_type); @@ -493,6 +495,8 @@ public: ETSChecker *checker); void SetArrayPreferredTypeForNestedMemberExpressions(ir::MemberExpression *expr, Type *annotation_type); bool ExtensionETSFunctionType(checker::Type *type); + void ValidateTupleMinElementSize(ir::ArrayExpression *array_expr, ETSTupleType *tuple); + void ModifyPreferredType(ir::ArrayExpression *array_expr, Type *new_preferred_type); // Exception ETSObjectType *CheckExceptionOrErrorType(checker::Type *type, lexer::SourcePosition pos); diff --git a/ets2panda/checker/TSAnalyzer.cpp b/ets2panda/checker/TSAnalyzer.cpp index 49ebfde42f51c16072b57f36c933341a4aee7e70..08e5bf60401aac1c249a91a5cb20f2c2502256ac 100644 --- a/ets2panda/checker/TSAnalyzer.cpp +++ b/ets2panda/checker/TSAnalyzer.cpp @@ -99,9 +99,8 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ScriptFunction *node) cons UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::SpreadElement *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::SpreadElement *expr) const { - (void)expr; UNREACHABLE(); } @@ -184,55 +183,84 @@ checker::Type *TSAnalyzer::Check(ir::TSPropertySignature *node) const checker::Type *TSAnalyzer::Check(ir::TSSignatureDeclaration *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + if (node->TsType() != nullptr) { + return node->TsType(); + } + + checker::ScopeContext scope_ctx(checker, node->Scope()); + + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + checker->CheckFunctionParameterDeclarations(node->Params(), signature_info); + + bool is_call_signature = (node->Kind() == ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE); + + if (node->ReturnTypeAnnotation() == nullptr) { + if (is_call_signature) { + checker->ThrowTypeError( + "Call signature, which lacks return-type annotation, implicitly has an 'any' return type.", + node->Start()); + } + + checker->ThrowTypeError( + "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.", + node->Start()); + } + + node->return_type_annotation_->Check(checker); + checker::Type *return_type = node->return_type_annotation_->GetType(checker); + + auto *signature = checker->Allocator()->New(signature_info, return_type); + + checker::Type *placeholder_obj = nullptr; + + if (is_call_signature) { + placeholder_obj = checker->CreateObjectTypeWithCallSignature(signature); + } else { + placeholder_obj = checker->CreateObjectTypeWithConstructSignature(signature); + } + + node->SetTsType(placeholder_obj); + return placeholder_obj; } // from ets folder -checker::Type *TSAnalyzer::Check(ir::ETSClassLiteral *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSClassLiteral *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSFunctionType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSFunctionType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSImportDeclaration *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSLaunchExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSLaunchExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::ETSPackageDeclaration *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSPackageDeclaration *st) const { - (void)st; UNREACHABLE(); } @@ -251,6 +279,12 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSStructDeclaration *node UNREACHABLE(); } +checker::Type *TSAnalyzer::Check(ir::ETSTuple *node) const +{ + (void)node; + UNREACHABLE(); +} + checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSTypeReference *node) const { UNREACHABLE(); @@ -272,10 +306,129 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ETSWildcardType *node) con UNREACHABLE(); } // compile methods for EXPRESSIONS in alphabetical order + +static void GetSpreadElementType(checker::TSChecker *checker, checker::Type *spread_type, + ArenaVector &element_types, const lexer::SourcePosition &loc) +{ + bool in_const_context = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); + + if (spread_type->IsObjectType() && spread_type->AsObjectType()->IsTupleType()) { + ArenaVector tuple_element_types(checker->Allocator()->Adapter()); + checker::TupleType *spread_tuple = spread_type->AsObjectType()->AsTupleType(); + + for (auto *it : spread_tuple->Properties()) { + if (in_const_context) { + element_types.push_back(it->TsType()); + continue; + } + + tuple_element_types.push_back(it->TsType()); + } + + if (in_const_context) { + return; + } + + element_types.push_back(checker->CreateUnionType(std::move(tuple_element_types))); + return; + } + + if (spread_type->IsUnionType()) { + ArenaVector spread_types(checker->Allocator()->Adapter()); + bool throw_error = false; + + for (auto *type : spread_type->AsUnionType()->ConstituentTypes()) { + if (type->IsArrayType()) { + spread_types.push_back(type->AsArrayType()->ElementType()); + continue; + } + + if (type->IsObjectType() && type->AsObjectType()->IsTupleType()) { + checker::TupleType *tuple = type->AsObjectType()->AsTupleType(); + + for (auto *it : tuple->Properties()) { + spread_types.push_back(it->TsType()); + } + + continue; + } + + throw_error = true; + break; + } + + if (!throw_error) { + element_types.push_back(checker->CreateUnionType(std::move(spread_types))); + return; + } + } + + checker->ThrowTypeError( + {"Type '", spread_type, "' must have a '[Symbol.iterator]()' method that returns an iterator."}, loc); +} + checker::Type *TSAnalyzer::Check(ir::ArrayExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + ArenaVector element_types(checker->Allocator()->Adapter()); + ArenaVector element_flags(checker->Allocator()->Adapter()); + bool in_const_context = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); + bool create_tuple = checker->HasStatus(checker::CheckerStatus::FORCE_TUPLE); + + for (auto *it : expr->Elements()) { + if (it->IsSpreadElement()) { + checker::Type *spread_type = it->AsSpreadElement()->Argument()->Check(checker); + + if (spread_type->IsArrayType()) { + element_types.push_back(in_const_context ? spread_type : spread_type->AsArrayType()->ElementType()); + element_flags.push_back(checker::ElementFlags::VARIADIC); + continue; + } + + GetSpreadElementType(checker, spread_type, element_types, it->Start()); + element_flags.push_back(checker::ElementFlags::REST); + continue; + } + + checker::Type *element_type = it->Check(checker); + + if (!in_const_context) { + element_type = checker->GetBaseTypeOfLiteralType(element_type); + } + + element_flags.push_back(checker::ElementFlags::REQUIRED); + element_types.push_back(element_type); + } + + if (in_const_context || create_tuple) { + checker::ObjectDescriptor *desc = checker->Allocator()->New(checker->Allocator()); + uint32_t index = 0; + + for (auto it = element_types.begin(); it != element_types.end(); it++, index++) { + util::StringView member_index = util::Helpers::ToStringView(checker->Allocator(), index); + varbinder::LocalVariable *tuple_member = varbinder::Scope::CreateVar( + checker->Allocator(), member_index, varbinder::VariableFlags::PROPERTY, nullptr); + + if (in_const_context) { + tuple_member->AddFlag(varbinder::VariableFlags::READONLY); + } + + tuple_member->SetTsType(*it); + desc->properties.push_back(tuple_member); + } + + return checker->CreateTupleType(desc, std::move(element_flags), checker::ElementFlags::REQUIRED, index, index, + in_const_context); + } + + checker::Type *array_element_type = nullptr; + if (element_types.empty()) { + array_element_type = checker->GlobalAnyType(); + } else { + array_element_type = checker->CreateUnionType(std::move(element_types)); + } + + return checker->Allocator()->New(array_element_type); } checker::Type *TSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const @@ -313,8 +466,73 @@ checker::Type *TSAnalyzer::Check(ir::ArrowFunctionExpression *expr) const checker::Type *TSAnalyzer::Check(ir::AssignmentExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + if (expr->Left()->IsArrayPattern()) { + auto saved_context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); + auto destructuring_context = + checker::ArrayDestructuringContext(checker, expr->Left(), true, true, nullptr, expr->Right()); + destructuring_context.Start(); + return destructuring_context.InferredType(); + } + + if (expr->Left()->IsObjectPattern()) { + auto saved_context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); + auto destructuring_context = + checker::ObjectDestructuringContext(checker, expr->Left(), true, true, nullptr, expr->Right()); + destructuring_context.Start(); + return destructuring_context.InferredType(); + } + + if (expr->Left()->IsIdentifier() && expr->Left()->AsIdentifier()->Variable() != nullptr && + expr->Left()->AsIdentifier()->Variable()->Declaration()->IsConstDecl()) { + checker->ThrowTypeError( + {"Cannot assign to ", expr->Left()->AsIdentifier()->Name(), " because it is a constant."}, + expr->Left()->Start()); + } + + auto *left_type = expr->Left()->Check(checker); + + if (left_type->HasTypeFlag(checker::TypeFlag::READONLY)) { + checker->ThrowTypeError("Cannot assign to this property because it is readonly.", expr->Left()->Start()); + } + + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + checker->ElaborateElementwise(left_type, expr->Right(), expr->Left()->Start()); + return checker->CheckTypeCached(expr->Right()); + } + + auto *right_type = expr->Right()->Check(checker); + + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: + case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: + case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: + case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: + case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: + case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: + case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: + case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: + case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: + case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { + return checker->CheckBinaryOperator(left_type, right_type, expr->Left(), expr->Right(), expr, + expr->OperatorType()); + } + case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { + return checker->CheckPlusOperator(left_type, right_type, expr->Left(), expr->Right(), expr, + expr->OperatorType()); + } + case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { + checker->CheckAssignmentOperator(expr->OperatorType(), expr->Left(), left_type, right_type); + return right_type; + } + default: { + UNREACHABLE(); + break; + } + } + + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::AwaitExpression *expr) const @@ -478,109 +696,477 @@ 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 varbinder::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(); + } + } + } + + varbinder::Variable *prop = checker->GetPropertyOfType(base_type, expr->Property()->AsIdentifier()->Name()); + + if (prop != nullptr) { + checker::Type *prop_type = checker->GetTypeOfVariable(prop); + if (prop->HasFlag(varbinder::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; +} +static const util::StringView &GetPropertyName(const ir::Expression *key) +{ + if (key->IsIdentifier()) { + return key->AsIdentifier()->Name(); + } + + if (key->IsStringLiteral()) { + return key->AsStringLiteral()->Str(); + } + + ASSERT(key->IsNumberLiteral()); + return key->AsNumberLiteral()->Str(); +} + +static varbinder::VariableFlags GetFlagsForProperty(const ir::Property *prop) +{ + if (!prop->IsMethod()) { + return varbinder::VariableFlags::PROPERTY; + } + + varbinder::VariableFlags prop_flags = varbinder::VariableFlags::METHOD; + + if (prop->IsAccessor() && prop->Kind() == ir::PropertyKind::GET) { + prop_flags |= varbinder::VariableFlags::READONLY; + } + + return prop_flags; +} + +static checker::Type *GetTypeForProperty(ir::Property *prop, checker::TSChecker *checker) +{ + if (prop->IsAccessor()) { + checker::Type *func_type = prop->Value()->Check(checker); + + if (prop->Kind() == ir::PropertyKind::SET) { + return checker->GlobalAnyType(); + } + + ASSERT(func_type->IsObjectType() && func_type->AsObjectType()->IsFunctionType()); + return func_type->AsObjectType()->CallSignatures()[0]->ReturnType(); + } + + if (prop->IsShorthand()) { + return prop->Key()->Check(checker); + } + + return prop->Value()->Check(checker); } checker::Type *TSAnalyzer::Check(ir::ObjectExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + + checker::ObjectDescriptor *desc = checker->Allocator()->New(checker->Allocator()); + std::unordered_map all_properties_map; + bool in_const_context = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); + ArenaVector computed_number_prop_types(checker->Allocator()->Adapter()); + ArenaVector computed_string_prop_types(checker->Allocator()->Adapter()); + bool has_computed_number_property = false; + bool has_computed_string_property = false; + bool seen_spread = false; + + for (auto *it : expr->Properties()) { + if (it->IsProperty()) { + auto *prop = it->AsProperty(); + + if (prop->IsComputed()) { + checker::Type *computed_name_type = checker->CheckComputedPropertyName(prop->Key()); + + if (computed_name_type->IsNumberType()) { + has_computed_number_property = true; + computed_number_prop_types.push_back(prop->Value()->Check(checker)); + continue; + } + + if (computed_name_type->IsStringType()) { + has_computed_string_property = true; + computed_string_prop_types.push_back(prop->Value()->Check(checker)); + continue; + } + } + + checker::Type *prop_type = GetTypeForProperty(prop, checker); + varbinder::VariableFlags flags = GetFlagsForProperty(prop); + const util::StringView &prop_name = GetPropertyName(prop->Key()); + + auto *member_var = varbinder::Scope::CreateVar(checker->Allocator(), prop_name, flags, it); + + if (in_const_context) { + member_var->AddFlag(varbinder::VariableFlags::READONLY); + } else { + prop_type = checker->GetBaseTypeOfLiteralType(prop_type); + } + + member_var->SetTsType(prop_type); + + if (prop->Key()->IsNumberLiteral()) { + member_var->AddFlag(varbinder::VariableFlags::NUMERIC_NAME); + } + + varbinder::LocalVariable *found_member = desc->FindProperty(prop_name); + all_properties_map.insert({prop_name, it->Start()}); + + if (found_member != nullptr) { + found_member->SetTsType(prop_type); + continue; + } + + desc->properties.push_back(member_var); + continue; + } + + ASSERT(it->IsSpreadElement()); + + checker::Type *const spread_type = it->AsSpreadElement()->Argument()->Check(checker); + seen_spread = true; + + // NOTE: aszilagyi. handle union of object types + if (!spread_type->IsObjectType()) { + checker->ThrowTypeError("Spread types may only be created from object types.", it->Start()); + } + + for (auto *spread_prop : spread_type->AsObjectType()->Properties()) { + auto found = all_properties_map.find(spread_prop->Name()); + if (found != all_properties_map.end()) { + checker->ThrowTypeError( + {found->first, " is specified more than once, so this usage will be overwritten."}, found->second); + } + + varbinder::LocalVariable *found_member = desc->FindProperty(spread_prop->Name()); + + if (found_member != nullptr) { + found_member->SetTsType(spread_prop->TsType()); + continue; + } + + desc->properties.push_back(spread_prop); + } + } + + if (!seen_spread && (has_computed_number_property || has_computed_string_property)) { + for (auto *it : desc->properties) { + computed_string_prop_types.push_back(it->TsType()); + + if (has_computed_number_property && it->HasFlag(varbinder::VariableFlags::NUMERIC_NAME)) { + computed_number_prop_types.push_back(it->TsType()); + } + } + + if (has_computed_number_property) { + desc->number_index_info = checker->Allocator()->New( + checker->CreateUnionType(std::move(computed_number_prop_types)), "x", in_const_context); + } + + if (has_computed_string_property) { + desc->string_index_info = checker->Allocator()->New( + checker->CreateUnionType(std::move(computed_string_prop_types)), "x", in_const_context); + } + } + + checker::Type *return_type = checker->Allocator()->New(desc); + return_type->AsObjectType()->AddObjectFlag(checker::ObjectFlags::RESOLVED_MEMBERS | + checker::ObjectFlags::CHECK_EXCESS_PROPS); + return return_type; } -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 +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::OpaqueTypeNode *expr) const { - (void)expr; - UNREACHABLE(); + return expr->TsType(); } -checker::Type *TSAnalyzer::Check(ir::SequenceExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::SequenceExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // NOTE: 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(); + // NOTE: aszilagyi. + return checker->GlobalAnyType(); } -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 +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TemplateLiteral *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // TODO(aszilagyi) + return checker->GlobalAnyType(); } -checker::Type *TSAnalyzer::Check(ir::ThisExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ThisExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // NOTE: aszilagyi + return checker->GlobalAnyType(); +} + +checker::Type *TSAnalyzer::CheckDeleteKeyword([[maybe_unused]] checker::TSChecker *checker, + ir::UnaryExpression *expr) const +{ + checker::Type *prop_type = expr->argument_->Check(checker); + if (!expr->Argument()->IsMemberExpression()) { + checker->ThrowTypeError("The operand of a delete operator must be a property reference.", + expr->Argument()->Start()); + } + if (prop_type->Variable()->HasFlag(varbinder::VariableFlags::READONLY)) { + checker->ThrowTypeError("The operand of a delete operator cannot be a readonly property.", + expr->Argument()->Start()); + } + if (!prop_type->Variable()->HasFlag(varbinder::VariableFlags::OPTIONAL)) { + checker->ThrowTypeError("The operand of a delete operator must be a optional.", expr->Argument()->Start()); + } + return checker->GlobalBooleanType(); +} + +checker::Type *TSAnalyzer::CheckLiteral([[maybe_unused]] checker::TSChecker *checker, ir::UnaryExpression *expr) const +{ + if (!expr->Argument()->IsLiteral()) { + return nullptr; + } + + const ir::Literal *lit = expr->Argument()->AsLiteral(); + if (lit->IsNumberLiteral()) { + auto number_value = lit->AsNumberLiteral()->Number().GetDouble(); + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS) { + return checker->CreateNumberLiteralType(number_value); + } + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { + return checker->CreateNumberLiteralType(-number_value); + } + } else if (lit->IsBigIntLiteral() && expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { + return checker->CreateBigintLiteralType(lit->AsBigIntLiteral()->Str(), true); + } + + return nullptr; } checker::Type *TSAnalyzer::Check(ir::UnaryExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::Type *operand_type = expr->argument_->Check(checker); + + if (expr->operator_ == lexer::TokenType::KEYW_TYPEOF) { + return operand_type; + } + + if (expr->operator_ == lexer::TokenType::KEYW_DELETE) { + return CheckDeleteKeyword(checker, expr); + } + + auto *res = CheckLiteral(checker, expr); + if (res != nullptr) { + return res; + } + + switch (expr->operator_) { + case lexer::TokenType::PUNCTUATOR_PLUS: + case lexer::TokenType::PUNCTUATOR_MINUS: + case lexer::TokenType::PUNCTUATOR_TILDE: { + checker->CheckNonNullType(operand_type, expr->Start()); + // NOTE: aszilagyi. check Symbol like types + + if (expr->operator_ == lexer::TokenType::PUNCTUATOR_PLUS) { + if (checker::TSChecker::MaybeTypeOfKind(operand_type, checker::TypeFlag::BIGINT_LIKE)) { + checker->ThrowTypeError({"Operator '+' cannot be applied to type '", operand_type, "'"}, + expr->Start()); + } + + return checker->GlobalNumberType(); + } + + return checker->GetUnaryResultType(operand_type); + } + case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { + checker->CheckTruthinessOfType(operand_type, expr->Start()); + auto facts = operand_type->GetTypeFacts(); + if ((facts & checker::TypeFacts::TRUTHY) != 0) { + return checker->GlobalFalseType(); + } + + if ((facts & checker::TypeFacts::FALSY) != 0) { + return checker->GlobalTrueType(); + } + + return checker->GlobalBooleanType(); + } + default: { + UNREACHABLE(); + } + } + + return nullptr; } 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 +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::YieldExpression *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + // NOTE: aszilagyi. + return checker->GlobalAnyType(); } // 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 { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + return expr->Value() ? checker->GlobalTrueType() : checker->GlobalFalseType(); } -checker::Type *TSAnalyzer::Check(ir::CharLiteral *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::CharLiteral *expr) const { - (void)expr; UNREACHABLE(); } @@ -671,22 +1257,26 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ImportSpecifier *st) const UNREACHABLE(); } // compile methods for STATEMENTS in alphabetical order -checker::Type *TSAnalyzer::Check(ir::AssertStatement *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::AssertStatement *st) const { - (void)st; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::BlockStatement *st) const { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::ScopeContext scope_ctx(checker, st->Scope()); + + for (auto *it : st->Statements()) { + it->Check(checker); + } + + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::BreakStatement *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::BreakStatement *st) const { - (void)st; - UNREACHABLE(); + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ClassDeclaration *st) const @@ -874,34 +1464,138 @@ checker::Type *TSAnalyzer::Check(ir::SwitchStatement *st) const return nullptr; } -checker::Type *TSAnalyzer::Check(ir::ThrowStatement *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::ThrowStatement *st) const { - (void)st; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TryStatement *st) const { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + st->Block()->Check(checker); + + for (auto *catch_clause : st->CatchClauses()) { + if (catch_clause != nullptr) { + catch_clause->Check(checker); + } + } + + if (st->HasFinalizer()) { + st->finalizer_->Check(checker); + } + + return nullptr; +} + +static void CheckSimpleVariableDeclaration(checker::TSChecker *checker, ir::VariableDeclarator *declarator) +{ + varbinder::Variable *const binding_var = declarator->Id()->AsIdentifier()->Variable(); + checker::Type *previous_type = binding_var->TsType(); + auto *const type_annotation = declarator->Id()->AsIdentifier()->TypeAnnotation(); + auto *const initializer = declarator->Init(); + const bool is_const = declarator->Parent()->AsVariableDeclaration()->Kind() == + ir::VariableDeclaration::VariableDeclarationKind::CONST; + + if (is_const) { + checker->AddStatus(checker::CheckerStatus::IN_CONST_CONTEXT); + } + + if (type_annotation != nullptr) { + type_annotation->Check(checker); + } + + if (type_annotation != nullptr && initializer != nullptr) { + checker::Type *const annotation_type = type_annotation->GetType(checker); + checker->ElaborateElementwise(annotation_type, initializer, declarator->Id()->Start()); + binding_var->SetTsType(annotation_type); + } else if (type_annotation != nullptr) { + binding_var->SetTsType(type_annotation->GetType(checker)); + } else if (initializer != nullptr) { + checker::Type *initializer_type = checker->CheckTypeCached(initializer); + + if (!is_const) { + initializer_type = checker->GetBaseTypeOfLiteralType(initializer_type); + } + + if (initializer_type->IsNullType()) { + checker->ThrowTypeError( + {"Cannot infer type for variable '", declarator->Id()->AsIdentifier()->Name(), "'."}, + declarator->Id()->Start()); + } + + binding_var->SetTsType(initializer_type); + } else { + checker->ThrowTypeError({"Variable ", declarator->Id()->AsIdentifier()->Name(), " implicitly has an any type."}, + declarator->Id()->Start()); + } + + if (previous_type != nullptr) { + checker->IsTypeIdenticalTo(binding_var->TsType(), previous_type, + {"Subsequent variable declaration must have the same type. Variable '", + binding_var->Name(), "' must be of type '", previous_type, "', but here has type '", + binding_var->TsType(), "'."}, + declarator->Id()->Start()); + } + + checker->RemoveStatus(checker::CheckerStatus::IN_CONST_CONTEXT); } checker::Type *TSAnalyzer::Check(ir::VariableDeclarator *st) const { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + + if (st->TsType() == st->CHECKED) { + return nullptr; + } + + if (st->Id()->IsIdentifier()) { + CheckSimpleVariableDeclaration(checker, st); + st->SetTsType(st->CHECKED); + return nullptr; + } + + if (st->Id()->IsArrayPattern()) { + auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); + checker::ArrayDestructuringContext(checker, st->Id(), false, + st->Id()->AsArrayPattern()->TypeAnnotation() == nullptr, + st->Id()->AsArrayPattern()->TypeAnnotation(), st->Init()) + .Start(); + + st->SetTsType(st->CHECKED); + return nullptr; + } + + ASSERT(st->Id()->IsObjectPattern()); + auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); + checker::ObjectDestructuringContext(checker, st->Id(), false, + st->Id()->AsObjectPattern()->TypeAnnotation() == nullptr, + st->Id()->AsObjectPattern()->TypeAnnotation(), st->Init()) + .Start(); + + st->SetTsType(st->CHECKED); + return nullptr; } 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 { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::ScopeContext scope_ctx(checker, st->Scope()); + + checker::Type *test_type = st->Test()->Check(checker); + checker->CheckTruthinessOfType(test_type, st->Test()->Start()); + + st->Body()->Check(checker); + return nullptr; } // from ts folder checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSAnyKeyword *node) const @@ -911,20 +1605,86 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSAnyKeyword *node) const checker::Type *TSAnalyzer::Check(ir::TSArrayType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->element_type_->Check(checker); + return nullptr; +} + +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 +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSBigintKeyword *node) const { - (void)node; - UNREACHABLE(); + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSBooleanKeyword *node) const @@ -932,22 +1692,28 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSBooleanKeyword *node) co return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSClassImplements *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSConditionalType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSConditionalType *node) const { - (void)node; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TSConstructorType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::ScopeContext scope_ctx(checker, node->Scope()); + + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + checker->CheckFunctionParameterDeclarations(node->Params(), signature_info); + node->return_type_->Check(checker); + auto *construct_signature = + checker->Allocator()->New(signature_info, node->return_type_->GetType(checker)); + + return checker->CreateConstructorTypeWithSignature(construct_signature); } static varbinder::EnumMemberResult EvaluateIdentifier(checker::TSChecker *checker, varbinder::EnumVariable *enum_var, @@ -1292,104 +2058,194 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSExternalModuleReference checker::Type *TSAnalyzer::Check(ir::TSFunctionType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::ScopeContext scope_ctx(checker, node->Scope()); + + auto *signature_info = checker->Allocator()->New(checker->Allocator()); + checker->CheckFunctionParameterDeclarations(node->Params(), signature_info); + node->return_type_->Check(checker); + auto *call_signature = + checker->Allocator()->New(signature_info, node->return_type_->GetType(checker)); + + return checker->CreateFunctionTypeWithSignature(call_signature); } -checker::Type *TSAnalyzer::Check(ir::TSImportEqualsDeclaration *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSImportEqualsDeclaration *st) const { - (void)st; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSImportType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSImportType *node) const { - (void)node; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TSIndexedAccessType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->object_type_->Check(checker); + node->index_type_->Check(checker); + checker::Type *resolved = node->GetType(checker); + + if (resolved != nullptr) { + return nullptr; + } + + checker::Type *index_type = checker->CheckTypeCached(node->index_type_); + + if (!index_type->HasTypeFlag(checker::TypeFlag::STRING_LIKE | checker::TypeFlag::NUMBER_LIKE)) { + checker->ThrowTypeError({"Type ", index_type, " cannot be used as index type"}, node->IndexType()->Start()); + } + + if (index_type->IsNumberType()) { + checker->ThrowTypeError("Type has no matching signature for type 'number'", node->Start()); + } + + checker->ThrowTypeError("Type has no matching signature for type 'string'", node->Start()); + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSInferType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSInferType *node) const { - (void)node; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TSInterfaceBody *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + for (auto *it : expr->Body()) { + it->Check(checker); + } + + return nullptr; +} + +static void CheckInheritedPropertiesAreIdentical(checker::TSChecker *checker, checker::InterfaceType *type, + const lexer::SourcePosition &loc_info) +{ + checker->GetBaseTypes(type); + + size_t constexpr BASE_SIZE_LIMIT = 2; + if (type->Bases().size() < BASE_SIZE_LIMIT) { + return; + } + + checker->ResolveDeclaredMembers(type); + + checker::InterfacePropertyMap properties; + + for (auto *it : type->Properties()) { + properties.insert({it->Name(), {it, type}}); + } + + for (auto *base : type->Bases()) { + checker->ResolveStructuredTypeMembers(base); + ArenaVector inherited_properties(checker->Allocator()->Adapter()); + base->AsInterfaceType()->CollectProperties(&inherited_properties); + + for (auto *inherited_prop : inherited_properties) { + auto res = properties.find(inherited_prop->Name()); + if (res == properties.end()) { + properties.insert({inherited_prop->Name(), {inherited_prop, base->AsInterfaceType()}}); + } else if (res->second.second != type) { + checker::Type *source_type = checker->GetTypeOfVariable(inherited_prop); + checker::Type *target_type = checker->GetTypeOfVariable(res->second.first); + checker->IsTypeIdenticalTo(source_type, target_type, + {"Interface '", type, "' cannot simultaneously extend types '", + res->second.second, "' and '", base->AsInterfaceType(), "'."}, + loc_info); + } + } + } } checker::Type *TSAnalyzer::Check(ir::TSInterfaceDeclaration *st) const { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + varbinder::Variable *var = st->Id()->Variable(); + ASSERT(var->Declaration()->Node() && var->Declaration()->Node()->IsTSInterfaceDeclaration()); + + if (st == var->Declaration()->Node()) { + checker::Type *resolved_type = var->TsType(); + + if (resolved_type == nullptr) { + checker::ObjectDescriptor *desc = + checker->Allocator()->New(checker->Allocator()); + resolved_type = + checker->Allocator()->New(checker->Allocator(), st->Id()->Name(), desc); + resolved_type->SetVariable(var); + var->SetTsType(resolved_type); + } + + checker::InterfaceType *resolved_interface = resolved_type->AsObjectType()->AsInterfaceType(); + CheckInheritedPropertiesAreIdentical(checker, resolved_interface, st->Id()->Start()); + + for (auto *base : resolved_interface->Bases()) { + checker->IsTypeAssignableTo( + resolved_interface, base, + {"Interface '", st->Id()->Name(), "' incorrectly extends interface '", base, "'"}, st->Id()->Start()); + } + + checker->CheckIndexConstraints(resolved_interface); + } + + st->Body()->Check(checker); + + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSInterfaceHeritage *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSIntersectionType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSIntersectionType *node) const { - (void)node; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TSLiteralType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->GetType(checker); + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSMappedType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSMappedType *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSModuleBlock *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSModuleBlock *st) const { - (void)st; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSModuleDeclaration *st) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSModuleDeclaration *st) const { - (void)st; UNREACHABLE(); } 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 +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNeverKeyword *node) const { - (void)node; - UNREACHABLE(); + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSNonNullExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNonNullExpression *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSNullKeyword *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNullKeyword *node) const { - (void)node; - UNREACHABLE(); + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNumberKeyword *node) const @@ -1402,22 +2258,39 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSObjectKeyword *node) con UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSParameterProperty *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSParameterProperty *expr) const { - (void)expr; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TSParenthesizedType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->type_->Check(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSQualifiedName *expr) const { - (void)expr; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + checker::Type *base_type = checker->CheckNonNullType(expr->Left()->Check(checker), expr->Left()->Start()); + varbinder::Variable *prop = checker->GetPropertyOfType(base_type, expr->Right()->Name()); + + if (prop != nullptr) { + return checker->GetTypeOfVariable(prop); + } + + if (base_type->IsObjectType()) { + checker::ObjectType *obj_type = base_type->AsObjectType(); + + if (obj_type->StringIndexInfo() != nullptr) { + return obj_type->StringIndexInfo()->GetType(); + } + } + + checker->ThrowTypeError({"Property ", expr->Right()->Name(), " does not exist on this type."}, + expr->Right()->Start()); + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSStringKeyword *node) const @@ -1425,76 +2298,89 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSStringKeyword *node) con return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSThisType *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSThisType *node) const { - (void)node; UNREACHABLE(); } 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 { - (void)st; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + st->TypeAnnotation()->Check(checker); + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSTypeAssertion *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } checker::Type *TSAnalyzer::Check(ir::TSTypeLiteral *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + + for (auto *it : node->Members()) { + it->Check(checker); + } + + checker::Type *type = node->GetType(checker); + checker->CheckIndexConstraints(type); + + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSTypeOperator *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypeOperator *node) const { - (void)node; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSTypeParameter *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypeParameter *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSTypeParameterDeclaration *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypeParameterDeclaration *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSTypeParameterInstantiation *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypeParameterInstantiation *expr) const { - (void)expr; UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSTypePredicate *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSTypePredicate *node) const { - (void)node; UNREACHABLE(); } 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 { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->GetType(checker); + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSUndefinedKeyword *node) const @@ -1504,8 +2390,13 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSUndefinedKeyword *node) checker::Type *TSAnalyzer::Check(ir::TSUnionType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + for (auto *it : node->Types()) { + it->Check(checker); + } + + node->GetType(checker); + return nullptr; } checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSUnknownKeyword *node) const diff --git a/ets2panda/checker/TSAnalyzer.h b/ets2panda/checker/TSAnalyzer.h index 1f5979d31cba03f7f01fc980e5ccff15156645dc..d9b4699b23b2b6aa44f7d3001495a98d04714cad 100644 --- a/ets2panda/checker/TSAnalyzer.h +++ b/ets2panda/checker/TSAnalyzer.h @@ -35,6 +35,9 @@ public: AST_NODE_REINTERPRET_MAPPING(DECLARE_TSANALYZER_CHECK_METHOD) #undef DECLARE_TSANALYZER_CHECK_METHOD + checker::Type *CheckDeleteKeyword([[maybe_unused]] checker::TSChecker *checker, ir::UnaryExpression *expr) const; + checker::Type *CheckLiteral([[maybe_unused]] checker::TSChecker *checker, ir::UnaryExpression *expr) const; + private: TSChecker *GetTSChecker() const; diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 877aa2c46f4dd3317c812b50e2a51b3095e7a7dd..d244b95b5c31674abe19e61200c1d6a51b98dc24 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1628,33 +1628,6 @@ ir::ModifierFlags ETSChecker::GetFlagsForProxyLambda(bool is_static) return flags; } -ir::AstNode *ETSChecker::GetProxyMethodBody(ir::ArrowFunctionExpression *lambda, varbinder::FunctionScope *scope) -{ - // Copy the lambda function body for the proxy method and replace the bodies scope to the proxy function - auto *body = lambda->Function()->Body(); - - if (body->IsBlockStatement()) { - body->AsBlockStatement()->SetScope(scope); - } else { - const auto lambda_return_type = lambda->Function()->ReturnTypeAnnotation() != nullptr - ? lambda->Function()->ReturnTypeAnnotation()->GetType(this) - : body->Check(this); - - ASSERT(lambda_return_type != nullptr); - ArenaVector lambda_block_statements(Allocator()->Adapter()); - - if (lambda_return_type->IsETSVoidType()) { - lambda_block_statements.push_back(AllocNode(body->AsExpression())); - } else { - lambda_block_statements.push_back(AllocNode(body->AsExpression())); - } - - body = AllocNode(Allocator(), scope, std::move(lambda_block_statements)); - } - - return body; -} - ir::ScriptFunction *ETSChecker::CreateProxyFunc(ir::ArrowFunctionExpression *lambda, ArenaVector &captured, bool is_static) { @@ -1666,8 +1639,8 @@ ir::ScriptFunction *ETSChecker::CreateProxyFunc(ir::ArrowFunctionExpression *lam auto param_ctx = varbinder::LexicalScope::Enter(VarBinder(), func_param_scope, false); auto *scope = VarBinder()->Allocator()->New(Allocator(), func_param_scope); - - auto *body = GetProxyMethodBody(lambda, scope); + auto *body = lambda->Function()->Body(); + body->AsBlockStatement()->SetScope(scope); ir::ScriptFunctionFlags func_flags = ir::ScriptFunctionFlags::METHOD | ir::ScriptFunctionFlags::PROXY; if (lambda->Function()->IsAsyncFunc()) { diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index ec7e32f122cce4a74b439fbbdbf6450e06b3ea0a..b662b6c757870346db686ff0efa2da6da4c697bf 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -929,7 +929,11 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T } if (init->IsArrayExpression() && annotation_type->IsETSArrayType()) { - init->AsArrayExpression()->SetPreferredType(annotation_type->AsETSArrayType()->ElementType()); + if (annotation_type->IsETSTupleType()) { + ValidateTupleMinElementSize(init->AsArrayExpression(), annotation_type->AsETSTupleType()); + } + + init->AsArrayExpression()->SetPreferredType(annotation_type); } if (init->IsObjectExpression()) { @@ -1006,7 +1010,7 @@ void ETSChecker::SetArrayPreferredTypeForNestedMemberExpressions(ir::MemberExpre // Set explicit target type for array if ((object != nullptr) && (object->IsArrayExpression())) { ir::ArrayExpression *array = object->AsArrayExpression(); - array->SetPreferredType(element_type); + array->SetPreferredType(CreateETSArrayType(element_type)); } } @@ -2290,6 +2294,28 @@ bool ETSChecker::ExtensionETSFunctionType(checker::Type *type) return false; } +void ETSChecker::ValidateTupleMinElementSize(ir::ArrayExpression *const array_expr, ETSTupleType *tuple) +{ + if (array_expr->Elements().size() < static_cast(tuple->GetMinTupleSize())) { + ThrowTypeError({"Few elements in array initializer for tuple with size of ", + static_cast(tuple->GetMinTupleSize())}, + array_expr->Start()); + } +} + +void ETSChecker::ModifyPreferredType(ir::ArrayExpression *const array_expr, Type *const new_preferred_type) +{ + // After modifying the preferred type of an array expression, it needs to be rechecked at the call site + array_expr->SetPreferredType(new_preferred_type); + array_expr->SetTsType(nullptr); + + for (auto *const element : array_expr->Elements()) { + if (element->IsArrayExpression()) { + ModifyPreferredType(element->AsArrayExpression(), nullptr); + } + } +} + bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, const Type *resolved_type) { ASSERT(ident->Parent()->IsCallExpression()); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 4dadde3e03d98673deed41440d30b285896bce28..f754e0aa05c4028177fc2c6a4797c807311552a5 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -14,6 +14,7 @@ */ #include "varbinder/variableFlags.h" +#include "checker/ets/castingContext.h" #include "checker/types/ets/etsObjectType.h" #include "ir/astNode.h" #include "ir/typeNode.h" @@ -953,6 +954,46 @@ Type *ETSChecker::ValidateArrayIndex(ir::Expression *expr) return index_type; } +int32_t ETSChecker::GetTupleElementAccessValue(const Type *const type) const +{ + ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC)); + + switch (ETSType(type)) { + case TypeFlag::BYTE: { + return type->AsByteType()->GetValue(); + } + case TypeFlag::SHORT: { + return type->AsShortType()->GetValue(); + } + case TypeFlag::INT: { + return type->AsIntType()->GetValue(); + } + default: { + UNREACHABLE(); + } + } +} + +void ETSChecker::ValidateTupleIndex(const ETSTupleType *const tuple, const ir::MemberExpression *const expr) +{ + const auto *const expr_type = expr->Property()->TsType(); + ASSERT(expr_type != nullptr); + + if (!expr_type->HasTypeFlag(TypeFlag::CONSTANT) && !tuple->HasSpreadType()) { + ThrowTypeError("Only constant expression allowed for element access on tuples.", expr->Property()->Start()); + } + + if (!expr_type->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX)) { + ThrowTypeError("Only integer type allowed for element access on tuples.", expr->Property()->Start()); + } + + const int32_t expr_value = GetTupleElementAccessValue(expr_type); + + if (((expr_value >= tuple->GetTupleSize()) && !tuple->HasSpreadType()) || (expr_value < 0)) { + ThrowTypeError("Element accessor value is out of tuple size bounds.", expr->Property()->Start()); + } +} + ETSObjectType *ETSChecker::CheckThisOrSuperAccess(ir::Expression *node, ETSObjectType *class_type, std::string_view msg) { if ((Context().Status() & CheckerStatus::IGNORE_VISIBILITY) != 0U) { diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index bd75518d922c69b2a3d709a03d875c158a023f12..ef795371c752c862212c7b2df72d5aec8548ace3 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -13,18 +13,24 @@ * limitations under the License. */ -#include "generated/signatures.h" #include "checker/ETSchecker.h" +#include "checker/types/ets/byteType.h" +#include "checker/types/ets/charType.h" #include "checker/types/ets/etsDynamicFunctionType.h" -#include "varbinder/varbinder.h" -#include "varbinder/ETSBinder.h" -#include "ir/ets/etsScript.h" +#include "checker/types/ets/etsDynamicType.h" +#include "checker/types/ets/etsStringType.h" +#include "checker/types/ets/etsUnionType.h" +#include "checker/types/ets/shortType.h" +#include "generated/signatures.h" #include "ir/base/classDefinition.h" #include "ir/base/scriptFunction.h" +#include "ir/ets/etsScript.h" #include "ir/expressions/identifier.h" #include "ir/ts/tsEnumDeclaration.h" #include "ir/ts/tsEnumMember.h" #include "ir/ts/tsInterfaceDeclaration.h" +#include "varbinder/varbinder.h" +#include "varbinder/ETSBinder.h" #include "parser/program/program.h" #include "util/helpers.h" diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index b89612f33a37925d9309f4b441c900b639d1bce8..df9af96acc4b39244c929d14ae6e467ce6d47aae 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -14,18 +14,21 @@ */ #include "typeRelationContext.h" -#include "varbinder/variable.h" #include "varbinder/scope.h" +#include "varbinder/variable.h" #include "varbinder/declaration.h" +#include "checker/types/ets/etsUnionType.h" #include "ir/expressions/arrayExpression.h" -#include "ir/expressions/identifier.h" -#include "ir/ts/tsArrayType.h" #include "ir/ts/tsTypeParameter.h" namespace panda::es2panda::checker { void AssignmentContext::ValidateArrayTypeInitializerByElement(TypeRelation *relation, ir::ArrayExpression *node, ETSArrayType *target) { + if (target->IsETSTupleType()) { + return; + } + for (uint32_t index = 0; index < node->Elements().size(); index++) { ir::Expression *current_array_elem = node->Elements()[index]; AssignmentContext(relation, current_array_elem, diff --git a/ets2panda/checker/types/ets/etsTupleType.cpp b/ets2panda/checker/types/ets/etsTupleType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..616d74935dc38649f4a23c5353651fd89f2667f1 --- /dev/null +++ b/ets2panda/checker/types/ets/etsTupleType.cpp @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "etsTupleType.h" +#include "checker/ets/conversion.h" + +namespace panda::es2panda::checker { +void ETSTupleType::ToString(std::stringstream &ss) const +{ + ss << "["; + for (const auto *const type : type_list_) { + type->ToString(ss); + } + + if (spread_type_ != nullptr) { + ss << ", ..."; + spread_type_->ToString(ss); + ss << "[]"; + } + + ss << "]"; +} + +Type *ETSTupleType::GetTypeAtIndex(const TupleSizeType index) const +{ + return index >= GetTupleSize() ? GetSpreadType() : GetTupleTypesList().at(static_cast(index)); +} + +void ETSTupleType::Identical([[maybe_unused]] TypeRelation *const relation, Type *const other) +{ + if (!other->IsETSTupleType()) { + return; + } + + const auto *const other_tuple = other->AsETSTupleType(); + + if (GetMinTupleSize() != other_tuple->GetMinTupleSize()) { + return; + } + + for (TupleSizeType idx = 0; idx < GetMinTupleSize(); ++idx) { + if (!relation->IsIdenticalTo(GetTypeAtIndex(idx), other_tuple->GetTypeAtIndex(idx))) { + relation->Result(false); + return; + } + } + + if (HasSpreadType() != other_tuple->HasSpreadType()) { + relation->Result(false); + return; + } + + relation->Result(true); +} + +bool ETSTupleType::AssignmentSource(TypeRelation *const relation, Type *const target) +{ + if (!(target->IsETSTupleType() || target->IsETSArrayType())) { + return false; + } + + if (!target->IsETSTupleType()) { + ASSERT(target->IsETSArrayType()); + auto *const array_target = target->AsETSArrayType(); + + const SavedTypeRelationFlagsContext saved_flags_ctx( + relation, TypeRelationFlag::NO_BOXING | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_WIDENING); + + relation->Result(relation->IsAssignableTo(ElementType(), array_target->ElementType())); + } + + return relation->IsTrue(); +} + +void ETSTupleType::AssignmentTarget(TypeRelation *const relation, Type *const source) +{ + if (!(source->IsETSTupleType() || (source->IsETSArrayType() && HasSpreadType()))) { + return; + } + + if (!source->IsETSTupleType()) { + ASSERT(source->IsETSArrayType()); + auto *const array_source = source->AsETSArrayType(); + + const SavedTypeRelationFlagsContext saved_flags_ctx( + relation, TypeRelationFlag::NO_BOXING | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_WIDENING); + + relation->Result(relation->IsAssignableTo(array_source->ElementType(), ElementType())); + return; + } + + const auto *const tuple_source = source->AsETSTupleType(); + + if (tuple_source->GetMinTupleSize() != GetMinTupleSize()) { + return; + } + + for (int32_t idx = 0; idx < GetMinTupleSize(); ++idx) { + // because an array assignment to another array simply copies it's memory address, then it's not possible to + // make boxing/unboxing/widening for types. Only conversion allowed is reference widening, which won't generate + // bytecode for the conversion, same as for arrays. + + const SavedTypeRelationFlagsContext saved_flags_ctx( + relation, TypeRelationFlag::NO_BOXING | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_WIDENING); + + if (!relation->IsAssignableTo(tuple_source->GetTypeAtIndex(idx), GetTypeAtIndex(idx))) { + relation->Result(false); + return; + } + } + + if (!HasSpreadType() && tuple_source->HasSpreadType()) { + relation->Result(false); + return; + } + + relation->Result(true); +} + +void ETSTupleType::Cast(TypeRelation *const relation, Type *const target) +{ + // TODO(mmartin): Might be not the correct casting rules, as these aren't defined yet + + if (!(target->IsETSTupleType() || target->IsETSArrayType())) { + conversion::Forbidden(relation); + return; + } + + if (target->IsETSArrayType() && (!target->IsETSTupleType())) { + auto *const array_target = target->AsETSArrayType(); + + if (!array_target->ElementType()->IsETSObjectType()) { + conversion::Forbidden(relation); + return; + } + + const SavedTypeRelationFlagsContext saved_flags_ctx( + relation, TypeRelationFlag::NO_BOXING | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_WIDENING); + + const bool elements_assignable = + std::all_of(GetTupleTypesList().begin(), GetTupleTypesList().end(), + [&relation, &array_target](auto *const tuple_type_at_idx) { + return relation->IsAssignableTo(tuple_type_at_idx, array_target->ElementType()); + }); + + bool spread_assignable = true; + if (HasSpreadType()) { + spread_assignable = relation->IsAssignableTo(GetSpreadType(), array_target->ElementType()); + } + + relation->Result(elements_assignable && spread_assignable); + return; + } + + const auto *const tuple_target = target->AsETSTupleType(); + + if (tuple_target->GetTupleSize() != GetTupleSize()) { + return; + } + + for (int32_t idx = 0; idx < GetTupleSize(); ++idx) { + const SavedTypeRelationFlagsContext saved_flags_ctx( + relation, TypeRelationFlag::NO_BOXING | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_WIDENING); + + if (!relation->IsAssignableTo(tuple_target->GetTypeAtIndex(idx), GetTypeAtIndex(idx))) { + return; + } + } + + relation->Result(true); +} + +Type *ETSTupleType::Instantiate([[maybe_unused]] ArenaAllocator *allocator, [[maybe_unused]] TypeRelation *relation, + [[maybe_unused]] GlobalTypesHolder *global_types) +{ + return this; +} + +} // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsTupleType.h b/ets2panda/checker/types/ets/etsTupleType.h new file mode 100644 index 0000000000000000000000000000000000000000..2daefee0deb8286dfb73dde5ea222d546cb2374a --- /dev/null +++ b/ets2panda/checker/types/ets/etsTupleType.h @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_TUPLE_TYPE_H +#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_TUPLE_TYPE_H + +#include "checker/types/type.h" +#include "checker/types/ets/etsArrayType.h" + +namespace panda::es2panda::checker { + +class ETSTupleType : public ETSArrayType { + using TupleSizeType = int32_t; + +public: + explicit ETSTupleType(ArenaAllocator *const allocator, Type *const element_type = nullptr, + Type *const spread_type = nullptr) + : ETSArrayType(element_type), type_list_(allocator->Adapter()), spread_type_(spread_type) + { + type_flags_ |= TypeFlag::ETS_TUPLE; + } + + explicit ETSTupleType(ArenaAllocator *const allocator, const TupleSizeType size, Type *const element_type = nullptr, + Type *const spread_type = nullptr) + : ETSArrayType(element_type), type_list_(allocator->Adapter()), spread_type_(spread_type), size_(size) + { + type_flags_ |= TypeFlag::ETS_TUPLE; + } + explicit ETSTupleType(const ArenaVector &type_list, Type *const element_type = nullptr, + Type *const spread_type = nullptr) + : ETSArrayType(element_type), + type_list_(type_list), + spread_type_(spread_type), + size_(static_cast(type_list.size())) + { + type_flags_ |= TypeFlag::ETS_TUPLE; + } + + [[nodiscard]] TupleSizeType GetTupleSize() const + { + return size_; + } + + [[nodiscard]] TupleSizeType GetMinTupleSize() const + { + return size_ + (spread_type_ == nullptr ? 0 : 1); + } + + [[nodiscard]] ArenaVector GetTupleTypesList() const + { + return type_list_; + } + + [[nodiscard]] bool HasSpreadType() const + { + return spread_type_ != nullptr; + } + + [[nodiscard]] Type *GetSpreadType() const + { + return spread_type_; + } + + void SetSpreadType(Type *const new_spread_type) + { + spread_type_ = new_spread_type; + } + + [[nodiscard]] Type *GetTypeAtIndex(int32_t index) const; + + void ToString(std::stringstream &ss) const override; + + void Identical(TypeRelation *relation, Type *other) override; + void AssignmentTarget(TypeRelation *relation, Type *source) override; + bool AssignmentSource(TypeRelation *relation, Type *target) override; + void Cast(TypeRelation *relation, Type *target) override; + Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *global_types) override; + +private: + ArenaVector type_list_; + Type *spread_type_ {}; + TupleSizeType size_ {0}; +}; + +} // namespace panda::es2panda::checker + +#endif /* ES2PANDA_COMPILER_CHECKER_TYPES_ETS_TUPLE_TYPE_H */ diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index 58c04f812f895b62dc8f44893f4577fea54021ad..cfa698c62dbe3df0b840da3e2ef2cf1e088ce783 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -80,6 +80,7 @@ enum class TypeFlag : uint64_t { SETTER = 1ULL << 55ULL, // ETS Setter ETS_EXTENSION_FUNC_HELPER = 1ULL << 56ULL, // ETS Extension Function Helper ETS_UNION = 1ULL << 57ULL, // ETS union + ETS_TUPLE = 1ULL << 58ULL, // ETS tuple type ETS_DYNAMIC_TYPE = ETS_OBJECT | ETS_DYNAMIC_FLAG, ETS_DYNAMIC_FUNCTION_TYPE = FUNCTION | ETS_DYNAMIC_FLAG, ETS_TYPE = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_VOID | ETS_OBJECT | ETS_ARRAY | diff --git a/ets2panda/checker/types/typeMapping.h b/ets2panda/checker/types/typeMapping.h index 3d6d406d80b40dfd1b2daba10cc8576180a702cf..12bf57b7d4532a7d23292a1434e1b064f5ef2af2 100644 --- a/ets2panda/checker/types/typeMapping.h +++ b/ets2panda/checker/types/typeMapping.h @@ -19,47 +19,48 @@ #include "typeFlag.h" // NOLINTBEGIN(cppcoreguidelines-macro-usage) -#define TYPE_MAPPING(_) \ - _(TypeFlag::ARRAY, ArrayType) \ - _(TypeFlag::ANY, AnyType) \ - _(TypeFlag::BIGINT_LITERAL, BigintLiteralType) \ - _(TypeFlag::NUMBER, NumberType) \ - _(TypeFlag::STRING, StringType) \ - _(TypeFlag::BOOLEAN, BooleanType) \ - _(TypeFlag::VOID, VoidType) \ - _(TypeFlag::NULL_TYPE, NullType) \ - _(TypeFlag::UNDEFINED, UndefinedType) \ - _(TypeFlag::UNKNOWN, UnknownType) \ - _(TypeFlag::NEVER, NeverType) \ - _(TypeFlag::UNION, UnionType) \ - _(TypeFlag::OBJECT, ObjectType) \ - _(TypeFlag::BIGINT, BigintType) \ - _(TypeFlag::BOOLEAN_LITERAL, BooleanLiteralType) \ - _(TypeFlag::NUMBER_LITERAL, NumberLiteralType) \ - _(TypeFlag::STRING_LITERAL, StringLiteralType) \ - _(TypeFlag::ENUM, EnumType) \ - _(TypeFlag::ENUM_LITERAL, EnumLiteralType) \ - _(TypeFlag::TYPE_PARAMETER, TypeParameter) \ - _(TypeFlag::TYPE_REFERENCE, TypeReference) \ - _(TypeFlag::BYTE, ByteType) \ - _(TypeFlag::SHORT, ShortType) \ - _(TypeFlag::INT, IntType) \ - _(TypeFlag::LONG, LongType) \ - _(TypeFlag::FLOAT, FloatType) \ - _(TypeFlag::DOUBLE, DoubleType) \ - _(TypeFlag::CHAR, CharType) \ - _(TypeFlag::ETS_BOOLEAN, ETSBooleanType) \ - _(TypeFlag::ETS_VOID, ETSVoidType) \ - _(TypeFlag::FUNCTION, ETSFunctionType) \ - _(TypeFlag::ETS_OBJECT, ETSObjectType) \ - _(TypeFlag::ETS_ARRAY, ETSArrayType) \ - _(TypeFlag::ETS_UNION, ETSUnionType) \ - _(TypeFlag::NON_PRIMITIVE, NonPrimitiveType) \ - _(TypeFlag::WILDCARD, WildcardType) \ - _(TypeFlag::ETS_TYPE_PARAMETER, ETSTypeParameter) \ - _(TypeFlag::ETS_ENUM, ETSEnumType) \ - _(TypeFlag::ETS_STRING_ENUM, ETSStringEnumType) \ - _(TypeFlag::ETS_EXTENSION_FUNC_HELPER, ETSExtensionFuncHelperType) +#define TYPE_MAPPING(_) \ + _(TypeFlag::ARRAY, ArrayType) \ + _(TypeFlag::ANY, AnyType) \ + _(TypeFlag::BIGINT_LITERAL, BigintLiteralType) \ + _(TypeFlag::NUMBER, NumberType) \ + _(TypeFlag::STRING, StringType) \ + _(TypeFlag::BOOLEAN, BooleanType) \ + _(TypeFlag::VOID, VoidType) \ + _(TypeFlag::NULL_TYPE, NullType) \ + _(TypeFlag::UNDEFINED, UndefinedType) \ + _(TypeFlag::UNKNOWN, UnknownType) \ + _(TypeFlag::NEVER, NeverType) \ + _(TypeFlag::UNION, UnionType) \ + _(TypeFlag::OBJECT, ObjectType) \ + _(TypeFlag::BIGINT, BigintType) \ + _(TypeFlag::BOOLEAN_LITERAL, BooleanLiteralType) \ + _(TypeFlag::NUMBER_LITERAL, NumberLiteralType) \ + _(TypeFlag::STRING_LITERAL, StringLiteralType) \ + _(TypeFlag::ENUM, EnumType) \ + _(TypeFlag::ENUM_LITERAL, EnumLiteralType) \ + _(TypeFlag::TYPE_PARAMETER, TypeParameter) \ + _(TypeFlag::TYPE_REFERENCE, TypeReference) \ + _(TypeFlag::BYTE, ByteType) \ + _(TypeFlag::SHORT, ShortType) \ + _(TypeFlag::INT, IntType) \ + _(TypeFlag::LONG, LongType) \ + _(TypeFlag::FLOAT, FloatType) \ + _(TypeFlag::DOUBLE, DoubleType) \ + _(TypeFlag::CHAR, CharType) \ + _(TypeFlag::ETS_BOOLEAN, ETSBooleanType) \ + _(TypeFlag::ETS_VOID, ETSVoidType) \ + _(TypeFlag::FUNCTION, ETSFunctionType) \ + _(TypeFlag::ETS_OBJECT, ETSObjectType) \ + _(TypeFlag::ETS_ARRAY, ETSArrayType) \ + _(TypeFlag::ETS_UNION, ETSUnionType) \ + _(TypeFlag::NON_PRIMITIVE, NonPrimitiveType) \ + _(TypeFlag::WILDCARD, WildcardType) \ + _(TypeFlag::ETS_TYPE_PARAMETER, ETSTypeParameter) \ + _(TypeFlag::ETS_ENUM, ETSEnumType) \ + _(TypeFlag::ETS_STRING_ENUM, ETSStringEnumType) \ + _(TypeFlag::ETS_EXTENSION_FUNC_HELPER, ETSExtensionFuncHelperType) \ + _(TypeFlag::ETS_TUPLE, ETSTupleType) #define OBJECT_TYPE_MAPPING(_) \ _(ObjectType::ObjectTypeKind::FUNCTION, FunctionType) \ diff --git a/ets2panda/compiler/base/lreference.cpp b/ets2panda/compiler/base/lreference.cpp index eba0f7c898aee98c9666f3ee65c31a90ed968c7e..2087869948c7355e7ae5791a3252e2611b60e793 100644 --- a/ets2panda/compiler/base/lreference.cpp +++ b/ets2panda/compiler/base/lreference.cpp @@ -273,13 +273,26 @@ void ETSLReference::GetValue() const void ETSLReference::SetValueComputed(const ir::MemberExpression *member_expr) const { - auto object_type = member_expr->Object()->TsType(); + const auto *const object_type = member_expr->Object()->TsType(); + if (object_type->IsETSDynamicType()) { - auto lang = object_type->AsETSDynamicType()->Language(); + const auto lang = object_type->AsETSDynamicType()->Language(); etsg_->StoreElementDynamic(Node(), base_reg_, prop_reg_, lang); - } else { - etsg_->StoreArrayElement(Node(), base_reg_, prop_reg_, - etsg_->GetVRegType(base_reg_)->AsETSArrayType()->ElementType()); + return; + } + + // Same bypass for tuples, as at MemberExpression::Compile + const auto *const saved_vreg_type = etsg_->GetVRegType(base_reg_); + + if (object_type->IsETSTupleType()) { + etsg_->SetVRegType(base_reg_, object_type); + } + + etsg_->StoreArrayElement(Node(), base_reg_, prop_reg_, + etsg_->GetVRegType(base_reg_)->AsETSArrayType()->ElementType()); + + if (object_type->IsETSTupleType()) { + etsg_->SetVRegType(base_reg_, saved_vreg_type); } } @@ -299,49 +312,62 @@ void ETSLReference::SetValueGetterSetter(const ir::MemberExpression *member_expr void ETSLReference::SetValue() const { - if (Kind() == ReferenceKind::MEMBER) { - auto *member_expr = Node()->AsMemberExpression(); - if (!member_expr->IsIgnoreBox()) { - etsg_->ApplyConversion(Node(), member_expr->TsType()); - } + if (Kind() != ReferenceKind::MEMBER) { + etsg_->StoreVar(Node()->AsIdentifier(), Result()); + return; + } - if (member_expr->IsComputed()) { - SetValueComputed(member_expr); - return; - } + const auto *const member_expr = Node()->AsMemberExpression(); + const auto *const member_expr_ts_type = member_expr->Object()->TsType()->IsETSTupleType() + ? member_expr->Object()->TsType()->AsETSTupleType()->ElementType() + : member_expr->TsType(); - if (member_expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { - SetValueGetterSetter(member_expr); - return; - } + if (!member_expr->IsIgnoreBox()) { + etsg_->ApplyConversion(Node(), member_expr_ts_type); + } - auto &prop_name = member_expr->Property()->AsIdentifier()->Name(); - if (member_expr->PropVar()->HasFlag(varbinder::VariableFlags::STATIC)) { - util::StringView full_name = etsg_->FormClassPropReference(static_obj_ref_->AsETSObjectType(), prop_name); - if (static_obj_ref_->IsETSDynamicType()) { - auto lang = static_obj_ref_->AsETSDynamicType()->Language(); - etsg_->StorePropertyDynamic(Node(), member_expr->TsType(), base_reg_, prop_name, lang); - } else { - etsg_->StoreStaticProperty(Node(), member_expr->TsType(), full_name); - } - return; - } + if (member_expr->IsComputed()) { + SetValueComputed(member_expr); + return; + } + + if (member_expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { + SetValueGetterSetter(member_expr); + return; + } + + const auto &prop_name = member_expr->Property()->AsIdentifier()->Name(); + if (member_expr->PropVar()->HasFlag(varbinder::VariableFlags::STATIC)) { + const util::StringView full_name = etsg_->FormClassPropReference(static_obj_ref_->AsETSObjectType(), prop_name); if (static_obj_ref_->IsETSDynamicType()) { - auto lang = static_obj_ref_->AsETSDynamicType()->Language(); - etsg_->StorePropertyDynamic(Node(), member_expr->TsType(), base_reg_, prop_name, lang); - } else if (static_obj_ref_->IsETSUnionType()) { - etsg_->StoreUnionProperty(Node(), base_reg_, prop_name); + const auto lang = static_obj_ref_->AsETSDynamicType()->Language(); + etsg_->StorePropertyDynamic(Node(), member_expr_ts_type, base_reg_, prop_name, lang); } else { - auto type = etsg_->Checker()->MaybeBoxedType(member_expr->PropVar(), etsg_->Allocator()); - if (type->IsETSUnionType()) { - type = type->AsETSUnionType()->GetLeastUpperBoundType(); - } - etsg_->StoreProperty(Node(), type, base_reg_, prop_name); + etsg_->StoreStaticProperty(Node(), member_expr_ts_type, full_name); } - } else { - etsg_->StoreVar(Node()->AsIdentifier(), Result()); + + return; } + + if (static_obj_ref_->IsETSDynamicType()) { + const auto lang = static_obj_ref_->AsETSDynamicType()->Language(); + etsg_->StorePropertyDynamic(Node(), member_expr_ts_type, base_reg_, prop_name, lang); + return; + } + + if (static_obj_ref_->IsETSUnionType()) { + etsg_->StoreUnionProperty(Node(), base_reg_, prop_name); + return; + } + + const auto *type = etsg_->Checker()->MaybeBoxedType(member_expr->PropVar(), etsg_->Allocator()); + + if (type->IsETSUnionType()) { + type = type->AsETSUnionType()->GetLeastUpperBoundType(); + } + + etsg_->StoreProperty(Node(), type, base_reg_, prop_name); } } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 017fb37d608046bc0a8c45cc2d36d51cfd71c3be..8acce9a697840f33a2b0502e7c8f15934e52a9cc 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -16,12 +16,13 @@ #include "ETSCompiler.h" #include "checker/types/ets/etsDynamicFunctionType.h" +#include "compiler/base/catchTable.h" +#include "checker/types/ts/enumLiteralType.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/ETSGen.h" #include "compiler/core/switchBuilder.h" #include "compiler/function/functionBuilder.h" - namespace panda::es2panda::compiler { ETSGen *ETSCompiler::GetETSGen() const @@ -107,9 +108,8 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::ScriptFunction *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::SpreadElement *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::SpreadElement *expr) const { - (void)expr; UNREACHABLE(); } @@ -134,57 +134,157 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSPropertySignature *node) UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSSignatureDeclaration *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSSignatureDeclaration *node) const { - (void)node; UNREACHABLE(); } // from ets folder void ETSCompiler::Compile(const ir::ETSClassLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + if (expr->expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { + expr->expr_->Compile(etsg); + etsg->GetType(expr, false); + } else { + ASSERT(expr->expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)); + etsg->SetAccumulatorType(expr->expr_->TsType()); + etsg->GetType(expr, true); + } } -void ETSCompiler::Compile(const ir::ETSFunctionType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSFunctionType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ETSImportDeclaration *node) const +void ETSCompiler::Compile(const ir::ETSTuple *node) const { (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::ETSLaunchExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSImportDeclaration *node) const { - (void)expr; UNREACHABLE(); } +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSLaunchExpression *expr) const +{ +#ifdef PANDA_WITH_ETS + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs(etsg); + compiler::VReg callee_reg = etsg->AllocReg(); + checker::Signature *signature = expr->expr_->Signature(); + bool is_static = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); + bool is_reference = signature->HasSignatureFlag(checker::SignatureFlags::TYPE); + + if (!is_reference && expr->expr_->Callee()->IsIdentifier()) { + if (!is_static) { + etsg->LoadThis(expr->expr_); + etsg->StoreAccumulator(expr, callee_reg); + } + } else if (!is_reference && expr->expr_->Callee()->IsMemberExpression()) { + if (!is_static) { + expr->expr_->Callee()->AsMemberExpression()->Object()->Compile(etsg); + etsg->StoreAccumulator(expr, callee_reg); + } + } else { + expr->expr_->Callee()->Compile(etsg); + etsg->StoreAccumulator(expr, callee_reg); + } + + if (is_static) { + etsg->LaunchStatic(expr, signature, expr->expr_->Arguments()); + } else if (signature->HasSignatureFlag(checker::SignatureFlags::PRIVATE)) { + etsg->LaunchThisStatic(expr, callee_reg, signature, expr->expr_->Arguments()); + } else { + etsg->LaunchThisVirtual(expr, callee_reg, signature, expr->expr_->Arguments()); + } + + etsg->SetAccumulatorType(expr->TsType()); +#endif // PANDA_WITH_ETS +} + void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs(etsg); + compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); + + expr->dimension_->Compile(etsg); + + compiler::VReg arr = etsg->AllocReg(); + compiler::VReg dim = etsg->AllocReg(); + etsg->ApplyConversionAndStoreAccumulator(expr, dim, expr->dimension_->TsType()); + etsg->NewArray(expr, arr, dim, expr->TsType()); + etsg->SetVRegType(arr, expr->TsType()); + etsg->LoadAccumulator(expr, arr); +} + +static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, compiler::VReg &obj_reg, + ir::Expression *name, checker::Signature *signature, + const ArenaVector &arguments) +{ + auto qname_reg = etsg->AllocReg(); + + std::vector parts; + + while (name->IsTSQualifiedName()) { + auto *qname = name->AsTSQualifiedName(); + name = qname->Left(); + parts.push_back(qname->Right()->AsIdentifier()->Name()); + } + + auto *var = name->AsIdentifier()->Variable(); + auto *data = etsg->VarBinder()->DynamicImportDataForVar(var); + if (data != nullptr) { + auto *import = data->import; + auto *specifier = data->specifier; + ASSERT(import->Language().IsDynamic()); + etsg->LoadAccumulatorDynamicModule(node, import); + if (specifier->IsImportSpecifier()) { + parts.push_back(specifier->AsImportSpecifier()->Imported()->Name()); + } + } else { + name->Compile(etsg); + } + + etsg->StoreAccumulator(node, obj_reg); + + std::stringstream ss; + std::for_each(parts.rbegin(), parts.rend(), [&ss](util::StringView sv) { ss << "." << sv; }); + + etsg->LoadAccumulatorString(node, util::UString(ss.str(), etsg->Allocator()).View()); + etsg->StoreAccumulator(node, qname_reg); + + etsg->CallDynamic(node, obj_reg, qname_reg, signature, arguments); } void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + if (expr->TsType()->IsETSDynamicType()) { + auto obj_reg = etsg->AllocReg(); + auto *name = expr->GetTypeRef()->AsETSTypeReference()->Part()->Name(); + CreateDynamicObject(expr, etsg, obj_reg, name, expr->signature_, expr->GetArguments()); + } else { + etsg->InitObject(expr, expr->signature_, expr->GetArguments()); + } + + if (expr->GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE) { + etsg->SetAccumulatorType(expr->TsType()); + } } void ETSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->InitObject(expr, expr->signature_, expr->dimensions_); + etsg->SetAccumulatorType(expr->TsType()); } -void ETSCompiler::Compile(const ir::ETSPackageDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::ETSPackageDeclaration *st) const { - (void)st; UNREACHABLE(); } @@ -230,8 +330,39 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::ETSWildcardType *node) cons // compile methods for EXPRESSIONS in alphabetical order void ETSCompiler::Compile(const ir::ArrayExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + const compiler::RegScope rs(etsg); + + const auto arr = etsg->AllocReg(); + const auto dim = etsg->AllocReg(); + + const compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); + etsg->LoadAccumulatorInt(expr, static_cast(expr->Elements().size())); + etsg->StoreAccumulator(expr, dim); + etsg->NewArray(expr, arr, dim, expr->TsType()); + + const auto index_reg = etsg->AllocReg(); + for (std::uint32_t i = 0; i < expr->Elements().size(); ++i) { + const auto *const expression = expr->Elements()[i]; + etsg->LoadAccumulatorInt(expr, i); + etsg->StoreAccumulator(expr, index_reg); + + const compiler::TargetTypeContext ttctx2(etsg, expr->preferred_type_); + if (!etsg->TryLoadConstantExpression(expression)) { + expression->Compile(etsg); + } + + etsg->ApplyConversion(expression, nullptr); + etsg->ApplyConversion(expression); + + if (expression->TsType()->IsETSArrayType()) { + etsg->StoreArrayElement(expr, arr, index_reg, expression->TsType()); + } else { + etsg->StoreArrayElement(expr, arr, index_reg, expr->TsType()->AsETSArrayType()->ElementType()); + } + } + + etsg->LoadAccumulator(expr, arr); } void ETSCompiler::Compile(const ir::ArrowFunctionExpression *expr) const @@ -258,8 +389,20 @@ void ETSCompiler::Compile(const ir::ArrowFunctionExpression *expr) const void ETSCompiler::Compile(const ir::AssignmentExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + // All other operations are handled in OpAssignmentLowering + ASSERT(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + compiler::RegScope rs(etsg); + auto lref = compiler::ETSLReference::Create(etsg, expr->Left(), false); + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + + if (expr->Right()->IsNullLiteral()) { + etsg->LoadAccumulatorNull(expr, expr->Left()->TsType()); + } else { + expr->Right()->Compile(etsg); + etsg->ApplyConversion(expr->Right(), expr->TsType()); + } + lref.SetValue(); } void ETSCompiler::Compile(const ir::AwaitExpression *expr) const @@ -630,110 +773,335 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::FunctionExpression *expr) c void ETSCompiler::Compile(const ir::Identifier *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto lambda = etsg->VarBinder()->LambdaObjects().find(expr); + if (lambda != etsg->VarBinder()->LambdaObjects().end()) { + etsg->CreateLambdaObjectFromIdentReference(expr, lambda->second.first); + return; + } + + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + + ASSERT(expr->Variable() != nullptr); + if (!expr->Variable()->HasFlag(varbinder::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(); } +static bool CompileComputed(compiler::ETSGen *etsg, const ir::MemberExpression *expr) +{ + if (expr->IsComputed()) { + auto *const object_type = etsg->Checker()->GetNonNullishType(expr->Object()->TsType()); + + auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); + etsg->CompileAndCheck(expr->Object()); + + auto const load_element = [expr, etsg, object_type]() { + compiler::VReg obj_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, obj_reg); + + etsg->CompileAndCheck(expr->Property()); + etsg->ApplyConversion(expr->Property(), expr->Property()->TsType()); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); + + if (object_type->IsETSDynamicType()) { + auto lang = object_type->AsETSDynamicType()->Language(); + etsg->LoadElementDynamic(expr, obj_reg, lang); + } else { + etsg->LoadArrayElement(expr, obj_reg); + } + + if (expr->Object()->TsType()->IsETSTupleType() && (expr->GetTupleConvertedType() != nullptr)) { + etsg->EmitCheckedNarrowingReferenceConversion(expr, expr->GetTupleConvertedType()); + } + + etsg->ApplyConversion(expr); + }; + + etsg->EmitMaybeOptional(expr, load_element, expr->IsOptional()); + return true; + } + return false; +} + void ETSCompiler::Compile(const ir::MemberExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto lambda = etsg->VarBinder()->LambdaObjects().find(expr); + if (lambda != etsg->VarBinder()->LambdaObjects().end()) { + etsg->CreateLambdaObjectFromMemberReference(expr, expr->object_, lambda->second.first); + etsg->SetAccumulatorType(expr->TsType()); + return; + } + + compiler::RegScope rs(etsg); + + auto *const object_type = etsg->Checker()->GetNonNullishType(expr->Object()->TsType()); + + if (CompileComputed(etsg, expr)) { + return; + } + + auto &prop_name = expr->Property()->AsIdentifier()->Name(); + + if (object_type->IsETSArrayType() && prop_name.Is("length")) { + auto ottctx = compiler::TargetTypeContext(etsg, object_type); + etsg->CompileAndCheck(expr->Object()); + + auto const load_length = [expr, etsg]() { + compiler::VReg obj_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, obj_reg); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); + etsg->LoadArrayLength(expr, obj_reg); + etsg->ApplyConversion(expr, expr->TsType()); + }; + + etsg->EmitMaybeOptional(expr, load_length, expr->IsOptional()); + 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->OptionalType()->AsETSEnumType(); + } + return expr->OptionalType()->AsETSStringEnumType(); + }(); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); + etsg->LoadAccumulatorInt(expr, enum_interface->GetOrdinal()); + return; + } + + if (etsg->Checker()->IsVariableStatic(expr->PropVar())) { + auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); + + if (expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { + checker::Signature *sig = expr->PropVar()->TsType()->AsETSFunctionType()->FindGetter(); + etsg->CallStatic0(expr, sig->InternalName()); + etsg->SetAccumulatorType(expr->TsType()); + return; + } + + util::StringView full_name = + etsg->FormClassPropReference(expr->Object()->TsType()->AsETSObjectType(), prop_name); + etsg->LoadStaticProperty(expr, expr->OptionalType(), full_name); + return; + } + + auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); + etsg->CompileAndCheck(expr->Object()); + + auto const load_property = [expr, etsg, prop_name, object_type]() { + etsg->ApplyConversion(expr->Object()); + compiler::VReg obj_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, obj_reg); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); + + 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(expr->TsType()); + } else if (object_type->IsETSDynamicType()) { + auto lang = object_type->AsETSDynamicType()->Language(); + etsg->LoadPropertyDynamic(expr, expr->OptionalType(), obj_reg, prop_name, lang); + } else if (object_type->IsETSUnionType()) { + etsg->LoadUnionProperty(expr, expr->OptionalType(), expr->IsGenericField(), obj_reg, prop_name); + } else { + const auto full_name = etsg->FormClassPropReference(object_type->AsETSObjectType(), prop_name); + etsg->LoadProperty(expr, expr->OptionalType(), expr->IsGenericField(), obj_reg, full_name); + } + }; + + etsg->EmitMaybeOptional(expr, load_property, expr->IsOptional()); } -void ETSCompiler::Compile(const ir::NewExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::NewExpression *expr) const { - (void)expr; UNREACHABLE(); } void ETSCompiler::Compile(const ir::ObjectExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs {etsg}; + checker::ETSObjectType const *obj_type = expr->TsType()->AsETSObjectType(); + compiler::VReg obj_reg = etsg->AllocReg(); + if (expr->TsType()->IsETSDynamicType()) { + auto *signature_info = etsg->Allocator()->New(etsg->Allocator()); + auto *create_obj_sig = etsg->Allocator()->New( + signature_info, nullptr, compiler::Signatures::BUILTIN_JSRUNTIME_CREATE_OBJECT); + compiler::VReg dummy_reg = compiler::VReg::RegStart(); + etsg->CallDynamic(expr, dummy_reg, dummy_reg, create_obj_sig, + ArenaVector(etsg->Allocator()->Adapter())); + } else { + checker::Signature *empty_sig = nullptr; + for (checker::Signature *sig : obj_type->ConstructSignatures()) { + if (sig->Params().empty()) { + empty_sig = sig; + break; + } + } + if (empty_sig == nullptr) { // Would have already thrown in the checker. + UNREACHABLE(); + } + etsg->InitObject(expr, empty_sig, ArenaVector(etsg->Allocator()->Adapter())); + } + etsg->SetAccumulatorType(expr->TsType()); + etsg->StoreAccumulator(expr, obj_reg); + + for (ir::Expression *prop_expr : expr->Properties()) { + ASSERT(prop_expr->IsProperty()); + ir::Property *prop = prop_expr->AsProperty(); + ir::Expression *key = prop->Key(); + ir::Expression *value = prop->Value(); + + util::StringView pname; + if (key->IsStringLiteral()) { + pname = key->AsStringLiteral()->Str(); + } else if (key->IsIdentifier()) { + pname = key->AsIdentifier()->Name(); + } else { + UNREACHABLE(); + } + + value->Compile(etsg); + etsg->ApplyConversion(value, key->TsType()); + if (expr->TsType()->IsETSDynamicType()) { + etsg->StorePropertyDynamic(expr, value->TsType(), obj_reg, pname, + expr->TsType()->AsETSDynamicType()->Language()); + } else { + etsg->StoreProperty(expr, key->TsType(), obj_reg, pname); + } + } + + etsg->LoadAccumulator(expr, obj_reg); } -void ETSCompiler::Compile(const ir::OmittedExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::OmittedExpression *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::OpaqueTypeNode *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::OpaqueTypeNode *node) const { - (void)node; UNREACHABLE(); } 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); + etsg->SetAccumulatorType(etsg->GetAccumulatorType()->AsETSObjectType()->SuperType()); } -void ETSCompiler::Compile(const ir::TaggedTemplateExpression *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TaggedTemplateExpression *expr) const { - (void)expr; UNREACHABLE(); } void ETSCompiler::Compile(const ir::TemplateLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->BuildTemplateString(expr); } void ETSCompiler::Compile(const ir::ThisExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->LoadThis(expr); } void ETSCompiler::Compile(const ir::UnaryExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + if (!etsg->TryLoadConstantExpression(expr->Argument())) { + expr->Argument()->Compile(etsg); + } + etsg->ApplyConversion(expr->Argument(), nullptr); + etsg->Unary(expr, expr->OperatorType()); } 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 +void ETSCompiler::Compile([[maybe_unused]] const ir::YieldExpression *expr) const { - (void)expr; 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(); } void ETSCompiler::Compile(const ir::BooleanLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->LoadAccumulatorBoolean(expr, expr->Value()); } void ETSCompiler::Compile(const ir::CharLiteral *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->LoadAccumulatorChar(expr, expr->Char()); } void ETSCompiler::Compile(const ir::NullLiteral *expr) const @@ -834,23 +1202,73 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::ImportSpecifier *st) const { UNREACHABLE(); } + +static void ThrowError(compiler::ETSGen *const etsg, const ir::AssertStatement *st) +{ + const compiler::RegScope rs(etsg); + + if (st->Second() != nullptr) { + st->Second()->Compile(etsg); + } else { + etsg->LoadAccumulatorString(st, "Assertion failed."); + } + + const auto message = etsg->AllocReg(); + etsg->StoreAccumulator(st, message); + + const auto assertion_error = etsg->AllocReg(); + etsg->NewObject(st, assertion_error, compiler::Signatures::BUILTIN_ASSERTION_ERROR); + etsg->CallThisStatic1(st, assertion_error, compiler::Signatures::BUILTIN_ASSERTION_ERROR_CTOR, message); + etsg->EmitThrow(st, assertion_error); +} // compile methods for STATEMENTS in alphabetical order void ETSCompiler::Compile(const ir::AssertStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto res = compiler::Condition::CheckConstantExpr(etsg, st->Test()); + if (res == compiler::Condition::Result::CONST_TRUE) { + return; + } + + if (res == compiler::Condition::Result::CONST_FALSE) { + ThrowError(etsg, st); + return; + } + + compiler::Label *true_label = etsg->AllocLabel(); + compiler::Label *false_label = etsg->AllocLabel(); + + compiler::Condition::Compile(etsg, st->Test(), false_label); + etsg->JumpTo(st, true_label); + + etsg->SetLabel(st, false_label); + ThrowError(etsg, st); + + etsg->SetLabel(st, true_label); } void ETSCompiler::Compile(const ir::BlockStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::LocalRegScope lrs(etsg, st->Scope()); + + etsg->CompileStatements(st->Statements()); +} + +template +static void CompileImpl(const ir::BreakStatement *self, [[maybe_unused]] CodeGen *cg) +{ + compiler::Label *target = cg->ControlFlowChangeBreak(self->Ident()); + cg->Branch(self, target); } void ETSCompiler::Compile(const ir::BreakStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + if (etsg->ExtendWithFinalizer(st->parent_, st)) { + return; + } + CompileImpl(st, etsg); } void ETSCompiler::Compile([[maybe_unused]] const ir::ClassDeclaration *st) const @@ -1143,32 +1561,102 @@ void ETSCompiler::Compile(const ir::SwitchStatement *st) const void ETSCompiler::Compile(const ir::ThrowStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + etsg->ThrowException(st->Argument()); } void ETSCompiler::Compile(const ir::TryStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + + compiler::ETSTryContext try_ctx(etsg, etsg->Allocator(), st, st->FinallyBlock() != nullptr); + + compiler::LabelPair try_label_pair(etsg->AllocLabel(), etsg->AllocLabel()); + + for (ir::CatchClause *clause : st->CatchClauses()) { + try_ctx.AddNewCathTable(clause->TsType()->AsETSObjectType()->AssemblerName(), try_label_pair); + } + + compiler::Label *statement_end = etsg->AllocLabel(); + auto catch_tables = try_ctx.GetETSCatchTable(); + + etsg->SetLabel(st, try_label_pair.Begin()); + st->Block()->Compile(etsg); + etsg->Branch(st, statement_end); + etsg->SetLabel(st, try_label_pair.End()); + + ASSERT(st->CatchClauses().size() == catch_tables.size()); + + for (uint32_t i = 0; i < st->CatchClauses().size(); i++) { + etsg->SetLabel(st, catch_tables.at(i)->LabelSet().CatchBegin()); + + st->CatchClauses().at(i)->Compile(etsg); + + etsg->Branch(st, statement_end); + } + + etsg->SetLabel(st, statement_end); + + auto trycatch_label_pair = compiler::LabelPair(try_label_pair.Begin(), statement_end); + + try_ctx.EmitFinalizer(trycatch_label_pair, st->finalizer_insertions_); } void ETSCompiler::Compile(const ir::VariableDeclarator *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + auto lref = compiler::ETSLReference::Create(etsg, st->Id(), true); + auto ttctx = compiler::TargetTypeContext(etsg, st->TsType()); + + if (st->Id()->AsIdentifier()->Variable()->HasFlag(varbinder::VariableFlags::BOXED)) { + etsg->EmitLocalBoxCtor(st->Id()); + etsg->StoreAccumulator(st, lref.Variable()->AsLocalVariable()->Vreg()); + etsg->SetAccumulatorType(lref.Variable()->TsType()); + } + + if (st->Init() != nullptr) { + if (!etsg->TryLoadConstantExpression(st->Init())) { + st->Init()->Compile(etsg); + etsg->ApplyConversion(st->Init(), nullptr); + } + } else { + etsg->LoadDefaultValue(st, st->Id()->AsIdentifier()->Variable()->TsType()); + } + + etsg->ApplyConversion(st, st->TsType()); + lref.SetValue(); } void ETSCompiler::Compile(const ir::VariableDeclaration *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + for (const auto *it : st->Declarators()) { + it->Compile(etsg); + } +} + +template +void CompileImpl(const ir::WhileStatement *while_stmt, [[maybe_unused]] CodeGen *cg) +{ + compiler::LabelTarget label_target(cg); + + cg->SetLabel(while_stmt, label_target.ContinueTarget()); + compiler::Condition::Compile(cg, while_stmt->Test(), label_target.BreakTarget()); + + { + compiler::LocalRegScope reg_scope(cg, while_stmt->Scope()); + compiler::LabelContext label_ctx(cg, label_target); + while_stmt->Body()->Compile(cg); + } + + cg->Branch(while_stmt, label_target.ContinueTarget()); + cg->SetLabel(while_stmt, label_target.BreakTarget()); } void ETSCompiler::Compile(const ir::WhileStatement *st) const { - (void)st; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + CompileImpl(st, etsg); } // from ts folder void ETSCompiler::Compile([[maybe_unused]] const ir::TSAnyKeyword *node) const @@ -1176,21 +1664,86 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSAnyKeyword *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSArrayType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSArrayType *node) const { - (void)node; UNREACHABLE(); } 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 +void ETSCompiler::Compile([[maybe_unused]] const ir::TSBigintKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1199,21 +1752,18 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSBooleanKeyword *node) con UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSClassImplements *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSConditionalType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSConditionalType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSConstructorType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSConstructorType *node) const { - (void)node; UNREACHABLE(); } @@ -1232,105 +1782,113 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSExternalModuleReference * UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSFunctionType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSFunctionType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSImportEqualsDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSImportEqualsDeclaration *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSImportType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSImportType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSIndexedAccessType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSIndexedAccessType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSInferType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSInferType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSInterfaceBody *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceBody *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSInterfaceDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceDeclaration *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSInterfaceHeritage *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSIntersectionType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSIntersectionType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSLiteralType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSLiteralType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSMappedType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSMappedType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSModuleBlock *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSModuleBlock *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSModuleDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSModuleDeclaration *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSNamedTupleMember *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSNamedTupleMember *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSNeverKeyword *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSNeverKeyword *node) const { - (void)node; UNREACHABLE(); } void ETSCompiler::Compile(const ir::TSNonNullExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs(etsg); + + expr->Expr()->Compile(etsg); + + if (!etsg->GetAccumulatorType()->IsNullishOrNullLike()) { + return; + } + + if (etsg->GetAccumulatorType()->IsETSNullLike()) { + etsg->EmitNullishException(expr); + return; + } + + auto arg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, arg); + etsg->LoadAccumulator(expr, arg); + + auto end_label = etsg->AllocLabel(); + + etsg->BranchIfNotNullish(expr, end_label); + etsg->EmitNullishException(expr); + + etsg->SetLabel(expr, end_label); + etsg->LoadAccumulator(expr, arg); + etsg->ConvertToNonNullish(expr); } -void ETSCompiler::Compile(const ir::TSNullKeyword *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSNullKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1344,21 +1902,18 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSObjectKeyword *node) cons UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSParameterProperty *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSParameterProperty *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSParenthesizedType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSParenthesizedType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSQualifiedName *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSQualifiedName *expr) const { - (void)expr; UNREACHABLE(); } @@ -1367,75 +1922,63 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSStringKeyword *node) cons UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSThisType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSThisType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTupleType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTupleType *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeAliasDeclaration *st) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeAliasDeclaration *st) const { - (void)st; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeAssertion *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeLiteral *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeLiteral *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeOperator *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeOperator *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeParameter *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeParameter *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeParameterDeclaration *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeParameterDeclaration *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeParameterInstantiation *expr) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeParameterInstantiation *expr) const { - (void)expr; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypePredicate *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypePredicate *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeQuery *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeQuery *node) const { - (void)node; UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeReference *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeReference *node) const { - (void)node; UNREACHABLE(); } @@ -1444,9 +1987,8 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::TSUndefinedKeyword *node) c UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSUnionType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSUnionType *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 32f0f7800ab042adcb8af32662d4a3988d3e9a8f..f529a204cc5b529256a799d2547ee4dd3e2f4835 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -69,14 +69,24 @@ void ETSGen::CompileAndCheck(const ir::Expression *expr) // NOTE: vpukhov. bad accumulator type leads to terrible bugs in codegen // make exact types match mandatory expr->Compile(this); + + if (expr->TsType()->IsETSTupleType()) { + // This piece of code is necessary to handle multidimensional tuples. As a tuple is stored as an + // array of `Objects`. If we make an array inside of the tuple type, then we won't be able to derefer a + // 2 dimensional array, with an array that expects to return `Object` after index access. + EmitCheckedNarrowingReferenceConversion(expr, expr->TsType()); + } + auto const *const acc_type = GetAccumulatorType(); if (acc_type == expr->TsType()) { return; } + if (acc_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && ((acc_type->TypeFlags() ^ expr->TsType()->TypeFlags()) & ~checker::TypeFlag::CONSTANT) == 0) { return; } + ASSERT(!"Type mismatch after Expression::Compile"); } @@ -679,7 +689,8 @@ void ETSGen::InitLambdaObject(const ir::AstNode *node, checker::Signature *signa for (size_t i = 0; i < arguments.size(); i++) { auto ttctx = TargetTypeContext(this, signature->Params()[i]->TsType()); - StoreAccumulator(node, arguments[i]); + VReg arg_reg = AllocReg(); + MoveVreg(node, arg_reg, arguments[i]); } Rra().Emit(node, arg_start, arguments.size(), name, arg_start); diff --git a/ets2panda/compiler/core/ETSfunction.cpp b/ets2panda/compiler/core/ETSfunction.cpp index 318eddb3024c6e5a86253081acc922284019a461..bddfa6ec04982f1dcaafe9b8164d1452034d4a71 100644 --- a/ets2panda/compiler/core/ETSfunction.cpp +++ b/ets2panda/compiler/core/ETSfunction.cpp @@ -146,13 +146,7 @@ void ETSFunction::CompileSourceBlock(ETSGen *etsg, const ir::BlockStatement *blo void ETSFunction::CompileFunction(ETSGen *etsg) { - const auto *decl = etsg->RootNode()->AsScriptFunction(); - - if (const ir::AstNode *body = decl->Body(); body->IsExpression()) { - // NOTE - } else { - CompileSourceBlock(etsg, body->AsBlockStatement()); - } + CompileSourceBlock(etsg, etsg->RootNode()->AsScriptFunction()->Body()->AsBlockStatement()); } void ETSFunction::Compile(ETSGen *etsg) diff --git a/ets2panda/compiler/core/JSCompiler.cpp b/ets2panda/compiler/core/JSCompiler.cpp index 090f5f4ec79163bae0faa14f87f884d41aa6d6dd..a328ddf5657ea96b8ee07a09e3b4062991ad8532 100644 --- a/ets2panda/compiler/core/JSCompiler.cpp +++ b/ets2panda/compiler/core/JSCompiler.cpp @@ -15,13 +15,15 @@ #include "JSCompiler.h" +#include "varbinder/varbinder.h" +#include "compiler/base/catchTable.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/pandagen.h" #include "compiler/core/switchBuilder.h" #include "compiler/function/functionBuilder.h" +#include "util/bitset.h" #include "util/helpers.h" - namespace panda::es2panda::compiler { PandaGen *JSCompiler::GetPandaGen() const @@ -437,9 +439,8 @@ void JSCompiler::Compile([[maybe_unused]] const ir::ScriptFunction *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::SpreadElement *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::SpreadElement *expr) const { - (void)expr; UNREACHABLE(); } @@ -463,57 +464,54 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSPropertySignature *node) c UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSSignatureDeclaration *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSSignatureDeclaration *node) const { - (void)node; UNREACHABLE(); } // from ets folder -void JSCompiler::Compile(const ir::ETSClassLiteral *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSClassLiteral *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSFunctionType *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSFunctionType *expr) const +{ + UNREACHABLE(); +} + +void JSCompiler::Compile(const ir::ETSTuple *expr) const { (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSImportDeclaration *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSImportDeclaration *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSLaunchExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSLaunchExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSNewArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSNewClassInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSNewMultiDimArrayInstanceExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::ETSPackageDeclaration *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::ETSPackageDeclaration *expr) const { - (void)expr; UNREACHABLE(); } @@ -556,8 +554,11 @@ void JSCompiler::Compile([[maybe_unused]] const ir::ETSWildcardType *expr) const // JSCompiler::compile methods for EXPRESSIONS in alphabetical order void JSCompiler::Compile(const ir::ArrayExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::RegScope rs(pg); + compiler::VReg array_obj = pg->AllocReg(); + + pg->CreateArray(expr, expr->Elements(), array_obj); } void JSCompiler::Compile(const ir::ArrowFunctionExpression *expr) const @@ -568,8 +569,29 @@ void JSCompiler::Compile(const ir::ArrowFunctionExpression *expr) const void JSCompiler::Compile(const ir::AssignmentExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::RegScope rs(pg); + auto lref = compiler::JSLReference::Create(pg, expr->Left(), false); + + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL || + expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL) { + compiler::PandaGen::Unimplemented(); + } + + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + expr->Right()->Compile(pg); + lref.SetValue(); + return; + } + + compiler::VReg lhs_reg = pg->AllocReg(); + + lref.GetValue(); + pg->StoreAccumulator(expr->Left(), lhs_reg); + expr->Right()->Compile(pg); + pg->Binary(expr, expr->OperatorType(), lhs_reg); + + lref.SetValue(); } void JSCompiler::Compile(const ir::AwaitExpression *expr) const @@ -820,109 +842,516 @@ 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 { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + if (expr->Properties().empty()) { + pg->CreateEmptyObject(expr); + return; + } + + util::BitSet compiled(expr->Properties().size()); + CompileStaticProperties(pg, &compiled, expr); + + if (compiled.Any(false)) { + CompileRemainingProperties(pg, &compiled, expr); + } } -void JSCompiler::Compile(const ir::OpaqueTypeNode *node) const +static compiler::Literal CreateLiteral(const ir::Property *prop, util::BitSet *compiled, size_t prop_index) +{ + compiler::Literal lit = util::Helpers::ToConstantLiteral(prop->Value()); + if (!lit.IsInvalid()) { + compiled->Set(prop_index); + return lit; + } + + if (prop->Kind() != ir::PropertyKind::INIT) { + ASSERT(prop->IsAccessor()); + return compiler::Literal::AccessorLiteral(); + } + + if (!prop->Value()->IsFunctionExpression()) { + return compiler::Literal::NullLiteral(); + } + + const ir::ScriptFunction *method = prop->Value()->AsFunctionExpression()->Function(); + + compiler::LiteralTag tag = compiler::LiteralTag::METHOD; + + if (method->IsGenerator()) { + tag = compiler::LiteralTag::GENERATOR_METHOD; + + if (method->IsAsyncFunc()) { + tag = compiler::LiteralTag::ASYNC_GENERATOR_METHOD; + } + } + + compiled->Set(prop_index); + return compiler::Literal(tag, method->Scope()->InternalName()); +} + +static bool IsLiteralBufferCompatible(const ir::Expression *expr) +{ + if (expr->IsSpreadElement()) { + return false; + } + + const ir::Property *prop = expr->AsProperty(); + if (prop->Value()->IsFunctionExpression() && !prop->Value()->AsFunctionExpression()->Function()->IsMethod()) { + return false; + } + + return util::Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed()) && + prop->Kind() != ir::PropertyKind::PROTO; +} + +void JSCompiler::CompileStaticProperties(compiler::PandaGen *pg, util::BitSet *compiled, + const ir::ObjectExpression *expr) const +{ + bool has_method = false; + bool seen_computed = false; + compiler::LiteralBuffer buf; + std::unordered_map prop_name_map; + + for (size_t i = 0; i < expr->Properties().size(); i++) { + if (!IsLiteralBufferCompatible(expr->Properties()[i])) { + seen_computed = true; + continue; + } + + const ir::Property *prop = expr->Properties()[i]->AsProperty(); + + util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); + size_t buffer_pos = buf.size(); + auto res = prop_name_map.insert({name, buffer_pos}); + if (res.second) { + if (seen_computed) { + break; + } + + buf.emplace_back(name); + buf.emplace_back(); + } else { + buffer_pos = res.first->second; + } + + compiler::Literal lit = CreateLiteral(prop, compiled, i); + if (lit.IsTagMethod()) { + has_method = true; + } + + buf[buffer_pos + 1] = std::move(lit); + } + + if (buf.empty()) { + pg->CreateEmptyObject(expr); + return; + } + + uint32_t buf_idx = pg->AddLiteralBuffer(std::move(buf)); + + if (has_method) { + pg->CreateObjectHavingMethod(expr, buf_idx); + } else { + pg->CreateObjectWithBuffer(expr, buf_idx); + } +} + +void JSCompiler::CompileRemainingProperties(compiler::PandaGen *pg, const util::BitSet *compiled, + const ir::ObjectExpression *expr) const +{ + compiler::RegScope rs(pg); + compiler::VReg obj_reg = pg->AllocReg(); + + pg->StoreAccumulator(expr, obj_reg); + + for (size_t i = 0; i < expr->Properties().size(); i++) { + if (compiled->Test(i)) { + continue; + } + + compiler::RegScope prs(pg); + + if (expr->Properties()[i]->IsSpreadElement()) { + compiler::VReg src_obj = pg->AllocReg(); + auto const *const spread = expr->Properties()[i]->AsSpreadElement(); + + spread->Argument()->Compile(pg); + pg->StoreAccumulator(spread, src_obj); + + pg->CopyDataProperties(spread, obj_reg, src_obj); + continue; + } + + const ir::Property *prop = expr->Properties()[i]->AsProperty(); + + switch (prop->Kind()) { + case ir::PropertyKind::GET: + case ir::PropertyKind::SET: { + compiler::VReg key = pg->LoadPropertyKey(prop->Key(), prop->IsComputed()); + + compiler::VReg undef = pg->AllocReg(); + pg->LoadConst(expr, compiler::Constant::JS_UNDEFINED); + pg->StoreAccumulator(expr, undef); + + compiler::VReg getter = undef; + compiler::VReg setter = undef; + + compiler::VReg accessor = pg->AllocReg(); + pg->LoadAccumulator(prop->Value(), obj_reg); + prop->Value()->Compile(pg); + pg->StoreAccumulator(prop->Value(), accessor); + + if (prop->Kind() == ir::PropertyKind::GET) { + getter = accessor; + } else { + setter = accessor; + } + + pg->DefineGetterSetterByValue(expr, obj_reg, key, getter, setter, prop->IsComputed()); + break; + } + case ir::PropertyKind::INIT: { + compiler::Operand key = pg->ToOwnPropertyKey(prop->Key(), prop->IsComputed()); + + if (prop->IsMethod()) { + pg->LoadAccumulator(prop->Value(), obj_reg); + } + + prop->Value()->Compile(pg); + pg->StoreOwnProperty(expr, obj_reg, key); + break; + } + case ir::PropertyKind::PROTO: { + prop->Value()->Compile(pg); + compiler::VReg proto = pg->AllocReg(); + pg->StoreAccumulator(expr, proto); + + pg->SetObjectWithProto(expr, proto, obj_reg); + break; + } + default: { + UNREACHABLE(); + } + } + } + + pg->LoadAccumulator(expr, obj_reg); +} + +void JSCompiler::Compile([[maybe_unused]] const ir::OpaqueTypeNode *node) const { - (void)node; 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 { - (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 { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + auto quasis_it = expr->Quasis().begin(); + auto expression_it = expr->Expressions().begin(); + + pg->LoadAccumulatorString(expr, (*quasis_it)->Raw()); + + quasis_it++; + + bool is_quais = false; + size_t total = expr->Quasis().size() + expr->Expressions().size(); + + compiler::RegScope rs(pg); + compiler::VReg lhs = pg->AllocReg(); + + while (total != 1) { + const ir::AstNode *node = nullptr; + + if (is_quais) { + pg->StoreAccumulator(*quasis_it, lhs); + pg->LoadAccumulatorString(expr, (*quasis_it)->Raw()); + + node = *quasis_it; + quasis_it++; + } else { + const ir::Expression *element = *expression_it; + pg->StoreAccumulator(element, lhs); + + element->Compile(pg); + + node = element; + expression_it++; + } + + pg->Binary(node, lexer::TokenType::PUNCTUATOR_PLUS, lhs); + + is_quais = !is_quais; + total--; + } } void JSCompiler::Compile(const ir::ThisExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + auto res = pg->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS); + + ASSERT(res.variable && res.variable->IsLocalVariable()); + pg->LoadAccFromLexEnv(expr, res); + + const ir::ScriptFunction *func = util::Helpers::GetContainingConstructor(expr); + + if (func != nullptr) { + pg->ThrowIfSuperNotCorrectCall(expr, 0); + } } void JSCompiler::Compile(const ir::UnaryExpression *expr) const { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + switch (expr->OperatorType()) { + case lexer::TokenType::KEYW_DELETE: { + if (expr->Argument()->IsIdentifier()) { + auto result = pg->Scope()->Find(expr->Argument()->AsIdentifier()->Name()); + if (result.variable == nullptr || + (result.scope->IsGlobalScope() && result.variable->IsGlobalVariable())) { + compiler::RegScope rs(pg); + compiler::VReg variable = pg->AllocReg(); + compiler::VReg global = pg->AllocReg(); + + pg->LoadConst(expr, compiler::Constant::JS_GLOBAL); + pg->StoreAccumulator(expr, global); + + pg->LoadAccumulatorString(expr, expr->Argument()->AsIdentifier()->Name()); + pg->StoreAccumulator(expr, variable); + + pg->DeleteObjProperty(expr, global, variable); + } else { + // Otherwise it is a local variable which can't be deleted and we just + // return false. + pg->LoadConst(expr, compiler::Constant::JS_FALSE); + } + } else if (expr->Argument()->IsMemberExpression()) { + compiler::RegScope rs(pg); + compiler::VReg object = pg->AllocReg(); + compiler::VReg property = pg->AllocReg(); + + expr->Argument()->AsMemberExpression()->CompileToRegs(pg, object, property); + pg->DeleteObjProperty(expr, object, property); + } else { + // compile the delete operand. + expr->Argument()->Compile(pg); + // Deleting any value or a result of an expression returns True. + pg->LoadConst(expr, compiler::Constant::JS_TRUE); + } + break; + } + case lexer::TokenType::KEYW_TYPEOF: { + if (expr->Argument()->IsIdentifier()) { + const auto *ident = expr->Argument()->AsIdentifier(); + + auto res = pg->Scope()->Find(ident->Name()); + if (res.variable == nullptr) { + pg->LoadConst(expr, compiler::Constant::JS_GLOBAL); + pg->LoadObjByName(expr, ident->Name()); + } else { + pg->LoadVar(ident, res); + } + } else { + expr->Argument()->Compile(pg); + } + + pg->TypeOf(expr); + break; + } + case lexer::TokenType::KEYW_VOID: { + expr->Argument()->Compile(pg); + pg->LoadConst(expr, compiler::Constant::JS_UNDEFINED); + break; + } + default: { + expr->Argument()->Compile(pg); + + compiler::RegScope rs(pg); + compiler::VReg operand_reg = pg->AllocReg(); + pg->StoreAccumulator(expr, operand_reg); + pg->Unary(expr, expr->OperatorType(), operand_reg); + break; + } + } } 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 { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::RegScope rs(pg); + + if (expr->Argument() != nullptr) { + expr->Argument()->Compile(pg); + } else { + pg->LoadConst(expr, compiler::Constant::JS_UNDEFINED); + } + + if (expr->HasDelegate()) { + ASSERT(expr->Argument()); + pg->FuncBuilder()->YieldStar(expr); + } else { + pg->FuncBuilder()->Yield(expr); + } } + // 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 { - (void)expr; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + pg->LoadConst(expr, expr->Value() ? compiler::Constant::JS_TRUE : compiler::Constant::JS_FALSE); } -void JSCompiler::Compile(const ir::CharLiteral *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::CharLiteral *expr) const { - (void)expr; UNREACHABLE(); } @@ -1006,22 +1435,31 @@ void JSCompiler::Compile([[maybe_unused]] const ir::ImportSpecifier *st) const UNREACHABLE(); } // Compile methods for STATEMENTS in alphabetical order -void JSCompiler::Compile(const ir::AssertStatement *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::AssertStatement *st) const { - (void)st; UNREACHABLE(); } void JSCompiler::Compile(const ir::BlockStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + compiler::LocalRegScope lrs(pg, st->Scope()); + + for (const auto *it : st->Statements()) { + it->Compile(pg); + } } +template +static void CompileImpl(const ir::BreakStatement *self, [[maybe_unused]] CodeGen *cg) +{ + compiler::Label *target = cg->ControlFlowChangeBreak(self->Ident()); + cg->Branch(self, target); +} void JSCompiler::Compile(const ir::BreakStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + CompileImpl(st, pg); } void JSCompiler::Compile(const ir::ClassDeclaration *st) const @@ -1295,54 +1733,194 @@ void JSCompiler::Compile(const ir::SwitchStatement *st) const void JSCompiler::Compile(const ir::ThrowStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + st->Argument()->Compile(pg); + pg->EmitThrow(st); +} + +static void CompileTryCatch(compiler::PandaGen *pg, const ir::TryStatement *st) +{ + ASSERT(st->CatchClauses().size() == 1); + ASSERT(st->CatchClauses().front() && !st->FinallyBlock()); + + compiler::TryContext try_ctx(pg, st); + const auto &label_set = try_ctx.LabelSet(); + + pg->SetLabel(st, label_set.TryBegin()); + st->Block()->Compile(pg); + pg->SetLabel(st, label_set.TryEnd()); + + pg->Branch(st, label_set.CatchEnd()); + + pg->SetLabel(st, label_set.CatchBegin()); + st->CatchClauses().front()->Compile(pg); + pg->SetLabel(st, label_set.CatchEnd()); +} + +static void CompileFinally(compiler::PandaGen *pg, compiler::TryContext *try_ctx, + const compiler::TryLabelSet &label_set, const ir::TryStatement *st) +{ + compiler::RegScope rs(pg); + compiler::VReg exception = pg->AllocReg(); + pg->StoreConst(st, exception, compiler::Constant::JS_HOLE); + pg->Branch(st, label_set.CatchEnd()); + + pg->SetLabel(st, label_set.CatchBegin()); + pg->StoreAccumulator(st, exception); + + pg->SetLabel(st, label_set.CatchEnd()); + + compiler::Label *label = pg->AllocLabel(); + pg->LoadAccumulator(st, try_ctx->FinalizerRun()); + + pg->BranchIfNotUndefined(st, label); + pg->StoreAccumulator(st, try_ctx->FinalizerRun()); + try_ctx->EmitFinalizer(); + pg->SetLabel(st, label); + + pg->LoadAccumulator(st, exception); + pg->EmitRethrow(st); +} + +static void CompileTryCatchFinally(compiler::PandaGen *pg, const ir::TryStatement *st) +{ + ASSERT(st->CatchClauses().size() == 1); + ASSERT(st->CatchClauses().front() && st->FinallyBlock()); + + compiler::TryContext try_ctx(pg, st); + const auto &label_set = try_ctx.LabelSet(); + + pg->SetLabel(st, label_set.TryBegin()); + { + compiler::TryContext inner_try_ctx(pg, st, false); + const auto &inner_label_set = inner_try_ctx.LabelSet(); + + pg->SetLabel(st, inner_label_set.TryBegin()); + st->Block()->Compile(pg); + pg->SetLabel(st, inner_label_set.TryEnd()); + + pg->Branch(st, inner_label_set.CatchEnd()); + + pg->SetLabel(st, inner_label_set.CatchBegin()); + st->CatchClauses().front()->Compile(pg); + pg->SetLabel(st, inner_label_set.CatchEnd()); + } + pg->SetLabel(st, label_set.TryEnd()); + + CompileFinally(pg, &try_ctx, label_set, st); +} + +static void CompileTryFinally(compiler::PandaGen *pg, const ir::TryStatement *st) +{ + ASSERT(st->CatchClauses().empty() && st->FinallyBlock()); + + compiler::TryContext try_ctx(pg, st); + const auto &label_set = try_ctx.LabelSet(); + + pg->SetLabel(st, label_set.TryBegin()); + { + compiler::TryContext inner_try_ctx(pg, st, false); + const auto &inner_label_set = inner_try_ctx.LabelSet(); + + pg->SetLabel(st, inner_label_set.TryBegin()); + st->Block()->Compile(pg); + pg->SetLabel(st, inner_label_set.TryEnd()); + + pg->Branch(st, inner_label_set.CatchEnd()); + + pg->SetLabel(st, inner_label_set.CatchBegin()); + pg->EmitThrow(st); + pg->SetLabel(st, inner_label_set.CatchEnd()); + } + pg->SetLabel(st, label_set.TryEnd()); + + CompileFinally(pg, &try_ctx, label_set, st); } void JSCompiler::Compile(const ir::TryStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + if (st->finalizer_ != nullptr) { + if (!st->CatchClauses().empty()) { + CompileTryCatchFinally(pg, st); + } else { + CompileTryFinally(pg, st); + } + } else { + CompileTryCatch(pg, st); + } } void JSCompiler::Compile(const ir::VariableDeclarator *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + auto lref = compiler::JSLReference::Create(pg, st->Id(), true); + const ir::VariableDeclaration *decl = st->Parent()->AsVariableDeclaration(); + + if (st->Init() != nullptr) { + st->Init()->Compile(pg); + } else { + if (decl->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) { + return; + } + if (decl->Kind() == ir::VariableDeclaration::VariableDeclarationKind::LET && !decl->Parent()->IsCatchClause()) { + pg->LoadConst(st, compiler::Constant::JS_UNDEFINED); + } + } + + lref.SetValue(); } void JSCompiler::Compile(const ir::VariableDeclaration *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + for (const auto *it : st->Declarators()) { + it->Compile(pg); + } +} + +template +void CompileImpl(const ir::WhileStatement *while_stmt, [[maybe_unused]] CodeGen *cg) +{ + compiler::LabelTarget label_target(cg); + + cg->SetLabel(while_stmt, label_target.ContinueTarget()); + compiler::Condition::Compile(cg, while_stmt->Test(), label_target.BreakTarget()); + + { + compiler::LocalRegScope reg_scope(cg, while_stmt->Scope()); + compiler::LabelContext label_ctx(cg, label_target); + while_stmt->Body()->Compile(cg); + } + + cg->Branch(while_stmt, label_target.ContinueTarget()); + cg->SetLabel(while_stmt, label_target.BreakTarget()); } void JSCompiler::Compile(const ir::WhileStatement *st) const { - (void)st; - UNREACHABLE(); + PandaGen *pg = GetPandaGen(); + CompileImpl(st, pg); } + // from ts folder void JSCompiler::Compile([[maybe_unused]] const ir::TSAnyKeyword *node) const { UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSArrayType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSArrayType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSAsExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSAsExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSBigintKeyword *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSBigintKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1351,21 +1929,18 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSBooleanKeyword *node) cons UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSClassImplements *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSClassImplements *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSConditionalType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSConditionalType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSConstructorType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSConstructorType *node) const { - (void)node; UNREACHABLE(); } @@ -1384,105 +1959,88 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSExternalModuleReference *e UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSFunctionType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSFunctionType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSImportEqualsDeclaration *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSImportEqualsDeclaration *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSImportType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSImportType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSIndexedAccessType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSIndexedAccessType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSInferType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSInferType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSInterfaceBody *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceBody *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSInterfaceDeclaration *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceDeclaration *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSInterfaceHeritage *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceHeritage *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSIntersectionType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSIntersectionType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSLiteralType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSLiteralType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSMappedType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSMappedType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSModuleBlock *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSModuleBlock *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSModuleDeclaration *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSModuleDeclaration *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNamedTupleMember *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNamedTupleMember *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNeverKeyword *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNeverKeyword *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNonNullExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNonNullExpression *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNullKeyword *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNullKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1496,21 +2054,18 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSObjectKeyword *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSParameterProperty *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSParameterProperty *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSParenthesizedType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSParenthesizedType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSQualifiedName *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSQualifiedName *expr) const { - (void)expr; UNREACHABLE(); } @@ -1519,75 +2074,63 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSStringKeyword *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSThisType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSThisType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTupleType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTupleType *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeAliasDeclaration *st) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeAliasDeclaration *st) const { - (void)st; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeAssertion *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeAssertion *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeLiteral *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeLiteral *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeOperator *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeOperator *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeParameter *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeParameter *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeParameterDeclaration *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeParameterDeclaration *expr) const { - (void)expr; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeParameterInstantiation *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeParameterInstantiation *expr) const { - (void)expr; 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(); } -void JSCompiler::Compile(const ir::TSTypeReference *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeReference *node) const { - (void)node; UNREACHABLE(); } @@ -1596,9 +2139,8 @@ void JSCompiler::Compile([[maybe_unused]] const ir::TSUndefinedKeyword *node) co UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSUnionType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSUnionType *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/compiler/core/JSCompiler.h b/ets2panda/compiler/core/JSCompiler.h index 9d506416504cc8298c4bffcde4682922cd26ab9c..f0fd56738f9f3f1c46f74c63e5016119dcaa4dce 100644 --- a/ets2panda/compiler/core/JSCompiler.h +++ b/ets2panda/compiler/core/JSCompiler.h @@ -17,6 +17,7 @@ #define ES2PANDA_COMPILER_CORE_JSCOMPILER_H #include "compiler/core/ASTCompiler.h" +#include "util/bitset.h" namespace panda::es2panda::ir { class AstNode; @@ -36,6 +37,10 @@ public: #define DECLARE_JSCOMPILER_COMPILE_METHOD(_, __, nodeType, ___) void Compile(const ir::nodeType *node) const override; AST_NODE_REINTERPRET_MAPPING(DECLARE_JSCOMPILER_COMPILE_METHOD) #undef DECLARE_JSCOMPILER_COMPILE_METHOD + void CompileStaticProperties(compiler::PandaGen *pg, util::BitSet *compiled, + const ir::ObjectExpression *expr) const; + void CompileRemainingProperties(compiler::PandaGen *pg, const util::BitSet *compiled, + const ir::ObjectExpression *expr) const; private: PandaGen *GetPandaGen() const; diff --git a/ets2panda/compiler/core/codeGen.h b/ets2panda/compiler/core/codeGen.h index e06a982cad260779b94b10d71f4f1b60e4b24c2d..87e6faa6099d853f43618214d80b169243350414 100644 --- a/ets2panda/compiler/core/codeGen.h +++ b/ets2panda/compiler/core/codeGen.h @@ -20,7 +20,6 @@ #include "compiler/core/ASTCompiler.h" #include "compiler/core/regAllocator.h" #include "compiler/core/regScope.h" - namespace panda::es2panda::compiler { class CatchTable; class DynamicContext; diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 31f07dcbf9ed4c9d9456d4ecffe34ccea7b76813..c04cd5a129fe9ef40b5e3e3d46e0437b045f5770 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -16,6 +16,8 @@ #include "compilerImpl.h" #include "es2panda.h" +#include "checker/ETSAnalyzer.h" +#include "checker/TSAnalyzer.h" #include "compiler/core/compilerContext.h" #include "compiler/core/compileQueue.h" #include "compiler/core/compilerImpl.h" @@ -36,9 +38,7 @@ #include "varbinder/ASBinder.h" #include "varbinder/TSBinder.h" #include "varbinder/ETSBinder.h" -#include "checker/TSAnalyzer.h" #include "checker/TSchecker.h" -#include "checker/ETSAnalyzer.h" #include "checker/ETSchecker.h" #include "checker/ASchecker.h" #include "checker/JSchecker.h" diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ebf2ea93101495007c5e441e3ce0b1d6cc97250 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lambdaLowering.h" +#include "checker/checker.h" +#include "compiler/core/compilerContext.h" +#include "util/declgenEts2Ts.h" + +namespace panda::es2panda::compiler { + +std::string_view LambdaLowering::Name() +{ + return "lambda-lowering"; +} + +static ir::AstNode *ConvertExpression(checker::ETSChecker *const checker, ir::ArrowFunctionExpression *const arrow) +{ + auto *const function = arrow->Function(); + auto *const scope = function->Scope(); + auto *const expr = function->Body()->AsExpression(); + + ArenaVector statements(checker->Allocator()->Adapter()); + statements.emplace_back(checker->AllocNode(expr)); + auto *const block = checker->AllocNode(checker->Allocator(), scope, std::move(statements)); + block->SetParent(function); + + function->SetBody(block); + function->AddFlag(ir::ScriptFunctionFlags::HAS_RETURN); + + return arrow; +} + +bool LambdaLowering::Perform(public_lib::Context *ctx, parser::Program *program) +{ + for (auto &[_, ext_programs] : program->ExternalSources()) { + (void)_; + for (auto *ext_prog : ext_programs) { + Perform(ctx, ext_prog); + } + } + + checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); + + program->Ast()->TransformChildrenRecursively([checker](ir::AstNode *const node) -> ir::AstNode * { + if (node->IsArrowFunctionExpression() && + node->AsArrowFunctionExpression()->Function()->Body()->IsExpression()) { + return ConvertExpression(checker, node->AsArrowFunctionExpression()); + } + + return node; + }); + + return true; +} + +bool LambdaLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program) +{ + for (auto &[_, ext_programs] : program->ExternalSources()) { + (void)_; + for (auto *ext_prog : ext_programs) { + if (!Postcondition(ctx, ext_prog)) { + return false; + } + } + } + + return !program->Ast()->IsAnyChild([](const ir::AstNode *node) { + return node->IsArrowFunctionExpression() && + node->AsArrowFunctionExpression()->Function()->Body()->IsExpression(); + }); +} + +} // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.h b/ets2panda/compiler/lowering/ets/lambdaLowering.h new file mode 100644 index 0000000000000000000000000000000000000000..c06a4cd3fafc2cd822724b85910d84ea99747a0b --- /dev/null +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_LAMDBA_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_LAMDBA_LOWERING_H + +#include "compiler/lowering/phase.h" + +namespace panda::es2panda::compiler { + +class LambdaLowering : public Phase { +public: + std::string_view Name() override; + bool Perform(public_lib::Context *ctx, parser::Program *program) override; + bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; +}; + +} // namespace panda::es2panda::compiler + +#endif diff --git a/ets2panda/compiler/lowering/ets/tupleLowering.cpp b/ets2panda/compiler/lowering/ets/tupleLowering.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34ed65ad7dc0919f1cac0021d8a000fa7a8ac5f5 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/tupleLowering.cpp @@ -0,0 +1,264 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tupleLowering.h" + +#include "checker/ETSchecker.h" +#include "checker/checker.h" +#include "checker/types/type.h" +#include "compiler/core/compilerContext.h" +#include "compiler/lowering/util.h" +#include "ir/astNode.h" +#include "ir/expression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/updateExpression.h" +#include "ir/opaqueTypeNode.h" +#include "ir/statements/blockStatement.h" +#include "ir/ts/tsAsExpression.h" + +namespace panda::es2panda::compiler { + +std::string_view TupleLowering::Name() +{ + return "tuple-lowering"; +} + +static ir::Expression *ConvertTupleUpdate(checker::ETSChecker *const checker, ir::UpdateExpression *const update) +{ + // Converts `tuple[n]++` to + // ``` + // let gensym = tuple[n] as ; // line 1 + // let gensym2 = (gensym)++; // line 2 + // tuple[n] = (gensym as ) as ; // line 3 + // gensym2 as ; // line 4 + // ``` + // Notes: + // --- + // Because we can modify only 1 expression in the lowering (we don't want to add statements to the enclosing block), + // the expressions will be in a wrapper SequenceExpression + // --- + // At line 3 the double as expression is needed. If we simply write `gensym as `, then a + // boxing flag may be put on the `gensym` identifier node. It'll be boxed in 'line 2' instead of 'line 3', which + // cause error. If we put another as expression inside (which won't do any conversion, because the type of `gensym` + // is already ), the boxing flag will be on the as expression, instead of the identifier, so + // the identifier node won't be unboxed at 'line 2'. + + // Check if argument of update expression is tuple + auto *const argument = update->Argument(); + const bool is_argument_member_expression = argument->IsMemberExpression(); + auto *const argument_type = + is_argument_member_expression ? argument->AsMemberExpression()->Object()->TsType() : nullptr; + + if ((argument_type == nullptr) || (!argument_type->IsETSTupleType())) { + return update; + } + // -------------- + + // Set tuple type to Object (because we'll need implicit boxing) + auto *const saved_type = argument->TsType(); + argument->SetTsType(argument_type->AsETSTupleType()->ElementType()); + // -------------- + + // Compute necessary types and OpaqueTypeNodes + auto *const tuple_type_at_idx = argument_type->AsETSTupleType()->GetTypeAtIndex( + checker->GetTupleElementAccessValue(argument->AsMemberExpression()->Property()->TsType())); + + auto *const tuple_element_type_node = + checker->AllocNode(argument_type->AsETSTupleType()->ElementType()); + auto *const tuple_type_at_idx_node = checker->AllocNode(tuple_type_at_idx); + // -------------- + + // Clone argument of update expression (conversion flag might be added to it, so we need to duplicate it to not make + // conversions on 'line 3', that belongs to 'line 1' ) + auto *const member_expr = argument->AsMemberExpression(); + auto *const argument_clone = + checker->AllocNode(member_expr->Object(), member_expr->Property(), member_expr->Kind(), + member_expr->IsComputed(), member_expr->IsOptional()); + argument_clone->SetPropVar(member_expr->PropVar()); + argument_clone->SetParent(member_expr->Parent()); + argument_clone->SetTsType(member_expr->TsType()); + argument_clone->SetObjectType(member_expr->ObjType()); + // -------------- + + // Generate temporary symbols + auto *gensym = Gensym(checker->Allocator()); + auto *const tmp_var = NearestScope(update)->AddDecl( + checker->Allocator(), gensym->Name(), varbinder::VariableFlags::LOCAL); + tmp_var->SetTsType(tuple_type_at_idx); + gensym->SetVariable(tmp_var); + gensym->SetTsType(tmp_var->TsType()); + + auto *gensym_2 = Gensym(checker->Allocator()); + auto *const tmp_var_2 = NearestScope(update)->AddDecl( + checker->Allocator(), gensym_2->Name(), varbinder::VariableFlags::LOCAL); + tmp_var_2->SetTsType(tuple_type_at_idx); + gensym_2->SetVariable(tmp_var_2); + gensym_2->SetTsType(tmp_var_2->TsType()); + // -------------- + + // make node: let gensym = tuple[n] as ; + auto *const gensym_ts_as = checker->AllocNode(argument_clone, tuple_type_at_idx_node, false); + auto *const tuple_as_type = + checker->AllocNode(gensym, gensym_ts_as, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + // -------------- + + // make node: let gensym2 = (gensym)++; + auto *gensym_update = checker->AllocNode(gensym, update->OperatorType(), update->IsPrefix()); + auto *const gensym_2_assignment = checker->AllocNode( + gensym_2, gensym_update, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + // -------------- + + // make node: tuple[n] = (gensym as ) as ; + auto *gensym_as = checker->AllocNode(gensym, tuple_type_at_idx_node, false); + auto *gensym_as_tuple_type_at_idx = + checker->AllocNode(gensym_as, tuple_element_type_node, false); + auto *const tuple_assignment = checker->AllocNode( + argument, gensym_as_tuple_type_at_idx, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + // -------------- + + // make node: gensym2 as ; + auto *const final_tuple_node = checker->AllocNode(gensym_2, tuple_type_at_idx_node, false); + // -------------- + + // Construct sequence expression order + ArenaVector expression_list(checker->Allocator()->Adapter()); + expression_list.push_back(tuple_as_type); + expression_list.push_back(gensym_2_assignment); + expression_list.push_back(tuple_assignment); + expression_list.push_back(final_tuple_node); + // -------------- + + // Check the new sequence expression + auto *const sequence_expr = checker->AllocNode(std::move(expression_list)); + sequence_expr->SetParent(update->Parent()); + sequence_expr->Check(checker); + // -------------- + + // Set back TsType of argument (not necessarily needed now, but there can be a phase later, that need to get the + // right type of it) + argument->SetTsType(saved_type); + // -------------- + + return sequence_expr; +} + +static ir::AssignmentExpression *ConvertTupleAssignment(checker::ETSChecker *const checker, + ir::AssignmentExpression *const assignment) +{ + // Converts `tuple[n] = variable;` to + // `tuple[n] = ((variable as ) as )` + // This lowering is necessary to handle `an unboxing conversion followed by a widening primitive + // conversion`, eg. when `tuple[n]` has type of `int`, and assignment::right_ has type of `Short`. Because every + // type is stored as the LUB type in the tuple (which can be Object), then the following conversions need to be done + // for this case: Short->short->int->Int->Object which can't be made implicitly, hence lowering is needed + + // Check if the left side of an assignment expression is a tuple element access + auto *const left = assignment->Left(); + auto *const left_object_type = left->AsMemberExpression()->Object()->TsType(); + + if ((left_object_type == nullptr) || (!left_object_type->IsETSTupleType())) { + return assignment; + } + // -------------- + + // Set tuple type to (because we may need implicit boxing) + auto *const saved_left_type = left->TsType(); + left->SetTsType(left_object_type->AsETSTupleType()->ElementType()); + // -------------- + + // Compute necessary types and OpaqueTypeNodes + auto *const element_type_type_node = + checker->AllocNode(left_object_type->AsETSTupleType()->ElementType()); + auto *const tuple_type_at_idx_type_node = checker->AllocNode(saved_left_type); + // -------------- + + // make node: tuple[n] = ((variable as ) as ) + auto *const ts_as_expression_left = + checker->AllocNode(assignment->Right(), tuple_type_at_idx_type_node, false); + + auto *const ts_as_expression = + checker->AllocNode(ts_as_expression_left, element_type_type_node, false); + auto *const new_assignment = + checker->AllocNode(left, ts_as_expression, assignment->OperatorType()); + // -------------- + + // Check the new assignment + new_assignment->SetParent(assignment->Parent()); + new_assignment->Check(checker); + left->SetTsType(saved_left_type); + // -------------- + + return new_assignment; +} + +bool TupleLowering::Perform(public_lib::Context *const ctx, parser::Program *const program) +{ + for (const auto &[_, ext_programs] : program->ExternalSources()) { + (void)_; + for (auto *const ext_prog : ext_programs) { + Perform(ctx, ext_prog); + } + } + + checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); + + program->Ast()->TransformChildrenRecursively([checker](ir::AstNode *const ast) -> ir::AstNode * { + // Check if node is an 'assignment expression', with a member expression on the left (potentially tuple) + if (ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->Left()->IsMemberExpression()) { + return ConvertTupleAssignment(checker, ast->AsAssignmentExpression()); + } + + // Check if node is an 'update expression', with a member expression as an argument (potentially tuple) + if (ast->IsUpdateExpression() && ast->AsUpdateExpression()->Argument()->IsMemberExpression()) { + return ConvertTupleUpdate(checker, ast->AsUpdateExpression()); + } + + return ast; + }); + + return true; +} + +bool TupleLowering::Postcondition(public_lib::Context *const ctx, const parser::Program *const program) +{ + for (const auto &[_, ext_programs] : program->ExternalSources()) { + (void)_; + for (const auto *const ext_prog : ext_programs) { + if (!Postcondition(ctx, ext_prog)) { + return false; + } + } + } + + return !program->Ast()->IsAnyChild([](const ir::AstNode *const ast) { + const bool is_left_member_expr = + ast->IsAssignmentExpression() && ast->AsAssignmentExpression()->Left()->IsMemberExpression(); + const bool is_left_tuple = + is_left_member_expr + ? (ast->AsAssignmentExpression()->Left()->AsMemberExpression()->TsType() != nullptr) && + ast->AsAssignmentExpression()->Left()->AsMemberExpression()->TsType()->IsETSTupleType() + : false; + // Check if there is an 'assignment expression' with a 'member expression' on it's left, which is a tuple. If + // yes, then the right hand side must be a type of the element type. + return is_left_member_expr && is_left_tuple && + (ast->AsAssignmentExpression()->Right()->TsType() == + ast->AsAssignmentExpression()->Left()->AsMemberExpression()->TsType()->AsETSTupleType()->ElementType()); + }); +} + +} // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/tupleLowering.h b/ets2panda/compiler/lowering/ets/tupleLowering.h new file mode 100644 index 0000000000000000000000000000000000000000..1c5fce5b97f203cf1822152bade203bef3c168f7 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/tupleLowering.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_TUPLE_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_TUPLE_LOWERING_H + +#include "compiler/lowering/phase.h" + +namespace panda::es2panda::compiler { + +class TupleLowering : public Phase { +public: + std::string_view Name() override; + bool Perform(public_lib::Context *ctx, parser::Program *program) override; + bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; +}; + +} // namespace panda::es2panda::compiler + +#endif // ES2PANDA_COMPILER_LOWERING_TUPLE_LOWERING_H diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 19035aec00f28b0aa6daf67d5c65dfa20992a553..d9d06b2190d41d8967d746af15b213c0070f50f0 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -21,7 +21,9 @@ #include "compiler/lowering/checkerPhase.h" #include "compiler/lowering/plugin_phase.h" #include "compiler/lowering/ets/generateDeclarations.h" +#include "compiler/lowering/ets/lambdaLowering.h" #include "compiler/lowering/ets/opAssignment.h" +#include "compiler/lowering/ets/tupleLowering.h" #include "compiler/lowering/ets/unionLowering.h" #include "public/es2panda_lib.h" @@ -37,7 +39,9 @@ std::vector GetTrivialPhaseList() } static GenerateTsDeclarationsPhase GENERATE_TS_DECLARATIONS_PHASE; +static LambdaLowering LAMBDA_LOWERING; static OpAssignmentLowering OP_ASSIGNMENT_LOWERING; +static TupleLowering TUPLE_LOWERING; // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase static UnionLowering UNION_LOWERING; static PluginPhase PLUGINS_AFTER_PARSE {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse}; static PluginPhase PLUGINS_AFTER_CHECK {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}; @@ -47,8 +51,15 @@ static PluginPhase PLUGINS_AFTER_LOWERINGS {"plugins-after-lowering", ES2PANDA_S std::vector GetETSPhaseList() { return std::vector { - &PLUGINS_AFTER_PARSE, &CHECKER_PHASE, &PLUGINS_AFTER_CHECK, &GENERATE_TS_DECLARATIONS_PHASE, - &OP_ASSIGNMENT_LOWERING, &UNION_LOWERING, &PLUGINS_AFTER_LOWERINGS, + &PLUGINS_AFTER_PARSE, + &LAMBDA_LOWERING, + &CHECKER_PHASE, + &PLUGINS_AFTER_CHECK, + &GENERATE_TS_DECLARATIONS_PHASE, + &OP_ASSIGNMENT_LOWERING, + &TUPLE_LOWERING, + &UNION_LOWERING, + &PLUGINS_AFTER_LOWERINGS, }; } diff --git a/ets2panda/ir/astNodeMapping.h b/ets2panda/ir/astNodeMapping.h index e05e9a9c2fe3cbcb6303983fc3fbe7aca42cdbb7..6a1dd0e6d39a74f712539a6f44c532983336e695 100644 --- a/ets2panda/ir/astNodeMapping.h +++ b/ets2panda/ir/astNodeMapping.h @@ -90,6 +90,7 @@ _(ETS_NEW_CLASS_INSTANCE_EXPRESSION, ETSNewClassInstanceExpression) \ _(ETS_IMPORT_DECLARATION, ETSImportDeclaration) \ _(ETS_PARAMETER_EXPRESSION, ETSParameterExpression) \ + _(ETS_TUPLE, ETSTuple) \ _(SUPER_EXPRESSION, SuperExpression) \ _(STRUCT_DECLARATION, ETSStructDeclaration) \ _(SWITCH_CASE_STATEMENT, SwitchCaseStatement) \ diff --git a/ets2panda/ir/base/spreadElement.cpp b/ets2panda/ir/base/spreadElement.cpp index c6a722c3ad7a17e58e9e94ff6e11dd96478f1b4c..aa6719ad4d18c89d49b5e30816b30e3e2143af4d 100644 --- a/ets2panda/ir/base/spreadElement.cpp +++ b/ets2panda/ir/base/spreadElement.cpp @@ -16,6 +16,9 @@ #include "spreadElement.h" #include "es2panda.h" +#include "checker/TSchecker.h" +#include "compiler/core/pandagen.h" +#include "compiler/core/ETSGen.h" #include "ir/astDump.h" #include "ir/base/decorator.h" #include "ir/typeNode.h" @@ -137,15 +140,22 @@ void SpreadElement::Dump(ir::AstDumper *dumper) const {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}}); } -void SpreadElement::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void SpreadElement::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void SpreadElement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *SpreadElement::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *SpreadElement::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/base/spreadElement.h b/ets2panda/ir/base/spreadElement.h index d3c047434e7a3c33eba06c9e031f4aeeb569fc86..2c3eff8d3a19f1509c0cd5beb91630d4e0610770 100644 --- a/ets2panda/ir/base/spreadElement.h +++ b/ets2panda/ir/base/spreadElement.h @@ -88,6 +88,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([[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; diff --git a/ets2panda/ir/base/tsSignatureDeclaration.cpp b/ets2panda/ir/base/tsSignatureDeclaration.cpp index a36cf714a6a1d619871eb8b804e8240d92575d13..da7dc1bd9c96169f37a6e78916480b5e3248f810 100644 --- a/ets2panda/ir/base/tsSignatureDeclaration.cpp +++ b/ets2panda/ir/base/tsSignatureDeclaration.cpp @@ -16,12 +16,10 @@ #include "tsSignatureDeclaration.h" #include "varbinder/scope.h" -#include "ir/typeNode.h" -#include "ir/astDump.h" -#include "ir/ts/tsTypeParameter.h" -#include "ir/ts/tsTypeParameterDeclaration.h" - +#include "checker/ETSchecker.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void TSSignatureDeclaration::TransformChildren(const NodeTransformer &cb) @@ -64,50 +62,23 @@ void TSSignatureDeclaration::Dump(ir::AstDumper *dumper) const {"returnType", AstDumper::Optional(return_type_annotation_)}}); } -void TSSignatureDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -checker::Type *TSSignatureDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +void TSSignatureDeclaration::Compile(compiler::PandaGen *pg) const { - if (TsType() != nullptr) { - return TsType(); - } - - checker::ScopeContext scope_ctx(checker, scope_); - - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - checker->CheckFunctionParameterDeclarations(params_, signature_info); - - bool is_call_signature = (Kind() == ir::TSSignatureDeclaration::TSSignatureDeclarationKind::CALL_SIGNATURE); - - if (return_type_annotation_ == nullptr) { - if (is_call_signature) { - checker->ThrowTypeError( - "Call signature, which lacks return-type annotation, implicitly has an 'any' return type.", Start()); - } - - checker->ThrowTypeError( - "Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.", Start()); - } - - return_type_annotation_->Check(checker); - checker::Type *return_type = return_type_annotation_->GetType(checker); - - auto *signature = checker->Allocator()->New(signature_info, return_type); - - checker::Type *placeholder_obj = nullptr; + pg->GetAstCompiler()->Compile(this); +} - if (is_call_signature) { - placeholder_obj = checker->CreateObjectTypeWithCallSignature(signature); - } else { - placeholder_obj = checker->CreateObjectTypeWithConstructSignature(signature); - } +void TSSignatureDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} - SetTsType(placeholder_obj); - return placeholder_obj; +checker::Type *TSSignatureDeclaration::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } -checker::Type *TSSignatureDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *TSSignatureDeclaration::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/base/tsSignatureDeclaration.h b/ets2panda/ir/base/tsSignatureDeclaration.h index 20028f3aa848702267ad4baf9d862a158343e16d..5fa134bb6fa21ed516fef2eaa18fd6598e197235 100644 --- a/ets2panda/ir/base/tsSignatureDeclaration.h +++ b/ets2panda/ir/base/tsSignatureDeclaration.h @@ -18,6 +18,10 @@ #include "ir/astNode.h" +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSTypeParameterDeclaration; @@ -42,6 +46,8 @@ public: return_type_annotation_(return_type_annotation) { } + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class checker::TSAnalyzer; bool IsScopeBearer() const override { @@ -78,9 +84,10 @@ public: void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: varbinder::Scope *scope_; diff --git a/ets2panda/ir/ets/etsClassLiteral.cpp b/ets2panda/ir/ets/etsClassLiteral.cpp index 9d461309a1ecac09ea49b28c67e735499e41a92d..0168b7ddaf914abd097dc0ef03156e95ea638138 100644 --- a/ets2panda/ir/ets/etsClassLiteral.cpp +++ b/ets2panda/ir/ets/etsClassLiteral.cpp @@ -15,12 +15,10 @@ #include "etsClassLiteral.h" -#include "ir/astNode.h" -#include "ir/astDump.h" -#include "ir/typeNode.h" #include "checker/TSchecker.h" -#include "checker/ets/typeRelationContext.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSClassLiteral::TransformChildren(const NodeTransformer &cb) @@ -38,42 +36,24 @@ void ETSClassLiteral::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSClassLiteral"}}); } -void ETSClassLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void ETSClassLiteral::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSClassLiteral::Compile(compiler::PandaGen *pg) const { - if (expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { - expr_->Compile(etsg); - etsg->GetType(this, false); - } else { - ASSERT(expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)); - etsg->SetAccumulatorType(expr_->TsType()); - etsg->GetType(this, true); - } + pg->GetAstCompiler()->Compile(this); } -checker::Type *ETSClassLiteral::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSClassLiteral::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSClassLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSClassLiteral::Check(checker::TSChecker *checker) { - checker->ThrowTypeError("Class literal is not yet supported.", expr_->Start()); - - expr_->Check(checker); - auto *expr_type = expr_->GetType(checker); - - if (expr_type->IsETSVoidType()) { - checker->ThrowTypeError("Invalid .class reference", expr_->Start()); - } - - ArenaVector type_arg_types(checker->Allocator()->Adapter()); - type_arg_types.push_back(expr_type); // NOTE: Box it if it's a primitive type + return checker->GetAnalyzer()->Check(this); +} - checker::InstantiationContext ctx(checker, checker->GlobalBuiltinTypeType(), type_arg_types, range_.start); - SetTsType(ctx.Result()); - return TsType(); +checker::Type *ETSClassLiteral::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/ets/etsClassLiteral.h b/ets2panda/ir/ets/etsClassLiteral.h index 44fbf9c8ba0179b0caf85783579f81727f302c11..708c99bdc753792958362b9ec8da61cd5df06463 100644 --- a/ets2panda/ir/ets/etsClassLiteral.h +++ b/ets2panda/ir/ets/etsClassLiteral.h @@ -18,6 +18,14 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ETSClassLiteral : public Expression { @@ -33,13 +41,17 @@ public: // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ETSClassLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ir::TypeNode *expr_; diff --git a/ets2panda/ir/ets/etsFunctionType.cpp b/ets2panda/ir/ets/etsFunctionType.cpp index 57e2248c5636d922988e83ab2e0197695e8c9644..ba44e619633c78f02df22e2da0299bdef97f1727 100644 --- a/ets2panda/ir/ets/etsFunctionType.cpp +++ b/ets2panda/ir/ets/etsFunctionType.cpp @@ -18,17 +18,9 @@ #include "varbinder/scope.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" -#include "checker/types/signature.h" -#include "ir/astDump.h" -#include "ir/base/spreadElement.h" -#include "ir/base/methodDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/expressions/identifier.h" -#include "ir/ts/tsTypeParameter.h" -#include "ir/ts/tsInterfaceDeclaration.h" -#include "ir/ts/tsInterfaceBody.h" -#include "ir/ts/tsTypeParameterDeclaration.h" -#include "ir/ets/etsParameterExpression.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +// #include "ir/astDump.h" namespace panda::es2panda::ir { void ETSFunctionType::TransformChildren(const NodeTransformer &cb) @@ -73,11 +65,19 @@ void ETSFunctionType::Dump(ir::AstDumper *dumper) const } } -void ETSFunctionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSFunctionType::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -checker::Type *ETSFunctionType::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSFunctionType::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); +} + +checker::Type *ETSFunctionType::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSFunctionType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -87,60 +87,7 @@ checker::Type *ETSFunctionType::GetType([[maybe_unused]] checker::TSChecker *che checker::Type *ETSFunctionType::Check(checker::ETSChecker *checker) { - checker->CreateFunctionalInterfaceForFunctionType(this); - auto *interface_type = checker->CreateETSObjectType(functional_interface_->Id()->Name(), functional_interface_, - checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); - interface_type->SetSuperType(checker->GlobalETSObjectType()); - - auto *invoke_func = functional_interface_->Body()->Body()[0]->AsMethodDefinition()->Function(); - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - - for (auto *it : invoke_func->Params()) { - auto *const param = it->AsETSParameterExpression(); - if (param->IsRestParameter()) { - auto *rest_ident = param->Ident(); - - ASSERT(rest_ident->Variable()); - signature_info->rest_var = rest_ident->Variable()->AsLocalVariable(); - - ASSERT(param->TypeAnnotation()); - signature_info->rest_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - - auto array_type = signature_info->rest_var->TsType()->AsETSArrayType(); - checker->CreateBuiltinArraySignature(array_type, array_type->Rank()); - } else { - auto *param_ident = param->Ident(); - - ASSERT(param_ident->Variable()); - varbinder::Variable *param_var = param_ident->Variable(); - - ASSERT(param->TypeAnnotation()); - param_var->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - signature_info->params.push_back(param_var->AsLocalVariable()); - ++signature_info->min_arg_count; - } - } - - invoke_func->ReturnTypeAnnotation()->Check(checker); - auto *signature = - checker->Allocator()->New(signature_info, return_type_->GetType(checker), invoke_func); - signature->SetOwnerVar(invoke_func->Id()->Variable()->AsLocalVariable()); - signature->AddSignatureFlag(checker::SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); - signature->SetOwner(interface_type); - - auto *func_type = checker->CreateETSFunctionType(signature); - invoke_func->SetSignature(signature); - invoke_func->Id()->Variable()->SetTsType(func_type); - interface_type->AddProperty( - invoke_func->Id()->Variable()->AsLocalVariable()); - functional_interface_->SetTsType(interface_type); - - auto *this_var = invoke_func->Scope()->ParamScope()->Params().front(); - this_var->SetTsType(interface_type); - checker->BuildFunctionalInterfaceName(this); - - ts_type_ = interface_type; - return interface_type; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSFunctionType::GetType(checker::ETSChecker *checker) diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index d8323848934eb12c044460249b056ae6bdb1ca1a..917c68cd6200431718cf4688eeb9bf11b2a457ca 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -18,6 +18,10 @@ #include "ir/typeNode.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSTypeParameterDeclaration; @@ -35,6 +39,9 @@ public: { } + // TODO (csabahurton): friend relationship can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + bool IsScopeBearer() const override { return true; @@ -93,10 +100,11 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; private: diff --git a/ets2panda/ir/ets/etsLaunchExpression.cpp b/ets2panda/ir/ets/etsLaunchExpression.cpp index 280a1f05e2531d5bc58e42805d5a69a6ae531f7b..8c006c458827173b3aa9eca42808bcf041167b9b 100644 --- a/ets2panda/ir/ets/etsLaunchExpression.cpp +++ b/ets2panda/ir/ets/etsLaunchExpression.cpp @@ -19,10 +19,6 @@ #include "compiler/core/ETSGen.h" #include "checker/ETSchecker.h" #include "checker/TSchecker.h" -#include "ir/astDump.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/callExpression.h" -#include "ir/expressions/memberExpression.h" namespace panda::es2panda::ir { ETSLaunchExpression::ETSLaunchExpression(CallExpression *expr) @@ -45,70 +41,26 @@ void ETSLaunchExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSLaunchExpression"}, {"expr", expr_}}); } -void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSLaunchExpression::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} void ETSLaunchExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { #ifdef PANDA_WITH_ETS - compiler::RegScope rs(etsg); - compiler::VReg callee_reg = etsg->AllocReg(); - checker::Signature *signature = expr_->Signature(); - bool is_static = signature->HasSignatureFlag(checker::SignatureFlags::STATIC); - bool is_reference = signature->HasSignatureFlag(checker::SignatureFlags::TYPE); - if (!is_reference && expr_->Callee()->IsIdentifier()) { - if (!is_static) { - etsg->LoadThis(expr_); - etsg->StoreAccumulator(this, callee_reg); - } - } else if (!is_reference && expr_->Callee()->IsMemberExpression()) { - if (!is_static) { - expr_->Callee()->AsMemberExpression()->Object()->Compile(etsg); - etsg->StoreAccumulator(this, callee_reg); - } - } else { - expr_->Callee()->Compile(etsg); - etsg->StoreAccumulator(this, callee_reg); - } - - if (is_static) { - etsg->LaunchStatic(this, signature, expr_->Arguments()); - } else if (signature->HasSignatureFlag(checker::SignatureFlags::PRIVATE)) { - etsg->LaunchThisStatic(this, callee_reg, signature, expr_->Arguments()); - } else { - etsg->LaunchThisVirtual(this, callee_reg, signature, expr_->Arguments()); - } - - etsg->SetAccumulatorType(TsType()); + etsg->GetAstCompiler()->Compile(this); #endif // PANDA_WITH_ETS } -checker::Type *ETSLaunchExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSLaunchExpression::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ETSLaunchExpression::Check(checker::ETSChecker *checker) { - expr_->Check(checker); - auto *const launch_promise_type = - checker->GlobalBuiltinPromiseType() - ->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()) - ->AsETSObjectType(); - launch_promise_type->AddTypeFlag(checker::TypeFlag::GENERIC); - - // Launch expression returns a Promise type, so we need to insert the expression's type - // as type parameter for the Promise class. - - auto *expr_type = - expr_->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && !expr_->TsType()->IsETSVoidType() - ? checker->PrimitiveTypeAsETSBuiltinType(expr_->TsType()) - : expr_->TsType(); - checker::Substitution *substitution = checker->NewSubstitution(); - ASSERT(launch_promise_type->TypeArguments().size() == 1); - substitution->emplace(checker->GetOriginalBaseType(launch_promise_type->TypeArguments()[0]), expr_type); - - SetTsType(launch_promise_type->Substitute(checker->Relation(), substitution)); - return TsType(); + return checker->GetAnalyzer()->Check(this); } bool ETSLaunchExpression::IsStaticCall() const diff --git a/ets2panda/ir/ets/etsLaunchExpression.h b/ets2panda/ir/ets/etsLaunchExpression.h index 2863db9948045ae9f94f5adba6606e7e2333e716..3ec4bb83e8cdc8afb17338dec76958d5b0b1a195 100644 --- a/ets2panda/ir/ets/etsLaunchExpression.h +++ b/ets2panda/ir/ets/etsLaunchExpression.h @@ -18,6 +18,14 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class CallExpression; @@ -32,16 +40,20 @@ public: explicit ETSLaunchExpression(CallExpression *expr); + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ETSLaunchExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; bool IsStaticCall() const; [[nodiscard]] const CallExpression *Call() const noexcept diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp index b56d07341e770bf2117b4091904345c98e01cbfa..7ac314d183e4c1941af0cda89b55d111b22d2eb9 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -15,10 +15,12 @@ #include "etsNewArrayInstanceExpression.h" +#include "checker/ETSchecker.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" -#include "compiler/core/ETSGen.h" -#include "checker/ETSchecker.h" namespace panda::es2panda::ir { void ETSNewArrayInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -39,35 +41,23 @@ void ETSNewArrayInstanceExpression::Dump(ir::AstDumper *dumper) const {{"type", "ETSNewArrayInstanceExpression"}, {"typeReference", type_reference_}, {"dimension", dimension_}}); } -void ETSNewArrayInstanceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSNewArrayInstanceExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSNewArrayInstanceExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(etsg); - compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); - - dimension_->Compile(etsg); - - compiler::VReg arr = etsg->AllocReg(); - compiler::VReg dim = etsg->AllocReg(); - etsg->ApplyConversionAndStoreAccumulator(this, dim, dimension_->TsType()); - etsg->NewArray(this, arr, dim, TsType()); - etsg->SetVRegType(arr, TsType()); - etsg->LoadAccumulator(this, arr); + pg->GetAstCompiler()->Compile(this); } - -checker::Type *ETSNewArrayInstanceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSNewArrayInstanceExpression::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSNewArrayInstanceExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNewArrayInstanceExpression::Check(checker::TSChecker *checker) { - auto *element_type = type_reference_->GetType(checker); - checker->ValidateArrayIndex(dimension_); + return checker->GetAnalyzer()->Check(this); +} - SetTsType(checker->CreateETSArrayType(element_type)); - checker->CreateBuiltinArraySignature(TsType()->AsETSArrayType(), 1); - return TsType(); +checker::Type *ETSNewArrayInstanceExpression::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index 3528a7646afdb6c149fa8db7dcc2d7d5ec1db143..de377ff405fbd2ecc76414801b3cef5d142b3ee5 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -18,6 +18,14 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ETSNewArrayInstanceExpression : public Expression { @@ -34,6 +42,9 @@ public: dimension_(dimension) { } + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; ir::TypeNode *TypeReference() { @@ -61,10 +72,10 @@ public: void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ir::TypeNode *type_reference_; diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp index f39597c1c670cd66b670a4125d64a644c651a9cc..21e9c8c6d05d81d5723d30d1ccf4c91a3d72f17e 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp @@ -16,17 +16,9 @@ #include "etsNewClassInstanceExpression.h" #include "compiler/core/ETSGen.h" -#include "ir/base/classDefinition.h" -#include "ir/base/scriptFunction.h" -#include "ir/astDump.h" -#include "ir/ets/etsTypeReference.h" -#include "ir/ets/etsTypeReferencePart.h" -#include "ir/expressions/identifier.h" -#include "ir/statements/variableDeclarator.h" -#include "ir/ts/tsQualifiedName.h" +#include "compiler/core/pandagen.h" #include "checker/TSchecker.h" -#include "checker/ETSchecker.h" -#include "checker/types/ets/types.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSNewClassInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -63,128 +55,24 @@ void ETSNewClassInstanceExpression::Dump(ir::AstDumper *dumper) const {"classBody", AstDumper::Optional(class_def_)}}); } -void ETSNewClassInstanceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void ETSNewClassInstanceExpression::CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, - compiler::VReg &obj_reg, ir::Expression *name, - checker::Signature *signature, - const ArenaVector &arguments) +void ETSNewClassInstanceExpression::Compile(compiler::PandaGen *pg) const { - auto qname_reg = etsg->AllocReg(); - - std::vector parts; - - while (name->IsTSQualifiedName()) { - auto *qname = name->AsTSQualifiedName(); - name = qname->Left(); - parts.push_back(qname->Right()->AsIdentifier()->Name()); - } - - auto *var = name->AsIdentifier()->Variable(); - auto *data = etsg->VarBinder()->DynamicImportDataForVar(var); - if (data != nullptr) { - auto *import = data->import; - auto *specifier = data->specifier; - ASSERT(import->Language().IsDynamic()); - etsg->LoadAccumulatorDynamicModule(node, import); - if (specifier->IsImportSpecifier()) { - parts.push_back(specifier->AsImportSpecifier()->Imported()->Name()); - } - } else { - name->Compile(etsg); - } - - etsg->StoreAccumulator(node, obj_reg); - - std::stringstream ss; - std::for_each(parts.rbegin(), parts.rend(), [&ss](util::StringView sv) { ss << "." << sv; }); - - etsg->LoadAccumulatorString(node, util::UString(ss.str(), etsg->Allocator()).View()); - etsg->StoreAccumulator(node, qname_reg); - - etsg->CallDynamic(node, obj_reg, qname_reg, signature, arguments); + pg->GetAstCompiler()->Compile(this); } -void ETSNewClassInstanceExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSNewClassInstanceExpression::Compile(compiler::ETSGen *etsg) const { - if (TsType()->IsETSDynamicType()) { - auto obj_reg = etsg->AllocReg(); - auto *name = type_reference_->AsETSTypeReference()->Part()->Name(); - CreateDynamicObject(this, etsg, obj_reg, name, signature_, arguments_); - } else { - etsg->InitObject(this, signature_, arguments_); - } - - if (GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE) { - etsg->SetAccumulatorType(TsType()); - } + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSNewClassInstanceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSNewClassInstanceExpression::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *ETSNewClassInstanceExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNewClassInstanceExpression::Check(checker::ETSChecker *checker) { - checker::Type *callee_type = type_reference_->Check(checker); - - if (!callee_type->IsETSObjectType()) { - checker->ThrowTypeError("This expression is not constructible.", Start()); - } - - auto *callee_obj = callee_type->AsETSObjectType(); - SetTsType(callee_obj); - - if (class_def_ != nullptr) { - if (!callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT) && callee_obj->GetDeclNode()->IsFinal()) { - checker->ThrowTypeError({"Class ", callee_obj->Name(), " cannot be both 'abstract' and 'final'."}, - callee_obj->GetDeclNode()->Start()); - } - - bool from_interface = callee_obj->HasObjectFlag(checker::ETSObjectFlags::INTERFACE); - auto *class_type = checker->BuildAnonymousClassProperties( - class_def_, from_interface ? checker->GlobalETSObjectType() : callee_obj); - if (from_interface) { - class_type->AddInterface(callee_obj); - callee_obj = checker->GlobalETSObjectType(); - } - class_def_->SetTsType(class_type); - checker->CheckClassDefinition(class_def_); - checker->CheckInnerClassMembers(class_type); - SetTsType(class_type); - } else if (callee_obj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) { - checker->ThrowTypeError({callee_obj->Name(), " is abstract therefore cannot be instantiated."}, Start()); - } - - if (callee_type->IsETSDynamicType() && !callee_type->AsETSDynamicType()->HasDecl()) { - auto lang = callee_type->AsETSDynamicType()->Language(); - signature_ = checker->ResolveDynamicCallExpression(type_reference_, arguments_, lang, true); - } else { - auto *signature = checker->ResolveConstructExpression(callee_obj, arguments_, Start()); - - checker->CheckObjectLiteralArguments(signature, arguments_); - checker->AddUndefinedParamsForDefaultParams(signature, arguments_, checker); - - checker->ValidateSignatureAccessibility(callee_obj, signature, Start()); - - ASSERT(signature->Function() != nullptr); - - if (signature->Function()->IsThrowing() || signature->Function()->IsRethrowing()) { - checker->CheckThrowingStatements(this); - } - - if (callee_type->IsETSDynamicType()) { - ASSERT(signature->Function()->IsDynamic()); - auto lang = callee_type->AsETSDynamicType()->Language(); - signature_ = checker->ResolveDynamicCallExpression(type_reference_, signature->Params(), lang, true); - } else { - ASSERT(!signature->Function()->IsDynamic()); - signature_ = signature; - } - } - - return TsType(); + return checker->GetAnalyzer()->Check(this); } ETSNewClassInstanceExpression::ETSNewClassInstanceExpression(ETSNewClassInstanceExpression const &other, diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.h b/ets2panda/ir/ets/etsNewClassInstanceExpression.h index 25cd7607ff939b0d2b1de559525514646d09be1c..b778f4f001c9ade46502edd6592ceeaeb6cdaf8d 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.h @@ -20,9 +20,14 @@ #include "ir/expression.h" namespace panda::es2panda::checker { +class ETSAnalyzer; class Signature; } // namespace panda::es2panda::checker +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ClassDefinition; @@ -44,6 +49,9 @@ public: class_def_(class_definition) { } + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; explicit ETSNewClassInstanceExpression(ETSNewClassInstanceExpression const &other, ArenaAllocator *allocator); @@ -72,10 +80,6 @@ public: signature_ = signature; } - static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, compiler::VReg &obj_reg, - ir::Expression *name, checker::Signature *signature, - const ArenaVector &arguments); - // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ETSNewClassInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; @@ -84,10 +88,10 @@ public: void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ir::Expression *type_reference_; diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp index 73a9fafa1f10cac753fe217a3b28092a44d9a4c7..f927e2d413bc556fcab1f2d9b8ae4a5d5137b202 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp @@ -16,11 +16,9 @@ #include "etsNewMultiDimArrayInstanceExpression.h" #include "varbinder/ETSBinder.h" -#include "ir/astDump.h" -#include "ir/typeNode.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" -#include "checker/ETSchecker.h" -#include "checker/types/signature.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { void ETSNewMultiDimArrayInstanceExpression::TransformChildren(const NodeTransformer &cb) @@ -46,30 +44,23 @@ void ETSNewMultiDimArrayInstanceExpression::Dump(ir::AstDumper *dumper) const {"dimensions", dimensions_}}); } -void ETSNewMultiDimArrayInstanceExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSNewMultiDimArrayInstanceExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSNewMultiDimArrayInstanceExpression::Compile(compiler::PandaGen *pg) const { - etsg->InitObject(this, signature_, dimensions_); - etsg->SetAccumulatorType(TsType()); + pg->GetAstCompiler()->Compile(this); } - -checker::Type *ETSNewMultiDimArrayInstanceExpression::Check([[maybe_unused]] checker::TSChecker *checker) +void ETSNewMultiDimArrayInstanceExpression::Compile(compiler::ETSGen *etsg) const { - return nullptr; + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSNewMultiDimArrayInstanceExpression::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSNewMultiDimArrayInstanceExpression::Check(checker::TSChecker *checker) { - auto *element_type = type_reference_->GetType(checker); - - for (auto *dim : dimensions_) { - checker->ValidateArrayIndex(dim); - element_type = checker->CreateETSArrayType(element_type); - } + return checker->GetAnalyzer()->Check(this); +} - SetTsType(element_type); - signature_ = checker->CreateBuiltinArraySignature(element_type->AsETSArrayType(), dimensions_.size()); - return TsType(); +checker::Type *ETSNewMultiDimArrayInstanceExpression::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } ETSNewMultiDimArrayInstanceExpression::ETSNewMultiDimArrayInstanceExpression( diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index d758b3427d4d8de283e1ad165380fc17c883c649..6c749bc95daf1b3922a56448aa6b62f12130d268 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -19,9 +19,14 @@ #include "ir/expression.h" namespace panda::es2panda::checker { +class ETSAnalyzer; class Signature; } // namespace panda::es2panda::checker +namespace panda::es2panda::compiler { +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ETSNewMultiDimArrayInstanceExpression : public Expression { @@ -39,6 +44,9 @@ public: dimensions_(std::move(dimensions)) { } + // TODO (csabahurton): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; explicit ETSNewMultiDimArrayInstanceExpression(ETSNewMultiDimArrayInstanceExpression const &other, ArenaAllocator *allocator); @@ -82,10 +90,10 @@ public: void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ir::TypeNode *type_reference_; diff --git a/ets2panda/ir/ets/etsPackageDeclaration.cpp b/ets2panda/ir/ets/etsPackageDeclaration.cpp index d78bc70007436b6924d85215c7adc11893d39c97..b9fe930d937570c302abbced5ceb93cb917ae21b 100644 --- a/ets2panda/ir/ets/etsPackageDeclaration.cpp +++ b/ets2panda/ir/ets/etsPackageDeclaration.cpp @@ -15,9 +15,10 @@ #include "etsPackageDeclaration.h" -#include "ir/astDump.h" #include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" +#include "ir/astDump.h" namespace panda::es2panda::ir { void ETSPackageDeclaration::TransformChildren(const NodeTransformer &cb) @@ -35,20 +36,23 @@ void ETSPackageDeclaration::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSPackageDeclaration"}, {"name", name_}}); } -void ETSPackageDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} -void ETSPackageDeclaration::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSPackageDeclaration::Compile(compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void ETSPackageDeclaration::Compile(compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } -checker::Type *ETSPackageDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +checker::Type *ETSPackageDeclaration::Check(checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } -checker::Type *ETSPackageDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +checker::Type *ETSPackageDeclaration::Check(checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/ets/etsPackageDeclaration.h b/ets2panda/ir/ets/etsPackageDeclaration.h index 50249d8c681dcf6dad4c8d05bda130833c8b1a85..44c147178c5ebffa0d065f25667bfe030e393654 100644 --- a/ets2panda/ir/ets/etsPackageDeclaration.h +++ b/ets2panda/ir/ets/etsPackageDeclaration.h @@ -41,10 +41,10 @@ public: void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; - void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; - checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; - checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Compile(compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; + checker::Type *Check(checker::TSChecker *checker) override; + checker::Type *Check(checker::ETSChecker *checker) override; private: ir::Expression *name_; diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e289cfd474ba62bcbfa752f53d041d5f1662f6c3 --- /dev/null +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "etsTuple.h" + +#include "checker/ETSchecker.h" +#include "checker/types/ets/etsTupleType.h" +#include "ir/astDump.h" + +namespace panda::es2panda::ir { + +void ETSTuple::TransformChildren([[maybe_unused]] const NodeTransformer &cb) +{ + for (auto *&it : GetTupleTypeAnnotationsList()) { + it = static_cast(cb(it)); + } + + if (HasSpreadType()) { + cb(spread_type_); + } +} + +void ETSTuple::Iterate([[maybe_unused]] const NodeTraverser &cb) const +{ + for (auto *const it : GetTupleTypeAnnotationsList()) { + cb(it); + } + + if (HasSpreadType()) { + cb(spread_type_); + } +} + +void ETSTuple::Dump(ir::AstDumper *const dumper) const +{ + dumper->Add({{"type", "ETSTuple"}, + {"types", AstDumper::Optional(type_annotation_list_)}, + {"spreadType", AstDumper::Nullish(spread_type_)}}); +} + +void ETSTuple::Compile([[maybe_unused]] compiler::PandaGen *const pg) const {} +void ETSTuple::Compile([[maybe_unused]] compiler::ETSGen *const etsg) const {} + +checker::Type *ETSTuple::Check([[maybe_unused]] checker::TSChecker *const checker) +{ + return nullptr; +} + +checker::Type *ETSTuple::Check([[maybe_unused]] checker::ETSChecker *const checker) +{ + return GetType(checker); +} + +checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker, + ArenaVector &type_list, checker::Type *const spread_type) +{ + if (type_list.empty()) { + return spread_type == nullptr ? checker->GlobalETSObjectType() : spread_type; + } + + bool all_elements_are_same = std::all_of(type_list.begin(), type_list.end(), [&checker, &type_list](auto *element) { + return checker->Relation()->IsIdenticalTo(type_list[0], element); + }); + + if (spread_type != nullptr) { + all_elements_are_same = all_elements_are_same && checker->Relation()->IsIdenticalTo(type_list[0], spread_type); + } + + // If only one type present in the tuple, that will be the holder array type. If any two not identical types + // present, primitives will be boxed, and LUB is calculated for all of them. + // That makes it possible to assign eg. `[int, int, ...int[]]` tuple type to `int[]` array type. Because a `short[]` + // array already isn't assignable to `int[]` array, that preserve that the `[int, short, ...int[]]` tuple type's + // element type will be calculated to `Object[]`, which is not assignable to `int[]` array either. + if (all_elements_are_same) { + return type_list[0]; + } + + auto *const saved_relation_node = checker->Relation()->GetNode(); + checker->Relation()->SetNode(this); + + auto get_boxed_type_or_type = [&checker](checker::Type *const type) { + auto *const boxed_type = checker->PrimitiveTypeAsETSBuiltinType(type); + return boxed_type == nullptr ? type : boxed_type; + }; + + checker::Type *lub_type = get_boxed_type_or_type(type_list[0]); + + for (std::size_t idx = 1; idx < type_list.size(); ++idx) { + lub_type = checker->FindLeastUpperBound(lub_type, get_boxed_type_or_type(type_list[idx])); + } + + if (spread_type != nullptr) { + lub_type = checker->FindLeastUpperBound(lub_type, get_boxed_type_or_type(spread_type)); + } + + checker->Relation()->SetNode(saved_relation_node); + + return lub_type; +} + +checker::Type *ETSTuple::GetType(checker::ETSChecker *const checker) +{ + if (TsType() != nullptr) { + return TsType(); + } + + ArenaVector type_list(checker->Allocator()->Adapter()); + + for (auto *const type_annotation : GetTupleTypeAnnotationsList()) { + auto *const checked_type = checker->GetTypeFromTypeAnnotation(type_annotation); + type_list.emplace_back(checked_type); + } + + if (HasSpreadType()) { + ASSERT(spread_type_->IsTSArrayType()); + auto *const array_type = spread_type_->GetType(checker); + ASSERT(array_type->IsETSArrayType()); + spread_type_->SetTsType(array_type->AsETSArrayType()->ElementType()); + } + + auto *const spread_element_type = spread_type_ != nullptr ? spread_type_->TsType() : nullptr; + + auto *const tuple_type = checker->Allocator()->New( + type_list, CalculateLUBForTuple(checker, type_list, spread_element_type), spread_element_type); + + SetTsType(tuple_type); + return TsType(); +} + +} // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ets/etsTuple.h b/ets2panda/ir/ets/etsTuple.h new file mode 100644 index 0000000000000000000000000000000000000000..5b4b28ddfe9d4b2ac19c2305015a1d23edf022c8 --- /dev/null +++ b/ets2panda/ir/ets/etsTuple.h @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_IR_ETS_TUPLE_H +#define ES2PANDA_IR_ETS_TUPLE_H + +#include "ir/typeNode.h" + +namespace panda::es2panda::ir { + +class ETSTuple : public TypeNode { +public: + using TupleSizeType = uint32_t; + + explicit ETSTuple(ArenaAllocator *const allocator) + : TypeNode(AstNodeType::ETS_TUPLE), type_annotation_list_(allocator->Adapter()) + { + } + + explicit ETSTuple(ArenaAllocator *const allocator, const TupleSizeType size) + : TypeNode(AstNodeType::ETS_TUPLE), type_annotation_list_(allocator->Adapter()), size_(size) + { + } + explicit ETSTuple(const ArenaVector &type_list) + : TypeNode(AstNodeType::ETS_TUPLE), + type_annotation_list_(type_list), + size_(static_cast(type_list.size())) + { + } + + [[nodiscard]] TupleSizeType GetTupleSize() const + { + return size_; + } + + [[nodiscard]] ArenaVector GetTupleTypeAnnotationsList() const + { + return type_annotation_list_; + } + + [[nodiscard]] bool HasSpreadType() const + { + return spread_type_ != nullptr; + } + + void SetSpreadType(TypeNode *const new_spread_type) + { + spread_type_ = new_spread_type; + } + + void SetTypeAnnotationsList(const ArenaVector &type_node_list) + { + type_annotation_list_ = type_node_list; + } + + 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; + checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + + checker::Type *CalculateLUBForTuple(checker::ETSChecker *checker, ArenaVector &type_list, + checker::Type *spread_type); + +private: + ArenaVector type_annotation_list_; + TypeNode *spread_type_ {}; + TupleSizeType size_ {0}; +}; + +} // namespace panda::es2panda::ir + +#endif /* ES2PANDA_IR_ETS_TUPLE_H */ diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index a29a2de739e4ffe7f6e56282530f24668e08c445..e620acd9eda9e729a7553f2c251ec7910c5e1d63 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -15,21 +15,21 @@ #include "arrayExpression.h" -#include "ir/base/decorator.h" -#include "util/helpers.h" -#include "checker/TSchecker.h" #include "checker/ETSchecker.h" +#include "checker/TSchecker.h" +#include "checker/ets/castingContext.h" #include "checker/ets/typeRelationContext.h" #include "checker/ts/destructuringContext.h" -#include "compiler/base/literals.h" -#include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" -#include "ir/typeNode.h" +#include "ir/base/decorator.h" #include "ir/base/spreadElement.h" -#include "ir/expressions/identifier.h" #include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/identifier.h" #include "ir/expressions/objectExpression.h" +#include "ir/typeNode.h" +#include "util/helpers.h" namespace panda::es2panda::ir { ArrayExpression::ArrayExpression([[maybe_unused]] Tag const tag, ArrayExpression const &other, @@ -206,164 +206,17 @@ void ArrayExpression::Dump(ir::AstDumper *dumper) const void ArrayExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(pg); - compiler::VReg array_obj = pg->AllocReg(); - - pg->CreateArray(this, elements_, array_obj); + pg->GetAstCompiler()->Compile(this); } void ArrayExpression::Compile(compiler::ETSGen *const etsg) const { - const compiler::RegScope rs(etsg); - - const auto arr = etsg->AllocReg(); - const auto dim = etsg->AllocReg(); - - const compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); - etsg->LoadAccumulatorInt(this, static_cast(elements_.size())); - etsg->StoreAccumulator(this, dim); - etsg->NewArray(this, arr, dim, TsType()); - - const auto index_reg = etsg->AllocReg(); - for (std::uint32_t i = 0; i < elements_.size(); ++i) { - const auto *const expr = elements_[i]; - etsg->LoadAccumulatorInt(this, i); - etsg->StoreAccumulator(this, index_reg); - - const compiler::TargetTypeContext ttctx2(etsg, preferred_type_); - if (!etsg->TryLoadConstantExpression(expr)) { - expr->Compile(etsg); - } - - etsg->ApplyConversion(expr, nullptr); - etsg->ApplyConversion(expr); - etsg->StoreArrayElement(this, arr, index_reg, TsType()->AsETSArrayType()->ElementType()); - } - - etsg->LoadAccumulator(this, arr); -} - -void GetSpreadElementType(checker::TSChecker *checker, checker::Type *spread_type, - ArenaVector &element_types, const lexer::SourcePosition &loc) -{ - bool in_const_context = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); - - if (spread_type->IsObjectType() && spread_type->AsObjectType()->IsTupleType()) { - ArenaVector tuple_element_types(checker->Allocator()->Adapter()); - checker::TupleType *spread_tuple = spread_type->AsObjectType()->AsTupleType(); - - for (auto *it : spread_tuple->Properties()) { - if (in_const_context) { - element_types.push_back(it->TsType()); - continue; - } - - tuple_element_types.push_back(it->TsType()); - } - - if (in_const_context) { - return; - } - - element_types.push_back(checker->CreateUnionType(std::move(tuple_element_types))); - return; - } - - if (spread_type->IsUnionType()) { - ArenaVector spread_types(checker->Allocator()->Adapter()); - bool throw_error = false; - - for (auto *type : spread_type->AsUnionType()->ConstituentTypes()) { - if (type->IsArrayType()) { - spread_types.push_back(type->AsArrayType()->ElementType()); - continue; - } - - if (type->IsObjectType() && type->AsObjectType()->IsTupleType()) { - checker::TupleType *tuple = type->AsObjectType()->AsTupleType(); - - for (auto *it : tuple->Properties()) { - spread_types.push_back(it->TsType()); - } - - continue; - } - - throw_error = true; - break; - } - - if (!throw_error) { - element_types.push_back(checker->CreateUnionType(std::move(spread_types))); - return; - } - } - - checker->ThrowTypeError( - {"Type '", spread_type, "' must have a '[Symbol.iterator]()' method that returns an iterator."}, loc); + etsg->GetAstCompiler()->Compile(this); } checker::Type *ArrayExpression::Check(checker::TSChecker *checker) { - ArenaVector element_types(checker->Allocator()->Adapter()); - ArenaVector element_flags(checker->Allocator()->Adapter()); - bool in_const_context = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); - bool create_tuple = checker->HasStatus(checker::CheckerStatus::FORCE_TUPLE); - - for (auto *it : elements_) { - if (it->IsSpreadElement()) { - checker::Type *spread_type = it->AsSpreadElement()->Argument()->Check(checker); - - if (spread_type->IsArrayType()) { - element_types.push_back(in_const_context ? spread_type : spread_type->AsArrayType()->ElementType()); - element_flags.push_back(checker::ElementFlags::VARIADIC); - continue; - } - - GetSpreadElementType(checker, spread_type, element_types, it->Start()); - element_flags.push_back(checker::ElementFlags::REST); - continue; - } - - checker::Type *element_type = it->Check(checker); - - if (!in_const_context) { - element_type = checker->GetBaseTypeOfLiteralType(element_type); - } - - element_flags.push_back(checker::ElementFlags::REQUIRED); - element_types.push_back(element_type); - } - - if (in_const_context || create_tuple) { - checker::ObjectDescriptor *desc = checker->Allocator()->New(checker->Allocator()); - uint32_t index = 0; - - for (auto it = element_types.begin(); it != element_types.end(); it++, index++) { - util::StringView member_index = util::Helpers::ToStringView(checker->Allocator(), index); - varbinder::LocalVariable *tuple_member = varbinder::Scope::CreateVar( - checker->Allocator(), member_index, varbinder::VariableFlags::PROPERTY, nullptr); - - if (in_const_context) { - tuple_member->AddFlag(varbinder::VariableFlags::READONLY); - } - - tuple_member->SetTsType(*it); - desc->properties.push_back(tuple_member); - } - - return checker->CreateTupleType(desc, std::move(element_flags), checker::ElementFlags::REQUIRED, index, index, - in_const_context); - } - - checker::Type *array_element_type = nullptr; - if (element_types.empty()) { - array_element_type = checker->GlobalAnyType(); - } else { - array_element_type = checker->CreateUnionType(std::move(element_types)); - } - - return checker->Allocator()->New(array_element_type); + return checker->GetAnalyzer()->Check(this); } checker::Type *ArrayExpression::CheckPattern(checker::TSChecker *checker) @@ -477,39 +330,40 @@ checker::Type *ArrayExpression::CheckPattern(checker::TSChecker *checker) false); } -checker::Type *ArrayExpression::Check(checker::ETSChecker *checker) +void ArrayExpression::HandleNestedArrayExpression(checker::ETSChecker *const checker, + ArrayExpression *const current_element, const bool is_array, + const bool is_preferred_tuple, const std::size_t idx) { - if (TsType() != nullptr) { - return TsType(); - } + if (is_preferred_tuple) { + current_element->SetPreferredType(is_array ? preferred_type_ + : preferred_type_->AsETSTupleType()->GetTypeAtIndex(idx)); - if (!elements_.empty()) { - if (preferred_type_ == nullptr) { - preferred_type_ = elements_[0]->Check(checker); + if (current_element->GetPreferredType()->IsETSTupleType()) { + checker->ValidateTupleMinElementSize(current_element, + current_element->GetPreferredType()->AsETSTupleType()); } - for (auto *element : elements_) { - if (element->IsArrayExpression() && preferred_type_->IsETSArrayType()) { - element->AsArrayExpression()->SetPreferredType(preferred_type_->AsETSArrayType()->ElementType()); - } - if (element->IsObjectExpression()) { - element->AsObjectExpression()->SetPreferredType(preferred_type_); - } + return; + } - checker::Type *element_type = element->Check(checker); - checker::AssignmentContext(checker->Relation(), element, element_type, preferred_type_, element->Start(), - {"Array element type '", element_type, "' is not assignable to explicit type '", - GetPreferredType(), "'"}); + if (preferred_type_->IsETSArrayType()) { + if (preferred_type_->AsETSArrayType()->ElementType()->IsETSTupleType()) { + checker->ValidateTupleMinElementSize(current_element, + preferred_type_->AsETSArrayType()->ElementType()->AsETSTupleType()); } + + current_element->SetPreferredType(is_array ? preferred_type_ + : preferred_type_->AsETSArrayType()->ElementType()); + return; } - if (preferred_type_ == nullptr) { - checker->ThrowTypeError("Can't resolve array type", Start()); + if (current_element->GetPreferredType() == nullptr) { + current_element->SetPreferredType(preferred_type_); } +} - SetTsType(checker->CreateETSArrayType(preferred_type_)); - auto array_type = TsType()->AsETSArrayType(); - checker->CreateBuiltinArraySignature(array_type, array_type->Rank()); - return TsType(); +checker::Type *ArrayExpression::Check(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index 85a3fedbf0adf3b29f5021ea492a9d19d9926d72..4c039467c5636617fcead0dd29fd803fb9f54b5a 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -19,6 +19,12 @@ #include "ir/expression.h" #include "ir/validationInfo.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 ArrayExpression : public AnnotatedExpression { private: @@ -48,6 +54,10 @@ public: explicit ArrayExpression(Tag tag, ArrayExpression const &other, ArenaAllocator *allocator); + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class compiler::ETSCompiler; + [[nodiscard]] const ArenaVector &Elements() const noexcept { return elements_; @@ -121,6 +131,8 @@ public: checker::Type *Check(checker::TSChecker *checker) override; checker::Type *Check(checker::ETSChecker *checker) override; checker::Type *CheckPattern(checker::TSChecker *checker); + void HandleNestedArrayExpression(checker::ETSChecker *checker, ArrayExpression *current_element, bool is_array, + bool is_preferred_tuple, std::size_t idx); private: ArenaVector decorators_; diff --git a/ets2panda/ir/expressions/assignmentExpression.cpp b/ets2panda/ir/expressions/assignmentExpression.cpp index 4c3d14510fcfa13de7075c78b778596fc9d5fa17..175f28f0ff00107c132aabdb32ee27ed377af974 100644 --- a/ets2panda/ir/expressions/assignmentExpression.cpp +++ b/ets2panda/ir/expressions/assignmentExpression.cpp @@ -121,45 +121,12 @@ void AssignmentExpression::Dump(ir::AstDumper *dumper) const void AssignmentExpression::Compile(compiler::PandaGen *pg) const { - compiler::RegScope rs(pg); - auto lref = compiler::JSLReference::Create(pg, left_, false); - - if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL || - operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL) { - compiler::PandaGen::Unimplemented(); - } - - if (operator_ == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { - right_->Compile(pg); - lref.SetValue(); - return; - } - - compiler::VReg lhs_reg = pg->AllocReg(); - - lref.GetValue(); - pg->StoreAccumulator(left_, lhs_reg); - right_->Compile(pg); - pg->Binary(this, operator_, lhs_reg); - - lref.SetValue(); + pg->GetAstCompiler()->Compile(this); } void AssignmentExpression::Compile(compiler::ETSGen *etsg) const { - // All other operations are handled in OpAssignmentLowering - ASSERT(operator_ == lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - compiler::RegScope rs(etsg); - auto lref = compiler::ETSLReference::Create(etsg, left_, false); - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - if (right_->IsNullLiteral()) { - etsg->LoadAccumulatorNull(this, left_->TsType()); - } else { - right_->Compile(etsg); - etsg->ApplyConversion(right_, TsType()); - } - lref.SetValue(); + etsg->GetAstCompiler()->Compile(this); } void AssignmentExpression::CompilePattern(compiler::PandaGen *pg) const @@ -172,138 +139,12 @@ void AssignmentExpression::CompilePattern(compiler::PandaGen *pg) const checker::Type *AssignmentExpression::Check(checker::TSChecker *checker) { - if (left_->IsArrayPattern()) { - auto saved_context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); - auto destructuring_context = checker::ArrayDestructuringContext(checker, left_, true, true, nullptr, right_); - destructuring_context.Start(); - return destructuring_context.InferredType(); - } - - if (left_->IsObjectPattern()) { - auto saved_context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); - auto destructuring_context = checker::ObjectDestructuringContext(checker, left_, true, true, nullptr, right_); - destructuring_context.Start(); - return destructuring_context.InferredType(); - } - - if (left_->IsIdentifier() && left_->AsIdentifier()->Variable() != nullptr && - left_->AsIdentifier()->Variable()->Declaration()->IsConstDecl()) { - checker->ThrowTypeError({"Cannot assign to ", left_->AsIdentifier()->Name(), " because it is a constant."}, - left_->Start()); - } - - auto *left_type = left_->Check(checker); - - if (left_type->HasTypeFlag(checker::TypeFlag::READONLY)) { - checker->ThrowTypeError("Cannot assign to this property because it is readonly.", left_->Start()); - } - - if (operator_ == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { - checker->ElaborateElementwise(left_type, right_, left_->Start()); - return checker->CheckTypeCached(right_); - } - - auto *right_type = right_->Check(checker); - - switch (operator_) { - case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: - case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: - case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: - case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: - case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { - return checker->CheckBinaryOperator(left_type, right_type, left_, right_, this, operator_); - } - case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { - return checker->CheckPlusOperator(left_type, right_type, left_, right_, this, operator_); - } - case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { - checker->CheckAssignmentOperator(operator_, left_, left_type, right_type); - return right_type; - } - default: { - UNREACHABLE(); - break; - } - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *AssignmentExpression::Check([[maybe_unused]] checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - auto *left_type = left_->Check(checker); - if (left_->IsMemberExpression() && left_->AsMemberExpression()->Object()->TsType()->IsETSArrayType() && - left_->AsMemberExpression()->Property()->IsIdentifier() && - left_->AsMemberExpression()->Property()->AsIdentifier()->Name().Is("length")) { - checker->ThrowTypeError("Setting the length of an array is not permitted", left_->Start()); - } - - if (left_->IsIdentifier()) { - target_ = left_->AsIdentifier()->Variable(); - } else { - target_ = left_->AsMemberExpression()->PropVar(); - } - - if (target_ != nullptr) { - checker->ValidateUnaryOperatorOperand(target_); - } - - checker::Type *source_type {}; - ir::Expression *relation_node = right_; - switch (operator_) { - case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: - case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: - case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: - case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: - case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: - case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { - std::tie(std::ignore, operation_type_) = - checker->CheckBinaryOperator(left_, right_, this, operator_, Start(), true); - - auto unboxed_left = checker->ETSBuiltinTypeAsPrimitiveType(left_type); - source_type = unboxed_left == nullptr ? left_type : unboxed_left; - - relation_node = this; - break; - } - case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { - if (left_type->IsETSArrayType() && right_->IsArrayExpression()) { - right_->AsArrayExpression()->SetPreferredType(left_type->AsETSArrayType()->ElementType()); - } - if (right_->IsObjectExpression()) { - right_->AsObjectExpression()->SetPreferredType(left_type); - } - - source_type = right_->Check(checker); - break; - } - default: { - UNREACHABLE(); - break; - } - } - - checker::AssignmentContext(checker->Relation(), relation_node, source_type, left_type, right_->Start(), - {"Initializers type is not assignable to the target type"}); - - SetTsType(left_->TsType()); - return TsType(); + return checker->GetAnalyzer()->Check(this); } AssignmentExpression::AssignmentExpression([[maybe_unused]] Tag const tag, AssignmentExpression const &other, diff --git a/ets2panda/ir/expressions/assignmentExpression.h b/ets2panda/ir/expressions/assignmentExpression.h index dc1542c4b4322c808cea071419d5c3f0c4a03213..32d0669b1ae5ffaa1c8815079dfa5df7844c327b 100644 --- a/ets2panda/ir/expressions/assignmentExpression.h +++ b/ets2panda/ir/expressions/assignmentExpression.h @@ -18,7 +18,9 @@ #include "ir/expression.h" #include "lexer/token/tokenType.h" - +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class AssignmentExpression : public Expression { private: @@ -45,6 +47,9 @@ public: explicit AssignmentExpression(Tag tag, AssignmentExpression const &other, Expression *left, Expression *right); + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + [[nodiscard]] const Expression *Left() const noexcept { return left_; diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index 34f5fff812b1b6d319846bd8caa1a144b01a75cd..1913c2e1a1106f8be10bed070f2da6cdf2be1c27 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -16,14 +16,10 @@ #include "identifier.h" #include "varbinder/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) @@ -97,85 +93,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->VarBinder()->LambdaObjects().find(this); - if (lambda != etsg->VarBinder()->LambdaObjects().end()) { - etsg->CreateLambdaObjectFromIdentReference(this, lambda->second.first); - return; - } - - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - ASSERT(variable_ != nullptr); - if (!variable_->HasFlag(varbinder::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 varbinder::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)); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/identifier.h b/ets2panda/ir/expressions/identifier.h index 2d3e4394a840cf497f1cc4d493ad07a2a6f027d1..8f00441d133d7b7a95c74135c0ebab048f38d2c2 100644 --- a/ets2panda/ir/expressions/identifier.h +++ b/ets2panda/ir/expressions/identifier.h @@ -203,10 +203,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/ets2panda/ir/expressions/importExpression.cpp b/ets2panda/ir/expressions/importExpression.cpp index d9b39dcd391d6028b91e9e4243710f49e5bce488..c9d711027c00c9b54372f549cb3d629bcba390be 100644 --- a/ets2panda/ir/expressions/importExpression.cpp +++ b/ets2panda/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/ets2panda/ir/expressions/importExpression.h b/ets2panda/ir/expressions/importExpression.h index 5b37ae04ee7bf7422d017674f5b2e7efe4ec24ee..555ce71d82afc05dd9ccb50dcd0fe35796bcebc3 100644 --- a/ets2panda/ir/expressions/importExpression.h +++ b/ets2panda/ir/expressions/importExpression.h @@ -40,9 +40,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/ets2panda/ir/expressions/literals/bigIntLiteral.cpp b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp index 5887c20cd73cb0fc8aebd1a34de9e631d1e5d146..b721e9db21a5c78a8259908b7e0975262a2ca0ba 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp +++ b/ets2panda/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/ets2panda/ir/expressions/literals/bigIntLiteral.h b/ets2panda/ir/expressions/literals/bigIntLiteral.h index 32d4c40d30351f22165c52ebadbaa4c55e770d4e..a1555218d8c3a3392cfb3efb89145e27d6c47322 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.h +++ b/ets2panda/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/ets2panda/ir/expressions/literals/booleanLiteral.cpp b/ets2panda/ir/expressions/literals/booleanLiteral.cpp index d73eed1c05f8c58868b7de42bc5e2e452b273e1e..1eb3eee725f0a60ea9df530ab55b7667cfb219b4 100644 --- a/ets2panda/ir/expressions/literals/booleanLiteral.cpp +++ b/ets2panda/ir/expressions/literals/booleanLiteral.cpp @@ -32,25 +32,22 @@ void BooleanLiteral::Dump(ir::AstDumper *dumper) const void BooleanLiteral::Compile(compiler::PandaGen *pg) const { - pg->LoadConst(this, boolean_ ? compiler::Constant::JS_TRUE : compiler::Constant::JS_FALSE); + pg->GetAstCompiler()->Compile(this); } void BooleanLiteral::Compile(compiler::ETSGen *etsg) const { - etsg->LoadAccumulatorBoolean(this, boolean_); + etsg->GetAstCompiler()->Compile(this); } checker::Type *BooleanLiteral::Check(checker::TSChecker *checker) { - return boolean_ ? checker->GlobalTrueType() : checker->GlobalFalseType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *BooleanLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) { - if (TsType() == nullptr) { - SetTsType(checker->CreateETSBooleanType(boolean_)); - } - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/literals/charLiteral.cpp b/ets2panda/ir/expressions/literals/charLiteral.cpp index 4f333ee45fda52941941b61b3ec75a9600bee506..0a6adcf98d4e1c3056de72fcd47c9af2f197e251 100644 --- a/ets2panda/ir/expressions/literals/charLiteral.cpp +++ b/ets2panda/ir/expressions/literals/charLiteral.cpp @@ -15,6 +15,7 @@ #include "charLiteral.h" +#include "checker/TSchecker.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "checker/ETSchecker.h" @@ -31,24 +32,24 @@ void CharLiteral::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "CharLiteral"}, {"value", char_}}); } -void CharLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void CharLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} void CharLiteral::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - etsg->LoadAccumulatorChar(this, char_); + etsg->GetAstCompiler()->Compile(this); } checker::Type *CharLiteral::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *CharLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) { - if (TsType() == nullptr) { - SetTsType(checker->Allocator()->New(char_)); - } - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index c1e1349b8c9de0c9e036c48c9ee43c707164716b..30a8ce16a6a1499257e8c3611357a67fa78c115e 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -15,9 +15,10 @@ #include "memberExpression.h" -#include "compiler/core/pandagen.h" -#include "compiler/core/ETSGen.h" #include "checker/TSchecker.h" +#include "checker/ets/castingContext.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" namespace panda::es2panda::ir { MemberExpression::MemberExpression([[maybe_unused]] Tag const tag, MemberExpression const &other, @@ -99,9 +100,7 @@ void MemberExpression::CompileToRegs(compiler::PandaGen *pg, compiler::VReg obje void MemberExpression::Compile(compiler::PandaGen *pg) const { - object_->Compile(pg); - pg->OptionalChainCheck(IsOptional(), compiler::VReg::Invalid()); - LoadRhs(pg); + pg->GetAstCompiler()->Compile(this); } void MemberExpression::CompileToReg(compiler::PandaGen *pg, compiler::VReg obj_reg) const @@ -112,355 +111,19 @@ void MemberExpression::CompileToReg(compiler::PandaGen *pg, compiler::VReg obj_r LoadRhs(pg); } -bool MemberExpression::CompileComputed(compiler::ETSGen *etsg) const -{ - if (computed_) { - auto *const object_type = etsg->Checker()->GetNonNullishType(object_->TsType()); - - auto ottctx = compiler::TargetTypeContext(etsg, object_->TsType()); - etsg->CompileAndCheck(object_); - - auto const load_element = [this, etsg, object_type]() { - compiler::VReg obj_reg = etsg->AllocReg(); - etsg->StoreAccumulator(this, obj_reg); - - etsg->CompileAndCheck(property_); - etsg->ApplyConversion(property_, property_->TsType()); - - auto ttctx = compiler::TargetTypeContext(etsg, OptionalType()); - - if (object_type->IsETSDynamicType()) { - auto lang = object_type->AsETSDynamicType()->Language(); - etsg->LoadElementDynamic(this, obj_reg, lang); - } else { - etsg->LoadArrayElement(this, obj_reg); - } - }; - - etsg->EmitMaybeOptional(this, load_element, IsOptional()); - return true; - } - return false; -} - void MemberExpression::Compile(compiler::ETSGen *etsg) const { - auto lambda = etsg->VarBinder()->LambdaObjects().find(this); - if (lambda != etsg->VarBinder()->LambdaObjects().end()) { - etsg->CreateLambdaObjectFromMemberReference(this, object_, lambda->second.first); - etsg->SetAccumulatorType(TsType()); - return; - } - - compiler::RegScope rs(etsg); - - auto *const object_type = etsg->Checker()->GetNonNullishType(object_->TsType()); - - if (CompileComputed(etsg)) { - return; - } - - auto &prop_name = property_->AsIdentifier()->Name(); - - if (object_type->IsETSArrayType() && prop_name.Is("length")) { - auto ottctx = compiler::TargetTypeContext(etsg, object_type); - etsg->CompileAndCheck(object_); - - auto const load_length = [this, etsg]() { - compiler::VReg obj_reg = etsg->AllocReg(); - etsg->StoreAccumulator(this, obj_reg); - - auto ttctx = compiler::TargetTypeContext(etsg, OptionalType()); - etsg->LoadArrayLength(this, obj_reg); - etsg->ApplyConversion(this, TsType()); - }; - - etsg->EmitMaybeOptional(this, load_length, IsOptional()); - return; - } - - if (object_type->IsETSEnumType() || object_type->IsETSStringEnumType()) { - auto const *const enum_interface = [object_type, this]() -> checker::ETSEnumInterface const * { - if (object_type->IsETSEnumType()) { - return OptionalType()->AsETSEnumType(); - } - return OptionalType()->AsETSStringEnumType(); - }(); - - auto ottctx = compiler::TargetTypeContext(etsg, object_type); - auto ttctx = compiler::TargetTypeContext(etsg, OptionalType()); - etsg->LoadAccumulatorInt(this, enum_interface->GetOrdinal()); - return; - } - - if (etsg->Checker()->IsVariableStatic(prop_var_)) { - auto ttctx = compiler::TargetTypeContext(etsg, OptionalType()); - - if (prop_var_->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { - checker::Signature *sig = prop_var_->TsType()->AsETSFunctionType()->FindGetter(); - etsg->CallStatic0(this, sig->InternalName()); - etsg->SetAccumulatorType(TsType()); - return; - } - - util::StringView full_name = etsg->FormClassPropReference(object_->TsType()->AsETSObjectType(), prop_name); - etsg->LoadStaticProperty(this, OptionalType(), full_name); - return; - } - - auto ottctx = compiler::TargetTypeContext(etsg, object_->TsType()); - etsg->CompileAndCheck(object_); - - auto const load_property = [this, etsg, prop_name, object_type]() { - etsg->ApplyConversion(object_); - compiler::VReg obj_reg = etsg->AllocReg(); - etsg->StoreAccumulator(this, obj_reg); - - auto ttctx = compiler::TargetTypeContext(etsg, OptionalType()); - - 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(TsType()); - } else if (object_type->IsETSDynamicType()) { - auto lang = object_type->AsETSDynamicType()->Language(); - etsg->LoadPropertyDynamic(this, OptionalType(), obj_reg, prop_name, lang); - } else if (object_type->IsETSUnionType()) { - etsg->LoadUnionProperty(this, OptionalType(), IsGenericField(), obj_reg, prop_name); - } else { - const auto full_name = etsg->FormClassPropReference(object_type->AsETSObjectType(), prop_name); - etsg->LoadProperty(this, OptionalType(), IsGenericField(), obj_reg, full_name); - } - }; - - etsg->EmitMaybeOptional(this, load_property, IsOptional()); + 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(); - } - } - } - - varbinder::Variable *prop = checker->GetPropertyOfType(base_type, property_->AsIdentifier()->Name()); - - if (prop != nullptr) { - checker::Type *prop_type = checker->GetTypeOfVariable(prop); - if (prop->HasFlag(varbinder::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; -} - -std::pair MemberExpression::ResolveEnumMember(checker::ETSChecker *checker, - checker::Type *type) const -{ - auto const *const enum_interface = [type]() -> checker::ETSEnumInterface const * { - if (type->IsETSEnumType()) { - return type->AsETSEnumType(); - } - return type->AsETSStringEnumType(); - }(); - - if (parent_->Type() == ir::AstNodeType::CALL_EXPRESSION && parent_->AsCallExpression()->Callee() == this) { - return {enum_interface->LookupMethod(checker, object_, property_->AsIdentifier()), nullptr}; - } - - auto *const literal_type = enum_interface->LookupConstant(checker, object_, property_->AsIdentifier()); - return {literal_type, literal_type->GetMemberVar()}; -} - -std::pair MemberExpression::ResolveObjectMember( - checker::ETSChecker *checker) const -{ - auto resolve_res = checker->ResolveMemberReference(this, obj_type_); - switch (resolve_res.size()) { - case 1U: { - if (resolve_res[0]->Kind() == checker::ResolvedKind::PROPERTY) { - auto var = resolve_res[0]->Variable()->AsLocalVariable(); - checker->ValidatePropertyAccess(var, obj_type_, property_->Start()); - return {checker->GetTypeOfVariable(var), var}; - } - return {checker->GetTypeOfVariable(resolve_res[0]->Variable()), nullptr}; - } - case 2U: { - // ETSExtensionFuncHelperType(class_method_type, extension_method_type) - auto *resolved_type = checker->CreateETSExtensionFuncHelperType( - checker->GetTypeOfVariable(resolve_res[1]->Variable())->AsETSFunctionType(), - checker->GetTypeOfVariable(resolve_res[0]->Variable())->AsETSFunctionType()); - return {resolved_type, nullptr}; - } - default: { - UNREACHABLE(); - } - } -} - -checker::Type *MemberExpression::CheckUnionMember(checker::ETSChecker *checker, checker::Type *base_type) -{ - auto *const union_type = base_type->AsETSUnionType(); - checker::Type *common_prop_type = nullptr; - auto const add_prop_type = [this, checker, &common_prop_type](checker::Type *member_type) { - if (common_prop_type != nullptr && common_prop_type != member_type) { - checker->ThrowTypeError("Member type must be the same for all union objects.", Start()); - } - common_prop_type = member_type; - }; - for (auto *const type : union_type->ConstituentTypes()) { - if (type->IsETSObjectType()) { - SetObjectType(type->AsETSObjectType()); - add_prop_type(ResolveObjectMember(checker).first); - } else if (type->IsETSEnumType() || base_type->IsETSStringEnumType()) { - add_prop_type(ResolveEnumMember(checker, type).first); - } else { - UNREACHABLE(); - } - } - SetObjectType(union_type->GetLeastUpperBoundType(checker)->AsETSObjectType()); - return common_prop_type; -} - -checker::Type *MemberExpression::AdjustOptional(checker::ETSChecker *checker, checker::Type *type) -{ - SetOptionalType(type); - if (IsOptional() && Object()->TsType()->IsNullishOrNullLike()) { - checker->Relation()->SetNode(this); - type = checker->CreateOptionalResultType(type); - checker->Relation()->SetNode(nullptr); - } - SetTsType(type); - return TsType(); -} - -checker::Type *MemberExpression::CheckComputed(checker::ETSChecker *checker, checker::Type *base_type) -{ - if (!base_type->IsETSArrayType() && !base_type->IsETSDynamicType()) { - checker->ThrowTypeError("Indexed access expression can only be used in array type.", Object()->Start()); - } - checker->ValidateArrayIndex(Property()); - - if (Property()->IsIdentifier()) { - SetPropVar(Property()->AsIdentifier()->Variable()->AsLocalVariable()); - } else if (auto var = Property()->Variable(); (var != nullptr) && var->IsLocalVariable()) { - SetPropVar(var->AsLocalVariable()); - } - - // NOTE: apply capture conversion on this type - if (base_type->IsETSArrayType()) { - return base_type->AsETSArrayType()->ElementType(); - } - - // Dynamic - return checker->GlobalBuiltinDynamicType(base_type->AsETSDynamicType()->Language()); + return checker->GetAnalyzer()->Check(this); } checker::Type *MemberExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - auto *const left_type = object_->Check(checker); - auto *const base_type = IsOptional() ? checker->GetNonNullishType(left_type) : left_type; - if (!IsOptional()) { - checker->CheckNonNullishType(left_type, object_->Start()); - } - - if (computed_) { - return AdjustOptional(checker, CheckComputed(checker, base_type)); - } - - if (base_type->IsETSArrayType() && property_->AsIdentifier()->Name().Is("length")) { - return AdjustOptional(checker, checker->GlobalIntType()); - } - - if (base_type->IsETSObjectType()) { - SetObjectType(base_type->AsETSObjectType()); - auto [res_type, res_var] = ResolveObjectMember(checker); - SetPropVar(res_var); - return AdjustOptional(checker, res_type); - } - - if (base_type->IsETSEnumType() || base_type->IsETSStringEnumType()) { - auto [member_type, member_var] = ResolveEnumMember(checker, base_type); - SetPropVar(member_var); - return AdjustOptional(checker, member_type); - } - - if (base_type->IsETSUnionType()) { - return AdjustOptional(checker, CheckUnionMember(checker, base_type)); - } - - if (base_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - checker->Relation()->SetNode(this); - SetObjectType(checker->PrimitiveTypeAsETSBuiltinType(base_type)->AsETSObjectType()); - checker->AddBoxingUnboxingFlagToNode(this, obj_type_); - auto [res_type, res_var] = ResolveObjectMember(checker); - SetPropVar(res_var); - return AdjustOptional(checker, res_type); - } - - checker->ThrowTypeError({"Cannot access property of non-object or non-enum type"}, object_->Start()); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/memberExpression.h b/ets2panda/ir/expressions/memberExpression.h index 5deeabfe476ed3ad950d92cdf5b541477c1aa019..459084ed05be818bb84fb71cb0d2653b9952b05f 100644 --- a/ets2panda/ir/expressions/memberExpression.h +++ b/ets2panda/ir/expressions/memberExpression.h @@ -21,6 +21,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, MemberExpression const &other, 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_; @@ -139,6 +148,16 @@ public: ignore_box_ = true; } + checker::Type *GetTupleConvertedType() const noexcept + { + return tuple_converted_type_; + } + + void SetTupleConvertedType(checker::Type *conv_type) noexcept + { + tuple_converted_type_ = conv_type; + } + [[nodiscard]] bool IsPrivateReference() const noexcept; // NOLINTNEXTLINE(google-default-arguments) @@ -153,7 +172,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) : MaybeOptionalExpression(other) @@ -167,14 +186,6 @@ protected: } private: - std::pair ResolveEnumMember(checker::ETSChecker *checker, - checker::Type *type) const; - std::pair ResolveObjectMember(checker::ETSChecker *checker) const; - - checker::Type *AdjustOptional(checker::ETSChecker *checker, checker::Type *type); - checker::Type *CheckComputed(checker::ETSChecker *checker, checker::Type *base_type); - checker::Type *CheckUnionMember(checker::ETSChecker *checker, checker::Type *base_type); - void LoadRhs(compiler::PandaGen *pg) const; bool IsGenericField() const; @@ -185,6 +196,7 @@ private: bool ignore_box_ {false}; varbinder::LocalVariable *prop_var_ {}; checker::ETSObjectType *obj_type_ {}; + checker::Type *tuple_converted_type_ {}; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/newExpression.cpp b/ets2panda/ir/expressions/newExpression.cpp index ada998946446ca1934c1292feb440c4929caadf4..5959c7ffc15b3746e39404c6fb7b8d1fe3cc6ac3 100644 --- a/ets2panda/ir/expressions/newExpression.cpp +++ b/ets2panda/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() + 2U); - } 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/ets2panda/ir/expressions/newExpression.h b/ets2panda/ir/expressions/newExpression.h index 6fc447c38150639e107c1602e038233d3b586182..d2655e52a8717dbb1b1d6733f79e0bb477bd4520 100644 --- a/ets2panda/ir/expressions/newExpression.h +++ b/ets2panda/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/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index d39f3695ac9c118d2561341b11552ec063070a18..18c4b401005f3d55908422ce693442e3cbd92e85 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -229,199 +229,9 @@ void ObjectExpression::Dump(ir::AstDumper *dumper) const {"optional", AstDumper::Optional(optional_)}}); } -static compiler::Literal CreateLiteral(const ir::Property *prop, util::BitSet *compiled, size_t prop_index) -{ - compiler::Literal lit = util::Helpers::ToConstantLiteral(prop->Value()); - if (!lit.IsInvalid()) { - compiled->Set(prop_index); - return lit; - } - - if (prop->Kind() != ir::PropertyKind::INIT) { - ASSERT(prop->IsAccessor()); - return compiler::Literal::AccessorLiteral(); - } - - if (!prop->Value()->IsFunctionExpression()) { - return compiler::Literal::NullLiteral(); - } - - const ir::ScriptFunction *method = prop->Value()->AsFunctionExpression()->Function(); - - compiler::LiteralTag tag = compiler::LiteralTag::METHOD; - - if (method->IsGenerator()) { - tag = compiler::LiteralTag::GENERATOR_METHOD; - - if (method->IsAsyncFunc()) { - tag = compiler::LiteralTag::ASYNC_GENERATOR_METHOD; - } - } - - compiled->Set(prop_index); - return compiler::Literal(tag, method->Scope()->InternalName()); -} - -static bool IsLiteralBufferCompatible(const Expression *expr) -{ - if (expr->IsSpreadElement()) { - return false; - } - - const ir::Property *prop = expr->AsProperty(); - if (prop->Value()->IsFunctionExpression() && !prop->Value()->AsFunctionExpression()->Function()->IsMethod()) { - return false; - } - - return util::Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed()) && - prop->Kind() != ir::PropertyKind::PROTO; -} - -void ObjectExpression::CompileStaticProperties(compiler::PandaGen *pg, util::BitSet *compiled) const -{ - bool has_method = false; - bool seen_computed = false; - compiler::LiteralBuffer buf; - std::unordered_map prop_name_map; - - for (size_t i = 0; i < properties_.size(); i++) { - if (!IsLiteralBufferCompatible(properties_[i])) { - seen_computed = true; - continue; - } - - const ir::Property *prop = properties_[i]->AsProperty(); - - util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); - size_t buffer_pos = buf.size(); - auto res = prop_name_map.insert({name, buffer_pos}); - if (res.second) { - if (seen_computed) { - break; - } - - buf.emplace_back(name); - buf.emplace_back(); - } else { - buffer_pos = res.first->second; - } - - compiler::Literal lit = CreateLiteral(prop, compiled, i); - if (lit.IsTagMethod()) { - has_method = true; - } - - buf[buffer_pos + 1] = std::move(lit); - } - - if (buf.empty()) { - pg->CreateEmptyObject(this); - return; - } - - uint32_t buf_idx = pg->AddLiteralBuffer(std::move(buf)); - - if (has_method) { - pg->CreateObjectHavingMethod(this, buf_idx); - } else { - pg->CreateObjectWithBuffer(this, buf_idx); - } -} - -void ObjectExpression::CompileRemainingProperties(compiler::PandaGen *pg, const util::BitSet *compiled) const -{ - compiler::RegScope rs(pg); - compiler::VReg obj_reg = pg->AllocReg(); - - pg->StoreAccumulator(this, obj_reg); - - for (size_t i = 0; i < properties_.size(); i++) { - if (compiled->Test(i)) { - continue; - } - - compiler::RegScope prs(pg); - - if (properties_[i]->IsSpreadElement()) { - compiler::VReg src_obj = pg->AllocReg(); - auto const *const spread = properties_[i]->AsSpreadElement(); - - spread->Argument()->Compile(pg); - pg->StoreAccumulator(spread, src_obj); - - pg->CopyDataProperties(spread, obj_reg, src_obj); - continue; - } - - const ir::Property *prop = properties_[i]->AsProperty(); - - switch (prop->Kind()) { - case ir::PropertyKind::GET: - case ir::PropertyKind::SET: { - compiler::VReg key = pg->LoadPropertyKey(prop->Key(), prop->IsComputed()); - - compiler::VReg undef = pg->AllocReg(); - pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); - pg->StoreAccumulator(this, undef); - - compiler::VReg getter = undef; - compiler::VReg setter = undef; - - compiler::VReg accessor = pg->AllocReg(); - pg->LoadAccumulator(prop->Value(), obj_reg); - prop->Value()->Compile(pg); - pg->StoreAccumulator(prop->Value(), accessor); - - if (prop->Kind() == ir::PropertyKind::GET) { - getter = accessor; - } else { - setter = accessor; - } - - pg->DefineGetterSetterByValue(this, obj_reg, key, getter, setter, prop->IsComputed()); - break; - } - case ir::PropertyKind::INIT: { - compiler::Operand key = pg->ToOwnPropertyKey(prop->Key(), prop->IsComputed()); - - if (prop->IsMethod()) { - pg->LoadAccumulator(prop->Value(), obj_reg); - } - - prop->Value()->Compile(pg); - pg->StoreOwnProperty(this, obj_reg, key); - break; - } - case ir::PropertyKind::PROTO: { - prop->Value()->Compile(pg); - compiler::VReg proto = pg->AllocReg(); - pg->StoreAccumulator(this, proto); - - pg->SetObjectWithProto(this, proto, obj_reg); - break; - } - default: { - UNREACHABLE(); - } - } - } - - pg->LoadAccumulator(this, obj_reg); -} - void ObjectExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - if (properties_.empty()) { - pg->CreateEmptyObject(this); - return; - } - - util::BitSet compiled(properties_.size()); - CompileStaticProperties(pg, &compiled); - - if (compiled.Any(false)) { - CompileRemainingProperties(pg, &compiled); - } + pg->GetAstCompiler()->Compile(this); } checker::Type *ObjectExpression::CheckPattern(checker::TSChecker *checker) @@ -559,305 +369,18 @@ checker::Type *ObjectExpression::CheckPattern(checker::TSChecker *checker) return return_type; } -const util::StringView &GetPropertyName(const ir::Expression *key) -{ - if (key->IsIdentifier()) { - return key->AsIdentifier()->Name(); - } - - if (key->IsStringLiteral()) { - return key->AsStringLiteral()->Str(); - } - - ASSERT(key->IsNumberLiteral()); - return key->AsNumberLiteral()->Str(); -} - -varbinder::VariableFlags GetFlagsForProperty(const ir::Property *prop) -{ - if (!prop->IsMethod()) { - return varbinder::VariableFlags::PROPERTY; - } - - varbinder::VariableFlags prop_flags = varbinder::VariableFlags::METHOD; - - if (prop->IsAccessor() && prop->Kind() == PropertyKind::GET) { - prop_flags |= varbinder::VariableFlags::READONLY; - } - - return prop_flags; -} - -checker::Type *GetTypeForProperty(ir::Property *prop, checker::TSChecker *checker) -{ - if (prop->IsAccessor()) { - checker::Type *func_type = prop->Value()->Check(checker); - - if (prop->Kind() == PropertyKind::SET) { - return checker->GlobalAnyType(); - } - - ASSERT(func_type->IsObjectType() && func_type->AsObjectType()->IsFunctionType()); - return func_type->AsObjectType()->CallSignatures()[0]->ReturnType(); - } - - if (prop->IsShorthand()) { - return prop->Key()->Check(checker); - } - - return prop->Value()->Check(checker); -} - checker::Type *ObjectExpression::Check(checker::TSChecker *checker) { - checker::ObjectDescriptor *desc = checker->Allocator()->New(checker->Allocator()); - std::unordered_map all_properties_map; - bool in_const_context = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT); - ArenaVector computed_number_prop_types(checker->Allocator()->Adapter()); - ArenaVector computed_string_prop_types(checker->Allocator()->Adapter()); - bool has_computed_number_property = false; - bool has_computed_string_property = false; - bool seen_spread = false; - - for (auto *it : properties_) { - if (it->IsProperty()) { - auto *prop = it->AsProperty(); - - if (prop->IsComputed()) { - checker::Type *computed_name_type = checker->CheckComputedPropertyName(prop->Key()); - - if (computed_name_type->IsNumberType()) { - has_computed_number_property = true; - computed_number_prop_types.push_back(prop->Value()->Check(checker)); - continue; - } - - if (computed_name_type->IsStringType()) { - has_computed_string_property = true; - computed_string_prop_types.push_back(prop->Value()->Check(checker)); - continue; - } - } - - checker::Type *prop_type = GetTypeForProperty(prop, checker); - varbinder::VariableFlags flags = GetFlagsForProperty(prop); - const util::StringView &prop_name = GetPropertyName(prop->Key()); - - auto *member_var = varbinder::Scope::CreateVar(checker->Allocator(), prop_name, flags, it); - - if (in_const_context) { - member_var->AddFlag(varbinder::VariableFlags::READONLY); - } else { - prop_type = checker->GetBaseTypeOfLiteralType(prop_type); - } - - member_var->SetTsType(prop_type); - - if (prop->Key()->IsNumberLiteral()) { - member_var->AddFlag(varbinder::VariableFlags::NUMERIC_NAME); - } - - varbinder::LocalVariable *found_member = desc->FindProperty(prop_name); - all_properties_map.insert({prop_name, it->Start()}); - - if (found_member != nullptr) { - found_member->SetTsType(prop_type); - continue; - } - - desc->properties.push_back(member_var); - continue; - } - - ASSERT(it->IsSpreadElement()); - - checker::Type *const spread_type = it->AsSpreadElement()->Argument()->Check(checker); - seen_spread = true; - - // NOTE: aszilagyi. handle union of object types - if (!spread_type->IsObjectType()) { - checker->ThrowTypeError("Spread types may only be created from object types.", it->Start()); - } - - for (auto *spread_prop : spread_type->AsObjectType()->Properties()) { - auto found = all_properties_map.find(spread_prop->Name()); - if (found != all_properties_map.end()) { - checker->ThrowTypeError( - {found->first, " is specified more than once, so this usage will be overwritten."}, found->second); - } - - varbinder::LocalVariable *found_member = desc->FindProperty(spread_prop->Name()); - - if (found_member != nullptr) { - found_member->SetTsType(spread_prop->TsType()); - continue; - } - - desc->properties.push_back(spread_prop); - } - } - - if (!seen_spread && (has_computed_number_property || has_computed_string_property)) { - for (auto *it : desc->properties) { - computed_string_prop_types.push_back(it->TsType()); - - if (has_computed_number_property && it->HasFlag(varbinder::VariableFlags::NUMERIC_NAME)) { - computed_number_prop_types.push_back(it->TsType()); - } - } - - if (has_computed_number_property) { - desc->number_index_info = checker->Allocator()->New( - checker->CreateUnionType(std::move(computed_number_prop_types)), "x", in_const_context); - } - - if (has_computed_string_property) { - desc->string_index_info = checker->Allocator()->New( - checker->CreateUnionType(std::move(computed_string_prop_types)), "x", in_const_context); - } - } - - checker::Type *return_type = checker->Allocator()->New(desc); - return_type->AsObjectType()->AddObjectFlag(checker::ObjectFlags::RESOLVED_MEMBERS | - checker::ObjectFlags::CHECK_EXCESS_PROPS); - return return_type; + return checker->GetAnalyzer()->Check(this); } void ObjectExpression::Compile(compiler::ETSGen *etsg) const { - compiler::RegScope rs {etsg}; - checker::ETSObjectType const *obj_type = TsType()->AsETSObjectType(); - compiler::VReg obj_reg = etsg->AllocReg(); - if (TsType()->IsETSDynamicType()) { - auto *signature_info = etsg->Allocator()->New(etsg->Allocator()); - auto *create_obj_sig = etsg->Allocator()->New( - signature_info, nullptr, compiler::Signatures::BUILTIN_JSRUNTIME_CREATE_OBJECT); - compiler::VReg dummy_reg = compiler::VReg::RegStart(); - etsg->CallDynamic(this, dummy_reg, dummy_reg, create_obj_sig, - ArenaVector(etsg->Allocator()->Adapter())); - } else { - checker::Signature *empty_sig = nullptr; - for (checker::Signature *sig : obj_type->ConstructSignatures()) { - if (sig->Params().empty()) { - empty_sig = sig; - break; - } - } - if (empty_sig == nullptr) { // Would have already thrown in the checker. - UNREACHABLE(); - } - etsg->InitObject(this, empty_sig, ArenaVector(etsg->Allocator()->Adapter())); - } - etsg->SetAccumulatorType(TsType()); - etsg->StoreAccumulator(this, obj_reg); - - for (Expression *prop_expr : Properties()) { - ASSERT(prop_expr->IsProperty()); - Property *prop = prop_expr->AsProperty(); - Expression *key = prop->Key(); - Expression *value = prop->Value(); - - util::StringView pname; - if (key->IsStringLiteral()) { - pname = key->AsStringLiteral()->Str(); - } else if (key->IsIdentifier()) { - pname = key->AsIdentifier()->Name(); - } else { - UNREACHABLE(); - } - - value->Compile(etsg); - etsg->ApplyConversion(value, key->TsType()); - if (TsType()->IsETSDynamicType()) { - etsg->StorePropertyDynamic(this, value->TsType(), obj_reg, pname, TsType()->AsETSDynamicType()->Language()); - } else { - etsg->StoreProperty(this, key->TsType(), obj_reg, pname); - } - } - - etsg->LoadAccumulator(this, obj_reg); + etsg->GetAstCompiler()->Compile(this); } checker::Type *ObjectExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - if (PreferredType() == nullptr) { - checker->ThrowTypeError({"need to specify target type for class composite"}, Start()); - } - if (!PreferredType()->IsETSObjectType()) { - checker->ThrowTypeError({"target type for class composite needs to be an object type"}, Start()); - } - - if (PreferredType()->IsETSDynamicType()) { - for (Expression *prop_expr : Properties()) { - ASSERT(prop_expr->IsProperty()); - Property *prop = prop_expr->AsProperty(); - Expression *value = prop->Value(); - value->Check(checker); - ASSERT(value->TsType()); - } - - SetTsType(PreferredType()); - return PreferredType(); - } - - checker::ETSObjectType *obj_type = PreferredType()->AsETSObjectType(); - if (obj_type->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT | checker::ETSObjectFlags::INTERFACE)) { - checker->ThrowTypeError({"target type for class composite ", obj_type->Name(), " is not instantiable"}, - Start()); - } - - bool have_empty_constructor = false; - for (checker::Signature *sig : obj_type->ConstructSignatures()) { - if (sig->Params().empty()) { - have_empty_constructor = true; - checker->ValidateSignatureAccessibility(obj_type, sig, Start()); - break; - } - } - if (!have_empty_constructor) { - checker->ThrowTypeError({"type ", obj_type->Name(), " has no parameterless constructor"}, Start()); - } - - for (Expression *prop_expr : Properties()) { - ASSERT(prop_expr->IsProperty()); - Property *prop = prop_expr->AsProperty(); - Expression *key = prop->Key(); - Expression *value = prop->Value(); - - util::StringView pname; - if (key->IsStringLiteral()) { - pname = key->AsStringLiteral()->Str(); - } else if (key->IsIdentifier()) { - pname = key->AsIdentifier()->Name(); - } else { - checker->ThrowTypeError({"key in class composite should be either identifier or string literal"}, Start()); - } - varbinder::LocalVariable *lv = obj_type->GetProperty( - pname, checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | checker::PropertySearchFlags::SEARCH_IN_BASE); - if (lv == nullptr) { - checker->ThrowTypeError({"type ", obj_type->Name(), " has no property named ", pname}, prop_expr->Start()); - } - checker->ValidatePropertyAccess(lv, obj_type, prop_expr->Start()); - if (lv->HasFlag(varbinder::VariableFlags::READONLY)) { - checker->ThrowTypeError({"cannot assign to readonly property ", pname}, prop_expr->Start()); - } - - auto *prop_type = checker->GetTypeOfVariable(lv); - key->SetTsType(prop_type); - - if (value->IsObjectExpression()) { - value->AsObjectExpression()->SetPreferredType(prop_type); - } - value->SetTsType(value->Check(checker)); - checker::AssignmentContext(checker->Relation(), value, value->TsType(), prop_type, value->Start(), - {"value type is not assignable to the property type"}); - } - - SetTsType(obj_type); - return obj_type; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/objectExpression.h b/ets2panda/ir/expressions/objectExpression.h index 3499814cca3c61b1c81f50e55ea9ade5a66f1ade..aeb73e1708a5d221fad23b5a85a8433d53cf5b88 100644 --- a/ets2panda/ir/expressions/objectExpression.h +++ b/ets2panda/ir/expressions/objectExpression.h @@ -19,7 +19,9 @@ #include "varbinder/variable.h" #include "ir/expression.h" #include "ir/validationInfo.h" - +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::util { class BitSet; } // namespace panda::es2panda::util @@ -44,9 +46,11 @@ public: trailing_comma_(trailing_comma) { } - explicit ObjectExpression(Tag tag, ObjectExpression const &other, ArenaAllocator *allocator); + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + [[nodiscard]] const ArenaVector &Properties() const noexcept { return properties_; @@ -109,9 +113,6 @@ public: checker::Type *CheckPattern(checker::TSChecker *checker); private: - void CompileStaticProperties(compiler::PandaGen *pg, util::BitSet *compiled) const; - void CompileRemainingProperties(compiler::PandaGen *pg, const util::BitSet *compiled) const; - ArenaVector decorators_; ArenaVector properties_; checker::Type *preferred_type_ {}; diff --git a/ets2panda/ir/expressions/omittedExpression.cpp b/ets2panda/ir/expressions/omittedExpression.cpp index ab2a356ac6b9b8ee39d989fc697c0cf6c348091b..88634efef87cb2bc43cc23a9b3c5582b60d8b08e 100644 --- a/ets2panda/ir/expressions/omittedExpression.cpp +++ b/ets2panda/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/ets2panda/ir/expressions/omittedExpression.h b/ets2panda/ir/expressions/omittedExpression.h index 20f7f5ead9e959abb84db7903320aebd3a0c81c7..3c8116192868ef2c8a1e50ab0dd6b2610a0597e5 100644 --- a/ets2panda/ir/expressions/omittedExpression.h +++ b/ets2panda/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/ets2panda/ir/expressions/sequenceExpression.cpp b/ets2panda/ir/expressions/sequenceExpression.cpp index f855c5826d318cf7049e68b19dce7948dc290a28..477f6ef9d82bb5e8141820b6ff3daff93050dfcc 100644 --- a/ets2panda/ir/expressions/sequenceExpression.cpp +++ b/ets2panda/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) { - // NOTE: 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/ets2panda/ir/expressions/sequenceExpression.h b/ets2panda/ir/expressions/sequenceExpression.h index 79e9974db8d061a6b10ca30193b9eea37c4cf63a..727d74f63c167c8b632cd37ec1182d06446c1516 100644 --- a/ets2panda/ir/expressions/sequenceExpression.h +++ b/ets2panda/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/ets2panda/ir/expressions/superExpression.cpp b/ets2panda/ir/expressions/superExpression.cpp index b7d291a57f39b93f74a0cd3b4f45b3c238fd4904..1b5c777ab87336e5ac079d33aea69a6224c41d1b 100644 --- a/ets2panda/ir/expressions/superExpression.cpp +++ b/ets2panda/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,35 +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); // remains as long as we consider super 'super' expression - etsg->SetAccumulatorType(etsg->GetAccumulatorType()->AsETSObjectType()->SuperType()); + etsg->GetAstCompiler()->Compile(this); } checker::Type *SuperExpression::Check(checker::TSChecker *checker) { - // NOTE: 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/ets2panda/ir/expressions/superExpression.h b/ets2panda/ir/expressions/superExpression.h index 27d45416083710a98f04330679c5a7f43f2bcb7b..614c699f9a2440b68630ae117ea11f36860f3557 100644 --- a/ets2panda/ir/expressions/superExpression.h +++ b/ets2panda/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/ets2panda/ir/expressions/taggedTemplateExpression.cpp b/ets2panda/ir/expressions/taggedTemplateExpression.cpp index b68a413ab31afb6b1ea12d6e08e51467ae94f2bf..f13baf1d44905a7f1efdb674d4a21e170571bd70 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 6aeabf80f7bcebc9d807cfe829c990ec7c1e40d2..552ccb25b96b45db0a34b1715a80d574673c2b8f 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/templateLiteral.cpp b/ets2panda/ir/expressions/templateLiteral.cpp index 61c58acd1ee21815bdafb39788b142d871287703..e6bbee9f4325dc779ec174b95272b6a39decd192 100644 --- a/ets2panda/ir/expressions/templateLiteral.cpp +++ b/ets2panda/ir/expressions/templateLiteral.cpp @@ -79,43 +79,7 @@ void TemplateLiteral::Dump(ir::AstDumper *dumper) const void TemplateLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - auto quasis_it = quasis_.begin(); - auto expression_it = expressions_.begin(); - - pg->LoadAccumulatorString(this, (*quasis_it)->Raw()); - - quasis_it++; - - bool is_quais = false; - size_t total = quasis_.size() + expressions_.size(); - - compiler::RegScope rs(pg); - compiler::VReg lhs = pg->AllocReg(); - - while (total != 1) { - const ir::AstNode *node = nullptr; - - if (is_quais) { - pg->StoreAccumulator(*quasis_it, lhs); - pg->LoadAccumulatorString(this, (*quasis_it)->Raw()); - - node = *quasis_it; - quasis_it++; - } else { - const ir::Expression *element = *expression_it; - pg->StoreAccumulator(element, lhs); - - element->Compile(pg); - - node = element; - expression_it++; - } - - pg->Binary(node, lexer::TokenType::PUNCTUATOR_PLUS, lhs); - - is_quais = !is_quais; - total--; - } + pg->GetAstCompiler()->Compile(this); } checker::Type *TemplateLiteral::Check([[maybe_unused]] checker::TSChecker *checker) @@ -126,28 +90,11 @@ checker::Type *TemplateLiteral::Check([[maybe_unused]] checker::TSChecker *check void TemplateLiteral::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - etsg->BuildTemplateString(this); + etsg->GetAstCompiler()->Compile(this); } checker::Type *TemplateLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - if (quasis_.size() != expressions_.size() + 1U) { - checker->ThrowTypeError("Invalid string template expression", this->Start()); - } - - for (auto *it : expressions_) { - it->Check(checker); - } - - for (auto *it : quasis_) { - it->Check(checker); - } - - SetTsType(checker->GlobalBuiltinETSStringType()); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/thisExpression.cpp b/ets2panda/ir/expressions/thisExpression.cpp index 0c91e916486119c26058cbf27f381ee4c87ace5a..d8013b9d7a45e0dde9ab02cc9520978cf3032888 100644 --- a/ets2panda/ir/expressions/thisExpression.cpp +++ b/ets2panda/ir/expressions/thisExpression.cpp @@ -39,73 +39,22 @@ void ThisExpression::Dump(ir::AstDumper *dumper) const void ThisExpression::Compile(compiler::PandaGen *pg) const { - auto res = pg->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS); - - ASSERT(res.variable && res.variable->IsLocalVariable()); - pg->LoadAccFromLexEnv(this, res); - - const ir::ScriptFunction *func = util::Helpers::GetContainingConstructor(this); - - if (func != nullptr) { - pg->ThrowIfSuperNotCorrectCall(this, 0); - } + pg->GetAstCompiler()->Compile(this); } void ThisExpression::Compile(compiler::ETSGen *etsg) const { - etsg->LoadThis(this); + etsg->GetAstCompiler()->Compile(this); } checker::Type *ThisExpression::Check(checker::TSChecker *checker) { - // NOTE: aszilagyi - return checker->GlobalAnyType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *ThisExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - /* - example code: - ``` - class A { - prop - } - function A.method() { - let a = () => { - console.println(this.prop) - } - } - is identical to - function method(this: A) { - let a = () => { - console.println(this.prop) - } - } - ``` - here when "this" is used inside an extension function, we need to bind "this" to the first - parameter(MANDATORY_PARAM_THIS), and capture the paramter's variable other than containing class's variable - */ - auto *variable = checker->AsETSChecker()->Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS).variable; - if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) { - ASSERT(variable != nullptr); - SetTsType(variable->TsType()); - } else { - SetTsType(checker->CheckThisOrSuperAccess(this, checker->Context().ContainingClass(), "this")); - } - - if (checker->HasStatus(checker::CheckerStatus::IN_LAMBDA)) { - if (checker->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD)) { - checker->Context().AddCapturedVar(variable, this->Start()); - } else { - checker->Context().AddCapturedVar(checker->Context().ContainingClass()->Variable(), this->Start()); - } - } - - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/unaryExpression.cpp b/ets2panda/ir/expressions/unaryExpression.cpp index b9e2579f6586d106b32a2d6c45ce53ac3ee82c64..b76d05d63fed73305d93f5097bf801ae19b58776 100644 --- a/ets2panda/ir/expressions/unaryExpression.cpp +++ b/ets2panda/ir/expressions/unaryExpression.cpp @@ -45,263 +45,22 @@ void UnaryExpression::Dump(ir::AstDumper *dumper) const void UnaryExpression::Compile(compiler::PandaGen *pg) const { - switch (operator_) { - case lexer::TokenType::KEYW_DELETE: { - if (argument_->IsIdentifier()) { - auto result = pg->Scope()->Find(argument_->AsIdentifier()->Name()); - if (result.variable == nullptr || - (result.scope->IsGlobalScope() && result.variable->IsGlobalVariable())) { - compiler::RegScope rs(pg); - compiler::VReg variable = pg->AllocReg(); - compiler::VReg global = pg->AllocReg(); - - pg->LoadConst(this, compiler::Constant::JS_GLOBAL); - pg->StoreAccumulator(this, global); - - pg->LoadAccumulatorString(this, argument_->AsIdentifier()->Name()); - pg->StoreAccumulator(this, variable); - - pg->DeleteObjProperty(this, global, variable); - } else { - // Otherwise it is a local variable which can't be deleted and we just - // return false. - pg->LoadConst(this, compiler::Constant::JS_FALSE); - } - } else if (argument_->IsMemberExpression()) { - compiler::RegScope rs(pg); - compiler::VReg object = pg->AllocReg(); - compiler::VReg property = pg->AllocReg(); - - argument_->AsMemberExpression()->CompileToRegs(pg, object, property); - pg->DeleteObjProperty(this, object, property); - } else { - // compile the delete operand. - argument_->Compile(pg); - // Deleting any value or a result of an expression returns True. - pg->LoadConst(this, compiler::Constant::JS_TRUE); - } - break; - } - case lexer::TokenType::KEYW_TYPEOF: { - if (argument_->IsIdentifier()) { - const auto *ident = argument_->AsIdentifier(); - - auto res = pg->Scope()->Find(ident->Name()); - if (res.variable == nullptr) { - pg->LoadConst(this, compiler::Constant::JS_GLOBAL); - pg->LoadObjByName(this, ident->Name()); - } else { - pg->LoadVar(ident, res); - } - } else { - argument_->Compile(pg); - } - - pg->TypeOf(this); - break; - } - case lexer::TokenType::KEYW_VOID: { - argument_->Compile(pg); - pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); - break; - } - default: { - argument_->Compile(pg); - - compiler::RegScope rs(pg); - compiler::VReg operand_reg = pg->AllocReg(); - pg->StoreAccumulator(this, operand_reg); - pg->Unary(this, operator_, operand_reg); - break; - } - } + pg->GetAstCompiler()->Compile(this); } void UnaryExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - if (!etsg->TryLoadConstantExpression(argument_)) { - argument_->Compile(etsg); - } - etsg->ApplyConversion(argument_, nullptr); - etsg->Unary(this, operator_); -} - -checker::Type *UnaryExpression::CheckDeleteKeyword([[maybe_unused]] checker::TSChecker *checker) -{ - checker::Type *prop_type = argument_->Check(checker); - if (!argument_->IsMemberExpression()) { - checker->ThrowTypeError("The operand of a delete operator must be a property reference.", argument_->Start()); - } - if (prop_type->Variable()->HasFlag(varbinder::VariableFlags::READONLY)) { - checker->ThrowTypeError("The operand of a delete operator cannot be a readonly property.", argument_->Start()); - } - if (!prop_type->Variable()->HasFlag(varbinder::VariableFlags::OPTIONAL)) { - checker->ThrowTypeError("The operand of a delete operator must be a optional.", argument_->Start()); - } - return checker->GlobalBooleanType(); -} - -checker::Type *UnaryExpression::CheckLiteral([[maybe_unused]] checker::TSChecker *checker) -{ - if (!argument_->IsLiteral()) { - return nullptr; - } - - const ir::Literal *lit = argument_->AsLiteral(); - if (lit->IsNumberLiteral()) { - auto number_value = lit->AsNumberLiteral()->Number().GetDouble(); - if (operator_ == lexer::TokenType::PUNCTUATOR_PLUS) { - return checker->CreateNumberLiteralType(number_value); - } - if (operator_ == lexer::TokenType::PUNCTUATOR_MINUS) { - return checker->CreateNumberLiteralType(-number_value); - } - } else if (lit->IsBigIntLiteral() && operator_ == lexer::TokenType::PUNCTUATOR_MINUS) { - return checker->CreateBigintLiteralType(lit->AsBigIntLiteral()->Str(), true); - } - - return nullptr; + etsg->GetAstCompiler()->Compile(this); } checker::Type *UnaryExpression::Check([[maybe_unused]] checker::TSChecker *checker) { - checker::Type *operand_type = argument_->Check(checker); - - if (operator_ == lexer::TokenType::KEYW_TYPEOF) { - return operand_type; - } - - if (operator_ == lexer::TokenType::KEYW_DELETE) { - return CheckDeleteKeyword(checker); - } - - auto *res = CheckLiteral(checker); - if (res != nullptr) { - return res; - } - - switch (operator_) { - case lexer::TokenType::PUNCTUATOR_PLUS: - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::PUNCTUATOR_TILDE: { - checker->CheckNonNullType(operand_type, Start()); - // NOTE: aszilagyi. check Symbol like types - - if (operator_ == lexer::TokenType::PUNCTUATOR_PLUS) { - if (checker::TSChecker::MaybeTypeOfKind(operand_type, checker::TypeFlag::BIGINT_LIKE)) { - checker->ThrowTypeError({"Operator '+' cannot be applied to type '", operand_type, "'"}, Start()); - } - - return checker->GlobalNumberType(); - } - - return checker->GetUnaryResultType(operand_type); - } - case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { - checker->CheckTruthinessOfType(operand_type, Start()); - auto facts = operand_type->GetTypeFacts(); - if ((facts & checker::TypeFacts::TRUTHY) != 0) { - return checker->GlobalFalseType(); - } - - if ((facts & checker::TypeFacts::FALSY) != 0) { - return checker->GlobalTrueType(); - } - - return checker->GlobalBooleanType(); - } - default: { - UNREACHABLE(); - } - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *UnaryExpression::Check(checker::ETSChecker *checker) { - if (TsType() != nullptr) { - return TsType(); - } - - auto arg_type = argument_->Check(checker); - const auto is_cond_expr = operator_ == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK; - checker::Type *operand_type = checker->ApplyUnaryOperatorPromotion(arg_type, true, true, is_cond_expr); - auto unboxed_operand_type = is_cond_expr ? checker->ETSBuiltinTypeAsConditionalType(arg_type) - : checker->ETSBuiltinTypeAsPrimitiveType(arg_type); - - switch (operator_) { - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::PUNCTUATOR_PLUS: { - if (operand_type == nullptr || !operand_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->HasTypeFlag(checker::TypeFlag::CONSTANT) && - operator_ == lexer::TokenType::PUNCTUATOR_MINUS) { - SetTsType(checker->NegateNumericType(operand_type, this)); - break; - } - - SetTsType(operand_type); - break; - } - case lexer::TokenType::PUNCTUATOR_TILDE: { - if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - checker->ThrowTypeError("Bad operand type, the type of the operand must be integral type.", - argument_->Start()); - } - - if (operand_type->HasTypeFlag(checker::TypeFlag::CONSTANT)) { - SetTsType(checker->BitwiseNegateIntegralType(operand_type, this)); - break; - } - - SetTsType(operand_type); - break; - } - case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { - if (checker->IsNullLikeOrVoidExpression(argument_)) { - auto ts_type = checker->CreateETSBooleanType(true); - ts_type->AddTypeFlag(checker::TypeFlag::CONSTANT); - SetTsType(ts_type); - break; - } - - if (operand_type == nullptr || !operand_type->IsConditionalExprType()) { - checker->ThrowTypeError("Bad operand type, the type of the operand must be boolean type.", - argument_->Start()); - } - - auto expr_res = operand_type->ResolveConditionExpr(); - if (std::get<0>(expr_res)) { - auto ts_type = checker->CreateETSBooleanType(!std::get<1>(expr_res)); - ts_type->AddTypeFlag(checker::TypeFlag::CONSTANT); - SetTsType(ts_type); - break; - } - - SetTsType(checker->GlobalETSBooleanType()); - break; - } - case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR: { - SetTsType(arg_type); - break; - } - default: { - UNREACHABLE(); - break; - } - } - - if (arg_type->IsETSObjectType() && (unboxed_operand_type != nullptr) && - unboxed_operand_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - argument_->AddBoxingUnboxingFlag(checker->GetUnboxingFlag(unboxed_operand_type)); - } - - return TsType(); + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/unaryExpression.h b/ets2panda/ir/expressions/unaryExpression.h index ade78126852b73f78907de3db4bc4954627ca53e..757a8df4747c7c3ebcfbd167c4c528f80646d5b3 100644 --- a/ets2panda/ir/expressions/unaryExpression.h +++ b/ets2panda/ir/expressions/unaryExpression.h @@ -27,6 +27,8 @@ class ETSGen; namespace panda::es2panda::checker { class TSChecker; class Type; +class ETSAnalyzer; +class TSAnalyzer; } // namespace panda::es2panda::checker namespace panda::es2panda::ir { @@ -42,6 +44,9 @@ public: : Expression(AstNodeType::UNARY_EXPRESSION), argument_(argument), operator_(unary_operator) { } + // TODO (somasimon): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + friend class checker::TSAnalyzer; [[nodiscard]] lexer::TokenType OperatorType() const noexcept { @@ -63,8 +68,6 @@ public: 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 *CheckDeleteKeyword([[maybe_unused]] checker::TSChecker *checker); - checker::Type *CheckLiteral([[maybe_unused]] checker::TSChecker *checker); private: Expression *argument_; diff --git a/ets2panda/ir/expressions/updateExpression.cpp b/ets2panda/ir/expressions/updateExpression.cpp index ae49e98ae65b35975ade9f7f3a03571012e813f3..4f1fffbb898e0676b1bd06a36d184ab06b415047 100644 --- a/ets2panda/ir/expressions/updateExpression.cpp +++ b/ets2panda/ir/expressions/updateExpression.cpp @@ -24,6 +24,7 @@ #include "checker/ETSchecker.h" #include "ir/astDump.h" #include "ir/expressions/unaryExpression.h" +#include "ir/ts/tsAsExpression.h" #include "ir/expressions/identifier.h" #include "ir/expressions/memberExpression.h" @@ -45,107 +46,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 494fbaf2981e13e3c443338068176a4fb929d465..2a24e3b56ff41cae17cd6b4bfc964b2566f92318 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,11 +41,20 @@ 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_; } + [[nodiscard]] Expression *Argument() noexcept + { + return argument_; + } + [[nodiscard]] const Expression *Argument() const noexcept { return argument_; diff --git a/ets2panda/ir/expressions/yieldExpression.cpp b/ets2panda/ir/expressions/yieldExpression.cpp index 465498c428b001ee02f60fd2e9cabb698570705b..74b627b91403c2c00b821ca3a5770352941e5e17 100644 --- a/ets2panda/ir/expressions/yieldExpression.cpp +++ b/ets2panda/ir/expressions/yieldExpression.cpp @@ -15,11 +15,11 @@ #include "yieldExpression.h" +#include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" #include "compiler/function/generatorFunctionBuilder.h" #include "checker/TSchecker.h" #include "ir/astDump.h" - namespace panda::es2panda::ir { void YieldExpression::TransformChildren(const NodeTransformer &cb) { @@ -42,31 +42,22 @@ void YieldExpression::Dump(ir::AstDumper *dumper) const void YieldExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - compiler::RegScope rs(pg); - - if (argument_ != nullptr) { - argument_->Compile(pg); - } else { - pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); - } + pg->GetAstCompiler()->Compile(this); +} - if (delegate_) { - ASSERT(argument_); - pg->FuncBuilder()->YieldStar(this); - } else { - pg->FuncBuilder()->Yield(this); - } +void YieldExpression::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); } checker::Type *YieldExpression::Check([[maybe_unused]] checker::TSChecker *checker) { - // NOTE: aszilagyi. - return checker->GlobalAnyType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *YieldExpression::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/ir/expressions/yieldExpression.h b/ets2panda/ir/expressions/yieldExpression.h index 3c2f5282e2fc6549926d84443e13f0e9a8e1fc23..5847b155f7c175af2ffcbebb07b9cd43b93e0e66 100644 --- a/ets2panda/ir/expressions/yieldExpression.h +++ b/ets2panda/ir/expressions/yieldExpression.h @@ -53,6 +53,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const 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([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/opaqueTypeNode.cpp b/ets2panda/ir/opaqueTypeNode.cpp index caa23c61331bc4f76205925f84116c44f3979c7b..b09b065cb4cba3e35869a2cb44a6855fa5e8fb3b 100644 --- a/ets2panda/ir/opaqueTypeNode.cpp +++ b/ets2panda/ir/opaqueTypeNode.cpp @@ -14,8 +14,10 @@ */ #include "opaqueTypeNode.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" - namespace panda::es2panda::ir { void OpaqueTypeNode::TransformChildren([[maybe_unused]] const NodeTransformer &cb) {} @@ -26,16 +28,19 @@ void OpaqueTypeNode::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "OpaqueType"}}); } -void OpaqueTypeNode::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void OpaqueTypeNode::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} void OpaqueTypeNode::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - UNREACHABLE(); + etsg->GetAstCompiler()->Compile(this); } checker::Type *OpaqueTypeNode::Check([[maybe_unused]] checker::TSChecker *checker) { - return TsType(); + return checker->GetAnalyzer()->Check(this); } checker::Type *OpaqueTypeNode::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -50,6 +55,6 @@ checker::Type *OpaqueTypeNode::GetType([[maybe_unused]] checker::ETSChecker *che checker::Type *OpaqueTypeNode::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statements/assertStatement.cpp b/ets2panda/ir/statements/assertStatement.cpp index dd22e25631a5e9f0cb58731585230952c9379293..4b09acd2363cb58e067ae6d980f16ba92745b84f 100644 --- a/ets2panda/ir/statements/assertStatement.cpp +++ b/ets2panda/ir/statements/assertStatement.cpp @@ -48,68 +48,23 @@ void AssertStatement::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "AssertStatement"}, {"test", test_}, {"second", AstDumper::Nullish(second_)}}); } -void AssertStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void AssertStatement::ThrowError(compiler::ETSGen *const etsg) const +void AssertStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - const compiler::RegScope rs(etsg); - - if (second_ != nullptr) { - second_->Compile(etsg); - } else { - etsg->LoadAccumulatorString(this, "Assertion failed."); - } - - const auto message = etsg->AllocReg(); - etsg->StoreAccumulator(this, message); - - const auto assertion_error = etsg->AllocReg(); - etsg->NewObject(this, assertion_error, compiler::Signatures::BUILTIN_ASSERTION_ERROR); - etsg->CallThisStatic1(this, assertion_error, compiler::Signatures::BUILTIN_ASSERTION_ERROR_CTOR, message); - etsg->EmitThrow(this, assertion_error); + pg->GetAstCompiler()->Compile(this); } void AssertStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - auto res = compiler::Condition::CheckConstantExpr(etsg, test_); - if (res == compiler::Condition::Result::CONST_TRUE) { - return; - } - - if (res == compiler::Condition::Result::CONST_FALSE) { - ThrowError(etsg); - return; - } - - compiler::Label *true_label = etsg->AllocLabel(); - compiler::Label *false_label = etsg->AllocLabel(); - - compiler::Condition::Compile(etsg, test_, false_label); - etsg->JumpTo(this, true_label); - - etsg->SetLabel(this, false_label); - ThrowError(etsg); - - etsg->SetLabel(this, true_label); + etsg->GetAstCompiler()->Compile(this); } checker::Type *AssertStatement::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *AssertStatement::Check([[maybe_unused]] checker::ETSChecker *checker) { - checker->CheckTruthinessOfType(test_); - - if (second_ != nullptr) { - auto *msg_type = second_->Check(checker); - - if (!msg_type->IsETSStringType()) { - checker->ThrowTypeError("Assert message must be string", second_->Start()); - } - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statements/assertStatement.h b/ets2panda/ir/statements/assertStatement.h index e66acedc864197bd635f4c78263cf317a372a0b0..cf7c59ebb03fc40c1298195347151a907e33a551 100644 --- a/ets2panda/ir/statements/assertStatement.h +++ b/ets2panda/ir/statements/assertStatement.h @@ -18,6 +18,10 @@ #include "ir/statement.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class Expression; @@ -27,6 +31,8 @@ public: : Statement(AstNodeType::ASSERT_STATEMENT), test_(test), second_(second) { } + // TODO (somas): this friend relationship can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; const Expression *Test() const { @@ -46,9 +52,6 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; -protected: - void ThrowError(compiler::ETSGen *etsg) const; - private: Expression *test_; Expression *second_; diff --git a/ets2panda/ir/statements/blockStatement.cpp b/ets2panda/ir/statements/blockStatement.cpp index 948c0fc83d9bc093bcf44dea5bbd4936efd2ceb9..4bb8908d3267e607162f9dadd5ee17defdd5a595 100644 --- a/ets2panda/ir/statements/blockStatement.cpp +++ b/ets2panda/ir/statements/blockStatement.cpp @@ -16,6 +16,7 @@ #include "blockStatement.h" #include "varbinder/scope.h" +#include "compiler/core/pandagen.h" #include "compiler/core/regScope.h" #include "compiler/core/ETSGen.h" #include "checker/TSchecker.h" @@ -44,46 +45,21 @@ void BlockStatement::Dump(ir::AstDumper *dumper) const void BlockStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - compiler::LocalRegScope lrs(pg, scope_); - - for (const auto *it : statements_) { - it->Compile(pg); - } + pg->GetAstCompiler()->Compile(this); } void BlockStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - compiler::LocalRegScope lrs(etsg, scope_); - - etsg->CompileStatements(statements_); + etsg->GetAstCompiler()->Compile(this); } checker::Type *BlockStatement::Check([[maybe_unused]] checker::TSChecker *checker) { - checker::ScopeContext scope_ctx(checker, scope_); - - for (auto *it : statements_) { - it->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *BlockStatement::Check([[maybe_unused]] checker::ETSChecker *checker) { - checker::ScopeContext scope_ctx(checker, scope_); - - for (auto *it : statements_) { - it->Check(checker); - } - - for (auto [stmt, trailing_block] : trailing_blocks_) { - auto iterator = std::find(statements_.begin(), statements_.end(), stmt); - ASSERT(iterator != statements_.end()); - statements_.insert(iterator + 1, trailing_block); - trailing_block->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statements/blockStatement.h b/ets2panda/ir/statements/blockStatement.h index 2716162ef20cc46ff94cf86713ebf9e7c520eabb..86a00ffc80d01086bc4e05833df41a00a6130013 100644 --- a/ets2panda/ir/statements/blockStatement.h +++ b/ets2panda/ir/statements/blockStatement.h @@ -18,6 +18,10 @@ #include "ir/statement.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class BlockStatement : public Statement { public: @@ -30,6 +34,9 @@ public: { } + // TODO (somas): this friend relationship can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + bool IsScopeBearer() const override { return true; diff --git a/ets2panda/ir/statements/breakStatement.cpp b/ets2panda/ir/statements/breakStatement.cpp index 185f261d97272e2ac344cbaaf8ad88688660d1e1..674edc681c0e989196b346678710c8d284341d38 100644 --- a/ets2panda/ir/statements/breakStatement.cpp +++ b/ets2panda/ir/statements/breakStatement.cpp @@ -15,6 +15,7 @@ #include "breakStatement.h" +#include "checker/TSchecker.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "ir/astDump.h" @@ -41,34 +42,23 @@ void BreakStatement::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "BreakStatement"}, {"label", AstDumper::Nullish(ident_)}}); } -template -void CompileImpl(const BreakStatement *self, [[maybe_unused]] CodeGen *cg) -{ - compiler::Label *target = cg->ControlFlowChangeBreak(self->Ident()); - cg->Branch(self, target); -} - void BreakStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - CompileImpl(this, pg); + pg->GetAstCompiler()->Compile(this); } void BreakStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - if (etsg->ExtendWithFinalizer(parent_, this)) { - return; - } - CompileImpl(this, etsg); + etsg->GetAstCompiler()->Compile(this); } checker::Type *BreakStatement::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *BreakStatement::Check(checker::ETSChecker *checker) { - target_ = checker->FindJumpTarget(Type(), this, ident_); - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statements/breakStatement.h b/ets2panda/ir/statements/breakStatement.h index e9273960969cb2db367eca55bf3d22aa841a017a..e51f71040d11e53d898057087787f37402efba1c 100644 --- a/ets2panda/ir/statements/breakStatement.h +++ b/ets2panda/ir/statements/breakStatement.h @@ -18,6 +18,14 @@ #include "ir/statement.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 Identifier; @@ -26,6 +34,9 @@ public: explicit BreakStatement() : Statement(AstNodeType::BREAK_STATEMENT) {} explicit BreakStatement(Identifier *ident) : Statement(AstNodeType::BREAK_STATEMENT), ident_(ident) {} + friend checker::ETSAnalyzer; + friend compiler::ETSCompiler; + const Identifier *Ident() const { return ident_; diff --git a/ets2panda/ir/statements/returnStatement.h b/ets2panda/ir/statements/returnStatement.h index 2e2efaf8da232a47c16cb0ef0863994fb0032546..3bbe888c02dfb9cff9a5354fd776103d52f4e155 100644 --- a/ets2panda/ir/statements/returnStatement.h +++ b/ets2panda/ir/statements/returnStatement.h @@ -26,6 +26,11 @@ namespace panda::es2panda::compiler { class ETSCompiler; } // namespace panda::es2panda::compiler +namespace panda::es2panda::compiler { +class JSCompiler; +class ETSCompiler; +} // namespace panda::es2panda::compiler + namespace panda::es2panda::ir { class ReturnStatement : public Statement { public: diff --git a/ets2panda/ir/statements/throwStatement.cpp b/ets2panda/ir/statements/throwStatement.cpp index ab088aaab7aea733cb17e4cace70d632773a3238..28a3e2f54b1bbb6ce116c9c6bac617044b8ad53d 100644 --- a/ets2panda/ir/statements/throwStatement.cpp +++ b/ets2panda/ir/statements/throwStatement.cpp @@ -15,6 +15,7 @@ #include "throwStatement.h" +#include "checker/TSchecker.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "ir/astDump.h" @@ -38,28 +39,21 @@ void ThrowStatement::Dump(ir::AstDumper *dumper) const void ThrowStatement::Compile(compiler::PandaGen *pg) const { - argument_->Compile(pg); - pg->EmitThrow(this); + pg->GetAstCompiler()->Compile(this); } void ThrowStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - etsg->ThrowException(argument_); + etsg->GetAstCompiler()->Compile(this); } checker::Type *ThrowStatement::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *ThrowStatement::Check([[maybe_unused]] checker::ETSChecker *checker) { - auto *arg_type = argument_->Check(checker); - checker->CheckExceptionOrErrorType(arg_type, Start()); - - if (checker->Relation()->IsAssignableTo(arg_type, checker->GlobalBuiltinExceptionType())) { - checker->CheckThrowingStatements(this); - } - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statements/throwStatement.h b/ets2panda/ir/statements/throwStatement.h index dff234ec250d002201d7ad518cf8cdcd3651b0a6..cba26107ea3ad9710ed053e2b12c37e1f4d727df 100644 --- a/ets2panda/ir/statements/throwStatement.h +++ b/ets2panda/ir/statements/throwStatement.h @@ -18,6 +18,10 @@ #include "ir/statement.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class Expression; @@ -30,6 +34,8 @@ public: return argument_; } + friend class checker::ETSAnalyzer; + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/tryStatement.cpp b/ets2panda/ir/statements/tryStatement.cpp index b0026edcf642e5aa3351378ea182c3fef9fe7325..f325b681e959c93e98533dbeb08ac146cd2755cf 100644 --- a/ets2panda/ir/statements/tryStatement.cpp +++ b/ets2panda/ir/statements/tryStatement.cpp @@ -15,6 +15,7 @@ #include "tryStatement.h" +#include "checker/TSchecker.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "compiler/core/dynamicContext.h" @@ -63,208 +64,24 @@ bool TryStatement::HasDefaultCatchClause() const return (!catch_clauses_.empty() && catch_clauses_.back()->IsDefaultCatchClause()); } -void TryStatement::CompileTryCatch(compiler::PandaGen *pg) const -{ - ASSERT(catch_clauses_.size() == 1); - ASSERT(catch_clauses_.front() && !finalizer_); - - compiler::TryContext try_ctx(pg, this); - const auto &label_set = try_ctx.LabelSet(); - - pg->SetLabel(this, label_set.TryBegin()); - block_->Compile(pg); - pg->SetLabel(this, label_set.TryEnd()); - - pg->Branch(this, label_set.CatchEnd()); - - pg->SetLabel(this, label_set.CatchBegin()); - catch_clauses_.front()->Compile(pg); - pg->SetLabel(this, label_set.CatchEnd()); -} - -void TryStatement::CompileTryCatchFinally(compiler::PandaGen *pg) const -{ - ASSERT(catch_clauses_.size() == 1); - ASSERT(catch_clauses_.front() && finalizer_); - - compiler::TryContext try_ctx(pg, this); - const auto &label_set = try_ctx.LabelSet(); - - pg->SetLabel(this, label_set.TryBegin()); - { - compiler::TryContext inner_try_ctx(pg, this, false); - const auto &inner_label_set = inner_try_ctx.LabelSet(); - - pg->SetLabel(this, inner_label_set.TryBegin()); - block_->Compile(pg); - pg->SetLabel(this, inner_label_set.TryEnd()); - - pg->Branch(this, inner_label_set.CatchEnd()); - - pg->SetLabel(this, inner_label_set.CatchBegin()); - catch_clauses_.front()->Compile(pg); - pg->SetLabel(this, inner_label_set.CatchEnd()); - } - pg->SetLabel(this, label_set.TryEnd()); - - CompileFinally(pg, &try_ctx, label_set); -} - -void TryStatement::CompileFinally(compiler::PandaGen *pg, compiler::TryContext *try_ctx, - const compiler::TryLabelSet &label_set) const -{ - compiler::RegScope rs(pg); - compiler::VReg exception = pg->AllocReg(); - pg->StoreConst(this, exception, compiler::Constant::JS_HOLE); - pg->Branch(this, label_set.CatchEnd()); - - pg->SetLabel(this, label_set.CatchBegin()); - pg->StoreAccumulator(this, exception); - - pg->SetLabel(this, label_set.CatchEnd()); - - compiler::Label *label = pg->AllocLabel(); - pg->LoadAccumulator(this, try_ctx->FinalizerRun()); - - pg->BranchIfNotUndefined(this, label); - pg->StoreAccumulator(this, try_ctx->FinalizerRun()); - try_ctx->EmitFinalizer(); - pg->SetLabel(this, label); - - pg->LoadAccumulator(this, exception); - pg->EmitRethrow(this); -} - -void TryStatement::CompileTryFinally(compiler::PandaGen *pg) const -{ - ASSERT(catch_clauses_.empty() && finalizer_); - - compiler::TryContext try_ctx(pg, this); - const auto &label_set = try_ctx.LabelSet(); - - pg->SetLabel(this, label_set.TryBegin()); - { - compiler::TryContext inner_try_ctx(pg, this, false); - const auto &inner_label_set = inner_try_ctx.LabelSet(); - - pg->SetLabel(this, inner_label_set.TryBegin()); - block_->Compile(pg); - pg->SetLabel(this, inner_label_set.TryEnd()); - - pg->Branch(this, inner_label_set.CatchEnd()); - - pg->SetLabel(this, inner_label_set.CatchBegin()); - pg->EmitThrow(this); - pg->SetLabel(this, inner_label_set.CatchEnd()); - } - pg->SetLabel(this, label_set.TryEnd()); - - CompileFinally(pg, &try_ctx, label_set); -} - void TryStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - if (finalizer_ != nullptr) { - if (!catch_clauses_.empty()) { - CompileTryCatchFinally(pg); - } else { - CompileTryFinally(pg); - } - } else { - CompileTryCatch(pg); - } + pg->GetAstCompiler()->Compile(this); } void TryStatement::Compile(compiler::ETSGen *etsg) const { - compiler::ETSTryContext try_ctx(etsg, etsg->Allocator(), this, finalizer_ != nullptr); - - compiler::LabelPair try_label_pair(etsg->AllocLabel(), etsg->AllocLabel()); - - for (CatchClause *clause : catch_clauses_) { - try_ctx.AddNewCathTable(clause->TsType()->AsETSObjectType()->AssemblerName(), try_label_pair); - } - - compiler::Label *statement_end = etsg->AllocLabel(); - auto catch_tables = try_ctx.GetETSCatchTable(); - - etsg->SetLabel(this, try_label_pair.Begin()); - block_->Compile(etsg); - etsg->Branch(this, statement_end); - etsg->SetLabel(this, try_label_pair.End()); - - ASSERT(catch_clauses_.size() == catch_tables.size()); - - for (uint32_t i = 0; i < catch_clauses_.size(); i++) { - etsg->SetLabel(this, catch_tables.at(i)->LabelSet().CatchBegin()); - - catch_clauses_.at(i)->Compile(etsg); - - etsg->Branch(this, statement_end); - } - - etsg->SetLabel(this, statement_end); - - auto trycatch_label_pair = compiler::LabelPair(try_label_pair.Begin(), statement_end); - - try_ctx.EmitFinalizer(trycatch_label_pair, finalizer_insertions_); + etsg->GetAstCompiler()->Compile(this); } checker::Type *TryStatement::Check([[maybe_unused]] checker::TSChecker *checker) { - block_->Check(checker); - - for (auto *catch_clause : catch_clauses_) { - if (catch_clause != nullptr) { - catch_clause->Check(checker); - } - } - - if (finalizer_ != nullptr) { - finalizer_->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TryStatement::Check([[maybe_unused]] checker::ETSChecker *checker) { - std::vector exceptions; - block_->Check(checker); - - for (auto *catch_clause : catch_clauses_) { - auto exception_type = catch_clause->Check(checker); - - if ((exception_type != nullptr) && (catch_clause->Param() != nullptr)) { - auto *clause_type = exception_type->AsETSObjectType(); - - for (auto *exception : exceptions) { - checker->Relation()->IsIdenticalTo(clause_type, exception); - if (checker->Relation()->IsTrue()) { - checker->ThrowTypeError("Redeclaration of exception type", catch_clause->Start()); - } - } - - exceptions.push_back(clause_type); - } - } - - bool default_catch_found = false; - - for (auto *catch_clause : catch_clauses_) { - if (default_catch_found) { - checker->ThrowTypeError("Default catch clause should be the last in the try statement", - catch_clause->Start()); - } - - default_catch_found = catch_clause->IsDefaultCatchClause(); - } - - if (finalizer_ != nullptr) { - finalizer_->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } void TryStatement::SetReturnType(checker::ETSChecker *checker, checker::Type *type) diff --git a/ets2panda/ir/statements/tryStatement.h b/ets2panda/ir/statements/tryStatement.h index af69c1eb9d91f8f33a9ee79f4244c548b90e706b..79c58b6caf042ee36e1e6a16aa42f7b75734b781 100644 --- a/ets2panda/ir/statements/tryStatement.h +++ b/ets2panda/ir/statements/tryStatement.h @@ -19,7 +19,14 @@ #include "compiler/core/labelPair.h" #include "ir/statement.h" +namespace panda::es2panda::checker { +class TSAnalyzer; +class ETSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::compiler { +class JSCompiler; +class ETSCompiler; class PandaGen; class TryLabelSet; class TryContext; @@ -41,6 +48,11 @@ public: { } + friend class checker::TSAnalyzer; + friend class checker::ETSAnalyzer; + friend class compiler::JSCompiler; + friend class compiler::ETSCompiler; + const BlockStatement *FinallyBlock() const { return finalizer_; @@ -81,12 +93,6 @@ public: checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; private: - void CompileTryCatch(compiler::PandaGen *pg) const; - void CompileTryFinally(compiler::PandaGen *pg) const; - void CompileTryCatchFinally(compiler::PandaGen *pg) const; - void CompileFinally(compiler::PandaGen *pg, compiler::TryContext *try_ctx, - const compiler::TryLabelSet &label_set) const; - BlockStatement *block_; ArenaVector catch_clauses_; BlockStatement *finalizer_; 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/statements/variableDeclarator.cpp b/ets2panda/ir/statements/variableDeclarator.cpp index 3303096080170efbee1901e1d37ad1e4c66c9e44..3089bfd1cb17ff13b661abd5392bbed2c91555b8 100644 --- a/ets2panda/ir/statements/variableDeclarator.cpp +++ b/ets2panda/ir/statements/variableDeclarator.cpp @@ -58,144 +58,21 @@ void VariableDeclarator::Dump(ir::AstDumper *dumper) const void VariableDeclarator::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - auto lref = compiler::JSLReference::Create(pg, id_, true); - const ir::VariableDeclaration *decl = parent_->AsVariableDeclaration(); - - if (init_ != nullptr) { - init_->Compile(pg); - } else { - if (decl->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) { - return; - } - if (decl->Kind() == ir::VariableDeclaration::VariableDeclarationKind::LET && !decl->Parent()->IsCatchClause()) { - pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); - } - } - - lref.SetValue(); + pg->GetAstCompiler()->Compile(this); } void VariableDeclarator::Compile(compiler::ETSGen *etsg) const { - auto lref = compiler::ETSLReference::Create(etsg, id_, true); - auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - - if (id_->AsIdentifier()->Variable()->HasFlag(varbinder::VariableFlags::BOXED)) { - etsg->EmitLocalBoxCtor(id_); - etsg->StoreAccumulator(this, lref.Variable()->AsLocalVariable()->Vreg()); - etsg->SetAccumulatorType(lref.Variable()->TsType()); - } - - if (init_ != nullptr) { - if (!etsg->TryLoadConstantExpression(init_)) { - init_->Compile(etsg); - etsg->ApplyConversion(init_, nullptr); - } - } else { - etsg->LoadDefaultValue(this, id_->AsIdentifier()->Variable()->TsType()); - } - - etsg->ApplyConversion(this, TsType()); - lref.SetValue(); -} - -static void CheckSimpleVariableDeclaration(checker::TSChecker *checker, ir::VariableDeclarator *declarator) -{ - varbinder::Variable *const binding_var = declarator->Id()->AsIdentifier()->Variable(); - checker::Type *previous_type = binding_var->TsType(); - auto *const type_annotation = declarator->Id()->AsIdentifier()->TypeAnnotation(); - auto *const initializer = declarator->Init(); - const bool is_const = declarator->Parent()->AsVariableDeclaration()->Kind() == - ir::VariableDeclaration::VariableDeclarationKind::CONST; - - if (is_const) { - checker->AddStatus(checker::CheckerStatus::IN_CONST_CONTEXT); - } - - if (type_annotation != nullptr) { - type_annotation->Check(checker); - } - - if (type_annotation != nullptr && initializer != nullptr) { - checker::Type *const annotation_type = type_annotation->GetType(checker); - checker->ElaborateElementwise(annotation_type, initializer, declarator->Id()->Start()); - binding_var->SetTsType(annotation_type); - } else if (type_annotation != nullptr) { - binding_var->SetTsType(type_annotation->GetType(checker)); - } else if (initializer != nullptr) { - checker::Type *initializer_type = checker->CheckTypeCached(initializer); - - if (!is_const) { - initializer_type = checker->GetBaseTypeOfLiteralType(initializer_type); - } - - if (initializer_type->IsNullType()) { - checker->ThrowTypeError( - {"Cannot infer type for variable '", declarator->Id()->AsIdentifier()->Name(), "'."}, - declarator->Id()->Start()); - } - - binding_var->SetTsType(initializer_type); - } else { - checker->ThrowTypeError({"Variable ", declarator->Id()->AsIdentifier()->Name(), " implicitly has an any type."}, - declarator->Id()->Start()); - } - - if (previous_type != nullptr) { - checker->IsTypeIdenticalTo(binding_var->TsType(), previous_type, - {"Subsequent variable declaration must have the same type. Variable '", - binding_var->Name(), "' must be of type '", previous_type, "', but here has type '", - binding_var->TsType(), "'."}, - declarator->Id()->Start()); - } - - checker->RemoveStatus(checker::CheckerStatus::IN_CONST_CONTEXT); + etsg->GetAstCompiler()->Compile(this); } checker::Type *VariableDeclarator::Check([[maybe_unused]] checker::TSChecker *checker) { - if (TsType() == CHECKED) { - return nullptr; - } - - if (id_->IsIdentifier()) { - CheckSimpleVariableDeclaration(checker, this); - SetTsType(CHECKED); - return nullptr; - } - - if (id_->IsArrayPattern()) { - auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); - checker::ArrayDestructuringContext(checker, id_, false, id_->AsArrayPattern()->TypeAnnotation() == nullptr, - id_->AsArrayPattern()->TypeAnnotation(), init_) - .Start(); - - SetTsType(CHECKED); - return nullptr; - } - - ASSERT(id_->IsObjectPattern()); - auto context = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE); - checker::ObjectDestructuringContext(checker, id_, false, id_->AsObjectPattern()->TypeAnnotation() == nullptr, - id_->AsObjectPattern()->TypeAnnotation(), init_) - .Start(); - - SetTsType(CHECKED); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *VariableDeclarator::Check(checker::ETSChecker *checker) { - ASSERT(id_->IsIdentifier()); - ir::ModifierFlags flags = ir::ModifierFlags::NONE; - - if (id_->Parent()->Parent()->AsVariableDeclaration()->Kind() == - ir::VariableDeclaration::VariableDeclarationKind::CONST) { - flags |= ir::ModifierFlags::CONST; - } - - SetTsType( - checker->CheckVariableDeclaration(id_->AsIdentifier(), id_->AsIdentifier()->TypeAnnotation(), init_, flags)); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statements/variableDeclarator.h b/ets2panda/ir/statements/variableDeclarator.h index 1b1234ff3e01b1c93e834971ac0b4f050ebe183a..e6cdbc698cc833086cbe40b287a0c76efe532ada 100644 --- a/ets2panda/ir/statements/variableDeclarator.h +++ b/ets2panda/ir/statements/variableDeclarator.h @@ -18,7 +18,9 @@ #include "ir/expression.h" #include "ir/statement.h" - +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class Expression; @@ -31,6 +33,9 @@ public: { } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + Expression *Init() { return init_; diff --git a/ets2panda/ir/statements/whileStatement.cpp b/ets2panda/ir/statements/whileStatement.cpp index 7accd4a83125afb9bf8a9d94db396cc4822dcc6d..5624fd56d4d6aae09ac5f7bc615a6706952b3fda 100644 --- a/ets2panda/ir/statements/whileStatement.cpp +++ b/ets2panda/ir/statements/whileStatement.cpp @@ -43,52 +43,23 @@ void WhileStatement::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "WhileStatement"}, {"test", test_}, {"body", body_}}); } -template -void CompileImpl(const WhileStatement *while_stmt, [[maybe_unused]] CodeGen *cg) -{ - compiler::LabelTarget label_target(cg); - - cg->SetLabel(while_stmt, label_target.ContinueTarget()); - compiler::Condition::Compile(cg, while_stmt->Test(), label_target.BreakTarget()); - - { - compiler::LocalRegScope reg_scope(cg, while_stmt->Scope()); - compiler::LabelContext label_ctx(cg, label_target); - while_stmt->Body()->Compile(cg); - } - - cg->Branch(while_stmt, label_target.ContinueTarget()); - cg->SetLabel(while_stmt, label_target.BreakTarget()); -} - void WhileStatement::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - CompileImpl(this, pg); + pg->GetAstCompiler()->Compile(this); } void WhileStatement::Compile([[maybe_unused]] compiler::ETSGen *etsg) const { - CompileImpl(this, etsg); + etsg->GetAstCompiler()->Compile(this); } checker::Type *WhileStatement::Check([[maybe_unused]] checker::TSChecker *checker) { - checker::ScopeContext scope_ctx(checker, Scope()); - - checker::Type *test_type = Test()->Check(checker); - checker->CheckTruthinessOfType(test_type, Test()->Start()); - - Body()->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *WhileStatement::Check([[maybe_unused]] checker::ETSChecker *checker) { - checker::ScopeContext scope_ctx(checker, Scope()); - - checker->CheckTruthinessOfType(Test()); - - Body()->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index 725b911850243ecc5d0cd605f7b60baa1e4f9685..7233ca4ab5629f7689c2f7df9572fd7216b72ab5 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -15,6 +15,8 @@ #include "tsArrayType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" @@ -35,12 +37,19 @@ void TSArrayType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSArrayType"}, {"elementType", element_type_}}); } -void TSArrayType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSArrayType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSArrayType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSArrayType::Check([[maybe_unused]] checker::TSChecker *checker) { - element_type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSArrayType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -50,8 +59,7 @@ checker::Type *TSArrayType::GetType([[maybe_unused]] checker::TSChecker *checker checker::Type *TSArrayType::Check(checker::ETSChecker *checker) { - element_type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSArrayType::GetType(checker::ETSChecker *checker) diff --git a/ets2panda/ir/ts/tsArrayType.h b/ets2panda/ir/ts/tsArrayType.h index add9c0e33b5e3b66673c445dc79d538a4c55cb77..63c0795822b3be9d1bba0bc437f852da138432b1 100644 --- a/ets2panda/ir/ts/tsArrayType.h +++ b/ets2panda/ir/ts/tsArrayType.h @@ -18,6 +18,11 @@ #include "ir/typeNode.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +class TSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSArrayType : public TypeNode { public: @@ -28,10 +33,15 @@ public: return element_type_; } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + friend class checker::ETSAnalyzer; + 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::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/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/tsBigintKeyword.cpp b/ets2panda/ir/ts/tsBigintKeyword.cpp index 0d50b96a5ab9f8b1acd0c49958c48e156adcf09b..baa374d6690499b117dd1e3f6a60a62c8c8d1d0d 100644 --- a/ets2panda/ir/ts/tsBigintKeyword.cpp +++ b/ets2panda/ir/ts/tsBigintKeyword.cpp @@ -15,6 +15,9 @@ #include "tsBigintKeyword.h" +#include "checker/ETSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -27,11 +30,18 @@ void TSBigintKeyword::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSBigIntKeyword"}}); } -void TSBigintKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSBigintKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSBigintKeyword::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSBigintKeyword::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSBigintKeyword::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -41,6 +51,6 @@ checker::Type *TSBigintKeyword::GetType([[maybe_unused]] checker::TSChecker *che checker::Type *TSBigintKeyword::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsBigintKeyword.h b/ets2panda/ir/ts/tsBigintKeyword.h index 61fe591e040781010a4ff675898e2aea9c5894b1..9405c449a357e0d88a92e4738889042f14a9446d 100644 --- a/ets2panda/ir/ts/tsBigintKeyword.h +++ b/ets2panda/ir/ts/tsBigintKeyword.h @@ -27,6 +27,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/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/tsConditionalType.cpp b/ets2panda/ir/ts/tsConditionalType.cpp index 175de0652ff92201aaa38c1c0d7e0a05aed3fa8b..dc194f4b9cd1c0cf6687ed3a1fbd2980a9748423 100644 --- a/ets2panda/ir/ts/tsConditionalType.cpp +++ b/ets2panda/ir/ts/tsConditionalType.cpp @@ -15,6 +15,9 @@ #include "tsConditionalType.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -43,11 +46,18 @@ void TSConditionalType::Dump(ir::AstDumper *dumper) const {"falseType", false_type_}}); } -void TSConditionalType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSConditionalType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSConditionalType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSConditionalType::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSConditionalType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -57,6 +67,6 @@ checker::Type *TSConditionalType::GetType([[maybe_unused]] checker::TSChecker *c checker::Type *TSConditionalType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsConditionalType.h b/ets2panda/ir/ts/tsConditionalType.h index d2a26839ea1f37c9a65d12bc02216d786bc4529b..eb19607ef19c6f7af6e8acc6f3458f37b8a579ef 100644 --- a/ets2panda/ir/ts/tsConditionalType.h +++ b/ets2panda/ir/ts/tsConditionalType.h @@ -55,6 +55,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/tsConstructorType.cpp b/ets2panda/ir/ts/tsConstructorType.cpp index 0b720e9834e9bb124e3bd731ce63d9bd67ff9c37..8401dc267d7e9eace4dc45a57d203caff5955024 100644 --- a/ets2panda/ir/ts/tsConstructorType.cpp +++ b/ets2panda/ir/ts/tsConstructorType.cpp @@ -18,6 +18,8 @@ #include "varbinder/scope.h" #include "checker/TSchecker.h" #include "checker/types/signature.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterDeclaration.h" @@ -58,19 +60,18 @@ void TSConstructorType::Dump(ir::AstDumper *dumper) const {"abstract", AstDumper::Optional(abstract_)}}); } -void TSConstructorType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSConstructorType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSConstructorType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSConstructorType::Check(checker::TSChecker *checker) { - checker::ScopeContext scope_ctx(checker, scope_); - - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - checker->CheckFunctionParameterDeclarations(params_, signature_info); - return_type_->Check(checker); - auto *construct_signature = - checker->Allocator()->New(signature_info, return_type_->GetType(checker)); - - return checker->CreateConstructorTypeWithSignature(construct_signature); + return checker->GetAnalyzer()->Check(this); } checker::Type *TSConstructorType::GetType(checker::TSChecker *checker) @@ -80,6 +81,6 @@ checker::Type *TSConstructorType::GetType(checker::TSChecker *checker) checker::Type *TSConstructorType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsConstructorType.h b/ets2panda/ir/ts/tsConstructorType.h index c3e7d0e085b2b0e1e1b65d10c2b851d6ec9bfdca..c617833920eb235bc650ca19563ba766e25a02a5 100644 --- a/ets2panda/ir/ts/tsConstructorType.h +++ b/ets2panda/ir/ts/tsConstructorType.h @@ -18,6 +18,9 @@ #include "ir/typeNode.h" +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSTypeParameterDeclaration; @@ -33,6 +36,8 @@ public: abstract_(abstract) { } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; bool IsScopeBearer() const override { @@ -68,6 +73,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/tsFunctionType.cpp b/ets2panda/ir/ts/tsFunctionType.cpp index b58d0c2dcb746fe4f702e627028e5937234df5ac..61c32ed96f02fc15760cc7a6656c06981b28d2ab 100644 --- a/ets2panda/ir/ts/tsFunctionType.cpp +++ b/ets2panda/ir/ts/tsFunctionType.cpp @@ -19,6 +19,8 @@ #include "checker/TSchecker.h" #include "checker/ETSchecker.h" #include "checker/types/signature.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/base/spreadElement.h" #include "ir/expressions/identifier.h" @@ -61,19 +63,18 @@ void TSFunctionType::Dump(ir::AstDumper *dumper) const {"isNullable", AstDumper::Optional(nullable_)}}); } -void TSFunctionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSFunctionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSFunctionType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSFunctionType::Check(checker::TSChecker *checker) { - checker::ScopeContext scope_ctx(checker, scope_); - - auto *signature_info = checker->Allocator()->New(checker->Allocator()); - checker->CheckFunctionParameterDeclarations(params_, signature_info); - return_type_->Check(checker); - auto *call_signature = - checker->Allocator()->New(signature_info, return_type_->GetType(checker)); - - return checker->CreateFunctionTypeWithSignature(call_signature); + return checker->GetAnalyzer()->Check(this); } checker::Type *TSFunctionType::GetType(checker::TSChecker *checker) @@ -83,7 +84,7 @@ checker::Type *TSFunctionType::GetType(checker::TSChecker *checker) checker::Type *TSFunctionType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSFunctionType::GetType([[maybe_unused]] checker::ETSChecker *checker) diff --git a/ets2panda/ir/ts/tsFunctionType.h b/ets2panda/ir/ts/tsFunctionType.h index cebf62ad5f697a7db9c114de0ddb2b6d422b7c0e..d0ecd3539289008977a85caec6eaf1b0f26352b2 100644 --- a/ets2panda/ir/ts/tsFunctionType.h +++ b/ets2panda/ir/ts/tsFunctionType.h @@ -17,7 +17,9 @@ #define ES2PANDA_IR_TS_FUNCTION_TYPE_H #include "ir/typeNode.h" - +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSTypeParameterDeclaration; @@ -32,6 +34,8 @@ public: return_type_(return_type) { } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; bool IsScopeBearer() const override { @@ -67,6 +71,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/tsImportEqualsDeclaration.cpp b/ets2panda/ir/ts/tsImportEqualsDeclaration.cpp index eb615a791ebf495e47bb4b41db224e1e41bfbd76..3f08423270aaf6035b71c4e422312f5bf79acd15 100644 --- a/ets2panda/ir/ts/tsImportEqualsDeclaration.cpp +++ b/ets2panda/ir/ts/tsImportEqualsDeclaration.cpp @@ -15,6 +15,9 @@ #include "tsImportEqualsDeclaration.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/expression.h" #include "ir/expressions/identifier.h" @@ -40,15 +43,22 @@ void TSImportEqualsDeclaration::Dump(ir::AstDumper *dumper) const {"isExport", is_export_}}); } -void TSImportEqualsDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSImportEqualsDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSImportEqualsDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSImportEqualsDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSImportEqualsDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsImportEqualsDeclaration.h b/ets2panda/ir/ts/tsImportEqualsDeclaration.h index cc2d7dea4b72747b0df89e9983df872e5c92a575..eaca31099cabd74448200193c06129bbd92c4810 100644 --- a/ets2panda/ir/ts/tsImportEqualsDeclaration.h +++ b/ets2panda/ir/ts/tsImportEqualsDeclaration.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/tsImportType.cpp b/ets2panda/ir/ts/tsImportType.cpp index 6cdc3ba60ccc9f71c4dfd4b5cd79cb4c77545471..316ba0551154e56b010124d5e1fdd61efabd044d 100644 --- a/ets2panda/ir/ts/tsImportType.cpp +++ b/ets2panda/ir/ts/tsImportType.cpp @@ -15,6 +15,9 @@ #include "tsImportType.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" @@ -55,11 +58,19 @@ void TSImportType::Dump(ir::AstDumper *dumper) const {"isTypeOf", is_typeof_}}); } -void TSImportType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSImportType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSImportType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSImportType::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSImportType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -69,6 +80,6 @@ checker::Type *TSImportType::GetType([[maybe_unused]] checker::TSChecker *checke checker::Type *TSImportType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsImportType.h b/ets2panda/ir/ts/tsImportType.h index 2813e2a83178f566a339e93e735ba06d1763af8c..9f721f2cc0ca86407fa29645f8ca814dc59ed06e 100644 --- a/ets2panda/ir/ts/tsImportType.h +++ b/ets2panda/ir/ts/tsImportType.h @@ -57,6 +57,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/tsIndexedAccessType.cpp b/ets2panda/ir/ts/tsIndexedAccessType.cpp index 6c4f97c5699bf0c013e391c57659b8a2e1fc72fb..22d534af67ca2e7c2ba32f4340e059482c1fc213 100644 --- a/ets2panda/ir/ts/tsIndexedAccessType.cpp +++ b/ets2panda/ir/ts/tsIndexedAccessType.cpp @@ -15,6 +15,8 @@ #include "tsIndexedAccessType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -37,30 +39,18 @@ void TSIndexedAccessType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSIndexedAccessType"}, {"objectType", object_type_}, {"indexType", index_type_}}); } -void TSIndexedAccessType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSIndexedAccessType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSIndexedAccessType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSIndexedAccessType::Check([[maybe_unused]] checker::TSChecker *checker) { - object_type_->Check(checker); - index_type_->Check(checker); - checker::Type *resolved = GetType(checker); - - if (resolved != nullptr) { - return nullptr; - } - - checker::Type *index_type = checker->CheckTypeCached(index_type_); - - if (!index_type->HasTypeFlag(checker::TypeFlag::STRING_LIKE | checker::TypeFlag::NUMBER_LIKE)) { - checker->ThrowTypeError({"Type ", index_type, " cannot be used as index type"}, index_type_->Start()); - } - - if (index_type->IsNumberType()) { - checker->ThrowTypeError("Type has no matching signature for type 'number'", Start()); - } - - checker->ThrowTypeError("Type has no matching signature for type 'string'", Start()); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSIndexedAccessType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -79,6 +69,6 @@ checker::Type *TSIndexedAccessType::GetType([[maybe_unused]] checker::TSChecker checker::Type *TSIndexedAccessType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsIndexedAccessType.h b/ets2panda/ir/ts/tsIndexedAccessType.h index 1d456ed9b39d08f8ee1d1205ff6f9ff1003c1a10..13372ab35019a1d580a5177c6e0908617f1efe6e 100644 --- a/ets2panda/ir/ts/tsIndexedAccessType.h +++ b/ets2panda/ir/ts/tsIndexedAccessType.h @@ -18,6 +18,10 @@ #include "ir/typeNode.h" +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSIndexedAccessType : public TypeNode { public: @@ -25,6 +29,8 @@ public: : TypeNode(AstNodeType::TS_INDEXED_ACCESS_TYPE), object_type_(object_type), index_type_(index_type) { } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; const TypeNode *ObjectType() const { @@ -40,6 +46,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/tsInferType.cpp b/ets2panda/ir/ts/tsInferType.cpp index 5c06f1613556beebec0eba10434a272e058b3d0f..d108bb9540087e4571bec027eecfd970346b17c8 100644 --- a/ets2panda/ir/ts/tsInferType.cpp +++ b/ets2panda/ir/ts/tsInferType.cpp @@ -15,6 +15,9 @@ #include "tsInferType.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/ts/tsTypeParameter.h" @@ -34,11 +37,18 @@ void TSInferType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSInferType"}, {"typeParameter", type_param_}}); } -void TSInferType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSInferType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSInferType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSInferType::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSInferType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -48,6 +58,6 @@ checker::Type *TSInferType::GetType([[maybe_unused]] checker::TSChecker *checker checker::Type *TSInferType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsInferType.h b/ets2panda/ir/ts/tsInferType.h index 5d62c9776c69c87527c9f9809754817341d5cf0d..c06cb053c531172f4cb3cdac12f5bba46019fa96 100644 --- a/ets2panda/ir/ts/tsInferType.h +++ b/ets2panda/ir/ts/tsInferType.h @@ -34,6 +34,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/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/tsInterfaceDeclaration.cpp b/ets2panda/ir/ts/tsInterfaceDeclaration.cpp index 3740664b32e6f4fac4323668bfee774085bc99af..9dc4135dcef03f75145752a0ae9c485875a23d51 100644 --- a/ets2panda/ir/ts/tsInterfaceDeclaration.cpp +++ b/ets2panda/ir/ts/tsInterfaceDeclaration.cpp @@ -20,6 +20,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/identifier.h" @@ -77,99 +79,23 @@ void TSInterfaceDeclaration::Dump(ir::AstDumper *dumper) const {"typeParameters", AstDumper::Optional(type_params_)}}); } -void TSInterfaceDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -void CheckInheritedPropertiesAreIdentical(checker::TSChecker *checker, checker::InterfaceType *type, - const lexer::SourcePosition &loc_info) +void TSInterfaceDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - checker->GetBaseTypes(type); - - size_t constexpr BASE_SIZE_LIMIT = 2; - if (type->Bases().size() < BASE_SIZE_LIMIT) { - return; - } - - checker->ResolveDeclaredMembers(type); - - checker::InterfacePropertyMap properties; - - for (auto *it : type->Properties()) { - properties.insert({it->Name(), {it, type}}); - } + pg->GetAstCompiler()->Compile(this); +} - for (auto *base : type->Bases()) { - checker->ResolveStructuredTypeMembers(base); - ArenaVector inherited_properties(checker->Allocator()->Adapter()); - base->AsInterfaceType()->CollectProperties(&inherited_properties); - - for (auto *inherited_prop : inherited_properties) { - auto res = properties.find(inherited_prop->Name()); - if (res == properties.end()) { - properties.insert({inherited_prop->Name(), {inherited_prop, base->AsInterfaceType()}}); - } else if (res->second.second != type) { - checker::Type *source_type = checker->GetTypeOfVariable(inherited_prop); - checker::Type *target_type = checker->GetTypeOfVariable(res->second.first); - checker->IsTypeIdenticalTo(source_type, target_type, - {"Interface '", type, "' cannot simultaneously extend types '", - res->second.second, "' and '", base->AsInterfaceType(), "'."}, - loc_info); - } - } - } +void TSInterfaceDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); } checker::Type *TSInterfaceDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) { - varbinder::Variable *var = id_->Variable(); - ASSERT(var->Declaration()->Node() && var->Declaration()->Node()->IsTSInterfaceDeclaration()); - - if (this == var->Declaration()->Node()) { - checker::Type *resolved_type = var->TsType(); - - if (resolved_type == nullptr) { - checker::ObjectDescriptor *desc = - checker->Allocator()->New(checker->Allocator()); - resolved_type = checker->Allocator()->New(checker->Allocator(), id_->Name(), desc); - resolved_type->SetVariable(var); - var->SetTsType(resolved_type); - } - - checker::InterfaceType *resolved_interface = resolved_type->AsObjectType()->AsInterfaceType(); - CheckInheritedPropertiesAreIdentical(checker, resolved_interface, id_->Start()); - - for (auto *base : resolved_interface->Bases()) { - checker->IsTypeAssignableTo(resolved_interface, base, - {"Interface '", id_->Name(), "' incorrectly extends interface '", base, "'"}, - id_->Start()); - } - - checker->CheckIndexConstraints(resolved_interface); - } - - body_->Check(checker); - - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSInterfaceDeclaration::Check(checker::ETSChecker *checker) { - checker::ETSObjectType *interface_type {}; - - if (TsType() == nullptr) { - interface_type = checker->BuildInterfaceProperties(this); - ASSERT(interface_type != nullptr); - interface_type->SetSuperType(checker->GlobalETSObjectType()); - checker->CheckInvokeMethodsLegitimacy(interface_type); - SetTsType(interface_type); - } - - checker::ScopeContext scope_ctx(checker, scope_); - auto saved_context = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, interface_type); - - for (auto *it : body_->Body()) { - it->Check(checker); - } - - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsInterfaceDeclaration.h b/ets2panda/ir/ts/tsInterfaceDeclaration.h index 9ede275089e2f6b24cf5570e0da0f9de83682d62..ae4087680d6cee956c287204d1466e79e3b12512 100644 --- a/ets2panda/ir/ts/tsInterfaceDeclaration.h +++ b/ets2panda/ir/ts/tsInterfaceDeclaration.h @@ -145,6 +145,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; checker::Type *InferType(checker::TSChecker *checker, varbinder::Variable *binding_var) const; 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/tsIntersectionType.cpp b/ets2panda/ir/ts/tsIntersectionType.cpp index 2e96dbb3fffee08d5a902213a6c4c311b662543d..a25efa4371b2611fea732dc37e1ce2dd278bf8c0 100644 --- a/ets2panda/ir/ts/tsIntersectionType.cpp +++ b/ets2panda/ir/ts/tsIntersectionType.cpp @@ -15,6 +15,9 @@ #include "tsIntersectionType.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/ETSchecker.h" @@ -38,11 +41,18 @@ void TSIntersectionType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSIntersectionType"}, {"types", types_}}); } -void TSIntersectionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSIntersectionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSIntersectionType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSIntersectionType::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSIntersectionType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -58,6 +68,6 @@ checker::Type *TSIntersectionType::GetType([[maybe_unused]] checker::ETSChecker checker::Type *TSIntersectionType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsIntersectionType.h b/ets2panda/ir/ts/tsIntersectionType.h index 7ed628faa41db80069289bf66613f79a967e215c..70556f32db9e400242b432646fd04762bd23d6ce 100644 --- a/ets2panda/ir/ts/tsIntersectionType.h +++ b/ets2panda/ir/ts/tsIntersectionType.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 *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsLiteralType.cpp b/ets2panda/ir/ts/tsLiteralType.cpp index 08db35d343e5cac9a3331feac8c26e52e7f3408a..44d05c36f516a882d5a203942a870d6eadc0a5b6 100644 --- a/ets2panda/ir/ts/tsLiteralType.cpp +++ b/ets2panda/ir/ts/tsLiteralType.cpp @@ -15,6 +15,8 @@ #include "tsLiteralType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -34,12 +36,19 @@ void TSLiteralType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSLiteralType"}, {"literal", literal_}}); } -void TSLiteralType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSLiteralType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSLiteralType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSLiteralType::Check([[maybe_unused]] checker::TSChecker *checker) { - GetType(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSLiteralType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -54,6 +63,6 @@ checker::Type *TSLiteralType::GetType([[maybe_unused]] checker::TSChecker *check checker::Type *TSLiteralType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsLiteralType.h b/ets2panda/ir/ts/tsLiteralType.h index 9569ef38287ecc0ec06c255bd23e81b7731a616b..ee3e8e145581a388f7f47df3aca6814f4628a85a 100644 --- a/ets2panda/ir/ts/tsLiteralType.h +++ b/ets2panda/ir/ts/tsLiteralType.h @@ -32,6 +32,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/tsMappedType.cpp b/ets2panda/ir/ts/tsMappedType.cpp index bc7946d3f40fd0bd8e3b493254ea84c7afdb7e7c..cb9c54072d10beec131d13ad3906b1f410c81ad8 100644 --- a/ets2panda/ir/ts/tsMappedType.cpp +++ b/ets2panda/ir/ts/tsMappedType.cpp @@ -15,6 +15,9 @@ #include "tsMappedType.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" #include "ir/ts/tsTypeParameter.h" @@ -49,11 +52,18 @@ void TSMappedType::Dump(ir::AstDumper *dumper) const : AstDumper::Optional("-")}}); } -void TSMappedType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSMappedType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSMappedType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSMappedType::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSMappedType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -63,6 +73,6 @@ checker::Type *TSMappedType::GetType([[maybe_unused]] checker::TSChecker *checke checker::Type *TSMappedType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsMappedType.h b/ets2panda/ir/ts/tsMappedType.h index c2fe678170a84aa44e7233cf74eb2eaa2cee5430..33a22120f1fa5a47a054c792f7fa899cfe203ab5 100644 --- a/ets2panda/ir/ts/tsMappedType.h +++ b/ets2panda/ir/ts/tsMappedType.h @@ -56,6 +56,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/tsModuleBlock.cpp b/ets2panda/ir/ts/tsModuleBlock.cpp index 9c7b5a802983ce8b999ff0ffc33be970ed2f08aa..1b3443a72c8b68448e704a76dfe84cfdc75561fd 100644 --- a/ets2panda/ir/ts/tsModuleBlock.cpp +++ b/ets2panda/ir/ts/tsModuleBlock.cpp @@ -16,6 +16,9 @@ #include "tsModuleBlock.h" #include "varbinder/scope.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -38,15 +41,22 @@ void TSModuleBlock::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSModuleBlock"}, {"body", statements_}}); } -void TSModuleBlock::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSModuleBlock::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSModuleBlock::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSModuleBlock::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSModuleBlock::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsModuleBlock.h b/ets2panda/ir/ts/tsModuleBlock.h index 8154d30a82e187972d685df1cd8462ad02202d24..64c1479c7df8ea488d4896308e50a846449b0814 100644 --- a/ets2panda/ir/ts/tsModuleBlock.h +++ b/ets2panda/ir/ts/tsModuleBlock.h @@ -46,6 +46,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/tsModuleDeclaration.cpp b/ets2panda/ir/ts/tsModuleDeclaration.cpp index bc8abb3a0cf3d338c3934fd73af2b133fbeadaa1..25ad9e6570e9bdf2044c4983f8fc51e3772b035a 100644 --- a/ets2panda/ir/ts/tsModuleDeclaration.cpp +++ b/ets2panda/ir/ts/tsModuleDeclaration.cpp @@ -16,6 +16,9 @@ #include "tsModuleDeclaration.h" #include "varbinder/scope.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/base/decorator.h" #include "ir/expression.h" @@ -57,15 +60,23 @@ void TSModuleDeclaration::Dump(ir::AstDumper *dumper) const {"global", global_}}); } -void TSModuleDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSModuleDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSModuleDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSModuleDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSModuleDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsModuleDeclaration.h b/ets2panda/ir/ts/tsModuleDeclaration.h index e8f28c207fb66db398e1ccccea8005bf81ebf4a1..cc3aafc1146d8d301a28c0aa7272fd72da1b117f 100644 --- a/ets2panda/ir/ts/tsModuleDeclaration.h +++ b/ets2panda/ir/ts/tsModuleDeclaration.h @@ -80,6 +80,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/tsNeverKeyword.cpp b/ets2panda/ir/ts/tsNeverKeyword.cpp index 92b64c3dae72fe122fb79f48dee64df640dbc7dd..ee52a42c6b9b112dfa05c6ffbcdb6125fbcf0b5a 100644 --- a/ets2panda/ir/ts/tsNeverKeyword.cpp +++ b/ets2panda/ir/ts/tsNeverKeyword.cpp @@ -15,6 +15,8 @@ #include "tsNeverKeyword.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -27,11 +29,19 @@ void TSNeverKeyword::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSNeverKeyword"}}); } -void TSNeverKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNeverKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSNeverKeyword::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSNeverKeyword::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSNeverKeyword::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -41,6 +51,6 @@ checker::Type *TSNeverKeyword::GetType([[maybe_unused]] checker::TSChecker *chec checker::Type *TSNeverKeyword::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsNeverKeyword.h b/ets2panda/ir/ts/tsNeverKeyword.h index 20053e4aa2e1867b8afbc007fa250a07d3615612..35d4aa449f841cfae0e3cf1c47a97631e68c8686 100644 --- a/ets2panda/ir/ts/tsNeverKeyword.h +++ b/ets2panda/ir/ts/tsNeverKeyword.h @@ -27,6 +27,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/tsNonNullExpression.cpp b/ets2panda/ir/ts/tsNonNullExpression.cpp index 3ce576cef450cfd1c02badd1f54a094a752a0e9f..ac49f17ac8ae1bf8b21f7d09aac60c026cc46a87 100644 --- a/ets2panda/ir/ts/tsNonNullExpression.cpp +++ b/ets2panda/ir/ts/tsNonNullExpression.cpp @@ -16,7 +16,9 @@ #include "tsNonNullExpression.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 { @@ -35,52 +37,23 @@ void TSNonNullExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSNonNullExpression"}, {"expression", expr_}}); } -void TSNonNullExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNonNullExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} void TSNonNullExpression::Compile(compiler::ETSGen *etsg) const { - compiler::RegScope rs(etsg); - - expr_->Compile(etsg); - - if (!etsg->GetAccumulatorType()->IsNullishOrNullLike()) { - return; - } - - if (etsg->GetAccumulatorType()->IsETSNullLike()) { - etsg->EmitNullishException(this); - return; - } - - auto arg = etsg->AllocReg(); - etsg->StoreAccumulator(this, arg); - etsg->LoadAccumulator(this, arg); - - auto end_label = etsg->AllocLabel(); - - etsg->BranchIfNotNullish(this, end_label); - etsg->EmitNullishException(this); - - etsg->SetLabel(this, end_label); - etsg->LoadAccumulator(this, arg); - etsg->ConvertToNonNullish(this); + etsg->GetAstCompiler()->Compile(this); } checker::Type *TSNonNullExpression::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSNonNullExpression::Check(checker::ETSChecker *checker) { - auto expr_type = expr_->Check(checker); - - if (!expr_type->IsNullish()) { - checker->ThrowTypeError("Bad operand type, the operand of the non-null expression must be a nullable type", - expr_->Start()); - } - - SetTsType(expr_type->IsNullish() ? checker->GetNonNullishType(expr_type) : expr_type); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsNonNullExpression.h b/ets2panda/ir/ts/tsNonNullExpression.h index 22910a2211e31c8a723c6d1d2e871773678ecd52..0819a97fe46be0751d2f619cba5bb815100f2f49 100644 --- a/ets2panda/ir/ts/tsNonNullExpression.h +++ b/ets2panda/ir/ts/tsNonNullExpression.h @@ -18,11 +18,17 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSNonNullExpression : public Expression { public: explicit TSNonNullExpression(Expression *expr) : Expression(AstNodeType::TS_NON_NULL_EXPRESSION), expr_(expr) {} + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + const Expression *Expr() const { return expr_; diff --git a/ets2panda/ir/ts/tsNullKeyword.cpp b/ets2panda/ir/ts/tsNullKeyword.cpp index 49f02916f8439c5dcccab44cab1e9458e6c0f876..1ecd8382424dbc59c457fbed877881178e5524a4 100644 --- a/ets2panda/ir/ts/tsNullKeyword.cpp +++ b/ets2panda/ir/ts/tsNullKeyword.cpp @@ -15,6 +15,8 @@ #include "tsNullKeyword.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -27,11 +29,18 @@ void TSNullKeyword::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSNullKeyword"}}); } -void TSNullKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNullKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSNullKeyword::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSNullKeyword::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSNullKeyword::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -41,6 +50,6 @@ checker::Type *TSNullKeyword::GetType([[maybe_unused]] checker::TSChecker *check checker::Type *TSNullKeyword::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsNullKeyword.h b/ets2panda/ir/ts/tsNullKeyword.h index a443f194ed8276988fec7ef7d5892453b22f93d6..a53935ce169c56689fcd19340ad1a8e2cf0be5d1 100644 --- a/ets2panda/ir/ts/tsNullKeyword.h +++ b/ets2panda/ir/ts/tsNullKeyword.h @@ -27,6 +27,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/tsParameterProperty.cpp b/ets2panda/ir/ts/tsParameterProperty.cpp index d42b520c35bcbcce4200beb3a392c9d0b8cffed7..4f5cfd854a5e5408b0c0818b0562a41264efac1b 100644 --- a/ets2panda/ir/ts/tsParameterProperty.cpp +++ b/ets2panda/ir/ts/tsParameterProperty.cpp @@ -15,6 +15,9 @@ #include "tsParameterProperty.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/expression.h" @@ -42,15 +45,22 @@ void TSParameterProperty::Dump(ir::AstDumper *dumper) const {"parameter", parameter_}}); } -void TSParameterProperty::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSParameterProperty::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSParameterProperty::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSParameterProperty::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSParameterProperty::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsParameterProperty.h b/ets2panda/ir/ts/tsParameterProperty.h index 77b8fbb8321e61d3824d74d26d9521ba27fa5673..f11529dac3c418c46069a5d826f99da6177a1509 100644 --- a/ets2panda/ir/ts/tsParameterProperty.h +++ b/ets2panda/ir/ts/tsParameterProperty.h @@ -64,6 +64,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/tsParenthesizedType.cpp b/ets2panda/ir/ts/tsParenthesizedType.cpp index ba224d1c703a6ebaaa2c6849f46cf95149c8cb6f..04012a2b20bb43aa0060e3eef2119ab9ea7bb8b3 100644 --- a/ets2panda/ir/ts/tsParenthesizedType.cpp +++ b/ets2panda/ir/ts/tsParenthesizedType.cpp @@ -15,6 +15,8 @@ #include "tsParenthesizedType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -34,12 +36,19 @@ void TSParenthesizedType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSParenthesizedType"}, {"typeAnnotation", type_}}); } -void TSParenthesizedType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSParenthesizedType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSParenthesizedType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSParenthesizedType::Check([[maybe_unused]] checker::TSChecker *checker) { - type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSParenthesizedType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -54,6 +63,6 @@ checker::Type *TSParenthesizedType::GetType([[maybe_unused]] checker::TSChecker checker::Type *TSParenthesizedType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsParenthesizedType.h b/ets2panda/ir/ts/tsParenthesizedType.h index 8175be39783728c45789a32e77b61bdbbac46367..5818aa2e432f36151adb0cfd72d6289dfcdf49c2 100644 --- a/ets2panda/ir/ts/tsParenthesizedType.h +++ b/ets2panda/ir/ts/tsParenthesizedType.h @@ -17,12 +17,17 @@ #define ES2PANDA_IR_TS_PARENT_TYPE_H #include "ir/typeNode.h" - +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSParenthesizedType : public TypeNode { public: explicit TSParenthesizedType(TypeNode *type) : TypeNode(AstNodeType::TS_PARENT_TYPE), type_(type) {} + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + const Expression *Type() const { return type_; @@ -32,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/tsQualifiedName.cpp b/ets2panda/ir/ts/tsQualifiedName.cpp index cf72fa5f727e7be2f033ac105acb73b86c2836a7..c9099debbde40ea9d58efeaf21ecdd026ec2cf55 100644 --- a/ets2panda/ir/ts/tsQualifiedName.cpp +++ b/ets2panda/ir/ts/tsQualifiedName.cpp @@ -17,6 +17,8 @@ #include "checker/ETSchecker.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/expressions/identifier.h" @@ -38,42 +40,23 @@ void TSQualifiedName::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSQualifiedName"}, {"left", left_}, {"right", right_}}); } -void TSQualifiedName::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSQualifiedName::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSQualifiedName::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSQualifiedName::Check([[maybe_unused]] checker::TSChecker *checker) { - checker::Type *base_type = checker->CheckNonNullType(left_->Check(checker), left_->Start()); - varbinder::Variable *prop = checker->GetPropertyOfType(base_type, right_->Name()); - - if (prop != nullptr) { - return checker->GetTypeOfVariable(prop); - } - - if (base_type->IsObjectType()) { - checker::ObjectType *obj_type = base_type->AsObjectType(); - - if (obj_type->StringIndexInfo() != nullptr) { - return obj_type->StringIndexInfo()->GetType(); - } - } - - checker->ThrowTypeError({"Property ", right_->Name(), " does not exist on this type."}, right_->Start()); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSQualifiedName::Check(checker::ETSChecker *checker) { - checker::Type *base_type = left_->Check(checker); - if (base_type->IsETSObjectType()) { - varbinder::Variable *prop = - base_type->AsETSObjectType()->GetProperty(right_->Name(), checker::PropertySearchFlags::SEARCH_DECL); - - if (prop != nullptr) { - return checker->GetTypeOfVariable(prop); - } - } - - checker->ThrowTypeError({"'", right_->Name(), "' type does not exist."}, right_->Start()); + return checker->GetAnalyzer()->Check(this); } util::StringView TSQualifiedName::ToString(ArenaAllocator *allocator) const diff --git a/ets2panda/ir/ts/tsQualifiedName.h b/ets2panda/ir/ts/tsQualifiedName.h index d86985550f2cc90ca759c94879b9767efee6a4a9..89f24fdafa0d79dca9e9a53d5659464a7ada9520 100644 --- a/ets2panda/ir/ts/tsQualifiedName.h +++ b/ets2panda/ir/ts/tsQualifiedName.h @@ -55,6 +55,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/tsThisType.cpp b/ets2panda/ir/ts/tsThisType.cpp index 445cf9b41fead0940e374ff2049be6f713bfe537..9827778d624a63a5faa7d69a5a3b5240ec7b3dba 100644 --- a/ets2panda/ir/ts/tsThisType.cpp +++ b/ets2panda/ir/ts/tsThisType.cpp @@ -15,6 +15,9 @@ #include "tsThisType.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -26,11 +29,18 @@ void TSThisType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSThisType"}}); } -void TSThisType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSThisType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSThisType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSThisType::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSThisType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -40,6 +50,6 @@ checker::Type *TSThisType::GetType([[maybe_unused]] checker::TSChecker *checker) checker::Type *TSThisType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsThisType.h b/ets2panda/ir/ts/tsThisType.h index 0cbf2359b8ebfd1b9aaa3f358789b7ed6c662d39..d501237363dd12390bb5f5693450942f3e1df7c7 100644 --- a/ets2panda/ir/ts/tsThisType.h +++ b/ets2panda/ir/ts/tsThisType.h @@ -27,6 +27,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/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/tsTypeAliasDeclaration.cpp b/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp index 52028ef4fb687df6365785a0bb53b093e958ced6..83bf379328b27f1fb35a5f84590a85d7ecb6d82e 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp @@ -17,6 +17,8 @@ #include "varbinder/scope.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" #include "ir/base/decorator.h" @@ -69,17 +71,23 @@ void TSTypeAliasDeclaration::Dump(ir::AstDumper *dumper) const {"declare", AstDumper::Optional(declare_)}}); } -void TSTypeAliasDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeAliasDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSTypeAliasDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeAliasDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) { - TypeAnnotation()->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeAliasDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) { - TypeAnnotation()->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeAliasDeclaration.h b/ets2panda/ir/ts/tsTypeAliasDeclaration.h index 77061cb11274a031479d4f0c9e89fef551171035..a6030e9d6876c8c7ec552cc5bbeb10b4b0f0ac58 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.h +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.h @@ -96,6 +96,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/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/tsTypeLiteral.cpp b/ets2panda/ir/ts/tsTypeLiteral.cpp index 48fdf07d8633f6b9a13e972b5d695efcee0a6810..9f9471ab8fb7a9f39625d2f9b8eeb80f420333a7 100644 --- a/ets2panda/ir/ts/tsTypeLiteral.cpp +++ b/ets2panda/ir/ts/tsTypeLiteral.cpp @@ -15,6 +15,8 @@ #include "tsTypeLiteral.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "varbinder/variable.h" @@ -42,18 +44,19 @@ void TSTypeLiteral::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTypeLiteral"}, {"members", members_}}); } -void TSTypeLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -checker::Type *TSTypeLiteral::Check(checker::TSChecker *checker) +void TSTypeLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - for (auto *it : members_) { - it->Check(checker); - } + pg->GetAstCompiler()->Compile(this); +} - checker::Type *type = GetType(checker); - checker->CheckIndexConstraints(type); +void TSTypeLiteral::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} - return nullptr; +checker::Type *TSTypeLiteral::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeLiteral::GetType(checker::TSChecker *checker) @@ -72,6 +75,6 @@ checker::Type *TSTypeLiteral::GetType(checker::TSChecker *checker) checker::Type *TSTypeLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeLiteral.h b/ets2panda/ir/ts/tsTypeLiteral.h index 9f0cb0a1b7e7c84449abb901d562a46bb8ce0588..a91e051a9373de1e0f7075033ea1add8b3aee56a 100644 --- a/ets2panda/ir/ts/tsTypeLiteral.h +++ b/ets2panda/ir/ts/tsTypeLiteral.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 *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsTypeOperator.cpp b/ets2panda/ir/ts/tsTypeOperator.cpp index 538bb29e5c1e02f67009fb9c7d39246f824e347f..f945f6e43f3fccbac777ed96d7198f5d44a2dcb4 100644 --- a/ets2panda/ir/ts/tsTypeOperator.cpp +++ b/ets2panda/ir/ts/tsTypeOperator.cpp @@ -15,6 +15,9 @@ #include "tsTypeOperator.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -37,11 +40,18 @@ void TSTypeOperator::Dump(ir::AstDumper *dumper) const }); } -void TSTypeOperator::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeOperator::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSTypeOperator::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeOperator::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeOperator::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -51,6 +61,6 @@ checker::Type *TSTypeOperator::GetType([[maybe_unused]] checker::TSChecker *chec checker::Type *TSTypeOperator::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeOperator.h b/ets2panda/ir/ts/tsTypeOperator.h index ea2b54e731bcedf5eefd34db174e0d33e1627385..dd09a880341d3d93ae3db690396d04bacfff260b 100644 --- a/ets2panda/ir/ts/tsTypeOperator.h +++ b/ets2panda/ir/ts/tsTypeOperator.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 *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsTypeParameter.cpp b/ets2panda/ir/ts/tsTypeParameter.cpp index 3a92543a40cdfb2247589e3c2c787e35e15d31da..e464990af26f8ebd0bad98179ed160704bc00e1f 100644 --- a/ets2panda/ir/ts/tsTypeParameter.cpp +++ b/ets2panda/ir/ts/tsTypeParameter.cpp @@ -15,6 +15,9 @@ #include "tsTypeParameter.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" #include "ir/expressions/identifier.h" @@ -58,15 +61,22 @@ void TSTypeParameter::Dump(ir::AstDumper *dumper) const }); } -void TSTypeParameter::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeParameter::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSTypeParameter::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeParameter::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeParameter::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeParameter.h b/ets2panda/ir/ts/tsTypeParameter.h index aaf9227a7bde0c896f7e7baae133907c323bcc35..09f485eb512eef001625299760290f4dcbb83d47 100644 --- a/ets2panda/ir/ts/tsTypeParameter.h +++ b/ets2panda/ir/ts/tsTypeParameter.h @@ -61,6 +61,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/tsTypeParameterDeclaration.cpp b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp index a84b6d16cb7a6a8f6c21be72ea6df82aad1978aa..128f2abae2068a644352b0db973d26b3e4956116 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp @@ -16,6 +16,9 @@ #include "tsTypeParameterDeclaration.h" #include "varbinder/scope.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/ts/tsTypeParameter.h" @@ -39,15 +42,22 @@ void TSTypeParameterDeclaration::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTypeParameterDeclaration"}, {"params", params_}}); } -void TSTypeParameterDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeParameterDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSTypeParameterDeclaration::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeParameterDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeParameterDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.h b/ets2panda/ir/ts/tsTypeParameterDeclaration.h index 0d9b263ebab82dc22b4a58ea8853f394322fe39b..a723ce667215ee11fa0b0a15838b04371496f668 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.h +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.h @@ -65,6 +65,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/tsTypeParameterInstantiation.cpp b/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp index f9906355134f706cc9f02bc68efa1eebce3c9ef6..e4174bf081fb6118d623ad5ce439b0dee02a38c5 100644 --- a/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp +++ b/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp @@ -16,6 +16,9 @@ #include "es2panda.h" #include "tsTypeParameterInstantiation.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/expression.h" #include "ir/typeNode.h" @@ -63,16 +66,23 @@ void TSTypeParameterInstantiation::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTypeParameterInstantiation"}, {"params", params_}}); } -void TSTypeParameterInstantiation::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeParameterInstantiation::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSTypeParameterInstantiation::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypeParameterInstantiation::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeParameterInstantiation::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeParameterInstantiation.h b/ets2panda/ir/ts/tsTypeParameterInstantiation.h index 09db9a4b1df80ee993004e47adeab28c5347e851..542b4f0fe6fc18628cfec85bd5db08cd7a355784 100644 --- a/ets2panda/ir/ts/tsTypeParameterInstantiation.h +++ b/ets2panda/ir/ts/tsTypeParameterInstantiation.h @@ -49,6 +49,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/tsTypePredicate.cpp b/ets2panda/ir/ts/tsTypePredicate.cpp index 9e12cb8569dbd93034dcad3b9e919de7a3df937c..16c99b8747da8bd8615dc326242b48f93af2ba9a 100644 --- a/ets2panda/ir/ts/tsTypePredicate.cpp +++ b/ets2panda/ir/ts/tsTypePredicate.cpp @@ -15,6 +15,9 @@ #include "tsTypePredicate.h" +#include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/typeNode.h" #include "ir/expression.h" @@ -44,11 +47,18 @@ void TSTypePredicate::Dump(ir::AstDumper *dumper) const {"asserts", asserts_}}); } -void TSTypePredicate::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypePredicate::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSTypePredicate::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSTypePredicate::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypePredicate::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -58,6 +68,6 @@ checker::Type *TSTypePredicate::GetType([[maybe_unused]] checker::TSChecker *che checker::Type *TSTypePredicate::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypePredicate.h b/ets2panda/ir/ts/tsTypePredicate.h index e32610b702250e528746ac92b77bfc86facdc6d8..f19587cf064675abc5b461eff41ae3ab1d2d2077 100644 --- a/ets2panda/ir/ts/tsTypePredicate.h +++ b/ets2panda/ir/ts/tsTypePredicate.h @@ -48,6 +48,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/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; diff --git a/ets2panda/ir/ts/tsTypeReference.cpp b/ets2panda/ir/ts/tsTypeReference.cpp index df1c13a9c392748f8e7f154a71ad92cf1ad06ecb..ed6d359cefcf88b11ff1ff199c8c0aecb4c191ca 100644 --- a/ets2panda/ir/ts/tsTypeReference.cpp +++ b/ets2panda/ir/ts/tsTypeReference.cpp @@ -19,6 +19,8 @@ #include "varbinder/scope.h" #include "varbinder/variable.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/expressions/identifier.h" #include "ir/ts/tsInterfaceDeclaration.h" @@ -52,7 +54,14 @@ void TSTypeReference::Dump(ir::AstDumper *dumper) const {{"type", "TSTypeReference"}, {"typeName", type_name_}, {"typeParameters", AstDumper::Optional(type_params_)}}); } -void TSTypeReference::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSTypeReference::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSTypeReference::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} ir::Identifier *TSTypeReference::BaseName() const { @@ -71,8 +80,7 @@ ir::Identifier *TSTypeReference::BaseName() const checker::Type *TSTypeReference::Check([[maybe_unused]] checker::TSChecker *checker) { - GetType(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeReference::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -98,6 +106,6 @@ checker::Type *TSTypeReference::GetType([[maybe_unused]] checker::TSChecker *che checker::Type *TSTypeReference::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeReference.h b/ets2panda/ir/ts/tsTypeReference.h index 2f96fd8a6bb3875eb72a5f7a7d91e7a6440f5e3f..6f196294568164f7cb53ae20f4e1cef1cca1ed52 100644 --- a/ets2panda/ir/ts/tsTypeReference.h +++ b/ets2panda/ir/ts/tsTypeReference.h @@ -48,6 +48,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/tsUnionType.cpp b/ets2panda/ir/ts/tsUnionType.cpp index 6a55683ea6a051026af1846a669efbd3171eb8f2..802d5d65c7695cdd3ada084044b419d576a14186 100644 --- a/ets2panda/ir/ts/tsUnionType.cpp +++ b/ets2panda/ir/ts/tsUnionType.cpp @@ -16,6 +16,8 @@ #include "tsUnionType.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -38,21 +40,24 @@ void TSUnionType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSUnionType"}, {"types", types_}}); } -void TSUnionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSUnionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -checker::Type *TSUnionType::Check([[maybe_unused]] checker::TSChecker *checker) +void TSUnionType::Compile(compiler::ETSGen *etsg) const { - for (auto *it : types_) { - it->Check(checker); - } + etsg->GetAstCompiler()->Compile(this); +} - GetType(checker); - return nullptr; +checker::Type *TSUnionType::Check([[maybe_unused]] checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *TSUnionType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSUnionType::GetType(checker::TSChecker *checker) diff --git a/ets2panda/ir/ts/tsUnionType.h b/ets2panda/ir/ts/tsUnionType.h index feaa03b28268044c85a438751015bda6aded7c34..aa31b0ba6e9b9e574e79f953194e51a0aacf0c5c 100644 --- a/ets2panda/ir/ts/tsUnionType.h +++ b/ets2panda/ir/ts/tsUnionType.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; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; diff --git a/ets2panda/lexer/ETSLexer.cpp b/ets2panda/lexer/ETSLexer.cpp index aa5b41719e415209dd3a73e0980931a12c6fa3fc..ba264d73d84dee6fb1c11309233521df9912385c 100644 --- a/ets2panda/lexer/ETSLexer.cpp +++ b/ets2panda/lexer/ETSLexer.cpp @@ -72,6 +72,21 @@ bool ETSLexer::ScanCharLiteral() return true; } +void ETSLexer::CheckNumberLiteralEnd() +{ + if (Iterator().Peek() == LEX_CHAR_LOWERCASE_F) { + GetToken().flags_ |= TokenFlags::NUMBER_FLOAT; + GetToken().src_ = SourceView(GetToken().Start().index, Iterator().Index()); + Iterator().Forward(1); + const auto next_cp = Iterator().PeekCp(); + if (KeywordsUtil::IsIdentifierStart(next_cp) || IsDecimalDigit(next_cp)) { + ThrowError("Invalid numeric literal"); + } + } else { + Lexer::CheckNumberLiteralEnd(); + } +} + void ETSLexer::CheckUtf16Compatible(char32_t cp) const { if (cp >= util::StringView::Constants::CELESTIAL_OFFSET) { diff --git a/ets2panda/lexer/ETSLexer.h b/ets2panda/lexer/ETSLexer.h index 1ad9801099336f62558f21e607ea0b0dc1975223..6c7c7b43e9dbfd0973688763c19f02a692152add 100644 --- a/ets2panda/lexer/ETSLexer.h +++ b/ets2panda/lexer/ETSLexer.h @@ -48,6 +48,7 @@ public: } } + void CheckNumberLiteralEnd() override; void CheckUtf16Compatible(char32_t cp) const; void ConvertNumber(const std::string &utf8, NumberFlags flags) override; diff --git a/ets2panda/lexer/lexer.h b/ets2panda/lexer/lexer.h index 4f8cd73a1c419a0fb8f80c11bb5d906afc8a9bbb..e5f31a8d6dd3e1bcb007a8793b276013c65f1717 100644 --- a/ets2panda/lexer/lexer.h +++ b/ets2panda/lexer/lexer.h @@ -267,7 +267,7 @@ protected: virtual void ConvertNumber(const std::string &utf8, NumberFlags flags); void ScanDecimalLiteral(); void ScanDecimalDigits(bool allow_numeric_separator); - void CheckNumberLiteralEnd(); + virtual void CheckNumberLiteralEnd(); inline static uint32_t HexValue(char32_t ch); inline static bool IsDecimalDigit(uint32_t cp); diff --git a/ets2panda/lexer/token/token.h b/ets2panda/lexer/token/token.h index 860e5cbf4b5743e1d9c2a94a3735ca3d694c221f..500e7ae9a03a774d8356661c05a94fb4e51bf394 100644 --- a/ets2panda/lexer/token/token.h +++ b/ets2panda/lexer/token/token.h @@ -29,7 +29,8 @@ enum class TokenFlags : uint32_t { NEW_LINE = 1U << 0U, HAS_ESCAPE = 1U << 2U, NUMBER_BIGINT = 1U << 3U, - NUMBER_HAS_UNDERSCORE = 1U << 4U, + NUMBER_FLOAT = 1U << 4U, + NUMBER_HAS_UNDERSCORE = 1U << 5U, }; DEFINE_BITOPS(TokenFlags) diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 5d2da9eaafa61605feee038dbb1a7260cfcfc392..e588da27c2d3acc43b375c32e62e113be3417c62 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -88,6 +88,7 @@ #include "ir/ets/etsPackageDeclaration.h" #include "ir/ets/etsWildcardType.h" #include "ir/ets/etsNewArrayInstanceExpression.h" +#include "ir/ets/etsTuple.h" #include "ir/ets/etsFunctionType.h" #include "ir/ets/etsNewClassInstanceExpression.h" #include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" @@ -2313,13 +2314,15 @@ ir::MethodDefinition *ETSParser::CreateProxyMethodDefinition(ir::MethodDefinitio proxy_method += ' '; if (return_type != "void") { - if (auto *const cls_scope = VarBinder()->GetScope()->AsClassScope(); cls_scope->Parent()->IsGlobalScope()) { - proxy_method += "return "; - } else if (method->IsStatic()) { + proxy_method += "return "; + } + + if (auto *const cls_scope = VarBinder()->GetScope()->AsClassScope(); !cls_scope->Parent()->IsGlobalScope()) { + if (method->IsStatic()) { ASSERT(ident_node != nullptr); - proxy_method += "return " + ident_node->Name().Mutf8() + "."; + proxy_method += ident_node->Name().Mutf8() + "."; } else { - proxy_method += "return this."; + proxy_method += "this."; } } @@ -2714,6 +2717,77 @@ ir::TypeNode *ETSParser::ParseFunctionType() return func_type; } +ir::TypeNode *ETSParser::ParseETSTupleType(TypeAnnotationParsingOptions *const options) +{ + ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET); + + const auto start_loc = Lexer()->GetToken().Start(); + Lexer()->NextToken(); // eat '[' + + ArenaVector tuple_type_list(Allocator()->Adapter()); + auto *const tuple_type = AllocNode(Allocator()); + + bool spread_type_present = false; + + while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { + // Parse named parameter if name presents + if ((Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) && + (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON)) { + ExpectIdentifier(); + Lexer()->NextToken(); // eat ':' + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { + if (spread_type_present) { + ThrowSyntaxError("Only one spread type declaration allowed, at the last index"); + } + + spread_type_present = true; + Lexer()->NextToken(); // eat '...' + } else if (spread_type_present) { + // This can't be implemented to any index, with type consistency. If a spread type is in the middle of the + // tuple, then bounds check can't be made for element access, so the type of elements after the spread can't + // be determined in compile time. + ThrowSyntaxError("Spread type must be at the last index in the tuple type"); + } + + auto *const current_type_annotation = ParseTypeAnnotation(options); + current_type_annotation->SetParent(tuple_type); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { + // TODO(mmartin): implement optional types for tuples + ThrowSyntaxError("Optional types in tuples are not yet implemented."); + } + + if (spread_type_present) { + if (!current_type_annotation->IsTSArrayType()) { + ThrowSyntaxError("Spread type must be an array type"); + } + + tuple_type->SetSpreadType(current_type_annotation); + } else { + tuple_type_list.push_back(current_type_annotation); + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { + Lexer()->NextToken(); // eat comma + continue; + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { + ThrowSyntaxError("Comma is mandatory between elements in a tuple type declaration"); + } + } + + Lexer()->NextToken(); // eat ']' + + tuple_type->SetTypeAnnotationsList(tuple_type_list); + const auto end_loc = Lexer()->GetToken().End(); + tuple_type->SetRange({start_loc, end_loc}); + + return tuple_type; +} + // Just to reduce the size of ParseTypeAnnotation(...) method std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options) { @@ -2799,6 +2873,10 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota type_annotation = ParseTypeFormatPlaceholder(); break; } + case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { + type_annotation = ParseETSTupleType(options); + break; + } default: { break; } @@ -3732,7 +3810,7 @@ ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags) return ParseUndefinedLiteral(); } case lexer::TokenType::LITERAL_NUMBER: { - return ParseNumberLiteral(); + return ParseCoercedNumberLiteral(); } case lexer::TokenType::LITERAL_STRING: { return ParseStringLiteral(); @@ -4545,6 +4623,22 @@ void ETSParser::ParseTrailingBlock(ir::CallExpression *call_expr) } } +ir::Expression *ETSParser::ParseCoercedNumberLiteral() +{ + if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_FLOAT) != 0U) { + auto *number = AllocNode(Lexer()->GetToken().GetNumber()); + number->SetRange(Lexer()->GetToken().Loc()); + auto *float_type = AllocNode(ir::PrimitiveType::FLOAT); + float_type->SetRange(Lexer()->GetToken().Loc()); + auto *as_expression = AllocNode(number, float_type, true); + as_expression->SetRange(Lexer()->GetToken().Loc()); + + Lexer()->NextToken(); + return as_expression; + } + return ParseNumberLiteral(); +} + void ETSParser::CheckDeclare() { ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index e75558299cabb6bcf0f1fccb21b98a4e95f2d496..91146099b9cbddd623fa0f6bd88fea058b45f670 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -140,6 +140,7 @@ private: ir::ClassProperty *ParseInterfaceField(const lexer::SourcePosition &start_loc); ir::Expression *ParseInitializer(); ir::ArrayExpression *ParseArrayLiteral(); + ir::Expression *ParseCoercedNumberLiteral(); ir::MethodDefinition *ParseInterfaceMethod(ir::ModifierFlags flags); std::tuple ParseClassMemberAccessModifiers(); ir::ModifierFlags ParseClassFieldModifiers(bool seen_static); @@ -170,6 +171,7 @@ private: ir::TSIntersectionType *ParseIntersectionType(ir::Expression *type); ir::TypeNode *ParseWildcardType(TypeAnnotationParsingOptions *options); ir::TypeNode *ParseFunctionType(); + ir::TypeNode *ParseETSTupleType(TypeAnnotationParsingOptions *options); void CreateClassFunctionDeclaration(ir::MethodDefinition *method); std::pair CheckDefaultParameters(const ir::ScriptFunction *function) const; ir::MethodDefinition *CreateProxyMethodDefinition(ir::MethodDefinition const *method, diff --git a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt index 1a6d15476768b54e8e3d1f7ab39781b98ea452bd..358b42f55c98e3292723a560ce566c272d53dcda 100644 --- a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt @@ -267,7 +267,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "void", + "name": "string", "decorators": [], "loc": { "start": { @@ -276,7 +276,7 @@ }, "end": { "line": 17, - "column": 36 + "column": 38 } } }, @@ -287,7 +287,7 @@ }, "end": { "line": 17, - "column": 39 + "column": 41 } } }, @@ -298,21 +298,49 @@ }, "end": { "line": 17, - "column": 39 + "column": 41 } } }, "body": { - "type": "NumberLiteral", - "value": 10, + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "10", + "loc": { + "start": { + "line": 17, + "column": 42 + }, + "end": { + "line": 17, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], "loc": { "start": { - "line": 17, - "column": 40 + "line": 1, + "column": 1 }, "end": { - "line": 17, - "column": 42 + "line": 1, + "column": 1 } } }, @@ -323,7 +351,7 @@ }, "end": { "line": 17, - "column": 42 + "column": 46 } } }, @@ -334,7 +362,7 @@ }, "end": { "line": 17, - "column": 42 + "column": 46 } } }, @@ -345,7 +373,7 @@ }, "end": { "line": 17, - "column": 42 + "column": 46 } } } @@ -358,7 +386,7 @@ }, "end": { "line": 17, - "column": 43 + "column": 47 } } }, @@ -487,4 +515,4 @@ } } } -TypeError: Return statements return type is not compatible with the containing functions return type [lambdaExpressionWithoutBlockStatementDifferentType.ets:17:28] +TypeError: Initializers type is not assignable to the target type [lambdaExpressionWithoutBlockStatementDifferentType.ets:17:28] diff --git a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType.ets b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType.ets index d56badf324668d5b0fc4f7c84e247abee92f8dd6..0b10c1c6be260c23b1ec3ed8d345e1a2b0f97d28 100644 --- a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType.ets +++ b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType.ets @@ -14,6 +14,6 @@ */ function main(): void { - let test1: () => int = (): void => 10; + let test1: () => int = (): string => "10"; test1(); } diff --git a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction-expected.txt b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction-expected.txt index 7ea24132d85f3d62d07b9008fd4661f1826b0059..8d7e876115ad8ee8ae6cba16f7c3ea6c7ee8f5b2 100644 --- a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction-expected.txt @@ -438,32 +438,60 @@ } }, "body": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "test2", - "decorators": [], - "loc": { - "start": { - "line": 21, - "column": 39 + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "test2", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 39 + }, + "end": { + "line": 21, + "column": 44 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 21, + "column": 39 + }, + "end": { + "line": 21, + "column": 46 + } + } }, - "end": { - "line": 21, - "column": 44 + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } } } - }, - "arguments": [], - "optional": false, + ], "loc": { "start": { - "line": 21, - "column": 39 + "line": 1, + "column": 1 }, "end": { - "line": 21, - "column": 46 + "line": 1, + "column": 1 } } }, @@ -638,4 +666,4 @@ } } } -TypeError: Return statements return type is not compatible with the containing functions return type [lambdaExpressionWithoutBlockStatementDifferentTypeInfunction.ets:21:28] +TypeError: Return statement type is not compatible with the enclosing method's return type. [lambdaExpressionWithoutBlockStatementDifferentTypeInfunction.ets:21:39] diff --git a/ets2panda/test/compiler/ets/tuple_types_1-expected.txt b/ets2panda/test/compiler/ets/tuple_types_1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1fa7dad85ccf7b373d40cfabfe8231e8d165d1e1 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_1-expected.txt @@ -0,0 +1,7466 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 19 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 19 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 20 + }, + "end": { + "line": 16, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 17, + "column": 27 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 30 + }, + "end": { + "line": 17, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "num_str_str_type", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 6 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 26 + }, + "end": { + "line": 19, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 26 + }, + "end": { + "line": 19, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 26 + }, + "end": { + "line": 19, + "column": 33 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 34 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 34 + }, + "end": { + "line": 19, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 34 + }, + "end": { + "line": 19, + "column": 41 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 49 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 25 + }, + "end": { + "line": 19, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 50 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "num_str_str_with_spread", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 6 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "num_str_str_type", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 50 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 54 + }, + "end": { + "line": 20, + "column": 60 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 54 + }, + "end": { + "line": 20, + "column": 61 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 54 + }, + "end": { + "line": 20, + "column": 61 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 62 + }, + "end": { + "line": 20, + "column": 63 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 32 + }, + "end": { + "line": 20, + "column": 64 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 64 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 13 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a0", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 22, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 22, + "column": 25 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "args", + "typeAnnotation": { + "type": "ETSTuple", + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 36 + }, + "end": { + "line": 22, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 36 + }, + "end": { + "line": 22, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 36 + }, + "end": { + "line": 22, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 44 + }, + "end": { + "line": 22, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 32 + }, + "end": { + "line": 22, + "column": 46 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 26 + }, + "end": { + "line": 22, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 26 + }, + "end": { + "line": 22, + "column": 46 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 48 + }, + "end": { + "line": 22, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 48 + }, + "end": { + "line": 22, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 48 + }, + "end": { + "line": 22, + "column": 56 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 23, + "column": 12 + }, + "end": { + "line": 23, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 55 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 13 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 13 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "tup_arr_1", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "num_str_str_type", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 22 + }, + "end": { + "line": 28, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 22 + }, + "end": { + "line": 28, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 22 + }, + "end": { + "line": 28, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 41 + }, + "end": { + "line": 28, + "column": 42 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 20 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 29, + "column": 10 + }, + "end": { + "line": 29, + "column": 11 + } + } + }, + { + "type": "StringLiteral", + "value": "a", + "loc": { + "start": { + "line": 29, + "column": 13 + }, + "end": { + "line": 29, + "column": 16 + } + } + }, + { + "type": "StringLiteral", + "value": "d", + "loc": { + "start": { + "line": 29, + "column": 18 + }, + "end": { + "line": 29, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 29, + "column": 9 + }, + "end": { + "line": 29, + "column": 22 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 30, + "column": 10 + }, + "end": { + "line": 30, + "column": 11 + } + } + }, + { + "type": "StringLiteral", + "value": "b", + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 30, + "column": 16 + } + } + }, + { + "type": "StringLiteral", + "value": "e", + "loc": { + "start": { + "line": 30, + "column": 18 + }, + "end": { + "line": 30, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 30, + "column": 9 + }, + "end": { + "line": 30, + "column": 22 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 31, + "column": 10 + }, + "end": { + "line": 31, + "column": 11 + } + } + }, + { + "type": "StringLiteral", + "value": "c", + "loc": { + "start": { + "line": 31, + "column": 13 + }, + "end": { + "line": 31, + "column": 16 + } + } + }, + { + "type": "StringLiteral", + "value": "f", + "loc": { + "start": { + "line": 31, + "column": 18 + }, + "end": { + "line": 31, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 31, + "column": 9 + }, + "end": { + "line": 31, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 28, + "column": 43 + }, + "end": { + "line": 32, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 32, + "column": 6 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 32, + "column": 7 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "tup_arr_2", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "num_str_str_with_spread", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 34, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 34, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 34, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 48 + }, + "end": { + "line": 34, + "column": 49 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 11 + }, + "end": { + "line": 34, + "column": 20 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_1", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 10 + }, + "end": { + "line": 35, + "column": 19 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 35, + "column": 20 + }, + "end": { + "line": 35, + "column": 21 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 10 + }, + "end": { + "line": 35, + "column": 22 + } + } + }, + { + "type": "NumberLiteral", + "value": 250, + "loc": { + "start": { + "line": 35, + "column": 24 + }, + "end": { + "line": 35, + "column": 27 + } + } + } + ], + "loc": { + "start": { + "line": 35, + "column": 9 + }, + "end": { + "line": 35, + "column": 28 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_1", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 10 + }, + "end": { + "line": 36, + "column": 19 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 36, + "column": 20 + }, + "end": { + "line": 36, + "column": 21 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 36, + "column": 10 + }, + "end": { + "line": 36, + "column": 22 + } + } + }, + { + "type": "NumberLiteral", + "value": 250, + "loc": { + "start": { + "line": 36, + "column": 24 + }, + "end": { + "line": 36, + "column": 27 + } + } + }, + { + "type": "NumberLiteral", + "value": 260, + "loc": { + "start": { + "line": 36, + "column": 29 + }, + "end": { + "line": 36, + "column": 32 + } + } + } + ], + "loc": { + "start": { + "line": 36, + "column": 9 + }, + "end": { + "line": 36, + "column": 33 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_1", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 10 + }, + "end": { + "line": 37, + "column": 19 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 37, + "column": 20 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 37, + "column": 10 + }, + "end": { + "line": 37, + "column": 22 + } + } + }, + { + "type": "NumberLiteral", + "value": 300, + "loc": { + "start": { + "line": 37, + "column": 24 + }, + "end": { + "line": 37, + "column": 27 + } + } + }, + { + "type": "NumberLiteral", + "value": 300, + "loc": { + "start": { + "line": 37, + "column": 29 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + { + "type": "NumberLiteral", + "value": 300, + "loc": { + "start": { + "line": 37, + "column": 34 + }, + "end": { + "line": 37, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 38 + } + } + } + ], + "loc": { + "start": { + "line": 34, + "column": 50 + }, + "end": { + "line": 38, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 11 + }, + "end": { + "line": 38, + "column": 6 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 34, + "column": 5 + }, + "end": { + "line": 38, + "column": 7 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a_var", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 11 + }, + "end": { + "line": 40, + "column": 16 + } + } + }, + "init": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 19 + }, + "end": { + "line": 40, + "column": 28 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 40, + "column": 29 + }, + "end": { + "line": 40, + "column": 30 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 19 + }, + "end": { + "line": 40, + "column": 31 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 40, + "column": 32 + }, + "end": { + "line": 40, + "column": 33 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 19 + }, + "end": { + "line": 40, + "column": 34 + } + } + }, + "right": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 37 + }, + "end": { + "line": 40, + "column": 46 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 40, + "column": 47 + }, + "end": { + "line": 40, + "column": 48 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 37 + }, + "end": { + "line": 40, + "column": 49 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 40, + "column": 50 + }, + "end": { + "line": 40, + "column": 51 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 37 + }, + "end": { + "line": 40, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 40, + "column": 19 + }, + "end": { + "line": 40, + "column": 52 + } + } + }, + "right": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 55 + }, + "end": { + "line": 40, + "column": 64 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 40, + "column": 65 + }, + "end": { + "line": 40, + "column": 66 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 55 + }, + "end": { + "line": 40, + "column": 67 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 40, + "column": 68 + }, + "end": { + "line": 40, + "column": 69 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 55 + }, + "end": { + "line": 40, + "column": 70 + } + } + }, + "loc": { + "start": { + "line": 40, + "column": 19 + }, + "end": { + "line": 40, + "column": 70 + } + } + }, + "loc": { + "start": { + "line": 40, + "column": 11 + }, + "end": { + "line": 40, + "column": 70 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 40, + "column": 5 + }, + "end": { + "line": 40, + "column": 71 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b_var", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 11 + }, + "end": { + "line": 41, + "column": 16 + } + } + }, + "init": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 19 + }, + "end": { + "line": 41, + "column": 28 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 41, + "column": 29 + }, + "end": { + "line": 41, + "column": 30 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 41, + "column": 19 + }, + "end": { + "line": 41, + "column": 31 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 41, + "column": 32 + }, + "end": { + "line": 41, + "column": 33 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 41, + "column": 19 + }, + "end": { + "line": 41, + "column": 34 + } + } + }, + "right": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 37 + }, + "end": { + "line": 41, + "column": 46 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 41, + "column": 47 + }, + "end": { + "line": 41, + "column": 48 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 41, + "column": 37 + }, + "end": { + "line": 41, + "column": 49 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 41, + "column": 50 + }, + "end": { + "line": 41, + "column": 51 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 41, + "column": 37 + }, + "end": { + "line": 41, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 41, + "column": 19 + }, + "end": { + "line": 41, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 41, + "column": 11 + }, + "end": { + "line": 41, + "column": 52 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 41, + "column": 5 + }, + "end": { + "line": 41, + "column": 53 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c_var", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 11 + }, + "end": { + "line": 42, + "column": 16 + } + } + }, + "init": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 19 + }, + "end": { + "line": 42, + "column": 28 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 42, + "column": 29 + }, + "end": { + "line": 42, + "column": 30 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 42, + "column": 19 + }, + "end": { + "line": 42, + "column": 31 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 42, + "column": 32 + }, + "end": { + "line": 42, + "column": 33 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 42, + "column": 19 + }, + "end": { + "line": 42, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 42, + "column": 11 + }, + "end": { + "line": 42, + "column": 34 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 42, + "column": 5 + }, + "end": { + "line": 42, + "column": 35 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 44, + "column": 5 + }, + "end": { + "line": 44, + "column": 8 + } + } + }, + "arguments": [ + { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_1", + "decorators": [], + "loc": { + "start": { + "line": 44, + "column": 9 + }, + "end": { + "line": 44, + "column": 18 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 44, + "column": 19 + }, + "end": { + "line": 44, + "column": 20 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 44, + "column": 9 + }, + "end": { + "line": 44, + "column": 21 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 44, + "column": 22 + }, + "end": { + "line": 44, + "column": 23 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 44, + "column": 9 + }, + "end": { + "line": 44, + "column": 24 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 44, + "column": 27 + }, + "end": { + "line": 44, + "column": 36 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 44, + "column": 37 + }, + "end": { + "line": 44, + "column": 38 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 44, + "column": 27 + }, + "end": { + "line": 44, + "column": 39 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 44, + "column": 40 + }, + "end": { + "line": 44, + "column": 41 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 44, + "column": 27 + }, + "end": { + "line": 44, + "column": 42 + } + } + } + ], + "loc": { + "start": { + "line": 44, + "column": 26 + }, + "end": { + "line": 44, + "column": 43 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 44, + "column": 5 + }, + "end": { + "line": 44, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 44, + "column": 5 + }, + "end": { + "line": 44, + "column": 45 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 5 + }, + "end": { + "line": 45, + "column": 8 + } + } + }, + "arguments": [ + { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_1", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 9 + }, + "end": { + "line": 45, + "column": 18 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 45, + "column": 19 + }, + "end": { + "line": 45, + "column": 20 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 9 + }, + "end": { + "line": 45, + "column": 21 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 45, + "column": 22 + }, + "end": { + "line": 45, + "column": 23 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 9 + }, + "end": { + "line": 45, + "column": 24 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 27 + }, + "end": { + "line": 45, + "column": 36 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 45, + "column": 37 + }, + "end": { + "line": 45, + "column": 38 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 27 + }, + "end": { + "line": 45, + "column": 39 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 45, + "column": 40 + }, + "end": { + "line": 45, + "column": 41 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 27 + }, + "end": { + "line": 45, + "column": 42 + } + } + }, + { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "tup_arr_2", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 44 + }, + "end": { + "line": 45, + "column": 53 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 45, + "column": 54 + }, + "end": { + "line": 45, + "column": 55 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 44 + }, + "end": { + "line": 45, + "column": 56 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 45, + "column": 57 + }, + "end": { + "line": 45, + "column": 58 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 44 + }, + "end": { + "line": 45, + "column": 59 + } + } + } + ], + "loc": { + "start": { + "line": 45, + "column": 26 + }, + "end": { + "line": 45, + "column": 60 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 45, + "column": 5 + }, + "end": { + "line": 45, + "column": 61 + } + } + }, + "loc": { + "start": { + "line": 45, + "column": 5 + }, + "end": { + "line": 45, + "column": 62 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "arr", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 47, + "column": 14 + }, + "end": { + "line": 47, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 47, + "column": 14 + }, + "end": { + "line": 47, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 47, + "column": 14 + }, + "end": { + "line": 47, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 47, + "column": 23 + }, + "end": { + "line": 47, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 47, + "column": 9 + }, + "end": { + "line": 47, + "column": 12 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 47, + "column": 26 + }, + "end": { + "line": 47, + "column": 27 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 47, + "column": 28 + }, + "end": { + "line": 47, + "column": 29 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 47, + "column": 30 + }, + "end": { + "line": 47, + "column": 31 + } + } + }, + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 47, + "column": 32 + }, + "end": { + "line": 47, + "column": 33 + } + } + }, + { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 47, + "column": 34 + }, + "end": { + "line": 47, + "column": 35 + } + } + } + ], + "loc": { + "start": { + "line": 47, + "column": 25 + }, + "end": { + "line": 47, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 47, + "column": 9 + }, + "end": { + "line": 47, + "column": 36 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 47, + "column": 5 + }, + "end": { + "line": 47, + "column": 37 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "double_ref_tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 48, + "column": 26 + }, + "end": { + "line": 48, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 26 + }, + "end": { + "line": 48, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 26 + }, + "end": { + "line": 48, + "column": 33 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 48, + "column": 34 + }, + "end": { + "line": 48, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 34 + }, + "end": { + "line": 48, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 34 + }, + "end": { + "line": 48, + "column": 41 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 48, + "column": 42 + }, + "end": { + "line": 48, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 42 + }, + "end": { + "line": 48, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 42 + }, + "end": { + "line": 48, + "column": 49 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 48, + "column": 25 + }, + "end": { + "line": 48, + "column": 51 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 48, + "column": 9 + }, + "end": { + "line": 48, + "column": 23 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 6, + "loc": { + "start": { + "line": 48, + "column": 53 + }, + "end": { + "line": 48, + "column": 54 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 48, + "column": 58 + }, + "end": { + "line": 48, + "column": 64 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 53 + }, + "end": { + "line": 48, + "column": 54 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 7, + "loc": { + "start": { + "line": 48, + "column": 66 + }, + "end": { + "line": 48, + "column": 67 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 48, + "column": 71 + }, + "end": { + "line": 48, + "column": 77 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 66 + }, + "end": { + "line": 48, + "column": 67 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 8, + "loc": { + "start": { + "line": 48, + "column": 79 + }, + "end": { + "line": 48, + "column": 80 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 48, + "column": 84 + }, + "end": { + "line": 48, + "column": 90 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 79 + }, + "end": { + "line": 48, + "column": 80 + } + } + } + ], + "loc": { + "start": { + "line": 48, + "column": 52 + }, + "end": { + "line": 48, + "column": 91 + } + } + }, + "loc": { + "start": { + "line": 48, + "column": 9 + }, + "end": { + "line": 48, + "column": 91 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 48, + "column": 5 + }, + "end": { + "line": 48, + "column": 92 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a_arr", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 49, + "column": 16 + }, + "end": { + "line": 49, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 49, + "column": 16 + }, + "end": { + "line": 49, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 49, + "column": 16 + }, + "end": { + "line": 49, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 49, + "column": 19 + }, + "end": { + "line": 49, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 49, + "column": 9 + }, + "end": { + "line": 49, + "column": 14 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 49, + "column": 9 + }, + "end": { + "line": 49, + "column": 14 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 49, + "column": 5 + }, + "end": { + "line": 49, + "column": 20 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b_tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 50, + "column": 17 + }, + "end": { + "line": 50, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 17 + }, + "end": { + "line": 50, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 17 + }, + "end": { + "line": 50, + "column": 19 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 50, + "column": 20 + }, + "end": { + "line": 50, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 20 + }, + "end": { + "line": 50, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 20 + }, + "end": { + "line": 50, + "column": 22 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 50, + "column": 16 + }, + "end": { + "line": 50, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 50, + "column": 9 + }, + "end": { + "line": 50, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 50, + "column": 30 + }, + "end": { + "line": 50, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 30 + }, + "end": { + "line": 50, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 30 + }, + "end": { + "line": 50, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 50, + "column": 26 + }, + "end": { + "line": 50, + "column": 34 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 50, + "column": 39 + }, + "end": { + "line": 50, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 39 + }, + "end": { + "line": 50, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 39 + }, + "end": { + "line": 50, + "column": 41 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 50, + "column": 35 + }, + "end": { + "line": 50, + "column": 43 + } + } + } + ], + "loc": { + "start": { + "line": 50, + "column": 25 + }, + "end": { + "line": 50, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 50, + "column": 9 + }, + "end": { + "line": 50, + "column": 43 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 50, + "column": 5 + }, + "end": { + "line": 50, + "column": 44 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b_arr", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 16 + }, + "end": { + "line": 51, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 16 + }, + "end": { + "line": 51, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 16 + }, + "end": { + "line": 51, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 20 + }, + "end": { + "line": 51, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 9 + }, + "end": { + "line": 51, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 27 + }, + "end": { + "line": 51, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 27 + }, + "end": { + "line": 51, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 27 + }, + "end": { + "line": 51, + "column": 29 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 51, + "column": 23 + }, + "end": { + "line": 51, + "column": 31 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 36 + }, + "end": { + "line": 51, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 36 + }, + "end": { + "line": 51, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 36 + }, + "end": { + "line": 51, + "column": 38 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 51, + "column": 32 + }, + "end": { + "line": 51, + "column": 40 + } + } + } + ], + "loc": { + "start": { + "line": 51, + "column": 22 + }, + "end": { + "line": 51, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 51, + "column": 9 + }, + "end": { + "line": 51, + "column": 40 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 51, + "column": 5 + }, + "end": { + "line": 51, + "column": 41 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "arr", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 5 + }, + "end": { + "line": 53, + "column": 8 + } + } + }, + "right": { + "type": "Identifier", + "name": "double_ref_tup", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 11 + }, + "end": { + "line": 53, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 53, + "column": 5 + }, + "end": { + "line": 53, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 53, + "column": 5 + }, + "end": { + "line": 53, + "column": 26 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "a_arr", + "decorators": [], + "loc": { + "start": { + "line": 54, + "column": 5 + }, + "end": { + "line": 54, + "column": 10 + } + } + }, + "right": { + "type": "Identifier", + "name": "b_tup", + "decorators": [], + "loc": { + "start": { + "line": 54, + "column": 13 + }, + "end": { + "line": 54, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 54, + "column": 5 + }, + "end": { + "line": 54, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 54, + "column": 5 + }, + "end": { + "line": 54, + "column": 19 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "b_arr", + "decorators": [], + "loc": { + "start": { + "line": 55, + "column": 5 + }, + "end": { + "line": 55, + "column": 10 + } + } + }, + "right": { + "type": "Identifier", + "name": "b_tup", + "decorators": [], + "loc": { + "start": { + "line": 55, + "column": 13 + }, + "end": { + "line": 55, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 55, + "column": 5 + }, + "end": { + "line": 55, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 55, + "column": 5 + }, + "end": { + "line": 55, + "column": 19 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "spread_tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 22 + }, + "end": { + "line": 57, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 22 + }, + "end": { + "line": 57, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 22 + }, + "end": { + "line": 57, + "column": 29 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 33 + }, + "end": { + "line": 57, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 33 + }, + "end": { + "line": 57, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 33 + }, + "end": { + "line": 57, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 41 + }, + "end": { + "line": 57, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 21 + }, + "end": { + "line": 57, + "column": 44 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 9 + }, + "end": { + "line": 57, + "column": 19 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 6, + "loc": { + "start": { + "line": 57, + "column": 46 + }, + "end": { + "line": 57, + "column": 47 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 57, + "column": 51 + }, + "end": { + "line": 57, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 46 + }, + "end": { + "line": 57, + "column": 47 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 7, + "loc": { + "start": { + "line": 57, + "column": 58 + }, + "end": { + "line": 57, + "column": 59 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 57, + "column": 63 + }, + "end": { + "line": 57, + "column": 69 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 58 + }, + "end": { + "line": 57, + "column": 59 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 8, + "loc": { + "start": { + "line": 57, + "column": 70 + }, + "end": { + "line": 57, + "column": 71 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 57, + "column": 75 + }, + "end": { + "line": 57, + "column": 81 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 70 + }, + "end": { + "line": 57, + "column": 71 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 9, + "loc": { + "start": { + "line": 57, + "column": 83 + }, + "end": { + "line": 57, + "column": 84 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 57, + "column": 88 + }, + "end": { + "line": 57, + "column": 94 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 83 + }, + "end": { + "line": 57, + "column": 84 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 10, + "loc": { + "start": { + "line": 57, + "column": 96 + }, + "end": { + "line": 57, + "column": 98 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 57, + "column": 102 + }, + "end": { + "line": 57, + "column": 108 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 96 + }, + "end": { + "line": 57, + "column": 98 + } + } + } + ], + "loc": { + "start": { + "line": 57, + "column": 45 + }, + "end": { + "line": 57, + "column": 109 + } + } + }, + "loc": { + "start": { + "line": 57, + "column": 9 + }, + "end": { + "line": 57, + "column": 109 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 57, + "column": 5 + }, + "end": { + "line": 57, + "column": 110 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "num_ref_arr", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 58, + "column": 22 + }, + "end": { + "line": 58, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 22 + }, + "end": { + "line": 58, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 22 + }, + "end": { + "line": 58, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 31 + }, + "end": { + "line": 58, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 58, + "column": 9 + }, + "end": { + "line": 58, + "column": 20 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 58, + "column": 34 + }, + "end": { + "line": 58, + "column": 35 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 58, + "column": 39 + }, + "end": { + "line": 58, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 34 + }, + "end": { + "line": 58, + "column": 35 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 58, + "column": 46 + }, + "end": { + "line": 58, + "column": 47 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 58, + "column": 51 + }, + "end": { + "line": 58, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 46 + }, + "end": { + "line": 58, + "column": 47 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 58, + "column": 58 + }, + "end": { + "line": 58, + "column": 59 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 58, + "column": 63 + }, + "end": { + "line": 58, + "column": 69 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 58 + }, + "end": { + "line": 58, + "column": 59 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 58, + "column": 70 + }, + "end": { + "line": 58, + "column": 71 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 58, + "column": 75 + }, + "end": { + "line": 58, + "column": 81 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 70 + }, + "end": { + "line": 58, + "column": 71 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 58, + "column": 82 + }, + "end": { + "line": 58, + "column": 83 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 58, + "column": 87 + }, + "end": { + "line": 58, + "column": 93 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 82 + }, + "end": { + "line": 58, + "column": 83 + } + } + } + ], + "loc": { + "start": { + "line": 58, + "column": 33 + }, + "end": { + "line": 58, + "column": 94 + } + } + }, + "loc": { + "start": { + "line": 58, + "column": 9 + }, + "end": { + "line": 58, + "column": 94 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 58, + "column": 5 + }, + "end": { + "line": 58, + "column": 95 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "spread_tup", + "decorators": [], + "loc": { + "start": { + "line": 60, + "column": 5 + }, + "end": { + "line": 60, + "column": 15 + } + } + }, + "right": { + "type": "Identifier", + "name": "num_ref_arr", + "decorators": [], + "loc": { + "start": { + "line": 60, + "column": 18 + }, + "end": { + "line": 60, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 60, + "column": 5 + }, + "end": { + "line": 60, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 60, + "column": 5 + }, + "end": { + "line": 60, + "column": 30 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "num_tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 19 + }, + "end": { + "line": 62, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 62, + "column": 19 + }, + "end": { + "line": 62, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 62, + "column": 19 + }, + "end": { + "line": 62, + "column": 26 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 27 + }, + "end": { + "line": 62, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 62, + "column": 27 + }, + "end": { + "line": 62, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 62, + "column": 27 + }, + "end": { + "line": 62, + "column": 34 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 62, + "column": 18 + }, + "end": { + "line": 62, + "column": 36 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 9 + }, + "end": { + "line": 62, + "column": 16 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 11, + "loc": { + "start": { + "line": 62, + "column": 38 + }, + "end": { + "line": 62, + "column": 40 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 62, + "column": 41 + }, + "end": { + "line": 62, + "column": 42 + } + } + } + ], + "loc": { + "start": { + "line": 62, + "column": 37 + }, + "end": { + "line": 62, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 62, + "column": 9 + }, + "end": { + "line": 62, + "column": 43 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 62, + "column": 5 + }, + "end": { + "line": 62, + "column": 44 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "num_prim_arr", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 63, + "column": 23 + }, + "end": { + "line": 63, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 63, + "column": 23 + }, + "end": { + "line": 63, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 63, + "column": 23 + }, + "end": { + "line": 63, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 63, + "column": 32 + }, + "end": { + "line": 63, + "column": 33 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 63, + "column": 9 + }, + "end": { + "line": 63, + "column": 21 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 63, + "column": 35 + }, + "end": { + "line": 63, + "column": 36 + } + } + }, + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 63, + "column": 37 + }, + "end": { + "line": 63, + "column": 38 + } + } + } + ], + "loc": { + "start": { + "line": 63, + "column": 34 + }, + "end": { + "line": 63, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 63, + "column": 9 + }, + "end": { + "line": 63, + "column": 39 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 63, + "column": 5 + }, + "end": { + "line": 63, + "column": 40 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "num_prim_arr", + "decorators": [], + "loc": { + "start": { + "line": 65, + "column": 5 + }, + "end": { + "line": 65, + "column": 17 + } + } + }, + "right": { + "type": "Identifier", + "name": "num_tup", + "decorators": [], + "loc": { + "start": { + "line": 65, + "column": 20 + }, + "end": { + "line": 65, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 65, + "column": 5 + }, + "end": { + "line": 65, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 65, + "column": 5 + }, + "end": { + "line": 65, + "column": 28 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "d_var", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 67, + "column": 17 + }, + "end": { + "line": 67, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 67, + "column": 17 + }, + "end": { + "line": 67, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 67, + "column": 17 + }, + "end": { + "line": 67, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 67, + "column": 25 + }, + "end": { + "line": 67, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 67, + "column": 25 + }, + "end": { + "line": 67, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 67, + "column": 25 + }, + "end": { + "line": 67, + "column": 32 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 67, + "column": 16 + }, + "end": { + "line": 67, + "column": 34 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 67, + "column": 9 + }, + "end": { + "line": 67, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 67, + "column": 36 + }, + "end": { + "line": 67, + "column": 37 + } + } + }, + { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 67, + "column": 39 + }, + "end": { + "line": 67, + "column": 42 + } + } + } + ], + "loc": { + "start": { + "line": 67, + "column": 35 + }, + "end": { + "line": 67, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 67, + "column": 9 + }, + "end": { + "line": 67, + "column": 43 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 67, + "column": 5 + }, + "end": { + "line": 67, + "column": 44 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "e_var", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 68, + "column": 17 + }, + "end": { + "line": 68, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 68, + "column": 17 + }, + "end": { + "line": 68, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 68, + "column": 17 + }, + "end": { + "line": 68, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 68, + "column": 25 + }, + "end": { + "line": 68, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 68, + "column": 25 + }, + "end": { + "line": 68, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 68, + "column": 25 + }, + "end": { + "line": 68, + "column": 32 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 68, + "column": 33 + }, + "end": { + "line": 68, + "column": 40 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 68, + "column": 16 + }, + "end": { + "line": 68, + "column": 43 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 68, + "column": 9 + }, + "end": { + "line": 68, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 68, + "column": 45 + }, + "end": { + "line": 68, + "column": 46 + } + } + }, + { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 68, + "column": 48 + }, + "end": { + "line": 68, + "column": 51 + } + } + }, + { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 68, + "column": 53 + }, + "end": { + "line": 68, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 68, + "column": 44 + }, + "end": { + "line": 68, + "column": 58 + } + } + }, + "loc": { + "start": { + "line": 68, + "column": 9 + }, + "end": { + "line": 68, + "column": 58 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 68, + "column": 5 + }, + "end": { + "line": 68, + "column": 59 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "f_var", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 17 + }, + "end": { + "line": 69, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 17 + }, + "end": { + "line": 69, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 17 + }, + "end": { + "line": 69, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 25 + }, + "end": { + "line": 69, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 25 + }, + "end": { + "line": 69, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 25 + }, + "end": { + "line": 69, + "column": 32 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 69, + "column": 33 + }, + "end": { + "line": 69, + "column": 40 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 42 + }, + "end": { + "line": 69, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 42 + }, + "end": { + "line": 69, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 42 + }, + "end": { + "line": 69, + "column": 49 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 50 + }, + "end": { + "line": 69, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 50 + }, + "end": { + "line": 69, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 69, + "column": 50 + }, + "end": { + "line": 69, + "column": 57 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 69, + "column": 16 + }, + "end": { + "line": 69, + "column": 58 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 9 + }, + "end": { + "line": 69, + "column": 14 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 69, + "column": 9 + }, + "end": { + "line": 69, + "column": 14 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 69, + "column": 5 + }, + "end": { + "line": 69, + "column": 58 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "f_var", + "decorators": [], + "loc": { + "start": { + "line": 70, + "column": 5 + }, + "end": { + "line": 70, + "column": 10 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 70, + "column": 14 + }, + "end": { + "line": 70, + "column": 15 + } + } + }, + { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 70, + "column": 17 + }, + "end": { + "line": 70, + "column": 20 + } + } + }, + { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 70, + "column": 22 + }, + "end": { + "line": 70, + "column": 26 + } + } + }, + { + "type": "NumberLiteral", + "value": 20, + "loc": { + "start": { + "line": 70, + "column": 28 + }, + "end": { + "line": 70, + "column": 30 + } + } + }, + { + "type": "StringLiteral", + "value": "B", + "loc": { + "start": { + "line": 70, + "column": 32 + }, + "end": { + "line": 70, + "column": 35 + } + } + } + ], + "loc": { + "start": { + "line": 70, + "column": 13 + }, + "end": { + "line": 70, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 70, + "column": 5 + }, + "end": { + "line": 70, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 70, + "column": 5 + }, + "end": { + "line": 70, + "column": 37 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "g_var", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 72, + "column": 17 + }, + "end": { + "line": 72, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 72, + "column": 17 + }, + "end": { + "line": 72, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 72, + "column": 17 + }, + "end": { + "line": 72, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 72, + "column": 25 + }, + "end": { + "line": 72, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 72, + "column": 25 + }, + "end": { + "line": 72, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 72, + "column": 25 + }, + "end": { + "line": 72, + "column": 32 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 72, + "column": 16 + }, + "end": { + "line": 72, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 72, + "column": 34 + }, + "end": { + "line": 72, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 72, + "column": 9 + }, + "end": { + "line": 72, + "column": 14 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 72, + "column": 9 + }, + "end": { + "line": 72, + "column": 14 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 72, + "column": 5 + }, + "end": { + "line": 72, + "column": 35 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "g_var", + "decorators": [], + "loc": { + "start": { + "line": 73, + "column": 5 + }, + "end": { + "line": 73, + "column": 10 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 73, + "column": 15 + }, + "end": { + "line": 73, + "column": 16 + } + } + }, + { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 73, + "column": 18 + }, + "end": { + "line": 73, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 73, + "column": 14 + }, + "end": { + "line": 73, + "column": 22 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 73, + "column": 25 + }, + "end": { + "line": 73, + "column": 26 + } + } + }, + { + "type": "StringLiteral", + "value": "B", + "loc": { + "start": { + "line": 73, + "column": 28 + }, + "end": { + "line": 73, + "column": 31 + } + } + } + ], + "loc": { + "start": { + "line": 73, + "column": 24 + }, + "end": { + "line": 73, + "column": 32 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 73, + "column": 35 + }, + "end": { + "line": 73, + "column": 36 + } + } + }, + { + "type": "StringLiteral", + "value": "C", + "loc": { + "start": { + "line": 73, + "column": 38 + }, + "end": { + "line": 73, + "column": 41 + } + } + } + ], + "loc": { + "start": { + "line": 73, + "column": 34 + }, + "end": { + "line": 73, + "column": 42 + } + } + } + ], + "loc": { + "start": { + "line": 73, + "column": 13 + }, + "end": { + "line": 73, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 73, + "column": 5 + }, + "end": { + "line": 73, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 73, + "column": 5 + }, + "end": { + "line": 73, + "column": 44 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "h_var", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 75, + "column": 17 + }, + "end": { + "line": 75, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 17 + }, + "end": { + "line": 75, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 17 + }, + "end": { + "line": 75, + "column": 24 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 75, + "column": 25 + }, + "end": { + "line": 75, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 75, + "column": 30 + }, + "end": { + "line": 75, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 30 + }, + "end": { + "line": 75, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 30 + }, + "end": { + "line": 75, + "column": 37 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 75, + "column": 38 + }, + "end": { + "line": 75, + "column": 45 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 75, + "column": 47 + }, + "end": { + "line": 75, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 47 + }, + "end": { + "line": 75, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 47 + }, + "end": { + "line": 75, + "column": 54 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 75, + "column": 16 + }, + "end": { + "line": 75, + "column": 56 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 75, + "column": 9 + }, + "end": { + "line": 75, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 75, + "column": 58 + }, + "end": { + "line": 75, + "column": 59 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 75, + "column": 61 + }, + "end": { + "line": 75, + "column": 62 + } + } + }, + { + "type": "StringLiteral", + "value": "asd", + "loc": { + "start": { + "line": 75, + "column": 64 + }, + "end": { + "line": 75, + "column": 69 + } + } + }, + { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 75, + "column": 71 + }, + "end": { + "line": 75, + "column": 76 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 75, + "column": 82 + }, + "end": { + "line": 75, + "column": 88 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 82 + }, + "end": { + "line": 75, + "column": 89 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 82 + }, + "end": { + "line": 75, + "column": 89 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 75, + "column": 78 + }, + "end": { + "line": 75, + "column": 91 + } + } + } + ], + "loc": { + "start": { + "line": 75, + "column": 57 + }, + "end": { + "line": 75, + "column": 91 + } + } + }, + "loc": { + "start": { + "line": 75, + "column": 9 + }, + "end": { + "line": 75, + "column": 91 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 75, + "column": 5 + }, + "end": { + "line": 75, + "column": 92 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "i_var", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 76, + "column": 16 + }, + "end": { + "line": 76, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 76, + "column": 9 + }, + "end": { + "line": 76, + "column": 14 + } + } + }, + "init": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "h_var", + "decorators": [], + "loc": { + "start": { + "line": 76, + "column": 24 + }, + "end": { + "line": 76, + "column": 29 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 76, + "column": 30 + }, + "end": { + "line": 76, + "column": 31 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 76, + "column": 24 + }, + "end": { + "line": 76, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 76, + "column": 9 + }, + "end": { + "line": 76, + "column": 32 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 76, + "column": 5 + }, + "end": { + "line": 76, + "column": 33 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "j_var", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 78, + "column": 17 + }, + "end": { + "line": 78, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 78, + "column": 22 + }, + "end": { + "line": 78, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 22 + }, + "end": { + "line": 78, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 22 + }, + "end": { + "line": 78, + "column": 29 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 78, + "column": 30 + }, + "end": { + "line": 78, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 30 + }, + "end": { + "line": 78, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 30 + }, + "end": { + "line": 78, + "column": 37 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 78, + "column": 38 + }, + "end": { + "line": 78, + "column": 45 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 78, + "column": 47 + }, + "end": { + "line": 78, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 47 + }, + "end": { + "line": 78, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 47 + }, + "end": { + "line": 78, + "column": 54 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 78, + "column": 16 + }, + "end": { + "line": 78, + "column": 56 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 78, + "column": 9 + }, + "end": { + "line": 78, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 6, + "loc": { + "start": { + "line": 78, + "column": 58 + }, + "end": { + "line": 78, + "column": 59 + } + } + }, + { + "type": "NumberLiteral", + "value": 7, + "loc": { + "start": { + "line": 78, + "column": 61 + }, + "end": { + "line": 78, + "column": 62 + } + } + }, + { + "type": "StringLiteral", + "value": "abc", + "loc": { + "start": { + "line": 78, + "column": 64 + }, + "end": { + "line": 78, + "column": 69 + } + } + }, + { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 78, + "column": 71 + }, + "end": { + "line": 78, + "column": 75 + } + } + }, + { + "type": "NumberLiteral", + "value": 666, + "loc": { + "start": { + "line": 78, + "column": 77 + }, + "end": { + "line": 78, + "column": 80 + } + } + } + ], + "loc": { + "start": { + "line": 78, + "column": 57 + }, + "end": { + "line": 78, + "column": 81 + } + } + }, + "loc": { + "start": { + "line": 78, + "column": 9 + }, + "end": { + "line": 78, + "column": 81 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 78, + "column": 5 + }, + "end": { + "line": 78, + "column": 82 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "empty", + "typeAnnotation": { + "type": "ETSTuple", + "spreadType": null, + "loc": { + "start": { + "line": 82, + "column": 16 + }, + "end": { + "line": 82, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 82, + "column": 9 + }, + "end": { + "line": 82, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [], + "loc": { + "start": { + "line": 82, + "column": 21 + }, + "end": { + "line": 82, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 82, + "column": 9 + }, + "end": { + "line": 82, + "column": 23 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 82, + "column": 5 + }, + "end": { + "line": 82, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 23 + }, + "end": { + "line": 83, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 83, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 83, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 83, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 84, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_1.ets b/ets2panda/test/compiler/ets/tuple_types_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..72de48fbadc209f634d2b658c732986ddcfb5be4 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_1.ets @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { foo() {}} +class B extends A { bar() {}} + +type num_str_str_type = [number, string, string]; +type num_str_str_with_spread = [num_str_str_type, ...number[]]; + +function foo(a0: number, args: [...number[]]): number { + return 2; +} + + +function main(): void { + const tup_arr_1: num_str_str_type[] = [ + [0, "a", "d"], + [1, "b", "e"], + [2, "c", "f"], + ]; + + const tup_arr_2: num_str_str_with_spread[] = [ + [tup_arr_1[0], 250], + [tup_arr_1[1], 250, 260], + [tup_arr_1[0], 300, 300, 300], + ]; + + const a_var = tup_arr_2[0][1] + tup_arr_2[1][1] + tup_arr_2[2][1]; + const b_var = tup_arr_2[1][2] + tup_arr_2[2][2]; + const c_var = tup_arr_2[2][2]; + + foo(tup_arr_1[0][0], [tup_arr_2[0][1]]); + foo(tup_arr_1[1][0], [tup_arr_2[1][1], tup_arr_2[1][2]]); + + let arr: Object[] = [1,2,3,4,5]; + let double_ref_tup: [Number, Number, Number] = [6 as double, 7 as double, 8 as double]; + let a_arr: A[]; + let b_tup: [B, B] = [new B(), new B()]; + let b_arr: B[] = [new B(), new B()]; + + arr = double_ref_tup; + a_arr = b_tup; + b_arr = b_tup; + + let spread_tup: [Number, ...Number[]] = [6 as double,7 as double,8 as double, 9 as double, 10 as double]; + let num_ref_arr: Number[] = [1 as double,2 as double,3 as double,4 as double,5 as double]; + + spread_tup = num_ref_arr; + + let num_tup: [number, number] = [11,2]; + let num_prim_arr: number[] = [3,4]; + + num_prim_arr = num_tup; + + let d_var: [number, string] = [1, "A"]; + let e_var: [number, string, boolean] = [1, "A", true]; + let f_var: [number, string, boolean, number, string]; + f_var = [1, "A", true, 20, "B"]; + + let g_var: [number, string][]; + g_var = [[1, "A"], [2, "B"], [3, "C"]]; + + let h_var: [number, int, string, boolean, Object] = [1, 2, "asd", false, new Object()]; + let i_var: float = h_var[1]; + + let j_var: [int, number, string, boolean, Object] = [6, 7, "abc", true, 666]; + // NOTE: Bug in op_assignment lowering (removes const from property) + // j_var[0] += new Short(2 as short); + + let empty: [] = []; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_10_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_10_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d72397b08129f0c4baff9b180854da7793e1d7b8 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_10_neg-expected.txt @@ -0,0 +1,673 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 36 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 36 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 38 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 39 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 40 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 41 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} +TypeError: Initializers type is not assignable to the target type [tuple_types_10_neg.ets:19:39] diff --git a/ets2panda/test/compiler/ets/tuple_types_10_neg.ets b/ets2panda/test/compiler/ets/tuple_types_10_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..1757a67a057f40882604c4db7fe7b662358b7cca --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_10_neg.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, number] = [2, 3]; + let b: [number, number, number] = a; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_11_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_11_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..669daa1144697c1a660006e303b6418a12aff12f --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_11_neg-expected.txt @@ -0,0 +1,687 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 36 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 40 + }, + "end": { + "line": 18, + "column": 41 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 18, + "column": 43 + }, + "end": { + "line": 18, + "column": 44 + } + } + }, + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 18, + "column": 46 + }, + "end": { + "line": 18, + "column": 47 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 39 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 48 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 49 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 31 + }, + "end": { + "line": 19, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 32 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 33 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} +TypeError: Initializers type is not assignable to the target type [tuple_types_11_neg.ets:19:31] diff --git a/ets2panda/test/compiler/ets/tuple_types_11_neg.ets b/ets2panda/test/compiler/ets/tuple_types_11_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..e50a7e53f338572a4cd5ded770ac4d1809f69e42 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_11_neg.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, number, number] = [2, 3, 4]; + let b: [number, number] = a; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_12-expected.txt b/ets2panda/test/compiler/ets/tuple_types_12-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..19124a264bc8b876bc2b360fc99ea265c1ec0f3f --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_12-expected.txt @@ -0,0 +1,2204 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "custom_tuple_type", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 27 + }, + "end": { + "line": 16, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 27 + }, + "end": { + "line": 16, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 27 + }, + "end": { + "line": 16, + "column": 34 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 35 + }, + "end": { + "line": 16, + "column": 38 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 40 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 7 + }, + "end": { + "line": 18, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 19, + "column": 25 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 19, + "column": 28 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 19 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a_tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 22, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 22, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 22, + "column": 30 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 31 + } + } + }, + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "custom_tuple_type", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 33 + }, + "end": { + "line": 22, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 33 + }, + "end": { + "line": 22, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 33 + }, + "end": { + "line": 22, + "column": 51 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 22, + "column": 32 + }, + "end": { + "line": 22, + "column": 52 + } + } + }, + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 54 + }, + "end": { + "line": 22, + "column": 55 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 54 + }, + "end": { + "line": 22, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 54 + }, + "end": { + "line": 22, + "column": 56 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 57 + }, + "end": { + "line": 22, + "column": 58 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 57 + }, + "end": { + "line": 22, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 57 + }, + "end": { + "line": 22, + "column": 59 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 22, + "column": 53 + }, + "end": { + "line": 22, + "column": 60 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "custom_tuple_type", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 64 + }, + "end": { + "line": 22, + "column": 81 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 64 + }, + "end": { + "line": 22, + "column": 82 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 64 + }, + "end": { + "line": 22, + "column": 82 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 83 + }, + "end": { + "line": 22, + "column": 84 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 16 + }, + "end": { + "line": 22, + "column": 86 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 22, + "column": 89 + }, + "end": { + "line": 22, + "column": 90 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 22, + "column": 92 + }, + "end": { + "line": 22, + "column": 93 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 88 + }, + "end": { + "line": 22, + "column": 94 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "StringLiteral", + "value": "a", + "loc": { + "start": { + "line": 22, + "column": 98 + }, + "end": { + "line": 22, + "column": 101 + } + } + }, + { + "type": "NumberLiteral", + "value": 6, + "loc": { + "start": { + "line": 22, + "column": 103 + }, + "end": { + "line": 22, + "column": 104 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 97 + }, + "end": { + "line": 22, + "column": 105 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 96 + }, + "end": { + "line": 22, + "column": 106 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 113 + }, + "end": { + "line": 22, + "column": 114 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 113 + }, + "end": { + "line": 22, + "column": 115 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 113 + }, + "end": { + "line": 22, + "column": 115 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 22, + "column": 109 + }, + "end": { + "line": 22, + "column": 117 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 122 + }, + "end": { + "line": 22, + "column": 123 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 122 + }, + "end": { + "line": 22, + "column": 124 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 122 + }, + "end": { + "line": 22, + "column": 124 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 22, + "column": 118 + }, + "end": { + "line": 22, + "column": 126 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 108 + }, + "end": { + "line": 22, + "column": 126 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "StringLiteral", + "value": "b", + "loc": { + "start": { + "line": 22, + "column": 129 + }, + "end": { + "line": 22, + "column": 132 + } + } + }, + { + "type": "NumberLiteral", + "value": 8, + "loc": { + "start": { + "line": 22, + "column": 134 + }, + "end": { + "line": 22, + "column": 135 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 128 + }, + "end": { + "line": 22, + "column": 136 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "StringLiteral", + "value": "c", + "loc": { + "start": { + "line": 22, + "column": 139 + }, + "end": { + "line": 22, + "column": 142 + } + } + }, + { + "type": "NumberLiteral", + "value": 10, + "loc": { + "start": { + "line": 22, + "column": 144 + }, + "end": { + "line": 22, + "column": 146 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 138 + }, + "end": { + "line": 22, + "column": 147 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "StringLiteral", + "value": "d", + "loc": { + "start": { + "line": 22, + "column": 150 + }, + "end": { + "line": 22, + "column": 153 + } + } + }, + { + "type": "NumberLiteral", + "value": 12, + "loc": { + "start": { + "line": 22, + "column": 155 + }, + "end": { + "line": 22, + "column": 157 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 149 + }, + "end": { + "line": 22, + "column": 158 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 87 + }, + "end": { + "line": 22, + "column": 159 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 159 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 160 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "my_str", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "init": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a_tup", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 23, + "column": 32 + }, + "end": { + "line": 23, + "column": 33 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 34 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 23, + "column": 35 + }, + "end": { + "line": 23, + "column": 36 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 37 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 23, + "column": 38 + }, + "end": { + "line": 23, + "column": 39 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 40 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 41 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "my_str_2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 19 + }, + "end": { + "line": 24, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 19 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 19 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 17 + } + } + }, + "init": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a_tup", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 33 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 6, + "loc": { + "start": { + "line": 24, + "column": 34 + }, + "end": { + "line": 24, + "column": 35 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 36 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 24, + "column": 37 + }, + "end": { + "line": 24, + "column": 38 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 39 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 40 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a_tup", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 10 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 25, + "column": 11 + }, + "end": { + "line": 25, + "column": 12 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 13 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 25, + "column": 14 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 16 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 17 + }, + "end": { + "line": 25, + "column": 20 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 20 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 23 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a_tup", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 10 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 26, + "column": 11 + }, + "end": { + "line": 26, + "column": 12 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 13 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 15 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 16 + } + } + }, + "property": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 23 + }, + "end": { + "line": 27, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 27, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 27, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 27, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 28, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_12.ets b/ets2panda/test/compiler/ets/tuple_types_12.ets new file mode 100644 index 0000000000000000000000000000000000000000..fce85859fd6262fdbc0d3e46c8a6164d073870b6 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_12.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type custom_tuple_type = [string, int]; + +class A {foo(){}} +class B extends A {bar(){}} + +function main(): void { + let a_tup: [[int, number], [custom_tuple_type], [A, B], ...custom_tuple_type[]] = [[2, 3], [["a", 6]], [new B(), new B()], ["b", 8], ["c", 10], ["d", 12]]; + let my_str: String = a_tup[1][0][0]; + let my_str_2: String = a_tup[6][0]; + a_tup[2][0].foo(); + a_tup[2][1].bar(); +} diff --git a/ets2panda/test/compiler/ets/tuple_types_13-expected.txt b/ets2panda/test/compiler/ets/tuple_types_13-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..aa16620a4d9ed0d571c23e28caf553a558e2bfbf --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_13-expected.txt @@ -0,0 +1,482 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "num_str_str", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 36 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 37 + }, + "end": { + "line": 16, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 37 + }, + "end": { + "line": 16, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 37 + }, + "end": { + "line": 16, + "column": 44 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 20 + }, + "end": { + "line": 16, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 45 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "tup_2", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 12 + } + } + }, + "value": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 13, + "loc": { + "start": { + "line": 20, + "column": 6 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 13 + } + } + }, + { + "type": "StringLiteral", + "value": "D", + "loc": { + "start": { + "line": 20, + "column": 15 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 30 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "num_str_str", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 19, + "column": 29 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 22, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_13.ets b/ets2panda/test/compiler/ets/tuple_types_13.ets new file mode 100644 index 0000000000000000000000000000000000000000..00fca809cf59bcfe0803308708d8e40ed5974726 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_13.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type num_str_str = [number, string, string]; + + +const tup_2: num_str_str[] = [ + [13, "A", "D"] +]; diff --git a/ets2panda/test/compiler/ets/tuple_types_14-expected.txt b/ets2panda/test/compiler/ets/tuple_types_14-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..fa310986d8a254bb9dca205b7a55a77ebe934ef5 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_14-expected.txt @@ -0,0 +1,2056 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 10 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "memb", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 13 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 13 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 8 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 8 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a0", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 15 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 8 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 8 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "property": { + "type": "Identifier", + "name": "memb", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 21 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 8 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 8 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 2 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 10 + }, + "end": { + "line": 24, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 10 + }, + "end": { + "line": 24, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 18 + }, + "end": { + "line": 24, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 18 + }, + "end": { + "line": 24, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 18 + }, + "end": { + "line": 24, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "my_var", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 17 + }, + "end": { + "line": 25, + "column": 18 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 25, + "column": 20 + }, + "end": { + "line": 25, + "column": 23 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 25 + }, + "end": { + "line": 25, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 25 + }, + "end": { + "line": 25, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 25 + }, + "end": { + "line": 25, + "column": 32 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 25, + "column": 19 + }, + "end": { + "line": 25, + "column": 33 + } + } + } + ], + "loc": { + "start": { + "line": 25, + "column": 18 + }, + "end": { + "line": 25, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 17 + }, + "end": { + "line": 25, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 17 + }, + "end": { + "line": 25, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 9 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 40 + }, + "end": { + "line": 25, + "column": 41 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 25, + "column": 43 + }, + "end": { + "line": 25, + "column": 46 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 48 + }, + "end": { + "line": 25, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 48 + }, + "end": { + "line": 25, + "column": 55 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 48 + }, + "end": { + "line": 25, + "column": 55 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 25, + "column": 42 + }, + "end": { + "line": 25, + "column": 56 + } + } + } + ], + "loc": { + "start": { + "line": 25, + "column": 41 + }, + "end": { + "line": 25, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 40 + }, + "end": { + "line": 25, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 40 + }, + "end": { + "line": 25, + "column": 57 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 25, + "column": 36 + }, + "end": { + "line": 25, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 9 + }, + "end": { + "line": 25, + "column": 59 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 59 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "my_var", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 11 + } + } + }, + "property": { + "type": "Identifier", + "name": "memb", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 12 + }, + "end": { + "line": 26, + "column": 16 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 16 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 26, + "column": 20 + }, + "end": { + "line": 26, + "column": 21 + } + } + }, + { + "type": "StringLiteral", + "value": "b", + "loc": { + "start": { + "line": 26, + "column": 23 + }, + "end": { + "line": 26, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 19 + }, + "end": { + "line": 26, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 28 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 27, + "column": 15 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 20 + }, + "end": { + "line": 27, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 20 + }, + "end": { + "line": 27, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 20 + }, + "end": { + "line": 27, + "column": 27 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 27, + "column": 12 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 6, + "loc": { + "start": { + "line": 27, + "column": 31 + }, + "end": { + "line": 27, + "column": 32 + } + } + }, + { + "type": "StringLiteral", + "value": "c", + "loc": { + "start": { + "line": 27, + "column": 34 + }, + "end": { + "line": 27, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 30 + }, + "end": { + "line": 27, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 27, + "column": 38 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 39 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "my_var", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 11 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 12 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "tup", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 16 + }, + "end": { + "line": 28, + "column": 19 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 21 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "my_var_2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 19 + }, + "end": { + "line": 30, + "column": 20 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 30, + "column": 22 + }, + "end": { + "line": 30, + "column": 25 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 27 + }, + "end": { + "line": 30, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 27 + }, + "end": { + "line": 30, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 27 + }, + "end": { + "line": 30, + "column": 34 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 35 + } + } + } + ], + "loc": { + "start": { + "line": 30, + "column": 20 + }, + "end": { + "line": 30, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 19 + }, + "end": { + "line": 30, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 19 + }, + "end": { + "line": 30, + "column": 37 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 9 + }, + "end": { + "line": 30, + "column": 17 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 42 + }, + "end": { + "line": 30, + "column": 43 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 30, + "column": 45 + }, + "end": { + "line": 30, + "column": 48 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 50 + }, + "end": { + "line": 30, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 50 + }, + "end": { + "line": 30, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 50 + }, + "end": { + "line": 30, + "column": 57 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 30, + "column": 44 + }, + "end": { + "line": 30, + "column": 58 + } + } + } + ], + "loc": { + "start": { + "line": 30, + "column": 43 + }, + "end": { + "line": 30, + "column": 58 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 42 + }, + "end": { + "line": 30, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 42 + }, + "end": { + "line": 30, + "column": 59 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 30, + "column": 38 + }, + "end": { + "line": 30, + "column": 61 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 9 + }, + "end": { + "line": 30, + "column": 61 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 30, + "column": 5 + }, + "end": { + "line": 30, + "column": 61 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "my_var_2", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 13 + } + } + }, + "property": { + "type": "Identifier", + "name": "memb", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 14 + }, + "end": { + "line": 31, + "column": 18 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 18 + } + } + }, + "right": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "my_var", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 21 + }, + "end": { + "line": 31, + "column": 27 + } + } + }, + "property": { + "type": "Identifier", + "name": "bar", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 28 + }, + "end": { + "line": 31, + "column": 31 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 21 + }, + "end": { + "line": 31, + "column": 31 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 21 + }, + "end": { + "line": 31, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 34 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 23 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 32, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 33, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_14.ets b/ets2panda/test/compiler/ets/tuple_types_14.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5b8c72e73f795c4a43856dc6506f1d4d0a658f8 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_14.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + memb: T; + foo(a0: T): void {} + bar(): T { + return this.memb; + } +} + +function main(): void { + let my_var: A<[int, String]> = new A<[int, String]>(); + my_var.memb = [1, "b"]; + let tup: [int, String] = [6, "c"]; + my_var.foo(tup); + + let my_var_2: A<[int, String]> = new A<[int, String]>(); + my_var_2.memb = my_var.bar(); +} diff --git a/ets2panda/test/compiler/ets/tuple_types_15-expected.txt b/ets2panda/test/compiler/ets/tuple_types_15-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..754f6acb255ba185d3da9537fb9053c1665b2011 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_15-expected.txt @@ -0,0 +1,2104 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "array_tuple", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 28 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 36 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 20 + }, + "end": { + "line": 16, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 38 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "getIntAndString", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "getIntAndString", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 30 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 30 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 30 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 38 + }, + "end": { + "line": 18, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 38 + }, + "end": { + "line": 18, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 38 + }, + "end": { + "line": 18, + "column": 45 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 47 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "tup", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 30 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 19, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 12 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 10, + "loc": { + "start": { + "line": 19, + "column": 34 + }, + "end": { + "line": 19, + "column": 36 + } + } + }, + { + "type": "StringLiteral", + "value": "c", + "loc": { + "start": { + "line": 19, + "column": 38 + }, + "end": { + "line": 19, + "column": 41 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 33 + }, + "end": { + "line": 19, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 42 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 43 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "tup", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 46 + }, + "end": { + "line": 21, + "column": 4 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 21, + "column": 4 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 21, + "column": 4 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 21, + "column": 4 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 18 + }, + "end": { + "line": 23, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 18 + }, + "end": { + "line": 23, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 18 + }, + "end": { + "line": 23, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "sample_tuple", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 24 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 24 + }, + "end": { + "line": 24, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 24 + }, + "end": { + "line": 24, + "column": 31 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 24, + "column": 32 + }, + "end": { + "line": 24, + "column": 39 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 41 + }, + "end": { + "line": 24, + "column": 47 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 41 + }, + "end": { + "line": 24, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 41 + }, + "end": { + "line": 24, + "column": 48 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 49 + }, + "end": { + "line": 24, + "column": 55 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 49 + }, + "end": { + "line": 24, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 49 + }, + "end": { + "line": 24, + "column": 56 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 24, + "column": 23 + }, + "end": { + "line": 24, + "column": 58 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 21 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 10, + "loc": { + "start": { + "line": 25, + "column": 9 + }, + "end": { + "line": 25, + "column": 11 + } + } + }, + { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 26, + "column": 13 + } + } + }, + { + "type": "StringLiteral", + "value": "B", + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 27, + "column": 12 + } + } + }, + { + "type": "NumberLiteral", + "value": 90, + "loc": { + "start": { + "line": 28, + "column": 9 + }, + "end": { + "line": 28, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 59 + }, + "end": { + "line": 29, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 29, + "column": 6 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 29, + "column": 7 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "values", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 17 + }, + "end": { + "line": 31, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 17 + }, + "end": { + "line": 31, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 17 + }, + "end": { + "line": 31, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 9 + }, + "end": { + "line": 31, + "column": 15 + } + } + }, + "init": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "sample_tuple", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 38 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 31, + "column": 39 + }, + "end": { + "line": 31, + "column": 40 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 41 + } + } + }, + "right": { + "type": "StringLiteral", + "value": " ", + "loc": { + "start": { + "line": 31, + "column": 44 + }, + "end": { + "line": 31, + "column": 47 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 47 + } + } + }, + "right": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "sample_tuple", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 50 + }, + "end": { + "line": 31, + "column": 62 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 31, + "column": 63 + }, + "end": { + "line": 31, + "column": 64 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 50 + }, + "end": { + "line": 31, + "column": 65 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 65 + } + } + }, + "right": { + "type": "StringLiteral", + "value": " ", + "loc": { + "start": { + "line": 31, + "column": 68 + }, + "end": { + "line": 31, + "column": 71 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 71 + } + } + }, + "right": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "sample_tuple", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 74 + }, + "end": { + "line": 31, + "column": 86 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 31, + "column": 87 + }, + "end": { + "line": 31, + "column": 88 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 74 + }, + "end": { + "line": 31, + "column": 89 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 89 + } + } + }, + "right": { + "type": "StringLiteral", + "value": " ", + "loc": { + "start": { + "line": 31, + "column": 92 + }, + "end": { + "line": 31, + "column": 95 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 95 + } + } + }, + "right": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "sample_tuple", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 98 + }, + "end": { + "line": 31, + "column": 110 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 31, + "column": 111 + }, + "end": { + "line": 31, + "column": 112 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 98 + }, + "end": { + "line": 31, + "column": 113 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 26 + }, + "end": { + "line": 31, + "column": 113 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 9 + }, + "end": { + "line": 31, + "column": 113 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 114 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "array", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "array_tuple", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 16 + }, + "end": { + "line": 32, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 16 + }, + "end": { + "line": 32, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 16 + }, + "end": { + "line": 32, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 30 + }, + "end": { + "line": 32, + "column": 31 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 9 + }, + "end": { + "line": 32, + "column": 14 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 32, + "column": 34 + }, + "end": { + "line": 32, + "column": 35 + } + } + }, + { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 32, + "column": 37 + }, + "end": { + "line": 32, + "column": 41 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 33 + }, + "end": { + "line": 32, + "column": 42 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 32, + "column": 45 + }, + "end": { + "line": 32, + "column": 46 + } + } + }, + { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 32, + "column": 48 + }, + "end": { + "line": 32, + "column": 53 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 44 + }, + "end": { + "line": 32, + "column": 54 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 32, + "column": 57 + }, + "end": { + "line": 32, + "column": 58 + } + } + }, + { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 32, + "column": 60 + }, + "end": { + "line": 32, + "column": 65 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 56 + }, + "end": { + "line": 32, + "column": 66 + } + } + }, + { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 32, + "column": 69 + }, + "end": { + "line": 32, + "column": 70 + } + } + }, + { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 32, + "column": 72 + }, + "end": { + "line": 32, + "column": 76 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 68 + }, + "end": { + "line": 32, + "column": 77 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 32 + }, + "end": { + "line": 32, + "column": 79 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 9 + }, + "end": { + "line": 32, + "column": 79 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 32, + "column": 5 + }, + "end": { + "line": 32, + "column": 80 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "array", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 5 + }, + "end": { + "line": 33, + "column": 10 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 33, + "column": 11 + }, + "end": { + "line": 33, + "column": 12 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 33, + "column": 5 + }, + "end": { + "line": 33, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 5 + }, + "end": { + "line": 33, + "column": 14 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "array", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 5 + }, + "end": { + "line": 34, + "column": 10 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 34, + "column": 11 + }, + "end": { + "line": 34, + "column": 12 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 34, + "column": 5 + }, + "end": { + "line": 34, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 5 + }, + "end": { + "line": 34, + "column": 14 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "array", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 10 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 35, + "column": 11 + }, + "end": { + "line": 35, + "column": 12 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 13 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 35, + "column": 14 + }, + "end": { + "line": 35, + "column": 15 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 17 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "tuple", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 17 + }, + "end": { + "line": 37, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 17 + }, + "end": { + "line": 37, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 17 + }, + "end": { + "line": 37, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 25 + }, + "end": { + "line": 37, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 25 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 25 + }, + "end": { + "line": 37, + "column": 32 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 37, + "column": 16 + }, + "end": { + "line": 37, + "column": 34 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 14 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getIntAndString", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 35 + }, + "end": { + "line": 37, + "column": 50 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 37, + "column": 35 + }, + "end": { + "line": 37, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 52 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 37, + "column": 5 + }, + "end": { + "line": 37, + "column": 53 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 23 + }, + "end": { + "line": 41, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 41, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 41, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 41, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 42, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_15.ets b/ets2panda/test/compiler/ets/tuple_types_15.ets new file mode 100644 index 0000000000000000000000000000000000000000..d32c8f2a30e356b2fc89e0b8bb36c43dc8e0d0b0 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_15.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type array_tuple = [number, boolean]; + +function getIntAndString(): [number, string] { + let tup: [number, string] = [10, "c"]; + return tup; + } + +function main(): void { + let sample_tuple: [number, boolean, string, number] = [ + 10, + true, + "B", + 90, + ]; + + let values: string = sample_tuple[0] + " " + sample_tuple[1] + " " + sample_tuple[2] + " " + sample_tuple[3]; + let array: array_tuple[] = [[1, true], [2, false], [3, false], [4, true],]; + array[1]; + array[2]; + array[3][1]; + + let tuple: [number, string] = getIntAndString(); + + + +} diff --git a/ets2panda/test/compiler/ets/tuple_types_2_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_2_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..b32a3a2104acb7fab23c9cf75758e03fd233c55c --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_2_neg-expected.txt @@ -0,0 +1,532 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 36 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "property": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "computed": true, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 10 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} +TypeError: Element accessor value is out of tuple size bounds. [tuple_types_2_neg.ets:19:7] diff --git a/ets2panda/test/compiler/ets/tuple_types_2_neg.ets b/ets2panda/test/compiler/ets/tuple_types_2_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..32de880ce63099236be36fadd2247dd5cb6c9e73 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_2_neg.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, number] = [1, 2]; + a[2]; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_3_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_3_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..cca4b7497d07671b2c9efd6f0d0039a535eaeafc --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_3_neg-expected.txt @@ -0,0 +1,434 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 29 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} +TypeError: Too many elements in array initializer for tuple with size of 1 [tuple_types_3_neg.ets:18:27] diff --git a/ets2panda/test/compiler/ets/tuple_types_3_neg.ets b/ets2panda/test/compiler/ets/tuple_types_3_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..f5ff5c2f70e365ff014782aed5b8f836288757c8 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_3_neg.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number] = [1, 2]; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_4_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_4_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..db9deb2371bc0cb683e83701cdb22bc5022e2fb0 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_4_neg-expected.txt @@ -0,0 +1,461 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 33 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 35 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} +TypeError: Few elements in array initializer for tuple with size of 2 [tuple_types_4_neg.ets:18:31] diff --git a/ets2panda/test/compiler/ets/tuple_types_4_neg.ets b/ets2panda/test/compiler/ets/tuple_types_4_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..12cc1cfde84d237798f6e250e18b16155e2d0180 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_4_neg.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, number] = [1]; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_5_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_5_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..c17eebbf4d311a0cf910e149a5ab435eab8088d2 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_5_neg-expected.txt @@ -0,0 +1,473 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 38 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 36 + }, + "end": { + "line": 18, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 39 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 40 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} +TypeError: Few elements in array initializer for tuple with size of 2 [tuple_types_5_neg.ets:18:36] diff --git a/ets2panda/test/compiler/ets/tuple_types_5_neg.ets b/ets2panda/test/compiler/ets/tuple_types_5_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..f89f1a8abe83d8eaacb736cf674e85a03ffeb2da --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_5_neg.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, ...number[]] = [1]; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_6_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_6_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..b54e94654925d1e947df0a94a2a422e77fb8d7d7 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_6_neg-expected.txt @@ -0,0 +1,536 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 25 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 26 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 24 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 25 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} +TypeError: Initializers type is not assignable to the target type [tuple_types_6_neg.ets:19:23] diff --git a/ets2panda/test/compiler/ets/tuple_types_6_neg.ets b/ets2panda/test/compiler/ets/tuple_types_6_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..8ea94146207182ef99d6be586f150fe4fa55df12 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_6_neg.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number] = [1]; + let b: [Number] = a; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_7-expected.txt b/ets2panda/test/compiler/ets/tuple_types_7-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1793aff6858ff7283910686fc9066fa3998a9daa --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_7-expected.txt @@ -0,0 +1,937 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 33 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + { + "type": "StringLiteral", + "value": "a", + "loc": { + "start": { + "line": 18, + "column": 40 + }, + "end": { + "line": 18, + "column": 43 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 18, + "column": 45 + }, + "end": { + "line": 18, + "column": 46 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 36 + }, + "end": { + "line": 18, + "column": 47 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 47 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 33 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 36 + }, + "end": { + "line": 19, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 38 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 21 + }, + "end": { + "line": 20, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 21 + }, + "end": { + "line": 20, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 21 + }, + "end": { + "line": 20, + "column": 28 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 32 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 32 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 32 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 37 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 40 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 42 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 43 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 22, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_7.ets b/ets2panda/test/compiler/ets/tuple_types_7.ets new file mode 100644 index 0000000000000000000000000000000000000000..9d1d70565f072c44bbe4101334f077036f0174b5 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_7.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, string, Int] = [2, "a", 3]; + let b: [number, string, Int] = a; + let c: [number, string, ...Int[]] = a; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_8-expected.txt b/ets2panda/test/compiler/ets/tuple_types_8-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..5443c594f1e4a36e3517d28c026c449d6ffac225 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_8-expected.txt @@ -0,0 +1,855 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 36 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 24 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 25 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 21, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 21, + "column": 20 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 24 + }, + "end": { + "line": 21, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 24 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 24 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 32 + }, + "end": { + "line": 21, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 21, + "column": 37 + }, + "end": { + "line": 21, + "column": 38 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 21, + "column": 40 + }, + "end": { + "line": 21, + "column": 41 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 21, + "column": 43 + }, + "end": { + "line": 21, + "column": 44 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 36 + }, + "end": { + "line": 21, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 45 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 21, + "column": 46 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "right": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 23, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_8.ets b/ets2panda/test/compiler/ets/tuple_types_8.ets new file mode 100644 index 0000000000000000000000000000000000000000..10506b0ea204c8ed3a4972d32d3537137f22314e --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_8.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, number] = [1, 2]; + let b: number[] = a; + + let c: [number, ...number[]] = [1, 2, 3]; + c = b; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_9_neg-expected.txt b/ets2panda/test/compiler/ets/tuple_types_9_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..b3ff7ada9a55d8e924a21cbf03450f3a735d4d72 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_9_neg-expected.txt @@ -0,0 +1,740 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 28 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 32 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 42 + }, + "end": { + "line": 18, + "column": 43 + } + } + }, + { + "type": "StringLiteral", + "value": "a", + "loc": { + "start": { + "line": 18, + "column": 45 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 18, + "column": 50 + }, + "end": { + "line": 18, + "column": 51 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 41 + }, + "end": { + "line": 18, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 52 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 53 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 33 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 10 + } + } + }, + "init": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 36 + }, + "end": { + "line": 19, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 38 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} +TypeError: Initializers type is not assignable to the target type [tuple_types_9_neg.ets:19:36] diff --git a/ets2panda/test/compiler/ets/tuple_types_9_neg.ets b/ets2panda/test/compiler/ets/tuple_types_9_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..090eb69040a7ca0890206cfe52ffa1b0b00fd18e --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_9_neg.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function main(): void { + let a: [number, string, ...Int[]] = [2, "a", 3]; + let b: [number, string, Int] = a; +} diff --git a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatement-expected.txt b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatement-expected.txt index 7aabe7cee926363341c299a8f222ae64d2252cf3..22c782deecc9bd7325fb725e882075f42a897525 100644 --- a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatement-expected.txt +++ b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatement-expected.txt @@ -346,17 +346,45 @@ } }, "body": { - "type": "Identifier", - "name": "x", - "decorators": [], + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], "loc": { "start": { - "line": 18, - "column": 35 + "line": 1, + "column": 1 }, "end": { - "line": 18, - "column": 36 + "line": 1, + "column": 1 } } }, diff --git a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementCallAVoidFunction-expected.txt b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementCallAVoidFunction-expected.txt index bc8c16dd2a5c1749f72944009bb670add693237b..abbbb1b23283cc50d15d29b65fa8ee5e0a7eb5fa 100644 --- a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementCallAVoidFunction-expected.txt +++ b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementCallAVoidFunction-expected.txt @@ -466,32 +466,60 @@ } }, "body": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "test_void", - "decorators": [], - "loc": { - "start": { - "line": 19, - "column": 41 + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "test_void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 41 + }, + "end": { + "line": 19, + "column": 50 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 41 + }, + "end": { + "line": 19, + "column": 52 + } + } }, - "end": { - "line": 19, - "column": 50 + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } } } - }, - "arguments": [], - "optional": false, + ], "loc": { "start": { - "line": 19, - "column": 41 + "line": 1, + "column": 1 }, "end": { - "line": 19, - "column": 52 + "line": 1, + "column": 1 } } }, diff --git a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementVoid-expected.txt b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementVoid-expected.txt index 043cace2a9e111130e1f440bd64fd357aff46e63..d1c490b6118a4ca8cbe50ac705bd20874a91b940 100644 --- a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementVoid-expected.txt +++ b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementVoid-expected.txt @@ -331,77 +331,105 @@ } }, "body": { - "type": "CallExpression", - "callee": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "console", - "decorators": [], - "loc": { - "start": { - "line": 17, - "column": 37 - }, - "end": { - "line": 17, - "column": 44 - } - } - }, - "property": { - "type": "Identifier", - "name": "println", - "decorators": [], - "loc": { - "start": { - "line": 17, - "column": 45 + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "console", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "property": { + "type": "Identifier", + "name": "println", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 45 + }, + "end": { + "line": 17, + "column": 52 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 52 + } + } }, - "end": { - "line": 17, - "column": 52 + "arguments": [ + { + "type": "NumberLiteral", + "value": 10, + "loc": { + "start": { + "line": 17, + "column": 53 + }, + "end": { + "line": 17, + "column": 55 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 56 + } } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 17, - "column": 37 }, - "end": { - "line": 17, - "column": 52 - } - } - }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 10, "loc": { "start": { - "line": 17, - "column": 53 + "line": 1, + "column": 1 }, "end": { - "line": 17, - "column": 55 + "line": 1, + "column": 1 } } } ], - "optional": false, "loc": { "start": { - "line": 17, - "column": 37 + "line": 1, + "column": 1 }, "end": { - "line": 17, - "column": 56 + "line": 1, + "column": 1 } } }, diff --git a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementWithFunctionParameters-expected.txt b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementWithFunctionParameters-expected.txt index e034df91924378611fccaaf006d8c4c8fba24282..4198ef2defa7f24d89bd70d1bf4d179be6c4e274 100644 --- a/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementWithFunctionParameters-expected.txt +++ b/ets2panda/test/parser/ets/lambdaExpressionWithoutBlockStatementWithFunctionParameters-expected.txt @@ -441,46 +441,74 @@ } }, "body": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 17, - "column": 61 - }, - "end": { - "line": 17, - "column": 62 - } - } - }, - "right": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 17, - "column": 63 + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 61 + }, + "end": { + "line": 17, + "column": 62 + } + } + }, + "right": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 63 + }, + "end": { + "line": 17, + "column": 64 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 61 + }, + "end": { + "line": 17, + "column": 64 + } + } }, - "end": { - "line": 17, - "column": 64 + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } } } - }, + ], "loc": { "start": { - "line": 17, - "column": 61 + "line": 1, + "column": 1 }, "end": { - "line": 17, - "column": 64 + "line": 1, + "column": 1 } } }, diff --git a/ets2panda/test/parser/ets/literals-expected.txt b/ets2panda/test/parser/ets/literals-expected.txt index 019093d519550c2c3fce3b09662c62afae81ba86..0ed4a571719e1efa9c2dc004b0b53c2889e5fd5f 100644 --- a/ets2panda/test/parser/ets/literals-expected.txt +++ b/ets2panda/test/parser/ets/literals-expected.txt @@ -799,8 +799,34 @@ } }, "value": { - "type": "ArrayExpression", - "elements": [], + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 123.45, + "loc": { + "start": { + "line": 31, + "column": 15 + }, + "end": { + "line": 31, + "column": 22 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 31, + "column": 15 + }, + "end": { + "line": 31, + "column": 22 + } + } + }, "loc": { "start": { "line": 31, @@ -808,7 +834,7 @@ }, "end": { "line": 31, - "column": 17 + "column": 22 } } }, @@ -827,7 +853,7 @@ }, "end": { "line": 31, - "column": 17 + "column": 22 } } }, @@ -848,6 +874,314 @@ } } }, + "value": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1.2345e+12, + "loc": { + "start": { + "line": 32, + "column": 15 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 32, + "column": 15 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 15 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 7 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit16", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 7 + }, + "end": { + "line": 33, + "column": 12 + } + } + }, + "value": { + "type": "UnaryExpression", + "operator": "-", + "prefix": true, + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 123.45, + "loc": { + "start": { + "line": 33, + "column": 16 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 33, + "column": 16 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 16 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 15 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 7 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit17", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 7 + }, + "end": { + "line": 34, + "column": 12 + } + } + }, + "value": { + "type": "UnaryExpression", + "operator": "-", + "prefix": true, + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1.2345e+12, + "loc": { + "start": { + "line": 34, + "column": 16 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 34, + "column": 16 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 16 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 15 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 7 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit18", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 7 + }, + "end": { + "line": 35, + "column": 12 + } + } + }, + "value": { + "type": "ArrayExpression", + "elements": [], + "loc": { + "start": { + "line": 35, + "column": 15 + }, + "end": { + "line": 35, + "column": 17 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 7 + }, + "end": { + "line": 35, + "column": 17 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit19", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 7 + }, + "end": { + "line": 36, + "column": 12 + } + } + }, "value": { "type": "ArrayExpression", "elements": [ @@ -856,11 +1190,11 @@ "value": 1, "loc": { "start": { - "line": 32, + "line": 36, "column": 16 }, "end": { - "line": 32, + "line": 36, "column": 17 } } @@ -870,11 +1204,11 @@ "value": 2, "loc": { "start": { - "line": 32, + "line": 36, "column": 18 }, "end": { - "line": 32, + "line": 36, "column": 19 } } @@ -884,11 +1218,11 @@ "value": 3, "loc": { "start": { - "line": 32, + "line": 36, "column": 20 }, "end": { - "line": 32, + "line": 36, "column": 21 } } @@ -896,11 +1230,11 @@ ], "loc": { "start": { - "line": 32, + "line": 36, "column": 15 }, "end": { - "line": 32, + "line": 36, "column": 22 } } @@ -915,11 +1249,11 @@ "decorators": [], "loc": { "start": { - "line": 32, + "line": 36, "column": 7 }, "end": { - "line": 32, + "line": 36, "column": 22 } } @@ -928,15 +1262,15 @@ "type": "ClassProperty", "key": { "type": "Identifier", - "name": "lit16", + "name": "lit20", "decorators": [], "loc": { "start": { - "line": 33, + "line": 37, "column": 7 }, "end": { - "line": 33, + "line": 37, "column": 12 } } @@ -949,11 +1283,11 @@ "value": "1", "loc": { "start": { - "line": 33, + "line": 37, "column": 16 }, "end": { - "line": 33, + "line": 37, "column": 19 } } @@ -963,11 +1297,11 @@ "value": "2", "loc": { "start": { - "line": 33, + "line": 37, "column": 20 }, "end": { - "line": 33, + "line": 37, "column": 23 } } @@ -977,11 +1311,11 @@ "value": "3", "loc": { "start": { - "line": 33, + "line": 37, "column": 24 }, "end": { - "line": 33, + "line": 37, "column": 27 } } @@ -989,11 +1323,11 @@ ], "loc": { "start": { - "line": 33, + "line": 37, "column": 15 }, "end": { - "line": 33, + "line": 37, "column": 28 } } @@ -1008,11 +1342,11 @@ "decorators": [], "loc": { "start": { - "line": 33, + "line": 37, "column": 7 }, "end": { - "line": 33, + "line": 37, "column": 28 } } @@ -1021,15 +1355,15 @@ "type": "ClassProperty", "key": { "type": "Identifier", - "name": "lit17", + "name": "lit21", "decorators": [], "loc": { "start": { - "line": 34, + "line": 38, "column": 7 }, "end": { - "line": 34, + "line": 38, "column": 12 } } @@ -1042,11 +1376,11 @@ "value": 1, "loc": { "start": { - "line": 34, + "line": 38, "column": 16 }, "end": { - "line": 34, + "line": 38, "column": 19 } } @@ -1056,11 +1390,11 @@ "value": 2, "loc": { "start": { - "line": 34, + "line": 38, "column": 20 }, "end": { - "line": 34, + "line": 38, "column": 23 } } @@ -1070,11 +1404,11 @@ "value": 3, "loc": { "start": { - "line": 34, + "line": 38, "column": 24 }, "end": { - "line": 34, + "line": 38, "column": 27 } } @@ -1082,11 +1416,11 @@ ], "loc": { "start": { - "line": 34, + "line": 38, "column": 15 }, "end": { - "line": 34, + "line": 38, "column": 28 } } @@ -1101,11 +1435,11 @@ "decorators": [], "loc": { "start": { - "line": 34, + "line": 38, "column": 7 }, "end": { - "line": 34, + "line": 38, "column": 28 } } @@ -1140,7 +1474,7 @@ "column": 1 }, "end": { - "line": 35, + "line": 40, "column": 1 } } diff --git a/ets2panda/test/parser/ets/literals.ets b/ets2panda/test/parser/ets/literals.ets index 5cc60089135a04d5e11b516a9ebbfb7fc2da1d99..66f10e29ace3cece102026e701dca4b7088308cc 100644 --- a/ets2panda/test/parser/ets/literals.ets +++ b/ets2panda/test/parser/ets/literals.ets @@ -28,7 +28,12 @@ const lit10 = c'\u0061'; const lit11 = true; const lit12 = false; const lit13 = null; -const lit14 = []; -const lit15 = [1,2,3]; -const lit16 = ["1","2","3"]; -const lit17 = [1.0,2.0,3.0]; +const lit14 = 123.45f; // equivalent to (123.45 as float) +const lit15 = 123.45e10f; +const lit16 = -123.45f; // equivalent to -(123.45 as float) +const lit17 = -123.45e10f; +const lit18 = []; +const lit19 = [1,2,3]; +const lit20 = ["1","2","3"]; +const lit21 = [1.0,2.0,3.0]; + diff --git a/ets2panda/test/parser/ets/proxyVoidGeneration-expected.txt b/ets2panda/test/parser/ets/proxyVoidGeneration-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..20b3942afa9487ecff4c39d57e45c9aa7f783ef7 --- /dev/null +++ b/ets2panda/test/parser/ets/proxyVoidGeneration-expected.txt @@ -0,0 +1,1860 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "exit", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "exit", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "log_", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Boolean", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "initializer": { + "type": "NullLiteral", + "value": null, + "loc": { + "start": { + "line": 17, + "column": 31 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 35 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 38 + }, + "end": { + "line": 17, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 38 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 38 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 17, + "column": 43 + }, + "end": { + "line": 17, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 45 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "exit_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "exit_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "log_", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Boolean", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "$proxy_mask$", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "$proxy_mask$", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "consequent": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "log_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NullLiteral", + "value": null, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "property": { + "type": "Identifier", + "name": "exit", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "log_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 45 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "exthat", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 11 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "exthat", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 11 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "log_", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Boolean", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "initializer": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 27 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 18, + "column": 34 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "exthat_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "exthat_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "log_", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Boolean", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "$proxy_mask$", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "$proxy_mask$", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "consequent": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "log_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "property": { + "type": "Identifier", + "name": "exthat", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "log_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 36 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 2 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 23, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/proxyVoidGeneration.ets b/ets2panda/test/parser/ets/proxyVoidGeneration.ets new file mode 100644 index 0000000000000000000000000000000000000000..05b7cbecefe60c952676c8a3a51bf94114d7a96c --- /dev/null +++ b/ets2panda/test/parser/ets/proxyVoidGeneration.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + exit(log_: Boolean|null = null): void {} + exthat(log_?: Boolean): void {} +} + +function main() { +} diff --git a/ets2panda/test/parser/ets/tuple_type_1-expected.txt b/ets2panda/test/parser/ets/tuple_type_1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..101d5111ac1423c4ab01bfac717452d510f6307e --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_1-expected.txt @@ -0,0 +1,2035 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "my_type", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 33 + } + } + }, + { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 35 + }, + "end": { + "line": 16, + "column": 38 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 40 + }, + "end": { + "line": 16, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 40 + }, + "end": { + "line": 16, + "column": 47 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 40 + }, + "end": { + "line": 16, + "column": 47 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 34 + }, + "end": { + "line": 16, + "column": 48 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 25 + }, + "end": { + "line": 16, + "column": 49 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 16 + }, + "end": { + "line": 16, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 50 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 22, + "column": 28 + }, + "end": { + "line": 22, + "column": 29 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 22, + "column": 31 + }, + "end": { + "line": 22, + "column": 32 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 27 + }, + "end": { + "line": 22, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 34 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 23, + "column": 31 + }, + "end": { + "line": 23, + "column": 32 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 23, + "column": 36 + }, + "end": { + "line": 23, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 31 + }, + "end": { + "line": 23, + "column": 32 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 23, + "column": 44 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 24, + "column": 41 + }, + "end": { + "line": 24, + "column": 42 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 24, + "column": 44 + }, + "end": { + "line": 24, + "column": 45 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 24, + "column": 47 + }, + "end": { + "line": 24, + "column": 48 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 40 + }, + "end": { + "line": 24, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 24, + "column": 50 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [], + "loc": { + "start": { + "line": 25, + "column": 13 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 1 + }, + "end": { + "line": 25, + "column": 16 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "e", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 6 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 26, + "column": 36 + }, + "end": { + "line": 26, + "column": 37 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 26, + "column": 39 + }, + "end": { + "line": 26, + "column": 40 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 35 + }, + "end": { + "line": 26, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 1 + }, + "end": { + "line": 26, + "column": 42 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 6 + } + } + }, + "right": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 27, + "column": 41 + }, + "end": { + "line": 27, + "column": 42 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 27, + "column": 44 + }, + "end": { + "line": 27, + "column": 45 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 27, + "column": 47 + }, + "end": { + "line": 27, + "column": 48 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 40 + }, + "end": { + "line": 27, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 27, + "column": 50 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 10 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a0", + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 18, + "column": 31 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 35 + }, + "end": { + "line": 18, + "column": 42 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 43 + }, + "end": { + "line": 18, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 43 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 43 + }, + "end": { + "line": 18, + "column": 50 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 34 + }, + "end": { + "line": 18, + "column": 52 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 51 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 16 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 24 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 22, + "column": 8 + }, + "end": { + "line": 22, + "column": 26 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 26 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 16 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 24 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 26 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 26 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 16 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 24 + } + } + } + ], + "spreadType": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 36 + }, + "end": { + "line": 24, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 8 + }, + "end": { + "line": 24, + "column": 39 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 39 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTuple", + "spreadType": null, + "loc": { + "start": { + "line": 25, + "column": 8 + }, + "end": { + "line": 25, + "column": 12 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 12 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "e", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 32 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 26, + "column": 8 + }, + "end": { + "line": 26, + "column": 34 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 34 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 20 + } + } + }, + { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 30 + }, + "end": { + "line": 27, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 30 + }, + "end": { + "line": 27, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 30 + }, + "end": { + "line": 27, + "column": 37 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 27, + "column": 8 + }, + "end": { + "line": 27, + "column": 39 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 39 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 28, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/tuple_type_1.ets b/ets2panda/test/parser/ets/tuple_type_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..00298b8b96986b3f90cdcaf52842c6470754c705 --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_1.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type my_type = [Number, [Number, [int, Object]]]; + +function foo(a0: [int, number]): [number, number] { + return [1, 2]; +} + +let a: [number, number] = [1, 2]; +let b: [Object, Number] = [1, 2 as double]; +let c: [number, number, ...number[]] = [1, 2, 3]; +let d: [] = []; +let e: [a0: number, a1: number] = [1, 2]; +let f: [a0: number, int, a1: number] = [1, 2, 3]; diff --git a/ets2panda/test/parser/ets/tuple_type_2_neg-expected.txt b/ets2panda/test/parser/ets/tuple_type_2_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..af3ec97047149b82892ae9742fcb2d6354329b54 --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_2_neg-expected.txt @@ -0,0 +1 @@ +SyntaxError: Spread type must be at the last index in the tuple type [tuple_type_2_neg.ets:17:30] diff --git a/ets2panda/test/parser/ets/tuple_type_2_neg.ets b/ets2panda/test/parser/ets/tuple_type_2_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..551fe58e836c5af47dc4073b7ac25aa3fbdd6748 --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_2_neg.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +let a: [number, ...number[], number] = [1, 2, 3]; diff --git a/ets2panda/test/parser/ets/tuple_type_3_neg-expected.txt b/ets2panda/test/parser/ets/tuple_type_3_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ffd97331c7d84e0a9525b1690cd5b42126e1da5 --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_3_neg-expected.txt @@ -0,0 +1 @@ +SyntaxError: Comma is mandatory between elements in a tuple type declaration [tuple_type_3_neg.ets:17:24] diff --git a/ets2panda/test/parser/ets/tuple_type_3_neg.ets b/ets2panda/test/parser/ets/tuple_type_3_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..112d7709a7ab8c87c63059f887f8d6559c3a6a6d --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_3_neg.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +let a: [number, number number] = [1, 2, 3]; diff --git a/ets2panda/test/parser/ets/tuple_type_4_neg-expected.txt b/ets2panda/test/parser/ets/tuple_type_4_neg-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..bc0cf53ee585f9d203d72d67ddf878b7ff7ead3d --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_4_neg-expected.txt @@ -0,0 +1 @@ +SyntaxError: Invalid Type [tuple_type_4_neg.ets:17:13] diff --git a/ets2panda/test/parser/ets/tuple_type_4_neg.ets b/ets2panda/test/parser/ets/tuple_type_4_neg.ets new file mode 100644 index 0000000000000000000000000000000000000000..94226d0d8437ccd33cc78a7a490671c38ffd4bc2 --- /dev/null +++ b/ets2panda/test/parser/ets/tuple_type_4_neg.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +let a: [a0: , a1: number] = [1, 2, 3]; diff --git a/ets2panda/test/runtime/ets/float-literal.ets b/ets2panda/test/runtime/ets/float-literal.ets new file mode 100644 index 0000000000000000000000000000000000000000..df9b6bf77192ec9eb7d60174dab64e6ca7c39894 --- /dev/null +++ b/ets2panda/test/runtime/ets/float-literal.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function id(value: float): float { + return value +} + +function main(): void { + assert id(10) == 10.0f + assert id(-10) == -10.0f + assert id(0) == 0.0f +} diff --git a/ets2panda/test/runtime/ets/tuple_types_runtime.ets b/ets2panda/test/runtime/ets/tuple_types_runtime.ets new file mode 100644 index 0000000000000000000000000000000000000000..5f57797cab21335e752f5e8d7956c1866ebe4774 --- /dev/null +++ b/ets2panda/test/runtime/ets/tuple_types_runtime.ets @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type num_str_str = [number, string, string]; +type num_str_str_with_spread = [num_str_str, ...number[]]; + +class A { + foo(): int { + return 1; + } +} + +class B extends A { + override foo(): int { + return 2; + } +} + + +function main(): void { + const tup_1: [string, number] = ["a", 12]; + + assert(tup_1[0] == "a"); + assert(tup_1[1] == 12); + + const tup_2: num_str_str[] = [ + [13, "A", "D"], + [14, "B", "E"], + [25, "C", "F"], + ]; + + const tup_3: num_str_str_with_spread[] = [ + [tup_2[0], 250], + [tup_2[1], 250, 260], + [tup_2[0], 300, 300, 300], + ]; + + const sum = tup_3[0][1] + tup_3[1][1] + tup_3[1][2] + tup_3[2][1] + tup_3[2][2] + tup_3[2][3]; + assert(sum == 1660); + + // Runs correctly, but fails on verifier + // It sees the type of `tup_3[0][0]` as an `Object`, what it really is an Array type. + + // tup_3[0][0][0]++; + // assert(tup_3[0][0][0] == 14); + // tup_3[0][0][0] = 4; + // assert(tup_3[0][0][0] == 4); + + let int_update: [int] = [42]; + assert(int_update[0] == 42); + assert(int_update[0]++ == 42); + assert(int_update[0] == 43); + assert(++int_update[0] == 44); + int_update[0]++; + assert(int_update[0] == 45); + + let spread_tup: [Number, ...Number[]] = [6 as double,7 as double,8 as double, 9 as double, 10 as double]; + let num_arr: Number[] = [1 as double,2 as double,3 as double,4 as double,5 as double, 6 as double]; + + spread_tup = num_arr; + + let test_arr: Number[] = [1 as double,2 as double,3 as double,4 as double,5 as double, 6 as double]; + for(let idx = 0; idx < spread_tup.length; idx++){ + assert(spread_tup[idx] == test_arr[idx]); + } + + let tup_4: [number, number] = [11,2]; + let prim_num_arr: number[] = [3,4]; + + prim_num_arr = tup_4; + + let test_arr_2: number[] = [11, 2]; + for(let idx = 0; idx < prim_num_arr.length; idx++){ + assert(prim_num_arr[idx] == test_arr_2[idx]); + } + + let tup_8: [number, string][]; + tup_8 = [[1, "E"], [2, "F"], [3, "G"]]; + assert(tup_8[0][0] == 1 && tup_8[0][1] == "E"); + assert(tup_8[1][0] == 2 && tup_8[1][1] == "F"); + assert(tup_8[2][0] == 3 && tup_8[2][1] == "G"); + + let tup_10: [number, int, string, boolean, Object] = [1, 2, "I", false, new Object()]; + let var_float: float = tup_10[1]; + let var_float_2: float = 2.0; + assert(var_float == var_float_2); + + let tup_11: [int, number, string, boolean, Object] = [6, 7, "J", true, 789]; + // NOTE: Bug in op_assignment lowering (removes const from property) + // tup_11[0] += new Short(2 as short); + // assert(tup_11[0] == 8); + assert(tup_11[4] == (789 as Object)); + + let tup_12: [number, ...number[]] = [1, 2, 3, 4]; + try { + tup_12[4]; + } catch (e: ArrayIndexOutOfBoundsException) { + } catch (f) { + assert(false); + } + + let tup_13: [number, number] = [8, 9]; + let tup_14: [number, number] = [10, 11]; + + tup_13 = tup_14; + assert(tup_13[0] == 10); + assert(tup_13[1] == 11); + tup_13[0] = 12; + tup_13[1] = Double.valueOf(13.0); + assert(tup_13[0] == 12); + assert(tup_13[1] == 13); + + let a_b_tup: [A, A, B] = [new A(), new B(), new B()]; + assert(a_b_tup[0].foo() == 1); + assert(a_b_tup[1].foo() == 2); + assert(a_b_tup[2].foo() == 2); +}