From 1b3c486779c04d738589ee3c51d2ca0a7b158cec Mon Sep 17 00:00:00 2001 From: Zelentsov Dmitry Date: Mon, 20 Nov 2023 14:04:41 +0300 Subject: [PATCH 01/12] Check constraint circular dependency for type parameters. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8HODT?from=project-issue Tests: .../05.generics/01.generic_declarations/generic_interfaces/generic_interface_self_dependency4,5.ets Signed-off-by: Zelentsov Dmitry --- ets2panda/checker/ETSchecker.h | 5 +++ ets2panda/checker/ets/object.cpp | 55 +++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 87fc469310..e6acf295cc 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -587,7 +587,12 @@ private: } ArenaVector CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration *type_params); + Type *CreateTypeParameterType(ir::TSTypeParameter *param); + + using Type2TypeMap = std::unordered_map; + void CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends); + void SetUpTypeParameterConstraint(ir::TSTypeParameter *param); ETSObjectType *SetUpParameterType(ir::TSTypeParameter *param); ETSObjectType *CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *decl_node, diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 3de0b51247..5baa4a4ab0 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -175,9 +175,20 @@ ArenaVector ETSChecker::CreateTypeForTypeParameters(ir::TSTypeParameterD ArenaVector result {Allocator()->Adapter()}; checker::ScopeContext scope_ctx(this, type_params->Scope()); - for (auto *const param : type_params->Params()) { - result.push_back(CreateTypeParameterType(param)); + // Note: we have to run pure check loop first to avoid endless loop because of possible circular dependencies + Type2TypeMap extends {}; + for (auto *const type_param : type_params->Params()) { + if (auto *const constraint = type_param->Constraint(); + constraint != nullptr && constraint->IsETSTypeReference() && + constraint->AsETSTypeReference()->Part()->Name()->IsIdentifier()) { + CheckTypeParameterConstraint(type_param, extends); + } + } + + for (auto *const type_param : type_params->Params()) { + result.emplace_back(CreateTypeParameterType(type_param)); } + // The type parameter might be used in the constraint, like 'K extend Comparable', // so we need to create their type first, then set up the constraint for (auto *const param : type_params->Params()) { @@ -187,6 +198,35 @@ ArenaVector ETSChecker::CreateTypeForTypeParameters(ir::TSTypeParameterD return result; } +void ETSChecker::CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends) +{ + const auto type_param_name = param->Name()->Name().Utf8(); + const auto constraint_name = + param->Constraint()->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Utf8(); + + if (type_param_name == constraint_name) { + ThrowTypeError({"Type parameter '", type_param_name, "' cannot extend/implement itself."}, + param->Constraint()->Start()); + } + + auto it = extends.find(type_param_name); + if (it != extends.cend()) { + ThrowTypeError({"Type parameter '", type_param_name, "' is duplicated in the list."}, + param->Constraint()->Start()); + } + + it = extends.find(constraint_name); + while (it != extends.cend()) { + if (it->second == type_param_name) { + ThrowTypeError({"Type parameter '", type_param_name, "' has circular constraint dependency."}, + param->Constraint()->Start()); + } + it = extends.find(it->second); + } + + extends.emplace(type_param_name, constraint_name); +} + Type *ETSChecker::CreateTypeParameterType(ir::TSTypeParameter *const param) { auto const instantiate_supertype = [this](TypeFlag nullish_flags) { @@ -217,19 +257,10 @@ void ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param) param_type = param->Name()->Variable()->TsType()->AsETSObjectType(); } if (param->Constraint() != nullptr) { - if (param->Constraint()->IsETSTypeReference() && - param->Constraint()->AsETSTypeReference()->Part()->Name()->IsIdentifier() && - param->Name()->Name() == - param->Constraint()->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name()) { - ThrowTypeError({"Type variable '", param->Name()->Name(), "' cannot depend on itself"}, - param->Constraint()->Start()); - } - if (param->Constraint()->IsETSTypeReference()) { const auto constraint_name = param->Constraint()->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name(); const auto *const type_param_scope = param->Parent()->AsTSTypeParameterDeclaration()->Scope(); - if (auto *const found_param = type_param_scope->FindLocal(constraint_name, varbinder::ResolveBindingOptions::BINDINGS); found_param != nullptr) { -- Gitee From c0c30fe8bcb72e6e694f290804de18bb6dd597ba Mon Sep 17 00:00:00 2001 From: Zelentsov Dmitry Date: Thu, 9 Nov 2023 14:46:23 +0300 Subject: [PATCH 02/12] Implement constructors with default parameters. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8FJLJ?from=project-issue Test: build Signed-off-by: Zelentsov Dmitry --- ets2panda/checker/ets/function.cpp | 30 ++-- .../ir/ets/etsNewClassInstanceExpression.cpp | 2 + ets2panda/ir/ets/etsParameterExpression.cpp | 4 + ets2panda/ir/ets/etsParameterExpression.h | 15 ++ ets2panda/parser/ETSparser.cpp | 159 +++++++++++++----- ets2panda/parser/ETSparser.h | 24 ++- .../ets/optionalLambdaParameter-expected.txt | 4 +- .../ets/default_parameter1-expected.txt | 4 +- .../ets/default_parameter2-expected.txt | 4 +- .../ets/default_parameter4-expected.txt | 10 +- .../ets/default_parameter5-expected.txt | 4 +- ..._implicitly_typed_return_void-expected.txt | 6 +- .../parser/ets/rest_parameter_02-expected.txt | 4 +- .../test/runtime/ets/default_parameters.ets | 49 ++++++ 14 files changed, 240 insertions(+), 79 deletions(-) create mode 100644 ets2panda/test/runtime/ets/default_parameters.ets diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index ed412dc646..9594d01036 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -290,10 +290,12 @@ bool ETSChecker::ValidateProxySignature(Signature *const signature, return false; } - const auto num_non_default_params = - signature->Params().size() - signature->Function()->Body()->AsBlockStatement()->Statements().size(); + auto const *const proxy_param = signature->Function()->Params().back()->AsETSParameterExpression(); + if (!proxy_param->Ident()->Name().Is(ir::PROXY_PARAMETER_NAME)) { + return false; + } - if (arguments.size() < num_non_default_params) { + if (arguments.size() < proxy_param->GetRequiredParams()) { return false; } @@ -366,17 +368,25 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, return nullptr; } + // Just to avoid extra nesting level + auto const check_ambiguous = [this, most_specific_signature, + &pos](Signature const *const proxy_signature) -> void { + auto const *const proxy_param = proxy_signature->Function()->Params().back()->AsETSParameterExpression(); + if (!proxy_param->Ident()->Name().Is(ir::PROXY_PARAMETER_NAME)) { + ThrowTypeError({"Proxy parameter '", proxy_param->Ident()->Name(), "' has invalid name."}, pos); + } + + if (most_specific_signature->Params().size() == proxy_param->GetRequiredParams()) { + ThrowTypeError({"Reference to ", most_specific_signature->Function()->Id()->Name(), " is ambiguous"}, + pos); + } + }; + if (!proxy_signatures.empty()) { auto *const proxy_signature = ChooseMostSpecificProxySignature( proxy_signatures, arguments, arg_type_inference_required, pos, arguments.size()); if (proxy_signature != nullptr) { - const size_t num_non_default_params = - proxy_signature->Params().size() - - proxy_signature->Function()->Body()->AsBlockStatement()->Statements().size(); - if (most_specific_signature->Params().size() == num_non_default_params) { - ThrowTypeError( - {"Reference to ", most_specific_signature->Function()->Id()->Name(), " is ambiguous"}, pos); - } + check_ambiguous(proxy_signature); } } diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp index e0a0ce1b2d..f39597c1c6 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp @@ -164,6 +164,8 @@ checker::Type *ETSNewClassInstanceExpression::Check([[maybe_unused]] checker::ET 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); diff --git a/ets2panda/ir/ets/etsParameterExpression.cpp b/ets2panda/ir/ets/etsParameterExpression.cpp index 3d00268107..0445df4d22 100644 --- a/ets2panda/ir/ets/etsParameterExpression.cpp +++ b/ets2panda/ir/ets/etsParameterExpression.cpp @@ -171,12 +171,16 @@ ETSParameterExpression *ETSParameterExpression::Clone(ArenaAllocator *const allo if (auto *const clone = allocator->New(ident_or_spread, initializer); clone != nullptr) { ident_or_spread->SetParent(clone); + if (initializer != nullptr) { initializer->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRequiredParams(extra_value_); return clone; } diff --git a/ets2panda/ir/ets/etsParameterExpression.h b/ets2panda/ir/ets/etsParameterExpression.h index 7786d77fc3..64af2b1778 100644 --- a/ets2panda/ir/ets/etsParameterExpression.h +++ b/ets2panda/ir/ets/etsParameterExpression.h @@ -23,6 +23,10 @@ class ETSAnalyzer; } // namespace panda::es2panda::checker namespace panda::es2panda::ir { +// NOLINTBEGIN(modernize-avoid-c-arrays) +inline constexpr char const PROXY_PARAMETER_NAME[] = "$proxy_mask$"; +// NOLINTEND(modernize-avoid-c-arrays) + class ETSParameterExpression final : public Expression { public: ETSParameterExpression() = delete; @@ -64,6 +68,16 @@ public: return spread_ != nullptr; } + [[nodiscard]] std::size_t GetRequiredParams() const noexcept + { + return extra_value_; + } + + void SetRequiredParams(std::size_t const value) noexcept + { + extra_value_ = value; + } + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ETSParameterExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; @@ -80,6 +94,7 @@ private: Expression *initializer_; SpreadElement *spread_ = nullptr; util::StringView saved_lexer_ = ""; + std::size_t extra_value_ = 0U; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 0becad2529..5d2da9eaaf 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -2205,13 +2205,15 @@ void ETSParser::CreateClassFunctionDeclaration(ir::MethodDefinition *method) method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); } -bool ETSParser::HasDefaultParam(const ir::ScriptFunction *const function) +std::pair ETSParser::CheckDefaultParameters(const ir::ScriptFunction *const function) const { bool has_default_parameter = false; bool has_rest_parameter = false; + std::size_t required_parameters_number = 0U; for (auto *const it : function->Params()) { auto const *const param = it->AsETSParameterExpression(); + if (param->IsRestParameter()) { has_rest_parameter = true; continue; @@ -2229,23 +2231,58 @@ bool ETSParser::HasDefaultParam(const ir::ScriptFunction *const function) if (has_default_parameter) { ThrowSyntaxError("Required parameter follows default parameter(s).", param->Start()); } - } - if (!has_default_parameter) { - return false; + ++required_parameters_number; } - if (has_rest_parameter) { + if (has_default_parameter && has_rest_parameter) { ThrowSyntaxError("Both optional and rest parameters are not allowed in function's parameter list.", function->Start()); } - return true; + return std::make_pair(has_default_parameter, required_parameters_number); } -std::string ETSParser::CreateProxyMethodName(const ir::ScriptFunction *const function, ir::MethodDefinition *method, - ir::Identifier *ident_node, varbinder::ClassScope *const cls_scope) +ir::MethodDefinition *ETSParser::CreateProxyConstructorDefinition(ir::MethodDefinition const *const method) { + ASSERT(method->IsConstructor()); + + const auto *const function = method->Function(); + std::string proxy_method = function->Id()->Name().Mutf8() + '('; + + for (const auto *const it : function->Params()) { + auto const *const param = it->AsETSParameterExpression(); + proxy_method += param->Ident()->Name().Mutf8() + ": " + GetNameForTypeNode(param->TypeAnnotation()) + ", "; + } + + proxy_method += ir::PROXY_PARAMETER_NAME; + proxy_method += ": int) { this("; + + auto const parameters_number = function->Params().size(); + for (size_t i = 0U; i < parameters_number; ++i) { + if (auto const *const param = function->Params()[i]->AsETSParameterExpression(); param->IsDefault()) { + std::string proxy_if = "(((" + std::string {ir::PROXY_PARAMETER_NAME} + " >> " + std::to_string(i) + + ") & 0x1) == 0) ? " + param->Ident()->Name().Mutf8() + " : (" + + param->LexerSaved().Mutf8() + "), "; + proxy_method += proxy_if; + } else { + proxy_method += function->Params()[i]->AsETSParameterExpression()->Ident()->Name().Mutf8() + ", "; + } + } + + proxy_method.pop_back(); // Note: at least one parameter always should present! + proxy_method.pop_back(); + proxy_method += ") }"; + + return CreateConstructorDefinition(method->Modifiers(), proxy_method, DEFAULT_PROXY_FILE); +} + +ir::MethodDefinition *ETSParser::CreateProxyMethodDefinition(ir::MethodDefinition const *const method, + ir::Identifier const *const ident_node) +{ + ASSERT(!method->IsConstructor()); + + const auto *const function = method->Function(); std::string proxy_method = function->Id()->Name().Mutf8() + "_proxy("; for (const auto *const it : function->Params()) { @@ -2253,32 +2290,42 @@ std::string ETSParser::CreateProxyMethodName(const ir::ScriptFunction *const fun proxy_method += param->Ident()->Name().Mutf8() + ": " + GetNameForTypeNode(param->TypeAnnotation()) + ", "; } - const bool has_function_return_type = method->Function()->ReturnTypeAnnotation() != nullptr; + const bool has_function_return_type = function->ReturnTypeAnnotation() != nullptr; const std::string return_type = - has_function_return_type ? GetNameForTypeNode(method->Function()->ReturnTypeAnnotation()) : ""; + has_function_return_type ? GetNameForTypeNode(function->ReturnTypeAnnotation()) : ""; - proxy_method += has_function_return_type ? "proxy_int:int):" + return_type + "{" : "proxy_int:int) {"; + proxy_method += ir::PROXY_PARAMETER_NAME; + proxy_method += ": int)"; + if (has_function_return_type) { + proxy_method += ": " + return_type; + } + proxy_method += " { "; auto const parameters_number = function->Params().size(); - for (size_t i = 0U; i < parameters_number; i++) { + for (size_t i = 0U; i < parameters_number; ++i) { if (auto const *const param = function->Params()[i]->AsETSParameterExpression(); param->IsDefault()) { - std::string proxy_if = "if (((proxy_int >> " + std::to_string(i) + ") & 0x1) == 1) { " + - param->Ident()->Name().Mutf8() + " = " + param->LexerSaved().Mutf8() + " }"; + std::string proxy_if = "if (((" + std::string {ir::PROXY_PARAMETER_NAME} + " >> " + std::to_string(i) + + ") & 0x1) == 1) { " + param->Ident()->Name().Mutf8() + " = " + + param->LexerSaved().Mutf8() + " } "; proxy_method += proxy_if; } } + proxy_method += ' '; if (return_type != "void") { - if (cls_scope->Parent()->IsGlobalScope()) { + if (auto *const cls_scope = VarBinder()->GetScope()->AsClassScope(); cls_scope->Parent()->IsGlobalScope()) { proxy_method += "return "; } else if (method->IsStatic()) { + ASSERT(ident_node != nullptr); proxy_method += "return " + ident_node->Name().Mutf8() + "."; } else { proxy_method += "return this."; } } - proxy_method += function->Id()->Name().Mutf8() + "("; + proxy_method += function->Id()->Name().Mutf8(); + proxy_method += '('; + for (const auto *const it : function->Params()) { proxy_method += it->AsETSParameterExpression()->Ident()->Name().Mutf8() + ", "; } @@ -2286,39 +2333,34 @@ std::string ETSParser::CreateProxyMethodName(const ir::ScriptFunction *const fun proxy_method.pop_back(); proxy_method += ") }"; - return proxy_method; + return CreateMethodDefinition(method->Modifiers(), proxy_method, DEFAULT_PROXY_FILE); } void ETSParser::AddProxyOverloadToMethodWithDefaultParams(ir::MethodDefinition *method, ir::Identifier *ident_node) { - if (method->IsConstructor()) { - return; // NOTE(szd): Fix constructors not working with default params - } - - const auto *const function = method->Function(); + if (auto const [has_default_parameters, required_parameters] = CheckDefaultParameters(method->Function()); + has_default_parameters) { + if (ir::MethodDefinition *proxy_method_def = !method->IsConstructor() + ? CreateProxyMethodDefinition(method, ident_node) + : CreateProxyConstructorDefinition(method); + proxy_method_def != nullptr) { + auto *const proxy_param = proxy_method_def->Function()->Params().back()->AsETSParameterExpression(); + proxy_param->SetRequiredParams(required_parameters); - if (!HasDefaultParam(function)) { - return; - } + proxy_method_def->Function()->SetDefaultParamProxy(); + proxy_method_def->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); - auto *const cls_scope = VarBinder()->GetScope()->AsClassScope(); - varbinder::LocalScope *target_scope = - method->IsStatic() ? cls_scope->StaticMethodScope() : cls_scope->InstanceMethodScope(); - auto *const found = target_scope->FindLocal(method->Id()->Name(), varbinder::ResolveBindingOptions::BINDINGS); + auto *const var = method->Id()->Variable(); + auto *const current_node = var->Declaration()->Node(); - std::string proxy_method = CreateProxyMethodName(function, method, ident_node, cls_scope); + proxy_method_def->Id()->SetVariable(var); + proxy_method_def->SetParent(current_node); - auto class_ctx = - varbinder::LexicalScope::Enter(VarBinder(), GetProgram()->GlobalClassScope()); - - auto *const proxy_method_def = CreateMethodDefinition(method->Modifiers(), proxy_method, ".ets"); - proxy_method_def->Function()->SetDefaultParamProxy(); - - auto *const current_node = found->Declaration()->Node(); - current_node->AsMethodDefinition()->AddOverload(proxy_method_def); - proxy_method_def->Id()->SetVariable(found); - proxy_method_def->SetParent(current_node); - proxy_method_def->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); + if (!method->IsConstructor()) { + current_node->AsMethodDefinition()->AddOverload(proxy_method_def); + } + } + } } std::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type) @@ -2347,7 +2389,7 @@ std::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type) } } -std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *type_annotation) +std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *type_annotation) const { if ((type_annotation->IsNullAssignable() || type_annotation->IsUndefinedAssignable()) && type_annotation->IsETSUnionType()) { @@ -4765,6 +4807,39 @@ ir::MethodDefinition *ETSParser::CreateMethodDefinition(ir::ModifierFlags modifi return method_definition; } +ir::MethodDefinition *ETSParser::CreateConstructorDefinition(ir::ModifierFlags modifiers, + std::string_view const source_code, + std::string_view const file_name) +{ + util::UString source {source_code, Allocator()}; + auto const isp = InnerSourceParser(this); + auto const lexer = InitLexer({file_name, source.View().Utf8()}); + + auto const start_loc = Lexer()->GetToken().Start(); + Lexer()->NextToken(); + + if (IsClassMethodModifier(Lexer()->GetToken().Type())) { + modifiers |= ParseClassMethodModifiers(false); + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_CONSTRUCTOR) { + ThrowSyntaxError({"Unexpected token. 'Constructor' keyword is expected."}); + } + + if ((modifiers & ir::ModifierFlags::ASYNC) != 0) { + ThrowSyntaxError({"Constructor should not be async."}); + } + + auto *member_name = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + modifiers |= ir::ModifierFlags::CONSTRUCTOR; + Lexer()->NextToken(); + + auto *const method_definition = ParseClassMethodDefinition(member_name, modifiers); + method_definition->SetStart(start_loc); + + return method_definition; +} + ir::Expression *ETSParser::CreateExpression(std::string_view const source_code, ExpressionParseFlags const flags, std::string_view const file_name) { diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index cf643c0d57..a2716bef27 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -170,12 +170,13 @@ private: ir::TypeNode *ParseWildcardType(TypeAnnotationParsingOptions *options); ir::TypeNode *ParseFunctionType(); void CreateClassFunctionDeclaration(ir::MethodDefinition *method); - bool HasDefaultParam(const ir::ScriptFunction *function); - std::string CreateProxyMethodName(const ir::ScriptFunction *function, ir::MethodDefinition *method, - ir::Identifier *ident_node, varbinder::ClassScope *cls_scope); + std::pair CheckDefaultParameters(const ir::ScriptFunction *function) const; + ir::MethodDefinition *CreateProxyMethodDefinition(ir::MethodDefinition const *method, + ir::Identifier const *ident_node); + ir::MethodDefinition *CreateProxyConstructorDefinition(ir::MethodDefinition const *method); void AddProxyOverloadToMethodWithDefaultParams(ir::MethodDefinition *method, ir::Identifier *ident_node = nullptr); static std::string PrimitiveTypeToName(ir::PrimitiveType type); - std::string GetNameForTypeNode(const ir::TypeNode *type_annotation); + std::string GetNameForTypeNode(const ir::TypeNode *type_annotation) const; ir::TSInterfaceDeclaration *ParseInterfaceBody(ir::Identifier *name, bool is_static); bool IsArrowFunctionExpressionStart(); ir::ArrowFunctionExpression *ParseArrowFunctionExpression(); @@ -307,10 +308,14 @@ private: void CheckDeclare(); - // Methods to create AST node(s) from the specified string (part of valid ETS-code!) - // NOTE: the correct initial scope should be entered BEFORE calling any of these methods, - // and correct parent and, probably, variable set to the node(s) after obtaining - + // Methods to create AST node(s) from the specified string (part of valid ETS-code!) + // NOTE: the correct initial scope should be entered BEFORE calling any of these methods, + // and correct parent and, probably, variable set to the node(s) after obtaining + // NOLINTBEGIN(modernize-avoid-c-arrays) + inline static constexpr char const DEFAULT_SOURCE_FILE[] = ".ets"; + inline static constexpr char const DEFAULT_PROXY_FILE[] = ".ets"; + // NOLINTEND(modernize-avoid-c-arrays) + // NOLINTBEGIN(google-default-arguments) ir::Statement *CreateStatement(std::string_view source_code, std::string_view file_name = DEFAULT_SOURCE_FILE); ir::Statement *CreateFormattedStatement(std::string_view source_code, std::vector &inserting_nodes, std::string_view file_name = DEFAULT_SOURCE_FILE); @@ -326,7 +331,8 @@ private: ir::MethodDefinition *CreateMethodDefinition(ir::ModifierFlags modifiers, std::string_view source_code, std::string_view file_name = DEFAULT_SOURCE_FILE); - + ir::MethodDefinition *CreateConstructorDefinition(ir::ModifierFlags modifiers, std::string_view source_code, + std::string_view file_name = DEFAULT_SOURCE_FILE); ir::TypeNode *CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view source_code, std::string_view file_name = DEFAULT_SOURCE_FILE); diff --git a/ets2panda/test/compiler/ets/optionalLambdaParameter-expected.txt b/ets2panda/test/compiler/ets/optionalLambdaParameter-expected.txt index ca7577b0c3..9924e957d6 100644 --- a/ets2panda/test/compiler/ets/optionalLambdaParameter-expected.txt +++ b/ets2panda/test/compiler/ets/optionalLambdaParameter-expected.txt @@ -513,7 +513,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -608,7 +608,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/default_parameter1-expected.txt b/ets2panda/test/parser/ets/default_parameter1-expected.txt index 70a65a1979..edf5d5438e 100644 --- a/ets2panda/test/parser/ets/default_parameter1-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter1-expected.txt @@ -691,7 +691,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -758,7 +758,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/default_parameter2-expected.txt b/ets2panda/test/parser/ets/default_parameter2-expected.txt index 0267fc1b3f..96e2d6dcdf 100644 --- a/ets2panda/test/parser/ets/default_parameter2-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter2-expected.txt @@ -676,7 +676,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -743,7 +743,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/default_parameter4-expected.txt b/ets2panda/test/parser/ets/default_parameter4-expected.txt index 35457f1bc8..5c072e7bcd 100644 --- a/ets2panda/test/parser/ets/default_parameter4-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter4-expected.txt @@ -816,7 +816,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -883,7 +883,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -1067,7 +1067,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -1656,7 +1656,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -1723,7 +1723,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/default_parameter5-expected.txt b/ets2panda/test/parser/ets/default_parameter5-expected.txt index c7eec11850..ab0a5a6760 100644 --- a/ets2panda/test/parser/ets/default_parameter5-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter5-expected.txt @@ -861,7 +861,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -928,7 +928,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/default_parameter_implicitly_typed_return_void-expected.txt b/ets2panda/test/parser/ets/default_parameter_implicitly_typed_return_void-expected.txt index fcf3644024..1e35125767 100644 --- a/ets2panda/test/parser/ets/default_parameter_implicitly_typed_return_void-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter_implicitly_typed_return_void-expected.txt @@ -690,7 +690,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -744,7 +744,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -928,7 +928,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/rest_parameter_02-expected.txt b/ets2panda/test/parser/ets/rest_parameter_02-expected.txt index 9dcbe17e90..87a53b8d5a 100644 --- a/ets2panda/test/parser/ets/rest_parameter_02-expected.txt +++ b/ets2panda/test/parser/ets/rest_parameter_02-expected.txt @@ -793,7 +793,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -860,7 +860,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/runtime/ets/default_parameters.ets b/ets2panda/test/runtime/ets/default_parameters.ets new file mode 100644 index 0000000000..a660a80c04 --- /dev/null +++ b/ets2panda/test/runtime/ets/default_parameters.ets @@ -0,0 +1,49 @@ +/* + * 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. + */ + +function foo(a: int = 3, b: int = 5): int { + return a * 10 + b; +} + +class C { + x: int; + y: int; + + constructor (a: int = 3, b: int = 5) { + this.x = a; + this.y = b; + } +} + +function main(): void { + + let res = foo(5, 7); + assert (res == 57); + + res = foo(7); + assert (res == 75); + + res = foo(); + assert (res == 35); + + let c0 = new C(); + assert (c0.x == 3 && c0.y == 5); + + let c1 = new C(7); + assert (c1.x == 7 && c1.y == 5); + + let c2 = new C(5, 7); + assert (c2.x == 5 && c2.y == 7); +} -- Gitee From 2c90854caf98b4b2ce749d6d1e9797b3f8459d09 Mon Sep 17 00:00:00 2001 From: Maxim Logaev Date: Mon, 27 Nov 2023 13:52:47 +0300 Subject: [PATCH 03/12] Fixed bug #I8G6U5 Signed-off-by: Maxim Logaev --- ets2panda/checker/ets/helpers.cpp | 4 ++++ .../test/compiler/ets/voidTypeInBinaryOperation-expected.txt | 1 + 2 files changed, 5 insertions(+) diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index d1e74e0835..c1d3dec4fc 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -75,6 +75,10 @@ void ETSChecker::CheckTruthinessOfType(ir::Expression *expr) checker::Type *type = expr->Check(this); auto *unboxed_type = ETSBuiltinTypeAsConditionalType(type); + if (unboxed_type == GlobalBuiltinVoidType() || unboxed_type->IsETSVoidType()) { + ThrowTypeError("An expression of type 'void' cannot be tested for truthiness", expr->Start()); + } + if (unboxed_type != nullptr && !unboxed_type->IsConditionalExprType()) { ThrowTypeError("Condition must be of possible condition type", expr->Start()); } diff --git a/ets2panda/test/compiler/ets/voidTypeInBinaryOperation-expected.txt b/ets2panda/test/compiler/ets/voidTypeInBinaryOperation-expected.txt index 9447d6cad0..b434ae012c 100644 --- a/ets2panda/test/compiler/ets/voidTypeInBinaryOperation-expected.txt +++ b/ets2panda/test/compiler/ets/voidTypeInBinaryOperation-expected.txt @@ -494,3 +494,4 @@ } } } +TypeError: An expression of type 'void' cannot be tested for truthiness [voidTypeInBinaryOperation.ets:20:19] -- Gitee From 0b868757c5dee62cfc8ce5b2d29b9a69fcd65e7e Mon Sep 17 00:00:00 2001 From: Molokanov Yaroslav Date: Mon, 23 Oct 2023 18:17:42 +0300 Subject: [PATCH 04/12] Implemented auto-boxing for primitive types in ets Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8D0AZ Test: .../test/runtime/ets/autoboxing.ets Signed-off-by: Molokanov Yaroslav --- ets2panda/checker/ets/helpers.cpp | 2 +- ets2panda/compiler/core/ETSCompiler.cpp | 4 ++- ets2panda/ir/expressions/memberExpression.cpp | 9 +++++ ets2panda/test/runtime/ets/autoboxing.ets | 35 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 ets2panda/test/runtime/ets/autoboxing.ets diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index c1d3dec4fc..97b3b385f2 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -443,7 +443,7 @@ void ETSChecker::ValidateResolvedIdentifier(ir::Identifier *const ident, varbind if (!resolved_type->IsETSObjectType() && !resolved_type->IsETSArrayType() && !resolved_type->IsETSEnumType() && !resolved_type->IsETSStringEnumType() && - !resolved_type->IsETSUnionType()) { + !resolved_type->IsETSUnionType() && !resolved_type->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { throw_error(); } diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 6ee70ad191..7df01ed603 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -524,7 +524,9 @@ void ETSCompiler::CompileDynamic(const ir::CallExpression *expr, compiler::VReg void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &callee_reg, bool is_static) const { ETSGen *etsg = GetETSGen(); - + if (expr->Callee()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { + etsg->ApplyConversionAndStoreAccumulator(expr->Callee(), callee_reg, nullptr); + } if (is_static) { etsg->CallStatic(expr, expr->Signature(), expr->Arguments()); } else if (expr->Signature()->HasSignatureFlag(checker::SignatureFlags::PRIVATE) || expr->IsETSConstructorCall() || diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index eda32a4f54..a308acfd14 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -451,6 +451,15 @@ checker::Type *MemberExpression::Check(checker::ETSChecker *checker) 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()); } diff --git a/ets2panda/test/runtime/ets/autoboxing.ets b/ets2panda/test/runtime/ets/autoboxing.ets new file mode 100644 index 0000000000..f66dbbb41b --- /dev/null +++ b/ets2panda/test/runtime/ets/autoboxing.ets @@ -0,0 +1,35 @@ +/* + * 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 foo_i(value: int): string { + return value.toString(); +} + +function foo_d(value: double): string { + return value.toString(); +} + +function foo_n(value: number): string { + return value.toString(); +} + +function main(): void { + let str_i: string = foo_i(4); + assert str_i == "4"; + let str_d: string = foo_d(3.14); + assert str_d == "3.14"; + let str_n: string = foo_n(5); + assert str_n == "5"; +} \ No newline at end of file -- Gitee From 12fe62e039b48404610654435473d537d4527529 Mon Sep 17 00:00:00 2001 From: Robert Sipka Date: Mon, 13 Nov 2023 15:18:10 +0100 Subject: [PATCH 05/12] [ETS] Minor fix for es2panda path in coverage measurement Signed-off-by: Robert Sipka --- ets2panda/cmake/coverage.cmake | 6 +++++- ets2panda/scripts/es2panda_coverage.sh | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ets2panda/cmake/coverage.cmake b/ets2panda/cmake/coverage.cmake index 8464c0fed8..794bf7a6e7 100644 --- a/ets2panda/cmake/coverage.cmake +++ b/ets2panda/cmake/coverage.cmake @@ -17,9 +17,13 @@ include(${PANDA_ROOT}/cmake/toolchain/coverage/unit_tests_lcov.cmake) add_custom_target(es2panda_coverage DEPENDS etsstdlib es2panda verifier ark) +if (NOT DEFINED ES2PANDA_PATH) + set(ES2PANDA_PATH ${PANDA_ROOT}/tools/es2panda) +endif() + add_custom_command(TARGET es2panda_coverage POST_BUILD WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND bash ${PANDA_ROOT}/plugins/ecmascript/es2panda/scripts/es2panda_coverage.sh --binary-dir=${PANDA_BINARY_ROOT} --root-dir=${PANDA_ROOT} + COMMAND bash ${ES2PANDA_PATH}/scripts/es2panda_coverage.sh --binary-dir=${PANDA_BINARY_ROOT} --root-dir=${PANDA_ROOT} ) if(ENABLE_ES2PANDA_COVERAGE) diff --git a/ets2panda/scripts/es2panda_coverage.sh b/ets2panda/scripts/es2panda_coverage.sh index 9af403a22b..a299f1c515 100644 --- a/ets2panda/scripts/es2panda_coverage.sh +++ b/ets2panda/scripts/es2panda_coverage.sh @@ -26,16 +26,16 @@ case "$ARGUMENT" in esac done -python $PANDA_ROOT/plugins/ecmascript/es2panda/scripts/test_runner.py \ +python $PANDA_ROOT/tools/es2panda/scripts/test_runner.py \ --builddir $PANDA_BINARY_ROOT --arkdir $PANDA_ROOT --all -gcov $PANDA_BINARY_ROOT/plugins/ecmascript/es2panda/CMakeFiles/es2panda-lib.dir/*/* +gcov $PANDA_BINARY_ROOT/tools/es2panda/CMakeFiles/es2panda-lib.dir/*/* if [ -x "$(command -v gcovr)" ]; then echo "gcovr found" gcovr --version - gcovr -v -r $PANDA_ROOT/plugins/ecmascript/es2panda \ - -e $PANDA_ROOT/plugins/ecmascript/es2panda/test \ + gcovr -v -r $PANDA_ROOT/tools/es2panda/ \ + -e $PANDA_ROOT/tools/es2panda/test \ --object-directory=$PANDA_BINARY_ROOT --html-details --html -o report.html else -- Gitee From 80439b9c252e62122a01e37cc4033976ed03adff Mon Sep 17 00:00:00 2001 From: Anton Berezin Date: Thu, 16 Nov 2023 11:54:12 +0400 Subject: [PATCH 06/12] Fix bug of assigning primitive to Number. Allow widening for boxed source type. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8EZ44 Signed-off-by: Anton Berezin --- ets2panda/checker/ets/helpers.cpp | 4 ++-- .../runtime/ets/number-from-narrow-prim.ets | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 ets2panda/test/runtime/ets/number-from-narrow-prim.ets diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 97b3b385f2..dd678cbfa3 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1793,7 +1793,7 @@ void ETSChecker::CheckUnboxedTypesAssignable(TypeRelation *relation, Type *sourc void ETSChecker::CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *source, Type *target) { checker::SavedTypeRelationFlagsContext saved_type_relation_flag_ctx( - relation, TypeRelationFlag::ONLY_CHECK_WIDENING | + relation, (relation->ApplyWidening() ? TypeRelationFlag::WIDENING : TypeRelationFlag::NONE) | (relation->ApplyNarrowing() ? TypeRelationFlag::NARROWING : TypeRelationFlag::NONE)); auto *boxed_source_type = relation->GetChecker()->AsETSChecker()->PrimitiveTypeAsETSBuiltinType(source); if (boxed_source_type == nullptr) { @@ -1811,7 +1811,7 @@ void ETSChecker::CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *so if (unboxed_target_type == nullptr) { return; } - NarrowingConverter(this, relation, unboxed_target_type, source); + NarrowingWideningConverter(this, relation, unboxed_target_type, source); if (relation->IsTrue()) { AddBoxingFlagToPrimitiveType(relation, target); } diff --git a/ets2panda/test/runtime/ets/number-from-narrow-prim.ets b/ets2panda/test/runtime/ets/number-from-narrow-prim.ets new file mode 100644 index 0000000000..0c4744297c --- /dev/null +++ b/ets2panda/test/runtime/ets/number-from-narrow-prim.ets @@ -0,0 +1,24 @@ +/* + * 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. + * + * + * Based on https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8EZ44 + */ + + +function main() { + let n: Number = 5 + + assert n == 5 +} -- Gitee From 9658417c675cb80d67d34f50d38bcc07d779a145 Mon Sep 17 00:00:00 2001 From: zhaoziming Date: Mon, 27 Nov 2023 16:23:54 +0800 Subject: [PATCH 07/12] Implement stricter function override validation Signed-off-by: zhaoziming --- ets2panda/checker/ETSchecker.h | 4 + ets2panda/checker/checker.h | 5 + ets2panda/checker/types/signature.cpp | 124 +- ets2panda/checker/types/signature.h | 1 + .../ets/default_parameter1-expected.txt | 2 +- .../ets/default_parameter2-expected.txt | 2 +- .../ets/default_parameter4-expected.txt | 2 +- .../ets/default_parameter6-expected.txt | 2637 +++++++++++++++++ .../test/parser/ets/default_parameter6.ets | 24 + .../ets/default_parameter7-expected.txt | 1655 +++++++++++ .../test/parser/ets/default_parameter7.ets | 24 + ets2panda/test/runtime/ets/DefaultParam_1.ets | 34 - ets2panda/test/runtime/ets/DefaultParam_2.ets | 33 - ets2panda/test/runtime/ets/DefaultParam_4.ets | 33 - 14 files changed, 4437 insertions(+), 143 deletions(-) create mode 100644 ets2panda/test/parser/ets/default_parameter6-expected.txt create mode 100644 ets2panda/test/parser/ets/default_parameter6.ets create mode 100644 ets2panda/test/parser/ets/default_parameter7-expected.txt create mode 100644 ets2panda/test/parser/ets/default_parameter7.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index e6acf295cc..3dd9b2fe45 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -124,6 +124,10 @@ public: Type *CheckTypeCached(ir::Expression *expr) override; void ResolveStructuredTypeMembers([[maybe_unused]] Type *type) override {} Type *GetTypeOfVariable([[maybe_unused]] varbinder::Variable *var) override; + bool IsETSChecker() override + { + return true; + } // Object ETSObjectType *BuildClassProperties(ir::ClassDefinition *class_def); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index 9927c78589..5113779226 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -139,6 +139,11 @@ public: return type_stack_; } + virtual bool IsETSChecker() + { + return false; + } + ETSChecker *AsETSChecker() { return reinterpret_cast(this); diff --git a/ets2panda/checker/types/signature.cpp b/ets2panda/checker/types/signature.cpp index ab2188c6c0..79019e3787 100644 --- a/ets2panda/checker/types/signature.cpp +++ b/ets2panda/checker/types/signature.cpp @@ -172,12 +172,44 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia return_type_->ToString(ss); } +namespace { +std::size_t GetToCheckParamCount(Signature *signature, bool is_ets) +{ + auto param_number = static_cast(signature->Params().size()); + if (!is_ets || signature->Function() == nullptr) { + return param_number; + } + for (auto i = param_number - 1; i >= 0; i--) { + if (!signature->Function()->Params()[i]->AsETSParameterExpression()->IsDefault()) { + return static_cast(i + 1); + } + } + return 0; +} +} // namespace + +bool Signature::IdenticalParameter(TypeRelation *relation, Type *type1, Type *type2) +{ + if (!CheckFunctionalInterfaces(relation, type1, type2)) { + relation->IsIdenticalTo(type1, type2); + } + return relation->IsTrue(); +} + void Signature::Identical(TypeRelation *relation, Signature *other) { - if ((this->MinArgCount() != other->MinArgCount() || this->Params().size() != other->Params().size()) && + bool is_ets = relation->GetChecker()->IsETSChecker(); + auto const this_to_check_parameters_number = GetToCheckParamCount(this, is_ets); + auto const other_to_check_parameters_number = GetToCheckParamCount(other, is_ets); + if ((this_to_check_parameters_number != other_to_check_parameters_number || + this->MinArgCount() != other->MinArgCount()) && this->RestVar() == nullptr && other->RestVar() == nullptr) { - relation->Result(false); - return; + // skip check for ets cases only when all parameters are mandatory + if (!is_ets || (this_to_check_parameters_number == this->Params().size() && + other_to_check_parameters_number == other->Params().size())) { + relation->Result(false); + return; + } } if (relation->NoReturnTypeCheck()) { @@ -187,51 +219,63 @@ void Signature::Identical(TypeRelation *relation, Signature *other) } if (relation->IsTrue()) { - // Lambda to check parameter types - auto const identical_parameters = [this, relation](checker::Type *const type1, - checker::Type *const type2) -> bool { - if (!CheckFunctionalInterfaces(relation, type1, type2)) { - relation->IsIdenticalTo(type1, type2); - } - return relation->IsTrue(); - }; - - auto const this_parameters_number = this->Params().size(); - auto const other_parameters_number = other->Params().size(); - auto const parameters_number = std::min(this_parameters_number, other_parameters_number); + /* In ETS, the functions "foo(a: int)" and "foo(a: int, b: int = 1)" should be considered as having an + equivalent signature. Hence, we only need to check if the mandatory parameters of the signature with + more mandatory parameters can match the parameters of the other signature (including the optional + parameter or rest parameters) here. + + XXX_to_check_parameters_number is calculated beforehand by counting mandatory parameters. + Signature::params() stores all parameters (mandatory and optional), excluding the rest parameter. + Signature::restVar() stores the rest parameters of the function. + + For example: + foo(a: int): params().size: 1, to_check_param_number: 1, restVar: nullptr + foo(a: int, b: int = 0): params().size: 2, to_check_param_number: 1, restVar: nullptr + foo(a: int, ...b: int[]): params().size: 1, to_check_param_number: 1, restVar: ...b: int[] + + Note that optional parameters always come after mandatory parameters, and signatures containing both + optional and rest parameters are not allowed. + + "to_check_parameters_number" is the number of parameters that need to be checked to ensure identical. + "parameters_number" is the number of parameters that can be checked in Signature::params(). + */ + auto const to_check_parameters_number = + std::max(this_to_check_parameters_number, other_to_check_parameters_number); + auto const parameters_number = + std::min({this->Params().size(), other->Params().size(), to_check_parameters_number}); std::size_t i = 0U; for (; i < parameters_number; ++i) { - auto *const this_sig_param_type = this->Params()[i]->TsType(); - auto *const other_sig_param_type = other->Params()[i]->TsType(); - if (!identical_parameters(this_sig_param_type, other_sig_param_type)) { + if (!IdenticalParameter(relation, this->Params()[i]->TsType(), other->Params()[i]->TsType())) { return; } } - // Lambda to check the rest parameters - auto const identical_rest_parameters = - [&i, &identical_parameters, relation](std::size_t const parameter_number, - ArenaVector const ¶meters, - varbinder::LocalVariable const *const rest_parameter) -> void { - if (rest_parameter != nullptr) { - auto *const other_sig_param_type = rest_parameter->TsType()->AsETSArrayType()->ElementType(); - - for (; i < parameter_number; ++i) { - auto *const this_sig_param_type = parameters[i]->TsType(); - if (!identical_parameters(this_sig_param_type, other_sig_param_type)) { - break; - } - } - } else { - relation->Result(false); + /* "i" could be one of the following three cases: + 1. == to_check_parameters_number, we have finished the checking and can directly return. + 2. == other->Params().size(), must be < this_to_check_parameters_number in this case since + xxx->Params().size() always >= xxx_to_check_parameters_number. We need to check the remaining + mandatory parameters of "this" against ths RestVar of "other". + 3. == this->Params().size(), must be < other_to_check_parameters_number as described in 2, and + we need to check the remaining mandatory parameters of "other" against the RestVar of "this". + */ + if (i == to_check_parameters_number) { + return; + } + bool is_other_mandatory_params_matched = i < this_to_check_parameters_number; + ArenaVector const ¶meters = + is_other_mandatory_params_matched ? this->Params() : other->Params(); + varbinder::LocalVariable const *rest_parameter = + is_other_mandatory_params_matched ? other->RestVar() : this->RestVar(); + if (rest_parameter == nullptr) { + relation->Result(false); + return; + } + auto *const rest_parameter_type = rest_parameter->TsType()->AsETSArrayType()->ElementType(); + for (; i < to_check_parameters_number; ++i) { + if (!IdenticalParameter(relation, parameters[i]->TsType(), rest_parameter_type)) { + return; } - }; - - if (i < this_parameters_number) { - identical_rest_parameters(this_parameters_number, this->Params(), other->RestVar()); - } else if (i < other_parameters_number) { - identical_rest_parameters(other_parameters_number, other->Params(), this->RestVar()); } } } diff --git a/ets2panda/checker/types/signature.h b/ets2panda/checker/types/signature.h index 2341dd5745..161325c6a0 100644 --- a/ets2panda/checker/types/signature.h +++ b/ets2panda/checker/types/signature.h @@ -250,6 +250,7 @@ public: void AssignmentTarget(TypeRelation *relation, Signature *source); private: + bool IdenticalParameter(TypeRelation *relation, Type *type1, Type *type2); checker::SignatureInfo *signature_info_; Type *return_type_; ir::ScriptFunction *func_ {}; diff --git a/ets2panda/test/parser/ets/default_parameter1-expected.txt b/ets2panda/test/parser/ets/default_parameter1-expected.txt index edf5d5438e..41c4146c87 100644 --- a/ets2panda/test/parser/ets/default_parameter1-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter1-expected.txt @@ -1276,4 +1276,4 @@ } } } -TypeError: Reference to foo is ambiguous [default_parameter1.ets:18:5] +TypeError: Function already declared. [default_parameter1.ets:26:1] diff --git a/ets2panda/test/parser/ets/default_parameter2-expected.txt b/ets2panda/test/parser/ets/default_parameter2-expected.txt index 96e2d6dcdf..1bc729dc18 100644 --- a/ets2panda/test/parser/ets/default_parameter2-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter2-expected.txt @@ -1261,4 +1261,4 @@ } } } -TypeError: No matching call signature [default_parameter2.ets:18:5] +TypeError: Function already declared. [default_parameter2.ets:26:1] diff --git a/ets2panda/test/parser/ets/default_parameter4-expected.txt b/ets2panda/test/parser/ets/default_parameter4-expected.txt index 5c072e7bcd..9ddd359583 100644 --- a/ets2panda/test/parser/ets/default_parameter4-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter4-expected.txt @@ -2048,4 +2048,4 @@ } } } -TypeError: Reference to foo is ambiguous [default_parameter4.ets:18:5] +TypeError: Function already declared. [default_parameter4.ets:26:1] diff --git a/ets2panda/test/parser/ets/default_parameter6-expected.txt b/ets2panda/test/parser/ets/default_parameter6-expected.txt new file mode 100644 index 0000000000..caaeb8826a --- /dev/null +++ b/ets2panda/test/parser/ets/default_parameter6-expected.txt @@ -0,0 +1,2637 @@ +{ + "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": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "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": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 27 + }, + "end": { + "line": 16, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 27 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 27 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 23 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 20, + "loc": { + "start": { + "line": 16, + "column": 33 + }, + "end": { + "line": 16, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 23 + }, + "end": { + "line": 16, + "column": 35 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 41 + }, + "end": { + "line": 16, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 41 + }, + "end": { + "line": 16, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 41 + }, + "end": { + "line": 16, + "column": 46 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 37 + }, + "end": { + "line": 16, + "column": 46 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 30, + "loc": { + "start": { + "line": 16, + "column": 47 + }, + "end": { + "line": 16, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 37 + }, + "end": { + "line": 16, + "column": 49 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 53 + }, + "end": { + "line": 16, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 53 + }, + "end": { + "line": 17, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 53 + }, + "end": { + "line": 17, + "column": 2 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo_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": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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_int", + "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": "Int", + "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_int", + "decorators": [], + "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 + } + } + }, + "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": "b", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 20, + "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": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "proxy_int", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 2, + "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": "c", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 30, + "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": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Identifier", + "name": "c", + "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 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "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": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 27 + }, + "end": { + "line": 21, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 27 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 27 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 23 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "initializer": { + "type": "StringLiteral", + "value": "a", + "loc": { + "start": { + "line": 21, + "column": 36 + }, + "end": { + "line": 21, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 23 + }, + "end": { + "line": 21, + "column": 39 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 45 + }, + "end": { + "line": 21, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 45 + }, + "end": { + "line": 21, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 45 + }, + "end": { + "line": 21, + "column": 50 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 41 + }, + "end": { + "line": 21, + "column": 50 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 30, + "loc": { + "start": { + "line": 21, + "column": 51 + }, + "end": { + "line": 21, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 41 + }, + "end": { + "line": 21, + "column": 53 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 57 + }, + "end": { + "line": 21, + "column": 60 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 57 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 57 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "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": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo_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": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "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": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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_int", + "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": "Int", + "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_int", + "decorators": [], + "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 + } + } + }, + "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": "b", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "StringLiteral", + "value": "a", + "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": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "proxy_int", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 2, + "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": "c", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 30, + "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": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Identifier", + "name": "c", + "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": 16, + "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": 25, + "column": 1 + } + } +} +TypeError: Function already declared. [default_parameter6.ets:21:1] diff --git a/ets2panda/test/parser/ets/default_parameter6.ets b/ets2panda/test/parser/ets/default_parameter6.ets new file mode 100644 index 0000000000..2cb74c5e65 --- /dev/null +++ b/ets2panda/test/parser/ets/default_parameter6.ets @@ -0,0 +1,24 @@ +/* + * 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 foo(a : Int, b : Int = 20, c : Int = 30) : Int +{ + return 1; +} + +function foo(a : Int, b : string = "a", c : Int = 30) : Int +{ + return 2; +} diff --git a/ets2panda/test/parser/ets/default_parameter7-expected.txt b/ets2panda/test/parser/ets/default_parameter7-expected.txt new file mode 100644 index 0000000000..ef5625ac46 --- /dev/null +++ b/ets2panda/test/parser/ets/default_parameter7-expected.txt @@ -0,0 +1,1655 @@ +{ + "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": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "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": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "rest parameter": { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 18 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 27 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 30 + }, + "end": { + "line": 16, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 30 + }, + "end": { + "line": 17, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 30 + }, + "end": { + "line": 17, + "column": 2 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "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": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 21, + "column": 22 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 28 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 28 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 28 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 23 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + "initializer": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 23 + }, + "end": { + "line": 21, + "column": 35 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 40 + }, + "end": { + "line": 21, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 40 + }, + "end": { + "line": 21, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 40 + }, + "end": { + "line": 21, + "column": 45 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 36 + }, + "end": { + "line": 21, + "column": 45 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 30, + "loc": { + "start": { + "line": 21, + "column": 46 + }, + "end": { + "line": 21, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 36 + }, + "end": { + "line": 21, + "column": 48 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 52 + }, + "end": { + "line": 21, + "column": 55 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 52 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 52 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "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": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo_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": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "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": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "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_int", + "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": "Int", + "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_int", + "decorators": [], + "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 + } + } + }, + "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": "b", + "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": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "proxy_int", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 2, + "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": "c", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 30, + "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": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "Identifier", + "name": "c", + "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": 16, + "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": 25, + "column": 1 + } + } +} +TypeError: Function already declared. [default_parameter7.ets:21:1] diff --git a/ets2panda/test/parser/ets/default_parameter7.ets b/ets2panda/test/parser/ets/default_parameter7.ets new file mode 100644 index 0000000000..490da83dbf --- /dev/null +++ b/ets2panda/test/parser/ets/default_parameter7.ets @@ -0,0 +1,24 @@ +/* + * 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 foo(...a : Int[]) : Int +{ + return 1; +} + +function foo(a : Int, b? : String, c : Int = 30) : Int +{ + return 2; +} diff --git a/ets2panda/test/runtime/ets/DefaultParam_1.ets b/ets2panda/test/runtime/ets/DefaultParam_1.ets index af964ea382..72368a9610 100644 --- a/ets2panda/test/runtime/ets/DefaultParam_1.ets +++ b/ets2panda/test/runtime/ets/DefaultParam_1.ets @@ -35,16 +35,6 @@ function main():void{ assert foo15(10,5) == 20; assert foo16(10,5) == 30; - - - assert foo17(1,2) == 1; - assert foo17(1,9999999999) == 2; - - assert foo18(1,2) == 1; - assert foo18(1,false) == 2; - - assert foo19(1,2) == 1; - assert foo19(1,c'a') == 2; } function foo1(a : int = 10) : int { @@ -96,27 +86,3 @@ function foo15(a : int, b : int, c : int = 5) : int { function foo16(a : int, b : int, c : int = 10, d : int = 5) : int { return a + b + c + d; } - -function foo17(a : int, b : int = 20, c : int = 30) : int { - return 1; -} - -function foo17(a : int, b : long = 20, c : int = 30) : int { - return 2; -} - -function foo18(a : int, b : int = 20, c : int = 30) : int { - return 1; -} - -function foo18(a : int, b : boolean = true, c : int = 30) : int { - return 2; -} - -function foo19(a : int, b : int = 20, c : int = 30) : int { - return 1; -} - -function foo19(a : int, b : char = c'a', c : int = 30) : int { - return 2; -} diff --git a/ets2panda/test/runtime/ets/DefaultParam_2.ets b/ets2panda/test/runtime/ets/DefaultParam_2.ets index d00f90d198..c82f36b460 100644 --- a/ets2panda/test/runtime/ets/DefaultParam_2.ets +++ b/ets2panda/test/runtime/ets/DefaultParam_2.ets @@ -43,15 +43,6 @@ function main():void{ assert foo15(new Int(10),new Int(5)) == 20; assert foo16(new Int(10),new Int(5)) == 30; - - assert foo17(new Int(1),new Int(2)) == 1; - assert foo17(new Int(1),new Long(9999999999)) == 2; - - assert foo18(new Int(1),new Int(2)) == 1; - assert foo18(new Int(1),new Boolean(true)) == 2; - - assert foo19(new Int(1),new Int(1)) == 1; - assert foo19(new Int(1),"a") == 2; } function foo1(a : Int = 10) : Int { @@ -142,27 +133,3 @@ function foo15(a : Int, b : Int, c : Int = 5) : Int { function foo16(a : Int, b : Int, c : Int = 10, d : Int = 5) : Int { return a + b + c + d; } - -function foo17(a : Int, b : Int = 20, c : Int = 30) : Int { - return 1; -} - -function foo17(a : Int, b : Long = 9999999999, c : Int = 30) : Int { - return 2; -} - -function foo18(a : Int, b : Int = 20, c : Int = 30) : Int { - return 1; -} - -function foo18(a : Int, b : Boolean = true, c : Int = 30) : Int { - return 2; -} - -function foo19(a : Int, b : Int = 20, c : Int = 30) : Int { - return 1; -} - -function foo19(a : Int, b : string = "a", c : Int = 30) : Int { - return 2; -} diff --git a/ets2panda/test/runtime/ets/DefaultParam_4.ets b/ets2panda/test/runtime/ets/DefaultParam_4.ets index 696647a3b7..38a37046f5 100644 --- a/ets2panda/test/runtime/ets/DefaultParam_4.ets +++ b/ets2panda/test/runtime/ets/DefaultParam_4.ets @@ -45,15 +45,6 @@ function main():void{ assert boo.foo15(new Int(10),new Int(5)) == 20; assert boo.foo16(new Int(10),new Int(5)) == 30; - - assert boo.foo17(new Int(1),new Int(2)) == 1; - assert boo.foo17(new Int(1),new Long(9999999999)) == 2; - - assert boo.foo18(new Int(1),new Int(2)) == 1; - assert boo.foo18(new Int(1),new Boolean(true)) == 2; - - assert boo.foo19(new Int(1),new Int(1)) == 1; - assert boo.foo19(new Int(1),"a") == 2; } class bar { @@ -145,28 +136,4 @@ class bar { foo16(a : Int, b : Int, c : Int = 10, d : Int = 5) : Int { return a + b + c + d; } - - foo17(a : Int, b : Int = 20, c : Int = 30) : Int { - return 1; - } - - foo17(a : Int, b : Long = 9999999999, c : Int = 30) : Int { - return 2; - } - - foo18(a : Int, b : Int = 20, c : Int = 30) : Int { - return 1; - } - - foo18(a : Int, b : Boolean = true, c : Int = 30) : Int { - return 2; - } - - foo19(a : Int, b : Int = 20, c : Int = 30) : Int { - return 1; - } - - foo19(a : Int, b : string = "a", c : Int = 30) : Int { - return 2; - } } -- Gitee From f6ebc7fdb6e12cc8e833505b15f2553697a460cc Mon Sep 17 00:00:00 2001 From: Anna Antipina Date: Mon, 13 Nov 2023 11:40:36 +0300 Subject: [PATCH 08/12] Title: Fix bugs related to extended conditional expressions. Description: * fix internal error during emitting function * fix TypeError during compilation * add runtime check for Object type and loading the length if the object turns out to be String * fix Number objects processiong (shouldn't be unboxed; always truthy) * fix long and float types processiong Issues: * https://gitee.com/open_harmony/dashboard?issue_id=I8FAPJ Testing: 1) cd $ARK_SOURCE_DIR; ./tests/tests-u-runner/runner.sh $ARK_SOURCE_DIR --parser --build-dir=$ARK_BUILD_BIR --force-generate --test-file compiler/ets/extended_conditional_expression_not.ets 2) cd $ARK_SOURCE_DIR; ./tests/tests-u-runner/runner.sh $ARK_SOURCE_DIR --parser --build-dir=$ARK_BUILD_BIR --force-generate --test-file compiler/ets/extended_conditional_expression_not_return_type.ets 3) cd $ARK_SOURCE_DIR; ./tests/tests-u-runner/runner.sh $ARK_SOURCE_DIR --ets-runtime --build-dir=$ARK_BUILD_BIR -heap-verifier="fail_on_verification:pre:into:before_g1_concurrent:post" --timeout=30 --force-generate --test-file extended_conditional_expression_string.ets 4) cd $ARK_SOURCE_DIR; ./tests/tests-u-runner/runner.sh $ARK_SOURCE_DIR --ets-cts --build-dir=$ARK_BUILD_BIR --heap-verifier="fail_on_verification:pre:into:before_g1_concurrent:post" --timeout=30 --force-generate --test-file 07.expressions/26.conditional_and_expression/conditional_and_boolean.ets 5) cd $ARK_SOURCE_DIR; ./tests/tests-u-runner/runner.sh $ARK_SOURCE_DIR --ets-runtime --build-dir=$ARK_BUILD_BIR --heap-verifier="fail_on_verification:pre:into:before_g1_concurrent:post" --timeout=30 --force-generate --test-file exdended_conditional_expression_float.ets Signed-off-by: Anna Antipina --- ets2panda/checker/ETSchecker.h | 2 + ets2panda/checker/ets/helpers.cpp | 21 +- ets2panda/checker/types/ets/etsEnumType.h | 5 + ets2panda/checker/types/ets/etsObjectType.h | 6 +- ets2panda/checker/types/ets/etsUnionType.h | 10 + ets2panda/checker/types/typeFlag.h | 4 +- ets2panda/compiler/base/condition.cpp | 84 +++- ets2panda/compiler/base/condition.h | 2 + ets2panda/compiler/core/ETSCompiler.cpp | 24 +- ets2panda/compiler/core/ETSGen.cpp | 1 + ets2panda/compiler/core/ETSGen.h | 107 +++-- ets2panda/ir/expressions/unaryExpression.cpp | 2 +- ...ed_conditional_expression_not-expected.txt | 444 ++++++++++++++++++ .../extended_conditional_expression_not.ets | 21 + ...al_expression_not_return_type-expected.txt | 374 +++++++++++++++ ...conditional_expression_not_return_type.ets | 18 + ets2panda/test/runtime/ets/StringBase64.ets | 2 +- .../ets/condition-with-boolean-reference.ets | 13 +- .../runtime/ets/conversion-char-boolean.ets | 2 +- .../exdended_conditional_expression_float.ets | 19 + ...extended_conditional_expression_string.ets | 32 ++ .../runtime/ets/unboxingBooleanConversion.ets | 2 +- 22 files changed, 1083 insertions(+), 112 deletions(-) create mode 100644 ets2panda/test/compiler/ets/extended_conditional_expression_not-expected.txt create mode 100644 ets2panda/test/compiler/ets/extended_conditional_expression_not.ets create mode 100644 ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type-expected.txt create mode 100644 ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type.ets create mode 100644 ets2panda/test/runtime/ets/exdended_conditional_expression_float.ets create mode 100644 ets2panda/test/runtime/ets/extended_conditional_expression_string.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 3dd9b2fe45..491a401a08 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -406,6 +406,8 @@ public: bool IsNullLikeOrVoidExpression(const ir::Expression *expr) const; bool IsConstantExpression(ir::Expression *expr, Type *type); void ValidateUnaryOperatorOperand(varbinder::Variable *variable); + bool TestUnionType(Type *type, TypeFlag test); + bool CheckPossibilityPromotion(Type *left, Type *right, TypeFlag test); std::tuple ApplyBinaryOperatorPromotion(Type *left, Type *right, TypeFlag test, bool do_promotion = true); checker::Type *ApplyConditionalOperatorPromotion(checker::ETSChecker *checker, checker::Type *unboxed_l, diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index dd678cbfa3..cd95e6668a 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -754,8 +754,13 @@ Type *ETSChecker::HandleBooleanLogicalOperatorsExtended(Type *left_type, Type *r IsNullLikeOrVoidExpression(expr->Right()) ? std::make_tuple(true, false) : right_type->ResolveConditionExpr(); if (!resolve_left) { - // return the UNION type when it is implemented - return IsTypeIdenticalTo(left_type, right_type) ? left_type : GlobalETSBooleanType(); + if (IsTypeIdenticalTo(left_type, right_type)) { + return left_type; + } + ArenaVector types(Allocator()->Adapter()); + types.push_back(left_type); + types.push_back(right_type); + return CreateETSUnionType(std::move(types)); } switch (expr->OperatorType()) { @@ -1453,18 +1458,6 @@ Type *ETSChecker::ETSBuiltinTypeAsConditionalType(Type *object_type) return nullptr; } - if (object_type->IsETSObjectType()) { - if (!object_type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) { - return object_type; - } - auto saved_result = Relation()->IsTrue(); - Relation()->Result(false); - - UnboxingConverter converter = UnboxingConverter(AsETSChecker(), Relation(), object_type, object_type); - Relation()->Result(saved_result); - return converter.Result(); - } - return object_type; } diff --git a/ets2panda/checker/types/ets/etsEnumType.h b/ets2panda/checker/types/ets/etsEnumType.h index fb9cc0debb..094790cab8 100644 --- a/ets2panda/checker/types/ets/etsEnumType.h +++ b/ets2panda/checker/types/ets/etsEnumType.h @@ -138,6 +138,11 @@ public: from_int_method_ = method; } + std::tuple ResolveConditionExpr() const override + { + return {true, !GetMembers().empty()}; + } + private: const ir::TSEnumDeclaration *decl_; const UType ordinal_; diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index a083979f86..391f54588c 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -512,11 +512,7 @@ public: std::tuple ResolveConditionExpr() const override { - if (IsNullish() || IsETSStringType()) { - return {false, false}; - } - - return {true, true}; + return {false, false}; } protected: diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 728c05665b..3572aae060 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -81,6 +81,16 @@ public: static Type *HandleUnionType(ETSUnionType *union_type); + std::tuple ResolveConditionExpr() const override + { + for (auto tp : ConstituentTypes()) { + if (!tp->IsConditionalExprType()) { + return {true, false}; + } + } + return {true, true}; + } + private: static bool EachTypeRelatedToSomeType(TypeRelation *relation, ETSUnionType *source, ETSUnionType *target); static bool TypeRelatedToSomeType(TypeRelation *relation, Type *source, ETSUnionType *target); diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index 7a26628209..58c04f812f 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -128,8 +128,8 @@ enum class TypeFlag : uint64_t { VALID_ARITHMETIC_TYPE = ANY | NUMBER_LIKE | BIGINT_LIKE | ENUM, UNIT = LITERAL | UNIQUE_SYMBOL | NULLISH, GETTER_SETTER = GETTER | SETTER, - CONDITION_EXPRESSION_TYPE = - NULLISH | CONSTANT | ETS_OBJECT | BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | ETS_BOOLEAN | ETS_ARRAY + CONDITION_EXPRESSION_TYPE = NULLISH | CONSTANT | ETS_OBJECT | BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | + ETS_BOOLEAN | ETS_ARRAY | ETS_ENUM | ETS_STRING_ENUM }; DEFINE_BITOPS(TypeFlag) diff --git a/ets2panda/compiler/base/condition.cpp b/ets2panda/compiler/base/condition.cpp index 0331d9342c..d2abcf9569 100644 --- a/ets2panda/compiler/base/condition.cpp +++ b/ets2panda/compiler/base/condition.cpp @@ -126,6 +126,67 @@ Condition::Result Condition::CheckConstantExpr(ETSGen *etsg, const ir::Expressio return Result::UNKNOWN; } +void Condition::CompileLogicalOrExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label) +{ + auto ttctx = TargetTypeContext(etsg, bin_expr->OperationType()); + RegScope rs(etsg); + VReg lhs = etsg->AllocReg(); + VReg rhs = etsg->AllocReg(); + auto *return_left_label = etsg->AllocLabel(); + auto *return_right_true_label = etsg->AllocLabel(); + auto *return_right_false_label = etsg->AllocLabel(); + + bin_expr->Left()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(bin_expr->Left(), lhs, bin_expr->OperationType()); + etsg->ResolveConditionalResultIfTrue(bin_expr->Left(), return_left_label); + etsg->BranchIfTrue(bin_expr, return_left_label); + + bin_expr->Right()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(bin_expr->Right(), rhs, bin_expr->OperationType()); + etsg->ResolveConditionalResultIfFalse(bin_expr->Right(), return_right_false_label); + etsg->BranchIfFalse(bin_expr, return_right_false_label); + etsg->LoadAccumulator(bin_expr, rhs); + etsg->Branch(bin_expr, return_right_true_label); + + etsg->SetLabel(bin_expr, return_right_false_label); + etsg->LoadAccumulator(bin_expr, rhs); + etsg->Branch(bin_expr, false_label); + etsg->SetLabel(bin_expr, return_left_label); + etsg->LoadAccumulator(bin_expr, lhs); + etsg->SetLabel(bin_expr, return_right_true_label); +} + +void Condition::CompileLogicalAndExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label) +{ + auto ttctx = TargetTypeContext(etsg, bin_expr->OperationType()); + RegScope rs(etsg); + VReg lhs = etsg->AllocReg(); + VReg rhs = etsg->AllocReg(); + auto *return_left_label = etsg->AllocLabel(); + auto *return_right_true_label = etsg->AllocLabel(); + auto *return_right_false_label = etsg->AllocLabel(); + + bin_expr->Left()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(bin_expr->Left(), lhs, bin_expr->OperationType()); + etsg->ResolveConditionalResultIfFalse(bin_expr->Left(), return_left_label); + etsg->BranchIfFalse(bin_expr, return_left_label); + + bin_expr->Right()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(bin_expr->Right(), rhs, bin_expr->OperationType()); + etsg->ResolveConditionalResultIfFalse(bin_expr->Right(), return_right_false_label); + etsg->BranchIfFalse(bin_expr, return_right_false_label); + etsg->LoadAccumulator(bin_expr, rhs); + etsg->Branch(bin_expr, return_right_true_label); + + etsg->SetLabel(bin_expr, return_left_label); + etsg->LoadAccumulator(bin_expr, lhs); + etsg->Branch(bin_expr, false_label); + etsg->SetLabel(bin_expr, return_right_false_label); + etsg->LoadAccumulator(bin_expr, rhs); + etsg->Branch(bin_expr, false_label); + etsg->SetLabel(bin_expr, return_right_true_label); +} + bool Condition::CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label) { switch (bin_expr->OperatorType()) { @@ -149,30 +210,11 @@ bool Condition::CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *bin_ return true; } case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { - bin_expr->Left()->Compile(etsg); - etsg->ApplyConversion(bin_expr->Left(), bin_expr->OperationType()); - etsg->ResolveConditionalResultIfFalse(bin_expr->Left(), false_label); - etsg->BranchIfFalse(bin_expr, false_label); - - bin_expr->Right()->Compile(etsg); - etsg->ApplyConversion(bin_expr->Right(), bin_expr->OperationType()); - etsg->ResolveConditionalResultIfFalse(bin_expr->Right(), false_label); - etsg->BranchIfFalse(bin_expr, false_label); + CompileLogicalAndExpr(etsg, bin_expr, false_label); return true; } case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - auto *end_label = etsg->AllocLabel(); - - bin_expr->Left()->Compile(etsg); - etsg->ApplyConversion(bin_expr->Left(), bin_expr->OperationType()); - etsg->ResolveConditionalResultIfTrue(bin_expr->Left(), end_label); - etsg->BranchIfTrue(bin_expr, end_label); - - bin_expr->Right()->Compile(etsg); - etsg->ApplyConversion(bin_expr->Right(), bin_expr->OperationType()); - etsg->ResolveConditionalResultIfFalse(bin_expr->Right(), false_label); - etsg->BranchIfFalse(bin_expr, false_label); - etsg->SetLabel(bin_expr, end_label); + CompileLogicalOrExpr(etsg, bin_expr, false_label); return true; } default: { diff --git a/ets2panda/compiler/base/condition.h b/ets2panda/compiler/base/condition.h index 11ed9e8670..6380ba538e 100644 --- a/ets2panda/compiler/base/condition.h +++ b/ets2panda/compiler/base/condition.h @@ -40,6 +40,8 @@ public: private: static bool CompileBinaryExpr(PandaGen *pg, const ir::BinaryExpression *bin_expr, Label *false_label); static bool CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label); + static void CompileLogicalAndExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label); + static void CompileLogicalOrExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label); }; } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 7df01ed603..017fb37d60 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -317,33 +317,33 @@ static void CompileLogical(compiler::ETSGen *etsg, const ir::BinaryExpression *e auto ttctx = compiler::TargetTypeContext(etsg, expr->OperationType()); compiler::RegScope rs(etsg); auto lhs = etsg->AllocReg(); - auto rhs = etsg->AllocReg(); + expr->Left()->Compile(etsg); etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); auto *end_label = etsg->AllocLabel(); - auto left_false_label = etsg->AllocLabel(); + auto return_left_label = etsg->AllocLabel(); if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) { - etsg->ResolveConditionalResultIfFalse(expr->Left(), left_false_label); - etsg->BranchIfFalse(expr, left_false_label); + etsg->ResolveConditionalResultIfFalse(expr->Left(), return_left_label); + etsg->BranchIfFalse(expr, return_left_label); expr->Right()->Compile(etsg); - etsg->ApplyConversionAndStoreAccumulator(expr->Right(), rhs, expr->OperationType()); + etsg->ApplyConversion(expr->Right(), expr->OperationType()); etsg->Branch(expr, end_label); - etsg->SetLabel(expr, left_false_label); + etsg->SetLabel(expr, return_left_label); etsg->LoadAccumulator(expr, lhs); } else { - etsg->ResolveConditionalResultIfFalse(expr->Left(), left_false_label); - etsg->BranchIfFalse(expr, left_false_label); + etsg->ResolveConditionalResultIfTrue(expr->Left(), return_left_label); + etsg->BranchIfTrue(expr, return_left_label); - etsg->LoadAccumulator(expr, lhs); + expr->Right()->Compile(etsg); + etsg->ApplyConversion(expr->Right(), expr->OperationType()); etsg->Branch(expr, end_label); - etsg->SetLabel(expr, left_false_label); - expr->Right()->Compile(etsg); - etsg->ApplyConversionAndStoreAccumulator(expr->Right(), rhs, expr->OperationType()); + etsg->SetLabel(expr, return_left_label); + etsg->LoadAccumulator(expr, lhs); } etsg->SetLabel(expr, end_label); diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 30b8519653..89f048ece1 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -2160,6 +2160,7 @@ void ETSGen::LogicalNot(const ir::AstNode *node) ASSERT(GetAccumulatorType()->IsConditionalExprType()); ResolveConditionalResultIfFalse(node); Sa().Emit(node, 1); + SetAccumulatorType(Checker()->GlobalETSBooleanType()); } void ETSGen::Unary(const ir::AstNode *node, lexer::TokenType op) diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index 7ee98c5619..f09b7301e9 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -102,10 +102,11 @@ public: bool TryLoadConstantExpression(const ir::Expression *node); void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, Label *if_false); - template - void ResolveConditionalResultFloat(const ir::AstNode *node, [[maybe_unused]] Label *if_false, Label *end) + template + void ResolveConditionalResultFloat(const ir::AstNode *node, Label *real_end_label) { - auto type = node->IsExpression() ? node->AsExpression()->TsType() : GetAccumulatorType(); + auto type = node->IsExpression() && !node->AsExpression()->IsUnaryExpression() ? node->AsExpression()->TsType() + : GetAccumulatorType(); VReg tmp_reg = AllocReg(); StoreAccumulator(node, tmp_reg); if (type->IsFloatType()) { @@ -113,17 +114,8 @@ public: } else { DoubleIsNaN(node); } - Sa().Emit(node, 1); - auto real_end_label = [](Label *end_label, Label *if_false_label, ETSGen *etsgn, bool use_false_label) { - if (use_false_label) { - return if_false_label; - } - if (end_label == nullptr) { - end_label = etsgn->AllocLabel(); - } - return end_label; - }(end, if_false, this, USE_FALSE_LABEL); + BranchIfFalse(node, real_end_label); LoadAccumulator(node, tmp_reg); VReg zero_reg = AllocReg(); @@ -138,39 +130,40 @@ public: } template - void ResolveConditionalResultNumeric(const ir::AstNode *node, [[maybe_unused]] Label *if_false, Label *end) + void ResolveConditionalResultNumeric(const ir::AstNode *node, [[maybe_unused]] Label *if_false, Label **end) { - auto type = node->IsExpression() ? node->AsExpression()->TsType() : GetAccumulatorType(); - switch (type->TypeFlags()) { - case checker::TypeFlag::LONG: { - CastToInt(node); - [[fallthrough]]; - } - case checker::TypeFlag::BYTE: - case checker::TypeFlag::CHAR: - case checker::TypeFlag::SHORT: - case checker::TypeFlag::INT: { - if constexpr (BEFORE_LOGICAL_NOT) { - Label *zero_primitive = AllocLabel(); - BranchIfFalse(node, zero_primitive); - ToBinaryResult(node, zero_primitive); - } - break; + auto type = node->IsExpression() && !node->AsExpression()->IsUnaryExpression() ? node->AsExpression()->TsType() + : GetAccumulatorType(); + + auto real_end_label = [end, if_false, this](bool use_false_label) { + if (use_false_label) { + return if_false; } - case checker::TypeFlag::DOUBLE: - case checker::TypeFlag::FLOAT: { - ResolveConditionalResultFloat(node, if_false, end); - break; + if ((*end) == nullptr) { + (*end) = AllocLabel(); } - default: - break; + return (*end); + }(USE_FALSE_LABEL); + if (type->IsDoubleType() || type->IsFloatType()) { + ResolveConditionalResultFloat(node, real_end_label); + } + if (type->IsLongType()) { + VReg zero_reg = AllocReg(); + MoveImmediateToRegister(node, zero_reg, checker::TypeFlag::LONG, 0); + BinaryNumberComparison(node, zero_reg, real_end_label); + } + if constexpr (BEFORE_LOGICAL_NOT) { + Label *zero_primitive = AllocLabel(); + BranchIfFalse(node, zero_primitive); + ToBinaryResult(node, zero_primitive); } } - template - void ResolveConditionalResultObject(const ir::AstNode *node, [[maybe_unused]] Label *if_false) + template + void ResolveConditionalResultObject(const ir::AstNode *node) { - auto type = node->IsExpression() ? node->AsExpression()->TsType() : GetAccumulatorType(); + auto type = node->IsExpression() && !node->AsExpression()->IsUnaryExpression() ? node->AsExpression()->TsType() + : GetAccumulatorType(); if (type->IsETSStringType()) { LoadStringLength(node); if constexpr (BEFORE_LOGICAL_NOT) { @@ -178,6 +171,27 @@ public: BranchIfFalse(node, zero_lenth); ToBinaryResult(node, zero_lenth); } + } else if (node->IsExpression() && node->AsExpression()->IsIdentifier() && + node->AsExpression()->AsIdentifier()->Variable()->HasFlag(varbinder::VariableFlags::VAR)) { + Label *is_string = AllocLabel(); + Label *end = AllocLabel(); + compiler::VReg obj_reg = AllocReg(); + StoreAccumulator(node, obj_reg); + + Sa().Emit(node, Checker()->GlobalBuiltinETSStringType()->AsETSStringType()->AssemblerName()); + BranchIfTrue(node, is_string); + Sa().Emit(node, 1); + Branch(node, end); + SetLabel(node, is_string); + LoadAccumulator(node, obj_reg); + CastToString(node); + LoadStringLength(node); + if constexpr (BEFORE_LOGICAL_NOT) { + Label *zero_lenth = AllocLabel(); + BranchIfFalse(node, zero_lenth); + ToBinaryResult(node, zero_lenth); + } + SetLabel(node, end); } else { Sa().Emit(node, 1); } @@ -200,11 +214,8 @@ public: template void ResolveConditionalResult(const ir::AstNode *node, [[maybe_unused]] Label *if_false) { - auto type = node->IsExpression() ? node->AsExpression()->TsType() : GetAccumulatorType(); - if (type->IsETSObjectType() && - type->AsETSObjectType()->HasObjectFlag(panda::es2panda::checker::ETSObjectFlags::UNBOXABLE_TYPE)) { - type = GetAccumulatorType(); - } + auto type = node->IsExpression() && !node->AsExpression()->IsUnaryExpression() ? node->AsExpression()->TsType() + : GetAccumulatorType(); if (type->IsETSBooleanType()) { return; } @@ -228,9 +239,9 @@ public: StoreAccumulator(node, obj_reg); LoadArrayLength(node, obj_reg); } else if (type->IsETSObjectType()) { - ResolveConditionalResultObject(node, if_false); + ResolveConditionalResultObject(node); } else { - ResolveConditionalResultNumeric(node, if_false, end); + ResolveConditionalResultNumeric(node, if_false, &end); } if (if_nullish != nullptr) { Branch(node, end); @@ -248,10 +259,10 @@ public: ResolveConditionalResult(node, if_false); } - template + template void ResolveConditionalResultIfTrue(const ir::AstNode *node, Label *if_false = nullptr) { - ResolveConditionalResult(node, if_false); + ResolveConditionalResult(node, if_false); } void BranchIfFalse(const ir::AstNode *node, Label *if_false) diff --git a/ets2panda/ir/expressions/unaryExpression.cpp b/ets2panda/ir/expressions/unaryExpression.cpp index a73cbef077..b9e2579f65 100644 --- a/ets2panda/ir/expressions/unaryExpression.cpp +++ b/ets2panda/ir/expressions/unaryExpression.cpp @@ -283,7 +283,7 @@ checker::Type *UnaryExpression::Check(checker::ETSChecker *checker) break; } - SetTsType(operand_type); + SetTsType(checker->GlobalETSBooleanType()); break; } case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR: { diff --git a/ets2panda/test/compiler/ets/extended_conditional_expression_not-expected.txt b/ets2panda/test/compiler/ets/extended_conditional_expression_not-expected.txt new file mode 100644 index 0000000000..60a0330b80 --- /dev/null +++ b/ets2panda/test/compiler/ets/extended_conditional_expression_not-expected.txt @@ -0,0 +1,444 @@ +{ + "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": "f", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "number", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 16, + "column": 22 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 24 + }, + "end": { + "line": 16, + "column": 27 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "UnaryExpression", + "operator": "!", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "n", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "consequent": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 28 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "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/extended_conditional_expression_not.ets b/ets2panda/test/compiler/ets/extended_conditional_expression_not.ets new file mode 100644 index 0000000000..a012fda36c --- /dev/null +++ b/ets2panda/test/compiler/ets/extended_conditional_expression_not.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 f(n: number): int { + if (!n) { + return 0; + } + return 1; +} diff --git a/ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type-expected.txt b/ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type-expected.txt new file mode 100644 index 0000000000..80a89ecb8f --- /dev/null +++ b/ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type-expected.txt @@ -0,0 +1,374 @@ +{ + "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": "f", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 16, + "column": 22 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 24 + }, + "end": { + "line": 16, + "column": 31 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "UnaryExpression", + "operator": "!", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "n", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 32 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 18, + "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": 18, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type.ets b/ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type.ets new file mode 100644 index 0000000000..1462fb5522 --- /dev/null +++ b/ets2panda/test/compiler/ets/extended_conditional_expression_not_return_type.ets @@ -0,0 +1,18 @@ +/* + * 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 f(n: string): boolean { + return !n; +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/StringBase64.ets b/ets2panda/test/runtime/ets/StringBase64.ets index 17e894db3d..ebca0d923b 100644 --- a/ets2panda/test/runtime/ets/StringBase64.ets +++ b/ets2panda/test/runtime/ets/StringBase64.ets @@ -67,7 +67,7 @@ export class StringBase64 { } return result.toString(); } - n1 : int = 8192; + n1 : int = 4096; n2 : int = 16384; public run(): void { let str : String = ""; diff --git a/ets2panda/test/runtime/ets/condition-with-boolean-reference.ets b/ets2panda/test/runtime/ets/condition-with-boolean-reference.ets index afeab4d428..1acb975493 100644 --- a/ets2panda/test/runtime/ets/condition-with-boolean-reference.ets +++ b/ets2panda/test/runtime/ets/condition-with-boolean-reference.ets @@ -14,7 +14,7 @@ */ function main() : void { - let cond: Boolean = true; + let cond: boolean = true; // Check conditional expression let a: String = "foo"; @@ -39,13 +39,14 @@ function main() : void { assert(i == 3); // Check while statement - while (cond) { - cond = false; + let while_cond = true + while (while_cond) { + while_cond = !cond; } - assert (cond == false); + assert (while_cond == false); // Check do-while statement do { - assert (cond == false); - } while (cond); + assert (while_cond == false); + } while (while_cond); } diff --git a/ets2panda/test/runtime/ets/conversion-char-boolean.ets b/ets2panda/test/runtime/ets/conversion-char-boolean.ets index baa0ddaf61..76f9ea8e29 100644 --- a/ets2panda/test/runtime/ets/conversion-char-boolean.ets +++ b/ets2panda/test/runtime/ets/conversion-char-boolean.ets @@ -20,7 +20,7 @@ function check(): Boolean { function main(): void { let x: Boolean = false; - assert !(x && check()); + assert (x || check()); let y: Char = c'a'; assert (y != c'b'); diff --git a/ets2panda/test/runtime/ets/exdended_conditional_expression_float.ets b/ets2panda/test/runtime/ets/exdended_conditional_expression_float.ets new file mode 100644 index 0000000000..1d07e49551 --- /dev/null +++ b/ets2panda/test/runtime/ets/exdended_conditional_expression_float.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(): int { + let res: int = 0.1 ? 0 : 1 + return res +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/extended_conditional_expression_string.ets b/ets2panda/test/runtime/ets/extended_conditional_expression_string.ets new file mode 100644 index 0000000000..f023797700 --- /dev/null +++ b/ets2panda/test/runtime/ets/extended_conditional_expression_string.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. + */ + +function fun(s: Object) : boolean { + if (s) { + return true; + } else { + return false; + } +} + + +function main(): int { + let emptyString = ""; + if (fun(emptyString)) { + return 1; + } else { + return 0 + } +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets index 4ee6904ae1..23ae74c084 100644 --- a/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets +++ b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets @@ -24,7 +24,7 @@ function returnRefBool(a: boolean): Boolean { function main(): void { let a: Boolean = false; - let b: Boolean = a || returnTrue(); + let b: Boolean = a && returnTrue(); assert b == true let c: Boolean = returnRefBool(a || returnRefBool(returnTrue() && returnRefBool(a))); -- Gitee From e9d8f11a114b5a24c550073935774761f043eae2 Mon Sep 17 00:00:00 2001 From: aakmaev Date: Mon, 13 Nov 2023 23:49:39 +0300 Subject: [PATCH 09/12] =?UTF-8?q?Support=20union=20types=20follow-up=20&?= =?UTF-8?q?=20bug=20fixes=20Issue=EF=BC=9Ahttps://gitee.com/openharmony/ar?= =?UTF-8?q?kcompiler=5Fets=5Ffrontend/issues/I8I1VZ=20Testing=20:=20All=20?= =?UTF-8?q?required=20pre-merge=20tests=20passed.=20Results=20are=20availi?= =?UTF-8?q?ble=20in=20the=20ggwatcher.=20Signed-off-by:=20Akmaev=20Alexey?= =?UTF-8?q?=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ets2panda/checker/ets/arithmetic.cpp | 30 +- ets2panda/checker/ets/helpers.cpp | 2 +- ets2panda/checker/ets/typeCreation.cpp | 1 + ets2panda/checker/types/ets/etsObjectType.cpp | 1 - ets2panda/checker/types/ets/etsUnionType.cpp | 109 +++++-- ets2panda/checker/types/ets/etsUnionType.h | 18 +- ets2panda/compiler/core/ETSGen.cpp | 79 ++--- ets2panda/compiler/core/ETSGen.h | 1 + .../compiler/lowering/ets/unionLowering.cpp | 303 +++++++++++++++--- ets2panda/ir/astNode.cpp | 21 ++ ets2panda/ir/astNode.h | 1 + ets2panda/ir/expressions/binaryExpression.h | 6 + ets2panda/ir/expressions/memberExpression.cpp | 10 +- ets2panda/ir/statements/ifStatement.h | 5 + .../ets/default_parameter6-expected.txt | 12 +- .../ets/default_parameter7-expected.txt | 6 +- ets2panda/test/union_types_4-expected.txt | 0 17 files changed, 494 insertions(+), 111 deletions(-) delete mode 100644 ets2panda/test/union_types_4-expected.txt diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index c78ac64ba9..de5372293c 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -139,6 +139,10 @@ checker::Type *ETSChecker::CheckBinaryOperatorMulDivMod(ir::Expression *left, ir FlagExpressionWithUnboxing(left_type, unboxed_l, left); FlagExpressionWithUnboxing(right_type, unboxed_r, right); + if (left_type->IsETSUnionType() || right_type->IsETSUnionType()) { + ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); + } + if (promotedType == nullptr && !bothConst) { ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); } @@ -156,6 +160,10 @@ checker::Type *ETSChecker::CheckBinaryOperatorPlus(ir::Expression *left, ir::Exp bool is_equal_op, checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) { + if (left_type->IsETSUnionType() || right_type->IsETSUnionType()) { + ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); + } + if (left_type->IsETSStringType() || right_type->IsETSStringType()) { return HandleStringConcatenation(left_type, right_type); } @@ -182,6 +190,10 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift(ir::Expression *left, ir::Ex bool is_equal_op, checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) { + if (left_type->IsETSUnionType() || right_type->IsETSUnionType()) { + ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); + } + auto promoted_left_type = ApplyUnaryOperatorPromotion(unboxed_l, false, !is_equal_op); auto promoted_right_type = ApplyUnaryOperatorPromotion(unboxed_r, false, !is_equal_op); @@ -225,6 +237,10 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise(ir::Expression *left, ir:: bool is_equal_op, checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) { + if (left_type->IsETSUnionType() || right_type->IsETSUnionType()) { + ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); + } + if (unboxed_l != nullptr && unboxed_l->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN) && unboxed_r != nullptr && unboxed_r->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN)) { FlagExpressionWithUnboxing(left_type, unboxed_l, left); @@ -253,6 +269,10 @@ checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir:: lexer::SourcePosition pos, checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) { + if (left_type->IsETSUnionType() || right_type->IsETSUnionType()) { + ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); + } + if (unboxed_l == nullptr || !unboxed_l->IsConditionalExprType() || unboxed_r == nullptr || !unboxed_r->IsConditionalExprType()) { ThrowTypeError("Bad operand type, the types of the operands must be of possible condition type.", pos); @@ -278,8 +298,8 @@ std::tuple ETSChecker::CheckBinaryOperatorStrictEqual(ir::Expres checker::Type *const right_type) { checker::Type *ts_type {}; - if (!(left_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) || - !(right_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT))) { + if (!(left_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT) || left_type->IsETSUnionType()) || + !(right_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT) || right_type->IsETSUnionType())) { ThrowTypeError("Both operands have to be reference types", pos); } @@ -374,6 +394,12 @@ std::tuple ETSChecker::CheckBinaryOperatorLessGreater( ir::Expression *left, ir::Expression *right, lexer::TokenType operation_type, lexer::SourcePosition pos, bool is_equal_op, checker::Type *const left_type, checker::Type *const right_type, Type *unboxed_l, Type *unboxed_r) { + if ((left_type->IsETSUnionType() || right_type->IsETSUnionType()) && + operation_type != lexer::TokenType::PUNCTUATOR_EQUAL && + operation_type != lexer::TokenType::PUNCTUATOR_NOT_EQUAL) { + ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", pos); + } + checker::Type *ts_type {}; auto [promotedType, bothConst] = ApplyBinaryOperatorPromotion(unboxed_l, unboxed_r, TypeFlag::ETS_NUMERIC, !is_equal_op); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index cd95e6668a..c07bb4b6ec 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2040,7 +2040,7 @@ Type *ETSChecker::GetTypeFromTypeAnnotation(ir::TypeNode *const type_annotation) return type; } - if (!type->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT)) { + if (!type->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT) && !type->HasTypeFlag(TypeFlag::ETS_UNION)) { ThrowTypeError("Non reference types cannot be nullish.", type_annotation->Start()); } diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 03be8f6bda..bd75518d92 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -143,6 +143,7 @@ Type *ETSChecker::CreateETSUnionType(ArenaVector &&constituent_types) } auto *new_union_type = Allocator()->New(std::move(new_constituent_types)); + new_union_type->SetLeastUpperBoundType(this); return ETSUnionType::HandleUnionType(new_union_type); } diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 7d060c93c5..6c6435e7ec 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -762,7 +762,6 @@ Type *ETSObjectType::Instantiate(ArenaAllocator *const allocator, TypeRelation * for (auto *const type_argument : TypeArguments()) { copied_type->TypeArguments().emplace_back(type_argument->Instantiate(allocator, relation, global_types)); } - copied_type->SetBaseType(this); copied_type->properties_instantiated_ = false; copied_type->relation_ = relation; diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index cca516221f..b3335689a1 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -19,6 +19,7 @@ #include "checker/ets/conversion.h" #include "checker/types/globalTypesHolder.h" #include "checker/ETSchecker.h" +#include "ir/astNode.h" namespace panda::es2panda::checker { void ETSUnionType::ToString(std::stringstream &ss) const @@ -26,11 +27,16 @@ void ETSUnionType::ToString(std::stringstream &ss) const for (auto it = constituent_types_.begin(); it != constituent_types_.end(); it++) { (*it)->ToString(ss); if (std::next(it) != constituent_types_.end()) { - ss << " | "; + ss << "|"; } } } +void ETSUnionType::ToAssemblerType(std::stringstream &ss) const +{ + ss << compiler::Signatures::BUILTIN_OBJECT; +} + bool ETSUnionType::EachTypeRelatedToSomeType(TypeRelation *relation, ETSUnionType *source, ETSUnionType *target) { return std::all_of(source->constituent_types_.begin(), source->constituent_types_.end(), @@ -43,7 +49,7 @@ bool ETSUnionType::TypeRelatedToSomeType(TypeRelation *relation, Type *source, E [relation, source](auto *t) { return relation->IsIdenticalTo(source, t); }); } -Type *ETSUnionType::GetLeastUpperBoundType(ETSChecker *checker) +void ETSUnionType::SetLeastUpperBoundType(ETSChecker *checker) { ASSERT(constituent_types_.size() > 1); if (lub_type_ == nullptr) { @@ -51,12 +57,11 @@ Type *ETSUnionType::GetLeastUpperBoundType(ETSChecker *checker) for (auto *t : constituent_types_) { if (!t->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT)) { lub_type_ = checker->GetGlobalTypesHolder()->GlobalETSObjectType(); - return lub_type_; + return; } lub_type_ = checker->FindLeastUpperBound(lub_type_, t); } } - return lub_type_; } void ETSUnionType::Identical(TypeRelation *relation, Type *other) @@ -86,10 +91,21 @@ bool ETSUnionType::AssignmentSource(TypeRelation *relation, Type *target) void ETSUnionType::AssignmentTarget(TypeRelation *relation, Type *source) { - auto *const ref_source = source->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) - ? relation->GetChecker()->AsETSChecker()->PrimitiveTypeAsETSBuiltinType(source) - : source; - + auto *const checker = relation->GetChecker()->AsETSChecker(); + auto *const ref_source = + source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) ? checker->PrimitiveTypeAsETSBuiltinType(source) : source; + auto exact_type = std::find_if( + constituent_types_.begin(), constituent_types_.end(), [checker, relation, source, ref_source](Type *ct) { + if (ct == ref_source && source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) && ct->IsETSObjectType() && + ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) { + relation->GetNode()->SetBoxingUnboxingFlags(checker->GetBoxingFlag(ct)); + return relation->IsAssignableTo(ref_source, ct); + } + return false; + }); + if (exact_type != constituent_types_.end()) { + return; + } for (auto *it : constituent_types_) { if (relation->IsAssignableTo(ref_source, it)) { if (ref_source != source) { @@ -98,6 +114,18 @@ void ETSUnionType::AssignmentTarget(TypeRelation *relation, Type *source) } return; } + bool assign_primitive = it->IsETSObjectType() && + it->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE) && + source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE); + if (assign_primitive && relation->IsAssignableTo(source, checker->ETSBuiltinTypeAsPrimitiveType(it))) { + Type *unboxed_it = checker->ETSBuiltinTypeAsPrimitiveType(it); + if (unboxed_it != source) { + relation->GetNode()->SetBoxingUnboxingFlags(checker->GetBoxingFlag(it)); + source->Cast(relation, unboxed_it); + ASSERT(relation->IsTrue()); + } + return; + } } } @@ -124,21 +152,32 @@ Type *ETSUnionType::Instantiate(ArenaAllocator *allocator, TypeRelation *relatio return copied_constituents[0]; } - Type *new_union_type = allocator->New(std::move(copied_constituents)); + auto *new_union_type = allocator->New(std::move(copied_constituents)); - lub_type_ = global_types->GlobalETSObjectType(); - return HandleUnionType(new_union_type->AsETSUnionType()); + new_union_type->SetLeastUpperBoundType(relation->GetChecker()->AsETSChecker()); + return HandleUnionType(new_union_type); } void ETSUnionType::Cast(TypeRelation *relation, Type *target) { - auto *const ref_target = target->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) - ? relation->GetChecker()->AsETSChecker()->PrimitiveTypeAsETSBuiltinType(target) - : target; - + auto *const checker = relation->GetChecker()->AsETSChecker(); + auto *const ref_target = + target->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) ? checker->PrimitiveTypeAsETSBuiltinType(target) : target; + auto exact_type = std::find_if(constituent_types_.begin(), constituent_types_.end(), + [this, checker, relation, ref_target](Type *src) { + if (src == ref_target && relation->IsCastableTo(src, ref_target)) { + GetLeastUpperBoundType(checker)->Cast(relation, ref_target); + ASSERT(relation->IsTrue()); + return true; + } + return false; + }); + if (exact_type != constituent_types_.end()) { + return; + } for (auto *source : constituent_types_) { if (relation->IsCastableTo(source, ref_target)) { - GetLeastUpperBoundType(relation->GetChecker()->AsETSChecker())->Cast(relation, ref_target); + GetLeastUpperBoundType(checker)->Cast(relation, ref_target); ASSERT(relation->IsTrue()); if (ref_target != target) { source->Cast(relation, target); @@ -147,6 +186,13 @@ void ETSUnionType::Cast(TypeRelation *relation, Type *target) } return; } + bool cast_primitive = source->IsETSObjectType() && + source->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE) && + target->HasTypeFlag(TypeFlag::ETS_PRIMITIVE); + if (cast_primitive && relation->IsCastableTo(checker->ETSBuiltinTypeAsPrimitiveType(source), target)) { + ASSERT(relation->IsTrue()); + return; + } } conversion::Forbidden(relation); @@ -241,9 +287,36 @@ Type *ETSUnionType::FindTypeIsCastableToSomeType(ir::Expression *node, TypeRelat return nullptr; } -void ETSUnionType::ToAssemblerType(std::stringstream &ss) const +Type *ETSUnionType::FindUnboxableType() const { - ss << compiler::Signatures::BUILTIN_OBJECT; + auto it = std::find_if(constituent_types_.begin(), constituent_types_.end(), + [](Type *t) { return t->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE); }); + if (it != constituent_types_.end()) { + return *it; + } + return nullptr; +} + +bool ETSUnionType::HasObjectType(ETSObjectFlags flag) const +{ + auto it = std::find_if(constituent_types_.begin(), constituent_types_.end(), + [flag](Type *t) { return t->AsETSObjectType()->HasObjectFlag(flag); }); + return it != constituent_types_.end(); +} + +Type *ETSUnionType::FindExactOrBoxedType(ETSChecker *checker, Type *const type) const +{ + auto it = std::find_if(constituent_types_.begin(), constituent_types_.end(), [checker, type](Type *ct) { + if (ct->IsETSObjectType() && ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) { + auto *const unboxed_ct = checker->ETSBuiltinTypeAsPrimitiveType(ct); + return unboxed_ct == type; + } + return ct == type; + }); + if (it != constituent_types_.end()) { + return *it; + } + return nullptr; } } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 3572aae060..ce032fcef4 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -17,6 +17,7 @@ #define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_UNION_TYPE_H #include "checker/types/type.h" +#include "checker/types/ets/etsObjectType.h" namespace panda::es2panda::checker { class GlobalTypesHolder; @@ -60,6 +61,7 @@ public: } void ToString(std::stringstream &ss) const override; + void ToAssemblerType(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; @@ -68,10 +70,18 @@ public: void CastToThis(TypeRelation *relation, Type *source); Type *FindTypeIsCastableToThis(ir::Expression *node, TypeRelation *relation, Type *source) const; Type *FindTypeIsCastableToSomeType(ir::Expression *node, TypeRelation *relation, Type *target) const; + Type *FindUnboxableType() const; - void ToAssemblerType(std::stringstream &ss) const override; + void SetLeastUpperBoundType(ETSChecker *checker); - Type *GetLeastUpperBoundType(ETSChecker *checker); + Type *GetLeastUpperBoundType(ETSChecker *checker) + { + if (lub_type_ == nullptr) { + SetLeastUpperBoundType(checker); + } + ASSERT(lub_type_ != nullptr); + return lub_type_; + } Type *GetLeastUpperBoundType() const { @@ -79,6 +89,10 @@ public: return lub_type_; } + bool HasObjectType(ETSObjectFlags flag) const; + + Type *FindExactOrBoxedType(ETSChecker *checker, Type *type) const; + static Type *HandleUnionType(ETSUnionType *union_type); std::tuple ResolveConditionExpr() const override diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 89f048ece1..6251d20f9c 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -15,7 +15,6 @@ #include "ETSGen.h" -#include "checker/ets/boxingConverter.h" #include "ir/base/scriptFunction.h" #include "ir/base/classDefinition.h" #include "ir/statement.h" @@ -40,6 +39,7 @@ #include "checker/types/typeFlag.h" #include "checker/checker.h" #include "checker/ETSchecker.h" +#include "checker/ets/boxingConverter.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/types.h" #include "parser/program/program.h" @@ -867,15 +867,35 @@ bool ETSGen::TryLoadConstantExpression(const ir::Expression *node) return true; } -// NOTE: vpukhov. lower (union_value) as (primitive_type) to be two as-nodes -static void ApplyUnboxingUnionPrimitive(ETSGen *etsg, const ir::AstNode *node) +void ETSGen::ApplyConversionCast(const ir::AstNode *node, const checker::Type *target_type) { - if (node->IsExpression() && node->Parent()->IsTSAsExpression()) { - auto const *from_type = node->AsExpression()->TsType(); - auto const *to_type = node->Parent()->AsTSAsExpression()->TsType(); - if (from_type->IsETSUnionType() && to_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - etsg->EmitCheckedNarrowingReferenceConversion( - node, checker::BoxingConverter::ETSTypeFromSource(etsg->Checker(), to_type)); + switch (checker::ETSChecker::TypeKind(target_type)) { + case checker::TypeFlag::DOUBLE: { + CastToDouble(node); + break; + } + case checker::TypeFlag::FLOAT: { + CastToFloat(node); + break; + } + case checker::TypeFlag::LONG: { + CastToLong(node); + break; + } + case checker::TypeFlag::ETS_ARRAY: + [[fallthrough]]; + case checker::TypeFlag::ETS_OBJECT: { + if (GetAccumulatorType() != nullptr && GetAccumulatorType()->IsETSDynamicType()) { + CastDynamicToObject(node, target_type); + } + break; + } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastToDynamic(node, target_type->AsETSDynamicType()); + break; + } + default: { + break; } } } @@ -897,7 +917,6 @@ void ETSGen::ApplyConversion(const ir::AstNode *node, const checker::Type *targe if (GetAccumulatorType()->IsNullishOrNullLike()) { // NOTE: vpukhov. should be a CTE EmitNullishGuardian(node); } - ApplyUnboxingUnionPrimitive(this, node); EmitUnboxingConversion(node); const auto unboxing_flags = static_cast(node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG); @@ -909,35 +928,12 @@ void ETSGen::ApplyConversion(const ir::AstNode *node, const checker::Type *targe return; } - switch (checker::ETSChecker::TypeKind(target_type)) { - case checker::TypeFlag::DOUBLE: { - CastToDouble(node); - break; - } - case checker::TypeFlag::FLOAT: { - CastToFloat(node); - break; - } - case checker::TypeFlag::LONG: { - CastToLong(node); - break; - } - case checker::TypeFlag::ETS_ARRAY: - [[fallthrough]]; - case checker::TypeFlag::ETS_OBJECT: { - if (GetAccumulatorType() != nullptr && GetAccumulatorType()->IsETSDynamicType()) { - CastDynamicToObject(node, target_type); - } - break; - } - case checker::TypeFlag::ETS_DYNAMIC_TYPE: { - CastToDynamic(node, target_type->AsETSDynamicType()); - break; - } - default: { - break; - } + if (target_type->IsETSUnionType()) { + SetAccumulatorType(target_type->AsETSUnionType()->GetLeastUpperBoundType()); + return; } + + ApplyConversionCast(node, target_type); } void ETSGen::ApplyCast(const ir::AstNode *node, const checker::Type *target_type) @@ -2423,6 +2419,10 @@ void ETSGen::LoadArrayElement(const ir::AstNode *node, VReg object_reg) { auto *element_type = GetVRegType(object_reg)->AsETSArrayType()->ElementType(); + if (element_type->IsETSUnionType()) { + element_type = element_type->AsETSUnionType()->GetLeastUpperBoundType(); + } + switch (checker::ETSChecker::ETSType(element_type)) { case checker::TypeFlag::ETS_BOOLEAN: case checker::TypeFlag::BYTE: { @@ -2473,6 +2473,9 @@ void ETSGen::LoadArrayElement(const ir::AstNode *node, VReg object_reg) void ETSGen::StoreArrayElement(const ir::AstNode *node, VReg object_reg, VReg index, const checker::Type *element_type) { + if (element_type->IsETSUnionType()) { + element_type = element_type->AsETSUnionType()->GetLeastUpperBoundType(); + } switch (checker::ETSChecker::ETSType(element_type)) { case checker::TypeFlag::ETS_BOOLEAN: case checker::TypeFlag::BYTE: { diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index f09b7301e9..f6e1c164dd 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -418,6 +418,7 @@ public: ApplyConversion(node, target_type_); } } + void ApplyConversionCast(const ir::AstNode *node, const checker::Type *target_type); void ApplyConversion(const ir::AstNode *node, const checker::Type *target_type); void ApplyCast(const ir::AstNode *node, const checker::Type *target_type); void EmitUnboxingConversion(const ir::AstNode *node); diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index f036bdab81..fbe3ea2305 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -17,21 +17,21 @@ #include "varbinder/variableFlags.h" #include "varbinder/ETSBinder.h" #include "checker/ETSchecker.h" +#include "checker/ets/conversion.h" +#include "checker/ets/boxingConverter.h" #include "compiler/core/compilerContext.h" +#include "compiler/lowering/util.h" #include "ir/base/classDefinition.h" #include "ir/base/classProperty.h" #include "ir/astNode.h" #include "ir/expression.h" #include "ir/opaqueTypeNode.h" -#include "ir/ets/etsParameterExpression.h" -#include "ir/expressions/assignmentExpression.h" #include "ir/expressions/binaryExpression.h" #include "ir/expressions/identifier.h" -#include "ir/expressions/functionExpression.h" #include "ir/expressions/memberExpression.h" -#include "ir/expressions/sequenceExpression.h" #include "ir/statements/blockStatement.h" #include "ir/statements/classDeclaration.h" +#include "ir/statements/variableDeclaration.h" #include "ir/ts/tsAsExpression.h" #include "type_helper.h" @@ -115,46 +115,261 @@ void HandleUnionPropertyAccess(checker::ETSChecker *checker, varbinder::VarBinde ASSERT(expr->PropVar() != nullptr); } -ir::Expression *HandleBinaryExpressionWithUnion(checker::ETSChecker *checker, ir::BinaryExpression *expr) +ir::TSAsExpression *GenAsExpression(checker::ETSChecker *checker, checker::Type *const opaque_type, + ir::Expression *const node, ir::AstNode *const parent) { - auto *union_type = expr->OperationType()->AsETSUnionType(); - ir::Expression *union_node; - ir::Expression *other_union_node = nullptr; - checker::Type *other_node_type; - if (expr->Left()->TsType()->IsETSUnionType()) { - union_node = expr->Left(); - other_node_type = expr->Right()->TsType(); - if (other_node_type->IsETSUnionType()) { - other_union_node = expr->Right(); + auto *const type_node = checker->AllocNode(opaque_type); + auto *const as_expression = checker->AllocNode(node, type_node, false); + as_expression->SetParent(parent); + node->SetParent(as_expression); + as_expression->Check(checker); + return as_expression; +} + +/* + * Function that generates conversion from (union) to (primitive) type as to `as` expressions: + * (union) as (prim) => ((union) as (ref)) as (prim), + * where (ref) is some unboxable type from union constituent types. + * Finally, `(union) as (prim)` expression replaces union_node that came above. + */ +ir::TSAsExpression *UnionCastToPrimitive(checker::ETSChecker *checker, checker::ETSObjectType *unboxable_ref, + checker::Type *unboxed_prim, ir::Expression *union_node) +{ + auto *const union_as_ref_expression = GenAsExpression(checker, unboxable_ref, union_node, nullptr); + union_as_ref_expression->SetBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxed_prim)); + union_node->SetParent(union_as_ref_expression); + + auto *const ref_as_prim_expression = + GenAsExpression(checker, unboxed_prim, union_as_ref_expression, union_node->Parent()); + union_as_ref_expression->SetParent(ref_as_prim_expression); + + return ref_as_prim_expression; +} + +ir::TSAsExpression *HandleUnionCastToPrimitive(checker::ETSChecker *checker, ir::TSAsExpression *expr) +{ + auto *const union_type = expr->Expr()->TsType()->AsETSUnionType(); + auto *source_type = union_type->FindExactOrBoxedType(checker, expr->TsType()); + if (source_type == nullptr) { + source_type = union_type->AsETSUnionType()->FindTypeIsCastableToSomeType(expr->Expr(), checker->Relation(), + expr->TsType()); + } + if (source_type != nullptr && expr->Expr()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { + if (expr->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + auto *const boxed_expr_type = checker::BoxingConverter::ETSTypeFromSource(checker, expr->TsType()); + auto *const as_expr = GenAsExpression(checker, boxed_expr_type, expr->Expr(), expr); + as_expr->SetBoxingUnboxingFlags(expr->Expr()->GetBoxingUnboxingFlags()); + expr->Expr()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); + expr->SetExpr(as_expr); } - } else { - union_node = expr->Right(); - other_node_type = expr->Left()->TsType(); + return expr; } - auto *source_type = - union_type->AsETSUnionType()->FindTypeIsCastableToSomeType(union_node, checker->Relation(), other_node_type); - if (source_type == nullptr) { - checker->ThrowTypeError("Bad operand type, some type of the union must be the same type as other expression.", - expr->Start()); - } - if ((union_node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U && - source_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { - union_node->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); - } - auto *union_type_node = checker->AllocNode(source_type); - auto *as_expression = checker->AllocNode(union_node, union_type_node, false); - as_expression->SetParent(expr); - expr->SetOperationType(source_type); - if (other_union_node != nullptr) { - auto *other_union_type_node = checker->AllocNode(other_node_type); - auto *other_as_expression = - checker->AllocNode(other_union_node, other_union_type_node, false); - other_as_expression->SetParent(expr); + auto *const unboxable_union_type = source_type != nullptr ? source_type : union_type->FindUnboxableType(); + auto *const unboxed_union_type = checker->ETSBuiltinTypeAsPrimitiveType(unboxable_union_type); + expr->SetExpr( + UnionCastToPrimitive(checker, unboxable_union_type->AsETSObjectType(), unboxed_union_type, expr->Expr())); + return expr; +} + +ir::BinaryExpression *GenInstanceofExpr(checker::ETSChecker *checker, ir::Expression *union_node, + checker::Type *constituent_type) +{ + auto *const lhs_expr = union_node->Clone(checker->Allocator())->AsExpression(); + lhs_expr->Check(checker); + lhs_expr->SetBoxingUnboxingFlags(union_node->GetBoxingUnboxingFlags()); + auto *rhs_type = constituent_type; + if (!constituent_type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { + checker->Relation()->SetNode(union_node); + rhs_type = checker::conversion::Boxing(checker->Relation(), constituent_type); + checker->Relation()->SetNode(nullptr); } + auto *const rhs_expr = + checker->Allocator()->New(rhs_type->AsETSObjectType()->Name(), checker->Allocator()); + auto *const instanceof_expr = + checker->Allocator()->New(lhs_expr, rhs_expr, lexer::TokenType::KEYW_INSTANCEOF); + lhs_expr->SetParent(instanceof_expr); + rhs_expr->SetParent(instanceof_expr); + auto rhs_var = NearestScope(union_node)->Find(rhs_expr->Name()); + rhs_expr->SetVariable(rhs_var.variable); + rhs_expr->SetTsType(rhs_var.variable->TsType()); + instanceof_expr->SetOperationType(checker->GlobalETSObjectType()); + instanceof_expr->SetTsType(checker->GlobalETSBooleanType()); + return instanceof_expr; +} + +ir::VariableDeclaration *GenVariableDeclForBinaryExpr(checker::ETSChecker *checker, varbinder::Scope *scope, + ir::BinaryExpression *expr) +{ + ASSERT(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL || + expr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_EQUAL); + auto *var_id = Gensym(checker->Allocator()); + auto *var = scope->AddDecl(checker->Allocator(), var_id->Name(), + varbinder::VariableFlags::LOCAL); + var->SetTsType(checker->GlobalETSBooleanType()); + var_id->SetVariable(var); + var_id->SetTsType(var->TsType()); + + auto declarator = checker->AllocNode(var_id); + ArenaVector declarators(checker->Allocator()->Adapter()); + declarators.push_back(declarator); + + auto var_kind = ir::VariableDeclaration::VariableDeclarationKind::LET; + auto *binary_var_decl = + checker->AllocNode(var_kind, checker->Allocator(), std::move(declarators), false); + binary_var_decl->SetRange({expr->Start(), expr->End()}); + return binary_var_decl; +} + +ir::ExpressionStatement *GenExpressionStmtWithAssignment(checker::ETSChecker *checker, ir::Identifier *var_decl_id, + ir::Expression *expr) +{ + auto *assignment_for_binary = + checker->AllocNode(var_decl_id, expr, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + assignment_for_binary->SetTsType(expr->TsType()); + return checker->AllocNode(assignment_for_binary); +} + +ir::BlockStatement *GenBlockStmtForAssignmentBinary(checker::ETSChecker *checker, ir::Identifier *var_decl_id, + ir::Expression *expr) +{ + auto local_ctx = varbinder::LexicalScope(checker->VarBinder()); + ArenaVector stmts(checker->Allocator()->Adapter()); + auto *stmt = GenExpressionStmtWithAssignment(checker, var_decl_id, expr); + stmts.push_back(stmt); + auto *const local_block_stmt = + checker->AllocNode(checker->Allocator(), local_ctx.GetScope(), std::move(stmts)); + stmt->SetParent(local_block_stmt); + local_block_stmt->SetRange(stmt->Range()); + local_ctx.GetScope()->BindNode(local_block_stmt); + return local_block_stmt; +} + +ir::Expression *SetBoxFlagOrGenAsExpression(checker::ETSChecker *checker, checker::Type *constituent_type, + ir::Expression *other_node) +{ + if (constituent_type->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::UNBOXABLE_TYPE) && + !other_node->IsETSUnionType() && other_node->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + auto *unboxed_constituent_type = checker->ETSBuiltinTypeAsPrimitiveType(constituent_type); + if (unboxed_constituent_type != other_node->TsType()) { + auto *const prim_as_expression = + GenAsExpression(checker, unboxed_constituent_type, other_node, other_node->Parent()); + prim_as_expression->SetBoxingUnboxingFlags(checker->GetBoxingFlag(constituent_type)); + return prim_as_expression; + } + return other_node; + } + if (other_node->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + other_node->SetBoxingUnboxingFlags( + checker->GetBoxingFlag(checker::BoxingConverter::ETSTypeFromSource(checker, other_node->TsType()))); + } + return other_node; +} + +ir::Expression *ProcessOperandsInBinaryExpr(checker::ETSChecker *checker, ir::BinaryExpression *expr, + checker::Type *constituent_type) +{ + ASSERT(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL || + expr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_EQUAL); + bool is_lhs_union; + ir::Expression *union_node = + (is_lhs_union = expr->Left()->TsType()->IsETSUnionType()) ? expr->Left() : expr->Right(); + auto *const as_expression = GenAsExpression(checker, constituent_type, union_node, expr); + if (is_lhs_union) { + expr->SetLeft(as_expression); + expr->SetRight(SetBoxFlagOrGenAsExpression(checker, constituent_type, expr->Right())); + } else { + expr->SetRight(as_expression); + expr->SetLeft(SetBoxFlagOrGenAsExpression(checker, constituent_type, expr->Left())); + } + expr->SetOperationType(checker->GlobalETSObjectType()); expr->SetTsType(checker->GlobalETSBooleanType()); return expr; } +ir::Statement *FindStatementFromNode(ir::Expression *expr) +{ + ir::AstNode *node = expr; + while (!node->IsStatement()) { + node = node->Parent(); + } + ASSERT(node->IsStatement()); + return node->AsStatement(); +} + +void InsertInstanceofTreeBeforeStmt(ir::Statement *stmt, ir::VariableDeclaration *binary_var_decl, + ir::Statement *instanceof_tree) +{ + if (stmt->IsVariableDeclarator()) { + ASSERT(stmt->Parent()->IsVariableDeclaration()); + stmt = stmt->Parent()->AsVariableDeclaration(); + } + ASSERT(stmt->Parent()->IsBlockStatement()); + auto *block = stmt->Parent()->AsBlockStatement(); + binary_var_decl->SetParent(block); + instanceof_tree->SetParent(block); + auto it_stmt = std::find(block->Statements().begin(), block->Statements().end(), stmt); + block->Statements().insert(it_stmt, {binary_var_decl, instanceof_tree}); +} + +ir::BlockStatement *ReplaceBinaryExprInStmt(checker::ETSChecker *checker, ir::Expression *union_node, + ir::BlockStatement *block, ir::BinaryExpression *expr) +{ + auto *stmt = FindStatementFromNode(expr); + ASSERT(stmt->IsVariableDeclarator() || block == stmt->Parent()); // statement with union + auto *const binary_var_decl = GenVariableDeclForBinaryExpr(checker, NearestScope(stmt), expr); + auto *const var_decl_id = binary_var_decl->Declarators().front()->Id(); // only one declarator was generated + ir::IfStatement *instanceof_tree = nullptr; + for (auto *u_type : union_node->TsType()->AsETSUnionType()->ConstituentTypes()) { + auto *const test = GenInstanceofExpr(checker, union_node, u_type); + auto *cloned_binary = expr->Clone(checker->Allocator(), expr->Parent())->AsBinaryExpression(); + cloned_binary->Check(checker); + auto *const consequent = GenBlockStmtForAssignmentBinary( + checker, var_decl_id->AsIdentifier(), ProcessOperandsInBinaryExpr(checker, cloned_binary, u_type)); + instanceof_tree = checker->Allocator()->New(test, consequent, instanceof_tree); + test->SetParent(instanceof_tree); + consequent->SetParent(instanceof_tree); + if (instanceof_tree->Alternate() != nullptr) { + instanceof_tree->Alternate()->SetParent(instanceof_tree); + } + } + ASSERT(instanceof_tree != nullptr); + // Replacing a binary expression with an identifier + // that was set in one of the branches of the `instanceof_tree` tree + stmt->TransformChildrenRecursively([var_decl_id](ir::AstNode *ast) -> ir::AstNode * { + if (ast->IsBinaryExpression() && ast->AsBinaryExpression()->OperationType() != nullptr && + ast->AsBinaryExpression()->OperationType()->IsETSUnionType()) { + return var_decl_id; + } + + return ast; + }); + InsertInstanceofTreeBeforeStmt(stmt, binary_var_decl, instanceof_tree); + return block; +} + +ir::BlockStatement *HandleBlockWithBinaryAndUnion(checker::ETSChecker *checker, ir::BlockStatement *block, + ir::BinaryExpression *bin_expr) +{ + if (bin_expr->OperatorType() != lexer::TokenType::PUNCTUATOR_EQUAL && + bin_expr->OperatorType() != lexer::TokenType::PUNCTUATOR_NOT_EQUAL) { + checker->ThrowTypeError("Bad operand type, unions are not allowed in binary expressions except equality.", + bin_expr->Start()); + } + ir::Expression *union_node = bin_expr->Left()->TsType()->IsETSUnionType() ? bin_expr->Left() : bin_expr->Right(); + return ReplaceBinaryExprInStmt(checker, union_node, block, bin_expr); +} + +ir::BlockStatement *HandleBlockWithBinaryAndUnions(checker::ETSChecker *checker, ir::BlockStatement *block, + const ir::NodePredicate &handle_binary) +{ + ir::BlockStatement *modified_ast_block = block; + while (modified_ast_block->IsAnyChild(handle_binary)) { + modified_ast_block = HandleBlockWithBinaryAndUnion( + checker, modified_ast_block, modified_ast_block->FindChild(handle_binary)->AsBinaryExpression()); + } + return modified_ast_block; +} + bool UnionLowering::Perform(CompilerContext *ctx, parser::Program *program) { for (auto &[_, ext_programs] : program->ExternalSources()) { @@ -173,9 +388,19 @@ bool UnionLowering::Perform(CompilerContext *ctx, parser::Program *program) return ast; } - if (ast->IsBinaryExpression() && ast->AsBinaryExpression()->OperationType() != nullptr && - ast->AsBinaryExpression()->OperationType()->IsETSUnionType()) { - return HandleBinaryExpressionWithUnion(checker, ast->AsBinaryExpression()); + if (ast->IsTSAsExpression() && ast->AsTSAsExpression()->Expr()->TsType() != nullptr && + ast->AsTSAsExpression()->Expr()->TsType()->IsETSUnionType() && + ast->AsTSAsExpression()->TsType() != nullptr && + ast->AsTSAsExpression()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + return HandleUnionCastToPrimitive(checker, ast->AsTSAsExpression()); + } + + auto handle_binary = [](const ir::AstNode *ast_node) { + return ast_node->IsBinaryExpression() && ast_node->AsBinaryExpression()->OperationType() != nullptr && + ast_node->AsBinaryExpression()->OperationType()->IsETSUnionType(); + }; + if (ast->IsBlockStatement() && ast->IsAnyChild(handle_binary)) { + return HandleBlockWithBinaryAndUnions(checker, ast->AsBlockStatement(), handle_binary); } return ast; diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 4db50cff07..3aee5eb547 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -89,6 +89,27 @@ bool AstNode::IsAnyChild(const NodePredicate &cb) const return found; } +void FindChildHelper(AstNode *&found, const NodePredicate &cb, AstNode *ast) +{ + if (found != nullptr) { + return; + } + + if (cb(ast)) { + found = ast; + return; + } + + ast->Iterate([&found, cb](AstNode *child) { FindChildHelper(found, cb, child); }); +} + +AstNode *AstNode::FindChild(const NodePredicate &cb) const +{ + AstNode *found = nullptr; + Iterate([&found, cb](AstNode *child) { FindChildHelper(found, cb, child); }); + return found; +} + void AnnotatedAstNode::CloneTypeAnnotation(ArenaAllocator *const allocator) { if (auto *annotation = const_cast(TypeAnnotation()); annotation != nullptr) { diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index f164f1660c..db3ab5e36e 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -460,6 +460,7 @@ public: void TransformChildrenRecursively(const NodeTransformer &cb); void IterateRecursively(const NodeTraverser &cb) const; bool IsAnyChild(const NodePredicate &cb) const; + AstNode *FindChild(const NodePredicate &cb) const; std::string DumpJSON() const; diff --git a/ets2panda/ir/expressions/binaryExpression.h b/ets2panda/ir/expressions/binaryExpression.h index 98416dc89f..69bdfa92f8 100644 --- a/ets2panda/ir/expressions/binaryExpression.h +++ b/ets2panda/ir/expressions/binaryExpression.h @@ -92,6 +92,12 @@ public: SetStart(left_->Start()); } + void SetRight(Expression *expr) noexcept + { + right_ = expr; + SetEnd(right_->End()); + } + void SetResult(Expression *expr) noexcept { left_ = expr; diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index a308acfd14..082e0be648 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -469,7 +469,15 @@ MemberExpression *MemberExpression::Clone(ArenaAllocator *const allocator, AstNo auto *const object = object_ != nullptr ? object_->Clone(allocator)->AsExpression() : nullptr; auto *const property = property_ != nullptr ? property_->Clone(allocator)->AsExpression() : nullptr; - if (auto *const clone = allocator->New(Tag {}, *this, object, property); clone != nullptr) { + if (auto *const clone = + allocator->New(object, property, kind_, computed_, MaybeOptionalExpression::IsOptional()); + clone != nullptr) { + if (object != nullptr) { + object->SetParent(clone); + } + if (property != nullptr) { + property->SetParent(clone); + } if (parent != nullptr) { clone->SetParent(parent); } diff --git a/ets2panda/ir/statements/ifStatement.h b/ets2panda/ir/statements/ifStatement.h index e124967507..57755853e4 100644 --- a/ets2panda/ir/statements/ifStatement.h +++ b/ets2panda/ir/statements/ifStatement.h @@ -47,6 +47,11 @@ public: return consequent_; } + Statement *Alternate() + { + return alternate_; + } + const Statement *Alternate() const { return alternate_; diff --git a/ets2panda/test/parser/ets/default_parameter6-expected.txt b/ets2panda/test/parser/ets/default_parameter6-expected.txt index caaeb8826a..ad8c1be4b1 100644 --- a/ets2panda/test/parser/ets/default_parameter6-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter6-expected.txt @@ -759,7 +759,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -854,7 +854,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -1038,7 +1038,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -2000,7 +2000,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -2095,7 +2095,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -2279,7 +2279,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/parser/ets/default_parameter7-expected.txt b/ets2panda/test/parser/ets/default_parameter7-expected.txt index ef5625ac46..c6d4b58f37 100644 --- a/ets2panda/test/parser/ets/default_parameter7-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter7-expected.txt @@ -1018,7 +1018,7 @@ "type": "ETSParameterExpression", "name": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "typeAnnotation": { "type": "ETSPrimitiveType", "loc": { @@ -1113,7 +1113,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { @@ -1297,7 +1297,7 @@ "operator": ">>", "left": { "type": "Identifier", - "name": "proxy_int", + "name": "$proxy_mask$", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/union_types_4-expected.txt b/ets2panda/test/union_types_4-expected.txt deleted file mode 100644 index e69de29bb2..0000000000 -- Gitee From bfceb5ca7d3358cd5ff7c83a217eb91f53dc6689 Mon Sep 17 00:00:00 2001 From: Csaba Hurton Date: Thu, 21 Sep 2023 17:23:26 +0200 Subject: [PATCH 10/12] Fix some function call ambiguities Fix function call ambiguities in such cases where there are classes and/or interfaces in the calling parameters. In cases where lang specs did not specify, solution falls back on the Java practice of choosing most specific signature. ChooseMostSpecificSignature() has been updated: now it first looks for most specific param signature among class type params, and later among interfaces. The method no longer needs the `arguments` param: thus it has been removed (as it is used to be this way before a recent change). Issue: I8IOL1 Change-Id: I225f4810dcecaf934e758793a98d5053a18604d3 Signed-off-by: Csaba Hurton --- ets2panda/checker/ETSchecker.h | 2 - ets2panda/checker/ets/function.cpp | 91 +- ...and-interface-in-signatures_1-expected.txt | 2409 +++++++++++++++ ...on-class-and-interface-in-signatures_1.ets | 40 + ...and-interface-in-signatures_2-expected.txt | 2409 +++++++++++++++ ...on-class-and-interface-in-signatures_2.ets | 40 + ...and-interface-in-signatures_3-expected.txt | 1833 ++++++++++++ ...on-class-and-interface-in-signatures_3.ets | 35 + ...and-interface-in-signatures_4-expected.txt | 1846 ++++++++++++ ...on-class-and-interface-in-signatures_4.ets | 37 + ...and-interface-in-signatures_5-expected.txt | 2078 +++++++++++++ ...on-class-and-interface-in-signatures_5.ets | 40 + ...and-interface-in-signatures_6-expected.txt | 2642 +++++++++++++++++ ...on-class-and-interface-in-signatures_6.ets | 44 + .../parser/ets/ambiguous_call_3-expected.txt | 2 +- 15 files changed, 13501 insertions(+), 47 deletions(-) create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1-expected.txt create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1.ets create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2-expected.txt create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2.ets create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3-expected.txt create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3.ets create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4-expected.txt create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4.ets create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5-expected.txt create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5.ets create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6-expected.txt create mode 100644 ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 491a401a08..285f7bb16d 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -289,11 +289,9 @@ public: const ArenaVector &arguments, const std::vector &arg_type_inference_required); Signature *ChooseMostSpecificSignature(ArenaVector &signatures, - const ArenaVector &arguments, const std::vector &arg_type_inference_required, const lexer::SourcePosition &pos, size_t arguments_size = ULONG_MAX); Signature *ChooseMostSpecificProxySignature(ArenaVector &signatures, - const ArenaVector &arguments, const std::vector &arg_type_inference_required, const lexer::SourcePosition &pos, size_t arguments_size); Signature *ResolveCallExpression(ArenaVector &signatures, diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 9594d01036..9ca1872b48 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -357,7 +357,7 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, if (!compatible_signatures.empty()) { Signature *most_specific_signature = - ChooseMostSpecificSignature(compatible_signatures, arguments, arg_type_inference_required, pos); + ChooseMostSpecificSignature(compatible_signatures, arg_type_inference_required, pos); if (most_specific_signature == nullptr) { ThrowTypeError({"Reference to ", compatible_signatures.front()->Function()->Id()->Name(), " is ambiguous"}, @@ -383,8 +383,8 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, }; if (!proxy_signatures.empty()) { - auto *const proxy_signature = ChooseMostSpecificProxySignature( - proxy_signatures, arguments, arg_type_inference_required, pos, arguments.size()); + auto *const proxy_signature = + ChooseMostSpecificProxySignature(proxy_signatures, arg_type_inference_required, pos, arguments.size()); if (proxy_signature != nullptr) { check_ambiguous(proxy_signature); } @@ -394,8 +394,8 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, } if (!proxy_signatures.empty()) { - auto *const proxy_signature = ChooseMostSpecificProxySignature( - proxy_signatures, arguments, arg_type_inference_required, pos, arguments.size()); + auto *const proxy_signature = + ChooseMostSpecificProxySignature(proxy_signatures, arg_type_inference_required, pos, arguments.size()); if (proxy_signature != nullptr) { return proxy_signature; } @@ -409,7 +409,6 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, } Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &signatures, - const ArenaVector &arguments, const std::vector &arg_type_inference_required, const lexer::SourcePosition &pos, size_t arguments_size) { @@ -432,8 +431,8 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig // Collect which signatures are most specific for each parameter. ArenaMultiMap best_signatures_for_parameter(Allocator()->Adapter()); - checker::SavedTypeRelationFlagsContext saved_type_relation_flag_ctx(Relation(), - TypeRelationFlag::ONLY_CHECK_WIDENING); + const checker::SavedTypeRelationFlagsContext saved_type_relation_flag_ctx(Relation(), + TypeRelationFlag::ONLY_CHECK_WIDENING); for (size_t i = 0; i < param_count; ++i) { if (arg_type_inference_required[i]) { @@ -444,51 +443,56 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig } // 1st step: check which is the most specific parameter type for i. parameter. Type *most_specific_type = signatures.front()->Params().at(i)->TsType(); + Signature *prev_sig = signatures.front(); - for (auto it = ++signatures.begin(); it != signatures.end(); ++it) { - Signature *sig = *it; - // Each signature must have the same amount of parameters. - if (arguments_size == ULONG_MAX) { - ASSERT(sig->Params().size() == param_count); - } - - Type *sig_type = sig->Params().at(i)->TsType(); - - if (Relation()->IsIdenticalTo(sig_type, most_specific_type)) { - continue; + auto init_most_specific_type = [&most_specific_type, &prev_sig, i](Signature *sig) { + if (Type *sig_type = sig->Params().at(i)->TsType(); + sig_type->IsETSObjectType() && !sig_type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { + most_specific_type = sig_type; + prev_sig = sig; + return true; } + return false; + }; + auto evaluate_result = [this, &most_specific_type, &prev_sig, pos](Signature *sig, Type *sig_type) { if (Relation()->IsAssignableTo(sig_type, most_specific_type)) { most_specific_type = sig_type; + prev_sig = sig; + } else if (sig_type->IsETSObjectType() && most_specific_type->IsETSObjectType() && + !Relation()->IsAssignableTo(most_specific_type, sig_type)) { + auto func_name = sig->Function()->Id()->Name(); + ThrowTypeError({"Call to `", func_name, "` is ambiguous as `2` versions of `", func_name, + "` are available: `", func_name, prev_sig, "` and `", func_name, sig, "`"}, + pos); } - } + }; - // 2nd step: collect which signatures fit to the i. most specific parameter type. - Type *prev_sig_type = nullptr; - Signature *prev_sig = nullptr; - Type *arg_type = arguments.at(i)->TsType(); - for (auto *sig : signatures) { + auto search_among_types = [this, &most_specific_type, arguments_size, param_count, i, + &evaluate_result](Signature *sig, const bool look_for_class_type) { + if (look_for_class_type && arguments_size == ULONG_MAX) { + [[maybe_unused]] const bool equal_param_size = sig->Params().size() == param_count; + ASSERT(equal_param_size); + } Type *sig_type = sig->Params().at(i)->TsType(); - if (arg_type->IsETSObjectType()) { - auto it = std::find(arg_type->AsETSObjectType()->Interfaces().begin(), - arg_type->AsETSObjectType()->Interfaces().end(), sig_type); - bool found_coincidence = it != arg_type->AsETSObjectType()->Interfaces().end() || - arg_type->AsETSObjectType()->SuperType() == sig_type; - if (found_coincidence && prev_sig_type != nullptr) { // Ambiguous call - bool is_assignable = - IsTypeAssignableTo(prev_sig_type, sig_type) || IsTypeAssignableTo(sig_type, prev_sig_type); - if (!is_assignable) { - auto func_name = sig->Function()->Id()->Name(); - ThrowTypeError({"Call to `", func_name, "` is ambiguous as `2` versions of `", func_name, - "` are available: `", func_name, prev_sig, "` and `", func_name, sig, "`"}, - pos); - } - } else if (found_coincidence && !arg_type->IsETSStringType()) { - prev_sig = sig; - prev_sig_type = sig_type; + const bool is_class_type = + sig_type->IsETSObjectType() && !sig_type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE); + if (is_class_type == look_for_class_type) { + if (Relation()->IsIdenticalTo(sig_type, most_specific_type)) { + return; } + evaluate_result(sig, sig_type); } + }; + + std::any_of(signatures.begin(), signatures.end(), init_most_specific_type); + std::for_each(signatures.begin(), signatures.end(), + [&search_among_types](Signature *sig) mutable { search_among_types(sig, true); }); + std::for_each(signatures.begin(), signatures.end(), + [&search_among_types](Signature *sig) mutable { search_among_types(sig, false); }); + for (auto *sig : signatures) { + Type *sig_type = sig->Params().at(i)->TsType(); if (Relation()->IsIdenticalTo(sig_type, most_specific_type)) { best_signatures_for_parameter.insert({i, sig}); } @@ -534,7 +538,6 @@ Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector &sig } Signature *ETSChecker::ChooseMostSpecificProxySignature(ArenaVector &signatures, - const ArenaVector &arguments, const std::vector &arg_type_inference_required, const lexer::SourcePosition &pos, size_t arguments_size) { @@ -543,7 +546,7 @@ Signature *ETSChecker::ChooseMostSpecificProxySignature(ArenaVector } const auto most_specific_signature = - ChooseMostSpecificSignature(signatures, arguments, arg_type_inference_required, pos, arguments_size); + ChooseMostSpecificSignature(signatures, arg_type_inference_required, pos, arguments_size); if (most_specific_signature == nullptr) { const auto str = signatures.front()->Function()->Id()->Name().Mutf8().substr( diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1-expected.txt b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1-expected.txt new file mode 100644 index 0000000000..f30d48b4da --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1-expected.txt @@ -0,0 +1,2409 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + } + ], + "body": [ + { + "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": 24 + }, + "end": { + "line": 19, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 22 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 20, + "column": 21 + }, + "end": { + "line": 20, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 29 + } + } + }, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 33 + } + } + } + ], + "body": [ + { + "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": 21, + "column": 34 + }, + "end": { + "line": 21, + "column": 34 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 32 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "D", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 21 + }, + "end": { + "line": 22, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 19 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + { + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "I", + "loc": { + "start": { + "line": 25, + "column": 12 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "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": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "J", + "loc": { + "start": { + "line": 28, + "column": 12 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 10 + }, + "end": { + "line": 30, + "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": 30, + "column": 10 + }, + "end": { + "line": 30, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "D", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 14 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 14 + }, + "end": { + "line": 30, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "D", + "loc": { + "start": { + "line": 31, + "column": 12 + }, + "end": { + "line": 31, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 30, + "column": 28 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 1 + }, + "end": { + "line": 32, + "column": 2 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 10 + }, + "end": { + "line": 34, + "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": 34, + "column": 10 + }, + "end": { + "line": 34, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 34, + "column": 18 + }, + "end": { + "line": 34, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 13 + }, + "end": { + "line": 35, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 13 + }, + "end": { + "line": 35, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 13 + }, + "end": { + "line": 35, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 9 + }, + "end": { + "line": 35, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 22 + }, + "end": { + "line": 35, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 30 + }, + "end": { + "line": 35, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 30 + }, + "end": { + "line": 35, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 30 + }, + "end": { + "line": 35, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 35, + "column": 26 + }, + "end": { + "line": 35, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 22 + }, + "end": { + "line": 35, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 9 + }, + "end": { + "line": 35, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 35 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 13 + }, + "end": { + "line": 36, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 13 + }, + "end": { + "line": 36, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 13 + }, + "end": { + "line": 36, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 9 + }, + "end": { + "line": 36, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 22 + }, + "end": { + "line": 36, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 30 + }, + "end": { + "line": 36, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 30 + }, + "end": { + "line": 36, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 30 + }, + "end": { + "line": 36, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 36, + "column": 26 + }, + "end": { + "line": 36, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 36, + "column": 22 + }, + "end": { + "line": 36, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 9 + }, + "end": { + "line": 36, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 36, + "column": 5 + }, + "end": { + "line": 36, + "column": 35 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 37, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 37, + "column": 26 + }, + "end": { + "line": 37, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 37, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 37, + "column": 5 + }, + "end": { + "line": 37, + "column": 35 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 38, + "column": 12 + }, + "end": { + "line": 38, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 38, + "column": 5 + }, + "end": { + "line": 38, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 14 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 14 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 1 + }, + "end": { + "line": 39, + "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": 41, + "column": 1 + } + } +} +TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(x: I): String` and `foo(x: J): String` [method-resolution-class-and-interface-in-signatures_1.ets:37:22] diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1.ets b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1.ets new file mode 100644 index 0000000000..2cf7a458b7 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_1.ets @@ -0,0 +1,40 @@ +/* + * 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. + */ + +interface I {} +interface J {} +interface K {} +class A implements J {} +class B extends A {} +class C extends B implements I {} +class D extends C {} + +function foo(x: I): string { + return "I"; +} +function foo(x: J): string { + return "J"; +} +function foo(x: D): string { + return "D"; +} + +function main(): int { + let a : string = foo(new A()); + let b : string = foo(new B()); + let c : string = foo(new C()); + return 0; +} + diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2-expected.txt b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2-expected.txt new file mode 100644 index 0000000000..095914af28 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2-expected.txt @@ -0,0 +1,2409 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 23 + } + } + } + ], + "body": [ + { + "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": 24 + }, + "end": { + "line": 19, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 22 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 20, + "column": 21 + }, + "end": { + "line": 20, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 29 + } + } + }, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 33 + } + } + } + ], + "body": [ + { + "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": 21, + "column": 34 + }, + "end": { + "line": 21, + "column": 34 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 32 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "D", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 21 + }, + "end": { + "line": 22, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 19 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + { + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "I", + "loc": { + "start": { + "line": 25, + "column": 12 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "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": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "J", + "loc": { + "start": { + "line": 28, + "column": 12 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 10 + }, + "end": { + "line": 30, + "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": 30, + "column": 10 + }, + "end": { + "line": 30, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 14 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 14 + }, + "end": { + "line": 30, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 21 + }, + "end": { + "line": 30, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "B", + "loc": { + "start": { + "line": 31, + "column": 12 + }, + "end": { + "line": 31, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 30, + "column": 28 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 1 + }, + "end": { + "line": 32, + "column": 2 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 10 + }, + "end": { + "line": 34, + "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": 34, + "column": 10 + }, + "end": { + "line": 34, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 34, + "column": 18 + }, + "end": { + "line": 34, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 13 + }, + "end": { + "line": 35, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 13 + }, + "end": { + "line": 35, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 13 + }, + "end": { + "line": 35, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 9 + }, + "end": { + "line": 35, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 22 + }, + "end": { + "line": 35, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 30 + }, + "end": { + "line": 35, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 30 + }, + "end": { + "line": 35, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 30 + }, + "end": { + "line": 35, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 35, + "column": 26 + }, + "end": { + "line": 35, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 22 + }, + "end": { + "line": 35, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 9 + }, + "end": { + "line": 35, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 35 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 13 + }, + "end": { + "line": 36, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 13 + }, + "end": { + "line": 36, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 13 + }, + "end": { + "line": 36, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 9 + }, + "end": { + "line": 36, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 22 + }, + "end": { + "line": 36, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 30 + }, + "end": { + "line": 36, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 30 + }, + "end": { + "line": 36, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 30 + }, + "end": { + "line": 36, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 36, + "column": 26 + }, + "end": { + "line": 36, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 36, + "column": 22 + }, + "end": { + "line": 36, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 9 + }, + "end": { + "line": 36, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 36, + "column": 5 + }, + "end": { + "line": 36, + "column": 35 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "d", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 37, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "D", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 37, + "column": 26 + }, + "end": { + "line": 37, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 37, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 37, + "column": 5 + }, + "end": { + "line": 37, + "column": 35 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 38, + "column": 12 + }, + "end": { + "line": 38, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 38, + "column": 5 + }, + "end": { + "line": 38, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 14 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 14 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 1 + }, + "end": { + "line": 39, + "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": 41, + "column": 1 + } + } +} +TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(x: B): String` and `foo(x: I): String` [method-resolution-class-and-interface-in-signatures_2.ets:37:22] diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2.ets b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2.ets new file mode 100644 index 0000000000..c0928f8716 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_2.ets @@ -0,0 +1,40 @@ +/* + * 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. + */ + +interface I {} +interface J {} +interface K {} +class A implements J {} +class B extends A {} +class C extends B implements I {} +class D extends C {} + +function foo(x: I): string { + return "I"; +} +function foo(x: J): string { + return "J"; +} +function foo(x: B): string { + return "B"; +} + +function main(): int { + let a : string = foo(new A()); + let b : string = foo(new B()); + let d : string = foo(new D()); + return 0; +} + diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3-expected.txt b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3-expected.txt new file mode 100644 index 0000000000..8e8b4891d9 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3-expected.txt @@ -0,0 +1,1833 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "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": 11 + }, + "end": { + "line": 19, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + } + ], + "body": [ + { + "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": 20, + "column": 37 + }, + "end": { + "line": 20, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 35 + }, + "end": { + "line": 20, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 37 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 21, + "column": 21 + }, + "end": { + "line": 21, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 19 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "D", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 17 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 21 + }, + "end": { + "line": 22, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 19 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + { + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "I", + "loc": { + "start": { + "line": 25, + "column": 12 + }, + "end": { + "line": 25, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "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": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "J", + "loc": { + "start": { + "line": 28, + "column": 12 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 10 + }, + "end": { + "line": 31, + "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": 31, + "column": 10 + }, + "end": { + "line": 31, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 31, + "column": 18 + }, + "end": { + "line": 31, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "d", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 13 + }, + "end": { + "line": 32, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 13 + }, + "end": { + "line": 32, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 13 + }, + "end": { + "line": 32, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 9 + }, + "end": { + "line": 32, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 22 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "D", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 30 + }, + "end": { + "line": 32, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 30 + }, + "end": { + "line": 32, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 30 + }, + "end": { + "line": 32, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 32, + "column": 26 + }, + "end": { + "line": 32, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 32, + "column": 22 + }, + "end": { + "line": 32, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 9 + }, + "end": { + "line": 32, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 32, + "column": 5 + }, + "end": { + "line": 32, + "column": 35 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 33, + "column": 12 + }, + "end": { + "line": 33, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 5 + }, + "end": { + "line": 33, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 31, + "column": 22 + }, + "end": { + "line": 34, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 14 + }, + "end": { + "line": 34, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 14 + }, + "end": { + "line": 34, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 1 + }, + "end": { + "line": 34, + "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": 36, + "column": 1 + } + } +} +TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(x: I): String` and `foo(x: J): String` [method-resolution-class-and-interface-in-signatures_3.ets:32:22] diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3.ets b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3.ets new file mode 100644 index 0000000000..ef412316e1 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_3.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +interface I {} +interface J {} +interface K {} +class A {} +class B extends A implements I, J {} +class C extends B {} +class D extends C {} + +function foo(x: I): string { + return "I"; +} +function foo(x: J): string { + return "J"; +} + +function main(): int { + let d : string = foo(new D()); + return 0; +} + diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4-expected.txt b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4-expected.txt new file mode 100644 index 0000000000..80ef2eedb6 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4-expected.txt @@ -0,0 +1,1846 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "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": 11 + }, + "end": { + "line": 19, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + } + ], + "body": [ + { + "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": 20, + "column": 37 + }, + "end": { + "line": 20, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 35 + }, + "end": { + "line": 20, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 37 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 21, + "column": 21 + }, + "end": { + "line": 21, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 19 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + { + "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": 23, + "column": 10 + }, + "end": { + "line": 23, + "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": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 23, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 23, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "I", + "loc": { + "start": { + "line": 24, + "column": 12 + }, + "end": { + "line": 24, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 10 + }, + "end": { + "line": 26, + "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": 26, + "column": 10 + }, + "end": { + "line": 26, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 26, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 26, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 26, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "J", + "loc": { + "start": { + "line": 27, + "column": 12 + }, + "end": { + "line": 27, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 10 + }, + "end": { + "line": 29, + "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": 29, + "column": 10 + }, + "end": { + "line": 29, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 17 + }, + "end": { + "line": 29, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 17 + }, + "end": { + "line": 29, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 17 + }, + "end": { + "line": 29, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 14 + }, + "end": { + "line": 29, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 14 + }, + "end": { + "line": 29, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 21 + }, + "end": { + "line": 29, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 21 + }, + "end": { + "line": 29, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 21 + }, + "end": { + "line": 29, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 30, + "column": 12 + }, + "end": { + "line": 30, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 5 + }, + "end": { + "line": 30, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 29, + "column": 28 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 13 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 13 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 1 + }, + "end": { + "line": 31, + "column": 2 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 10 + }, + "end": { + "line": 33, + "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": 33, + "column": 10 + }, + "end": { + "line": 33, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 33, + "column": 18 + }, + "end": { + "line": 33, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 13 + }, + "end": { + "line": 34, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 13 + }, + "end": { + "line": 34, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 13 + }, + "end": { + "line": 34, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 9 + }, + "end": { + "line": 34, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 34, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 30 + }, + "end": { + "line": 34, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 30 + }, + "end": { + "line": 34, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 30 + }, + "end": { + "line": 34, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 34, + "column": 26 + }, + "end": { + "line": 34, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 34, + "column": 22 + }, + "end": { + "line": 34, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 9 + }, + "end": { + "line": 34, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 34, + "column": 5 + }, + "end": { + "line": 34, + "column": 35 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 35, + "column": 12 + }, + "end": { + "line": 35, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 5 + }, + "end": { + "line": 35, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 33, + "column": 22 + }, + "end": { + "line": 36, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 14 + }, + "end": { + "line": 36, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 14 + }, + "end": { + "line": 36, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 1 + }, + "end": { + "line": 36, + "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": 38, + "column": 1 + } + } +} +TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(x: A): String` and `foo(x: I): String` [method-resolution-class-and-interface-in-signatures_4.ets:34:22] diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4.ets b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4.ets new file mode 100644 index 0000000000..7eb0e88eb2 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_4.ets @@ -0,0 +1,37 @@ +/* + * 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. + */ + +interface I {} +interface J {} + +class A {} +class B extends A implements I, J {} +class C extends B {} + +function foo(x: I): string { + return "I"; +} +function foo(x: J): string { + return "J"; +} +function foo(x: A): string { + return "A"; +} + +function main(): int { + let c : string = foo(new C()); + return 0; +} + diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5-expected.txt b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5-expected.txt new file mode 100644 index 0000000000..f4277701d6 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5-expected.txt @@ -0,0 +1,2078 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "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": 11 + }, + "end": { + "line": 19, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 29 + } + } + }, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 30 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 33 + }, + "end": { + "line": 20, + "column": 36 + } + } + } + ], + "body": [ + { + "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": 20, + "column": 37 + }, + "end": { + "line": 20, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 35 + }, + "end": { + "line": 20, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 37 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "C", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "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": 21, + "column": 21 + }, + "end": { + "line": 21, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 19 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + { + "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": 23, + "column": 10 + }, + "end": { + "line": 23, + "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": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 23, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 23, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "I", + "loc": { + "start": { + "line": 24, + "column": 12 + }, + "end": { + "line": 24, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 10 + }, + "end": { + "line": 26, + "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": 26, + "column": 10 + }, + "end": { + "line": 26, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 17 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 14 + }, + "end": { + "line": 26, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 26, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 26, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 26, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "J", + "loc": { + "start": { + "line": 27, + "column": 12 + }, + "end": { + "line": 27, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 10 + }, + "end": { + "line": 29, + "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": 29, + "column": 10 + }, + "end": { + "line": 29, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 17 + }, + "end": { + "line": 29, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 17 + }, + "end": { + "line": 29, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 17 + }, + "end": { + "line": 29, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 14 + }, + "end": { + "line": 29, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 14 + }, + "end": { + "line": 29, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 21 + }, + "end": { + "line": 29, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 21 + }, + "end": { + "line": 29, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 21 + }, + "end": { + "line": 29, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "A", + "loc": { + "start": { + "line": 30, + "column": 12 + }, + "end": { + "line": 30, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 5 + }, + "end": { + "line": 30, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 29, + "column": 28 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 13 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 13 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 1 + }, + "end": { + "line": 31, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 10 + }, + "end": { + "line": 32, + "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": 32, + "column": 10 + }, + "end": { + "line": 32, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 17 + }, + "end": { + "line": 32, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 17 + }, + "end": { + "line": 32, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 17 + }, + "end": { + "line": 32, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 14 + }, + "end": { + "line": 32, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 14 + }, + "end": { + "line": 32, + "column": 19 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 21 + }, + "end": { + "line": 32, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 21 + }, + "end": { + "line": 32, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 21 + }, + "end": { + "line": 32, + "column": 29 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "StringLiteral", + "value": "B", + "loc": { + "start": { + "line": 33, + "column": 12 + }, + "end": { + "line": 33, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 5 + }, + "end": { + "line": 33, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 32, + "column": 28 + }, + "end": { + "line": 34, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 13 + }, + "end": { + "line": 34, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 13 + }, + "end": { + "line": 34, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 1 + }, + "end": { + "line": 34, + "column": 2 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 10 + }, + "end": { + "line": 36, + "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": 36, + "column": 10 + }, + "end": { + "line": 36, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 36, + "column": 18 + }, + "end": { + "line": 36, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 13 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 10 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 37, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 30 + }, + "end": { + "line": 37, + "column": 32 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 37, + "column": 26 + }, + "end": { + "line": 37, + "column": 34 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 37, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 9 + }, + "end": { + "line": 37, + "column": 34 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 37, + "column": 5 + }, + "end": { + "line": 37, + "column": 35 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 38, + "column": 12 + }, + "end": { + "line": 38, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 38, + "column": 5 + }, + "end": { + "line": 38, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 36, + "column": 22 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 14 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 36, + "column": 14 + }, + "end": { + "line": 39, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 1 + }, + "end": { + "line": 39, + "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": 41, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5.ets b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5.ets new file mode 100644 index 0000000000..11d7372402 --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_5.ets @@ -0,0 +1,40 @@ +/* + * 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. + */ + +interface I {} +interface J {} + +class A {} +class B extends A implements I, J {} +class C extends B {} + +function foo(x: I): string { + return "I"; +} +function foo(x: J): string { + return "J"; +} +function foo(x: A): string { + return "A"; +} +function foo(x: B): string { + return "B"; +} + +function main(): int { + let b : string = foo(new B()); + return 0; +} + diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6-expected.txt b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6-expected.txt new file mode 100644 index 0000000000..789f220c2c --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6-expected.txt @@ -0,0 +1,2642 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [], + "loc": { + "start": { + "line": 17, + "column": 13 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "id": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 20 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 26 + } + } + } + ], + "body": [ + { + "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": 27 + }, + "end": { + "line": 19, + "column": 27 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 25 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 27 + } + } + }, + { + "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": 21, + "column": 10 + }, + "end": { + "line": 21, + "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": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 25 + }, + "end": { + "line": 21, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 25 + }, + "end": { + "line": 21, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 25 + }, + "end": { + "line": 21, + "column": 27 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 21, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 21, + "column": 27 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 21, + "column": 29 + }, + "end": { + "line": 21, + "column": 32 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 12 + }, + "end": { + "line": 22, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 33 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 10 + }, + "end": { + "line": 24, + "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": 24, + "column": 10 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "d", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 24, + "column": 17 + }, + "end": { + "line": 24, + "column": 23 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 23 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 28 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 30 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 24, + "column": 32 + }, + "end": { + "line": 24, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 12 + }, + "end": { + "line": 25, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 5 + }, + "end": { + "line": 25, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 39 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 1 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "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": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 17 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "b", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 27, + "column": 23 + }, + "end": { + "line": 27, + "column": 26 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 20 + }, + "end": { + "line": 27, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 20 + }, + "end": { + "line": 27, + "column": 26 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 27, + "column": 29 + }, + "end": { + "line": 27, + "column": 32 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 12 + }, + "end": { + "line": 28, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 28, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 33 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 10 + }, + "end": { + "line": 30, + "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": 30, + "column": 10 + }, + "end": { + "line": 30, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "J", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 17 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 14 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 14 + }, + "end": { + "line": 30, + "column": 19 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "d", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 30, + "column": 23 + }, + "end": { + "line": 30, + "column": 29 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 20 + }, + "end": { + "line": 30, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 20 + }, + "end": { + "line": 30, + "column": 29 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 30, + "column": 32 + }, + "end": { + "line": 30, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 12 + }, + "end": { + "line": 31, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 30, + "column": 39 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 30, + "column": 13 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 1 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 10 + }, + "end": { + "line": 33, + "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": 33, + "column": 10 + }, + "end": { + "line": 33, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "I", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 17 + }, + "end": { + "line": 33, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 17 + }, + "end": { + "line": 33, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 17 + }, + "end": { + "line": 33, + "column": 19 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 14 + }, + "end": { + "line": 33, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 14 + }, + "end": { + "line": 33, + "column": 19 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "d", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 33, + "column": 23 + }, + "end": { + "line": 33, + "column": 29 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 20 + }, + "end": { + "line": 33, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 20 + }, + "end": { + "line": 33, + "column": 29 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 33, + "column": 32 + }, + "end": { + "line": 33, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 12 + }, + "end": { + "line": 34, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 5 + }, + "end": { + "line": 34, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 33, + "column": 39 + }, + "end": { + "line": 35, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 13 + }, + "end": { + "line": 35, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 13 + }, + "end": { + "line": 35, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 1 + }, + "end": { + "line": 35, + "column": 2 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 10 + }, + "end": { + "line": 37, + "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": 37, + "column": 10 + }, + "end": { + "line": 37, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 37, + "column": 18 + }, + "end": { + "line": 37, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "asd1", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 38, + "column": 15 + }, + "end": { + "line": 38, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 38, + "column": 9 + }, + "end": { + "line": 38, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 38, + "column": 21 + }, + "end": { + "line": 38, + "column": 24 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 38, + "column": 25 + }, + "end": { + "line": 38, + "column": 26 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 38, + "column": 32 + }, + "end": { + "line": 38, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 38, + "column": 32 + }, + "end": { + "line": 38, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 38, + "column": 32 + }, + "end": { + "line": 38, + "column": 34 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 38, + "column": 28 + }, + "end": { + "line": 38, + "column": 36 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 38, + "column": 21 + }, + "end": { + "line": 38, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 38, + "column": 9 + }, + "end": { + "line": 38, + "column": 36 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 38, + "column": 5 + }, + "end": { + "line": 38, + "column": 37 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "asd2", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 39, + "column": 15 + }, + "end": { + "line": 39, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 9 + }, + "end": { + "line": 39, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 24 + }, + "end": { + "line": 39, + "column": 27 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 2.1, + "loc": { + "start": { + "line": 39, + "column": 28 + }, + "end": { + "line": 39, + "column": 31 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 37 + }, + "end": { + "line": 39, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 39, + "column": 37 + }, + "end": { + "line": 39, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 39, + "column": 37 + }, + "end": { + "line": 39, + "column": 39 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 39, + "column": 33 + }, + "end": { + "line": 39, + "column": 41 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 39, + "column": 24 + }, + "end": { + "line": 39, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 39, + "column": 9 + }, + "end": { + "line": 39, + "column": 41 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 39, + "column": 5 + }, + "end": { + "line": 39, + "column": 42 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "asd3", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 40, + "column": 15 + }, + "end": { + "line": 40, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 9 + }, + "end": { + "line": 40, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 24 + }, + "end": { + "line": 40, + "column": 27 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 40, + "column": 28 + }, + "end": { + "line": 40, + "column": 31 + } + } + }, + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 37 + }, + "end": { + "line": 40, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 40, + "column": 37 + }, + "end": { + "line": 40, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 40, + "column": 37 + }, + "end": { + "line": 40, + "column": 39 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 40, + "column": 33 + }, + "end": { + "line": 40, + "column": 41 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 40, + "column": 24 + }, + "end": { + "line": 40, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 40, + "column": 9 + }, + "end": { + "line": 40, + "column": 41 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 40, + "column": 5 + }, + "end": { + "line": 40, + "column": 42 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "asd4", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 41, + "column": 15 + }, + "end": { + "line": 41, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 9 + }, + "end": { + "line": 41, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 21 + }, + "end": { + "line": 41, + "column": 24 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 29 + }, + "end": { + "line": 41, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 41, + "column": 29 + }, + "end": { + "line": 41, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 41, + "column": 29 + }, + "end": { + "line": 41, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 41, + "column": 25 + }, + "end": { + "line": 41, + "column": 33 + } + } + }, + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 41, + "column": 34 + }, + "end": { + "line": 41, + "column": 35 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 41, + "column": 21 + }, + "end": { + "line": 41, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 41, + "column": 9 + }, + "end": { + "line": 41, + "column": 36 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 41, + "column": 5 + }, + "end": { + "line": 41, + "column": 37 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "asd5", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 42, + "column": 15 + }, + "end": { + "line": 42, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 9 + }, + "end": { + "line": 42, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 24 + }, + "end": { + "line": 42, + "column": 27 + } + } + }, + "arguments": [ + { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 32 + }, + "end": { + "line": 42, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 42, + "column": 32 + }, + "end": { + "line": 42, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 42, + "column": 32 + }, + "end": { + "line": 42, + "column": 34 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 42, + "column": 28 + }, + "end": { + "line": 42, + "column": 36 + } + } + }, + { + "type": "NumberLiteral", + "value": 2.1, + "loc": { + "start": { + "line": 42, + "column": 37 + }, + "end": { + "line": 42, + "column": 40 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 42, + "column": 24 + }, + "end": { + "line": 42, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 42, + "column": 9 + }, + "end": { + "line": 42, + "column": 41 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 42, + "column": 5 + }, + "end": { + "line": 42, + "column": 42 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 43, + "column": 12 + }, + "end": { + "line": 43, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 43, + "column": 5 + }, + "end": { + "line": 43, + "column": 14 + } + } + } + ], + "loc": { + "start": { + "line": 37, + "column": 22 + }, + "end": { + "line": 44, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 14 + }, + "end": { + "line": 44, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 37, + "column": 14 + }, + "end": { + "line": 44, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 1 + }, + "end": { + "line": 44, + "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": 44, + "column": 2 + } + } +} +TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(a: J, d: double): double` and `foo(a: I, d: double): double` [method-resolution-class-and-interface-in-signatures_6.ets:42:24] diff --git a/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets new file mode 100644 index 0000000000..a6b43ef72c --- /dev/null +++ b/ets2panda/test/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets @@ -0,0 +1,44 @@ +/* + * 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. + */ + +interface I {} +interface J {} + +class A implements I, J {} + +function foo(b: int, a: I): int { + return b; +} +function foo(d: double, a: J): double { + return d; +} +function foo(a: I, b: int): int { + return b; +} +function foo(a: J, d: double): double { + return d; +} +function foo(a: I, d: double): double { + return d; +} + +function main(): int { + let asd1: int = foo(1, new A()); + let asd2: double = foo(2.1, new A()); + let asd3: double = foo(2.0, new A()); + let asd4: int = foo(new A(), 1); + let asd5: double = foo(new A(), 2.1); + return 0; +} \ No newline at end of file diff --git a/ets2panda/test/parser/ets/ambiguous_call_3-expected.txt b/ets2panda/test/parser/ets/ambiguous_call_3-expected.txt index 03787bbfbc..eaca9b0b5c 100644 --- a/ets2panda/test/parser/ets/ambiguous_call_3-expected.txt +++ b/ets2panda/test/parser/ets/ambiguous_call_3-expected.txt @@ -1209,4 +1209,4 @@ } } } -TypeError: Call to `goo` is ambiguous as `2` versions of `goo` are available: `goo(p1: I1): void` and `goo(p2: B): void` [ambiguous_call_3.ets:23:5] +TypeError: Call to `goo` is ambiguous as `2` versions of `goo` are available: `goo(p2: B): void` and `goo(p1: I1): void` [ambiguous_call_3.ets:23:5] -- Gitee From 1e3793c0253b079beb7ab13bb0d6ec6e1438f0e1 Mon Sep 17 00:00:00 2001 From: Zelentsov Dmitry Date: Tue, 7 Nov 2023 17:41:16 +0300 Subject: [PATCH 11/12] Fix error in lambda type definition with rest parameter. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8FSWJ?from=project-issue Test: .../ets2panda/test/runtime/ets/lambdaExpressionWithRestParameter.ets Signed-off-by: Zelentsov Dmitry --- ets2panda/checker/ets/function.cpp | 22 ++++++------ ets2panda/ir/astNode.cpp | 7 ---- ets2panda/ir/astNode.h | 2 -- ets2panda/ir/base/spreadElement.cpp | 3 +- ets2panda/ir/ets/etsParameterExpression.cpp | 1 + ets2panda/ir/expression.cpp | 7 ++-- ets2panda/ir/expression.h | 9 ++--- ets2panda/ir/expressions/arrayExpression.cpp | 4 +-- ets2panda/ir/expressions/identifier.cpp | 3 +- ets2panda/ir/expressions/objectExpression.cpp | 4 +-- ets2panda/ir/statement.cpp | 7 ---- ets2panda/ir/statement.h | 2 -- .../ets/lambdaExpressionWithRestParameter.ets | 36 +++++++++++++++++++ .../ets-runtime/ets-runtime-ignored.txt | 5 +-- 14 files changed, 59 insertions(+), 53 deletions(-) create mode 100644 ets2panda/test/runtime/ets/lambdaExpressionWithRestParameter.ets diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 9ca1872b48..f7ed8b51d4 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -2539,21 +2539,21 @@ varbinder::FunctionParamScope *ETSChecker::CopyParams(const ArenaVector &out_params) { auto param_ctx = varbinder::LexicalScope(VarBinder()); + for (auto *const it : params) { - auto *const param_expr_ident = it->AsETSParameterExpression()->Ident(); - auto *const param_ident = Allocator()->New(param_expr_ident->Name(), Allocator()); + auto *const param_old = it->AsETSParameterExpression(); + auto *const param_new = param_old->Clone(Allocator(), param_old->Parent())->AsETSParameterExpression(); - auto *const param = Allocator()->New(param_ident, nullptr); - auto *const var = std::get<1>(VarBinder()->AddParamDecl(param)); - var->SetTsType(param_expr_ident->Variable()->TsType()); + auto *const var = std::get<1>(VarBinder()->AddParamDecl(param_new)); + var->SetTsType(param_old->Ident()->Variable()->TsType()); var->SetScope(param_ctx.GetScope()); - param->SetVariable(var); - param_ident->SetTsTypeAnnotation(param_expr_ident->TypeAnnotation()); - param->SetTsType(param_expr_ident->Variable()->TsType()); - param->SetParent(it->Parent()); - param_ident->SetParent(param_expr_ident->Parent()); - out_params.push_back(param); + param_new->SetVariable(var); + + param_new->SetTsType(param_old->TsType()); + + out_params.emplace_back(param_new); } + return param_ctx.GetScope(); } diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 3aee5eb547..4687db6902 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -110,13 +110,6 @@ AstNode *AstNode::FindChild(const NodePredicate &cb) const return found; } -void AnnotatedAstNode::CloneTypeAnnotation(ArenaAllocator *const allocator) -{ - if (auto *annotation = const_cast(TypeAnnotation()); annotation != nullptr) { - SetTsTypeAnnotation(annotation->Clone(allocator, this)); - } -} - std::string AstNode::DumpJSON() const { ir::AstDumper dumper {this}; diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index db3ab5e36e..9e948ee8aa 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -584,8 +584,6 @@ public: NO_COPY_OPERATOR(AnnotatedAstNode); NO_MOVE_SEMANTIC(AnnotatedAstNode); - void CloneTypeAnnotation(ArenaAllocator *allocator); - protected: explicit AnnotatedAstNode(AstNodeType const type, TypeNode *const type_annotation) : Annotated(type, type_annotation) diff --git a/ets2panda/ir/base/spreadElement.cpp b/ets2panda/ir/base/spreadElement.cpp index e7ff3e0622..c6a722c3ad 100644 --- a/ets2panda/ir/base/spreadElement.cpp +++ b/ets2panda/ir/base/spreadElement.cpp @@ -25,9 +25,8 @@ namespace panda::es2panda::ir { SpreadElement::SpreadElement([[maybe_unused]] Tag const tag, SpreadElement const &other, ArenaAllocator *const allocator) - : AnnotatedExpression(static_cast(other)), decorators_(allocator->Adapter()) + : AnnotatedExpression(static_cast(other), allocator), decorators_(allocator->Adapter()) { - CloneTypeAnnotation(allocator); optional_ = other.optional_; if (other.argument_ != nullptr) { diff --git a/ets2panda/ir/ets/etsParameterExpression.cpp b/ets2panda/ir/ets/etsParameterExpression.cpp index 0445df4d22..6065a8a5ce 100644 --- a/ets2panda/ir/ets/etsParameterExpression.cpp +++ b/ets2panda/ir/ets/etsParameterExpression.cpp @@ -39,6 +39,7 @@ ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const ident_ spread_ = ident_or_spread->AsRestElement(); ASSERT(spread_->Argument()->IsIdentifier()); ident_ = spread_->Argument()->AsIdentifier(); + ident_->SetParent(spread_); initializer_ = nullptr; // Just in case! } else { UNREACHABLE(); diff --git a/ets2panda/ir/expression.cpp b/ets2panda/ir/expression.cpp index 6415d5e172..88100c8f31 100644 --- a/ets2panda/ir/expression.cpp +++ b/ets2panda/ir/expression.cpp @@ -18,10 +18,11 @@ namespace panda::es2panda::ir { -void AnnotatedExpression::CloneTypeAnnotation(ArenaAllocator *const allocator) +AnnotatedExpression::AnnotatedExpression(AnnotatedExpression const &other, ArenaAllocator *const allocator) + : Annotated(static_cast const &>(other)) { - if (auto *annotation = const_cast(TypeAnnotation()); annotation != nullptr) { - SetTsTypeAnnotation(annotation->Clone(allocator, this)); + if (auto *const annotation = other.TypeAnnotation(); annotation != nullptr) { + SetTsTypeAnnotation(annotation->Clone(allocator, this)->AsTypeNode()); } } diff --git a/ets2panda/ir/expression.h b/ets2panda/ir/expression.h index 5b5479c3d6..e42d12c5a5 100644 --- a/ets2panda/ir/expression.h +++ b/ets2panda/ir/expression.h @@ -115,7 +115,7 @@ public: AnnotatedExpression() = delete; ~AnnotatedExpression() override = default; - NO_COPY_OPERATOR(AnnotatedExpression); + NO_COPY_SEMANTIC(AnnotatedExpression); NO_MOVE_SEMANTIC(AnnotatedExpression); [[nodiscard]] bool IsAnnotatedExpression() const noexcept override @@ -130,12 +130,7 @@ protected: } explicit AnnotatedExpression(AstNodeType const type) : Annotated(type) {} - AnnotatedExpression(AnnotatedExpression const &other) - : Annotated(static_cast const &>(other)) - { - } - - void CloneTypeAnnotation(ArenaAllocator *allocator); + explicit AnnotatedExpression(AnnotatedExpression const &other, ArenaAllocator *allocator); }; class MaybeOptionalExpression : public Expression { diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index 6b46553a1d..a29a2de739 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -34,12 +34,10 @@ namespace panda::es2panda::ir { ArrayExpression::ArrayExpression([[maybe_unused]] Tag const tag, ArrayExpression const &other, ArenaAllocator *const allocator) - : AnnotatedExpression(static_cast(other)), + : AnnotatedExpression(static_cast(other), allocator), decorators_(allocator->Adapter()), elements_(allocator->Adapter()) { - CloneTypeAnnotation(allocator); - preferred_type_ = other.preferred_type_; is_declaration_ = other.is_declaration_; trailing_comma_ = other.trailing_comma_; diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index 1ff485d894..34f5fff812 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -27,9 +27,8 @@ namespace panda::es2panda::ir { Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, ArenaAllocator *const allocator) - : AnnotatedExpression(static_cast(other)), decorators_(allocator->Adapter()) + : AnnotatedExpression(static_cast(other), allocator), decorators_(allocator->Adapter()) { - CloneTypeAnnotation(allocator); name_ = other.name_; flags_ = other.flags_; variable_ = other.variable_; diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index c5e6218895..d39f3695ac 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -46,12 +46,10 @@ namespace panda::es2panda::ir { ObjectExpression::ObjectExpression([[maybe_unused]] Tag const tag, ObjectExpression const &other, ArenaAllocator *const allocator) - : AnnotatedExpression(static_cast(other)), + : AnnotatedExpression(static_cast(other), allocator), decorators_(allocator->Adapter()), properties_(allocator->Adapter()) { - CloneTypeAnnotation(allocator); - preferred_type_ = other.preferred_type_; is_declaration_ = other.is_declaration_; trailing_comma_ = other.trailing_comma_; diff --git a/ets2panda/ir/statement.cpp b/ets2panda/ir/statement.cpp index 4bec779748..6fcc672337 100644 --- a/ets2panda/ir/statement.cpp +++ b/ets2panda/ir/statement.cpp @@ -17,11 +17,4 @@ #include "typeNode.h" namespace panda::es2panda::ir { -void AnnotatedStatement::CloneTypeAnnotation(ArenaAllocator *const allocator) -{ - if (auto *annotation = const_cast(TypeAnnotation()); annotation != nullptr) { - SetTsTypeAnnotation(annotation->Clone(allocator, this)); - } -} - } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/statement.h b/ets2panda/ir/statement.h index c1004f771c..bc98848eaa 100644 --- a/ets2panda/ir/statement.h +++ b/ets2panda/ir/statement.h @@ -80,8 +80,6 @@ protected: : Annotated(static_cast const &>(other)) { } - - void CloneTypeAnnotation(ArenaAllocator *allocator); }; } // namespace panda::es2panda::ir diff --git a/ets2panda/test/runtime/ets/lambdaExpressionWithRestParameter.ets b/ets2panda/test/runtime/ets/lambdaExpressionWithRestParameter.ets new file mode 100644 index 0000000000..b6f03111fa --- /dev/null +++ b/ets2panda/test/runtime/ets/lambdaExpressionWithRestParameter.ets @@ -0,0 +1,36 @@ +/* + * 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 LambdaType = (prefix: string, ...args: string[]) => string; + + +function main(): void { + + let lam: LambdaType = (prefix: string, ...args: string[]): string => { + let ret = prefix; + for (let arg of args) { + ret += arg; + } + return ret; + } + + let x: string = lam("Test 1:", " case 1,", " case 2,", " case 3."); + assert (x == "Test 1: case 1, case 2, case 3."); + + let arr: string[] = [" case 4,", " case 5,", " case 6."]; + + let y = lam("Test 2:", ...arr); + assert (y == "Test 2: case 4, case 5, case 6."); +} diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt index 8ca4924b09..d348c96b6c 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -22,9 +22,6 @@ unboxing.ets # panda#11326 GenericsTest.ets -# panda#11106 -LongLiteralLimits.ets - # panda#11327 objectEquality.ets @@ -33,4 +30,4 @@ CastReference3.ets conditionalExpressionGenericLUB.ets # Failed due to lambda captures -trailing-lambda-with-capture.ets \ No newline at end of file +trailing-lambda-with-capture.ets -- Gitee From e86005543d5e53edc23d947c2f13f5acaa1aa9c9 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Tue, 31 Oct 2023 21:38:04 +0300 Subject: [PATCH 12/12] Loadable plugins for es2panda Description: minimal C interface for loadable plugins, intended to support Koala. Issue: #I8I1XN Test: ninja es2panda-plugin-test Signed-off-by: Georgy Bronnikov --- ets2panda/BUILD.gn | 2 + ets2panda/CMakeLists.txt | 2 + ets2panda/aot/main.cpp | 23 +- ets2panda/checker/checker.h | 2 +- ets2panda/compiler/core/compilerImpl.cpp | 39 +- ets2panda/compiler/core/compilerImpl.h | 19 +- ets2panda/compiler/lowering/checkerPhase.cpp | 4 +- ets2panda/compiler/lowering/checkerPhase.h | 7 +- .../lowering/ets/generateDeclarations.cpp | 9 +- .../lowering/ets/generateDeclarations.h | 7 +- .../compiler/lowering/ets/opAssignment.cpp | 17 +- .../compiler/lowering/ets/opAssignment.h | 6 +- .../compiler/lowering/ets/unionLowering.cpp | 17 +- .../compiler/lowering/ets/unionLowering.h | 6 +- ets2panda/compiler/lowering/phase.cpp | 31 +- ets2panda/compiler/lowering/phase.h | 13 +- ets2panda/compiler/lowering/plugin_phase.cpp | 38 + ets2panda/compiler/lowering/plugin_phase.h | 47 + ets2panda/compiler/lowering/util.cpp | 4 + ets2panda/es2panda.cpp | 9 +- ets2panda/es2panda.h | 9 + ets2panda/ir/astNode.h | 6 + ets2panda/ir/base/classDefinition.h | 15 + ets2panda/ir/base/classElement.h | 10 + ets2panda/ir/base/methodDefinition.h | 10 + ets2panda/ir/base/spreadElement.h | 12 +- ets2panda/ir/ets/etsFunctionType.h | 5 + .../ir/ets/etsNewArrayInstanceExpression.h | 20 + .../etsNewMultiDimArrayInstanceExpression.h | 20 + ets2panda/ir/ets/etsStructDeclaration.h | 5 + ets2panda/ir/expressions/arrayExpression.h | 11 +- .../ir/expressions/assignmentExpression.h | 2 +- ets2panda/ir/expressions/identifier.h | 10 + ets2panda/ir/expressions/importExpression.h | 5 + ets2panda/ir/expressions/objectExpression.h | 11 +- ets2panda/ir/statements/classDeclaration.h | 5 + ets2panda/ir/statements/variableDeclaration.h | 5 + ets2panda/ir/ts/tsEnumDeclaration.h | 5 + ets2panda/ir/ts/tsInterfaceDeclaration.h | 5 + ets2panda/ir/ts/tsTypeAliasDeclaration.h | 5 + ets2panda/ir/ts/tsTypeParameterDeclaration.h | 10 +- ets2panda/parser/ETSparser.h | 3 +- ets2panda/parser/parserImpl.h | 2 +- ets2panda/public/es2panda_lib.cpp | 2258 ++++++++++++++++- ets2panda/public/es2panda_lib.h | 378 ++- ets2panda/public/public.h | 65 + ets2panda/test/CMakeLists.txt | 16 +- ets2panda/test/unit/public/e2p_test_plugin.c | 57 + .../test/unit/public/es2panda_public_test.cpp | 47 +- .../test/unit/public/plugin_test.expected.txt | 16 + ets2panda/test/unit/public/t.ets | 20 + ets2panda/util/options.cpp | 27 +- ets2panda/util/plugin.cpp | 55 + ets2panda/util/plugin.h | 87 + 54 files changed, 3360 insertions(+), 159 deletions(-) create mode 100644 ets2panda/compiler/lowering/plugin_phase.cpp create mode 100644 ets2panda/compiler/lowering/plugin_phase.h create mode 100644 ets2panda/public/public.h create mode 100644 ets2panda/test/unit/public/e2p_test_plugin.c create mode 100644 ets2panda/test/unit/public/plugin_test.expected.txt create mode 100644 ets2panda/test/unit/public/t.ets create mode 100644 ets2panda/util/plugin.cpp create mode 100644 ets2panda/util/plugin.h diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 6a29659a5f..39d208eac5 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -158,6 +158,7 @@ libes2panda_sources = [ "compiler/lowering/ets/opAssignment.cpp", "compiler/lowering/ets/unionLowering.cpp", "compiler/lowering/phase.cpp", + "compiler/lowering/plugin_phase.cpp", "compiler/lowering/util.cpp", "es2panda.cpp", "ir/as/namedType.cpp", @@ -343,6 +344,7 @@ libes2panda_sources = [ "util/bitset.cpp", "util/declgenEts2Ts.cpp", "util/helpers.cpp", + "util/plugin.cpp", "util/ustring.cpp", "varbinder/ASBinder.cpp", "varbinder/ETSBinder.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 463ac9740c..45978a26fe 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -135,6 +135,7 @@ set(ES2PANDA_LIB_SRC compiler/function/generatorFunctionBuilder.cpp compiler/lowering/checkerPhase.cpp compiler/lowering/phase.cpp + compiler/lowering/plugin_phase.cpp compiler/lowering/util.cpp compiler/lowering/ets/generateDeclarations.cpp compiler/lowering/ets/opAssignment.cpp @@ -461,6 +462,7 @@ set(ES2PANDA_PUBLIC_SOURCES public/es2panda_lib.cpp util/generateBin.cpp util/options.cpp + util/plugin.cpp ) diff --git a/ets2panda/aot/main.cpp b/ets2panda/aot/main.cpp index cfe42af479..cb4969c6ea 100644 --- a/ets2panda/aot/main.cpp +++ b/ets2panda/aot/main.cpp @@ -22,9 +22,11 @@ #include "util/arktsconfig.h" #include "util/generateBin.h" #include "util/options.h" +#include "util/plugin.h" #include #include +#include namespace panda::es2panda::aot { using mem::MemConfig; @@ -106,6 +108,21 @@ static int CompileFromConfig(es2panda::Compiler &compiler, util::Options *option return overall_res; } +static std::optional> InitializePlugins(std::vector const &names) +{ + std::vector res; + for (auto &name : names) { + auto plugin = util::Plugin(util::StringView {name}); + if (!plugin.IsOk()) { + std::cerr << "Error: Failed to load plugin " << name << std::endl; + return {}; + } + plugin.Initialize(); + res.push_back(std::move(plugin)); + } + return {std::move(res)}; +} + static int Run(int argc, const char **argv) { auto options = std::make_unique(); @@ -118,7 +135,11 @@ static int Run(int argc, const char **argv) Logger::ComponentMask mask {}; mask.set(Logger::Component::ES2PANDA); Logger::InitializeStdLogging(Logger::LevelFromString(options->LogLevel()), mask); - es2panda::Compiler compiler(options->Extension(), options->ThreadCount()); + auto plugins_opt = InitializePlugins(options->CompilerOptions().plugins); + if (!plugins_opt.has_value()) { + return 1; + } + es2panda::Compiler compiler(options->Extension(), options->ThreadCount(), std::move(plugins_opt.value())); if (options->CompilerOptions().compilation_mode == CompilationMode::PROJECT) { return CompileFromConfig(compiler, options.get()); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index 5113779226..d411772aa9 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -70,7 +70,7 @@ using ArgRange = std::pair; class Checker { public: explicit Checker(); - ~Checker() = default; + virtual ~Checker() = default; NO_COPY_SEMANTIC(Checker); NO_MOVE_SEMANTIC(Checker); diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 858ca20a05..31f07dcbf9 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -15,6 +15,7 @@ #include "compilerImpl.h" +#include "es2panda.h" #include "compiler/core/compilerContext.h" #include "compiler/core/compileQueue.h" #include "compiler/core/compilerImpl.h" @@ -41,7 +42,7 @@ #include "checker/ETSchecker.h" #include "checker/ASchecker.h" #include "checker/JSchecker.h" -#include "es2panda.h" +#include "public/public.h" #include "util/declgenEts2Ts.h" namespace panda::es2panda::compiler { @@ -86,13 +87,28 @@ static CompilerContext::CodeGenCb MakeCompileJob() }; } +static void SetupPublicContext(public_lib::Context *context, const SourceFile *source_file, ArenaAllocator *allocator, + CompileQueue *queue, std::vector const *plugins, + parser::ParserImpl *parser, CompilerContext *compiler_context) +{ + context->source_file = source_file; + context->allocator = allocator; + context->queue = queue; + context->plugins = plugins; + context->parser = parser; + context->checker = compiler_context->Checker(); + context->analyzer = context->checker->GetAnalyzer(); + context->compiler_context = compiler_context; + context->emitter = compiler_context->GetEmitter(); +} + using EmitCb = std::function; using PhaseListGetter = std::function()>; template static pandasm::Program *CreateCompiler(const CompilationUnit &unit, const PhaseListGetter &get_phases, - const EmitCb &emit_cb) + CompilerImpl *compiler_impl) { ArenaAllocator allocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); auto program = parser::Program::NewProgram(&allocator); @@ -111,53 +127,54 @@ static pandasm::Program *CreateCompiler(const CompilationUnit &unit, const Phase auto emitter = Emitter(&context); context.SetEmitter(&emitter); - context.SetParser(&parser); + public_lib::Context public_context; + SetupPublicContext(&public_context, &unit.input, &allocator, compiler_impl->Queue(), &compiler_impl->Plugins(), + &parser, &context); + parser.ParseScript(unit.input, unit.options.compilation_mode == CompilationMode::GEN_STD_LIB); if constexpr (std::is_same_v && std::is_same_v) { reinterpret_cast(varbinder)->FillResolvedImportPathes(parser.ResolvedParsedSourcesMap(), &allocator); } for (auto *phase : get_phases()) { - if (!phase->Apply(&context, &program)) { + if (!phase->Apply(&public_context, &program)) { return nullptr; } } emitter.GenAnnotation(); - return emit_cb(&context); + return compiler_impl->Emit(&context); } pandasm::Program *CompilerImpl::Compile(const CompilationUnit &unit) { - auto emit_cb = [this](CompilerContext *context) -> pandasm::Program * { return Emit(context); }; - switch (unit.ext) { case ScriptExtension::TS: { return CreateCompiler(unit, compiler::GetTrivialPhaseList, - emit_cb); + this); } case ScriptExtension::AS: { return CreateCompiler(unit, compiler::GetTrivialPhaseList, - emit_cb); + this); } case ScriptExtension::ETS: { return CreateCompiler(unit, compiler::GetETSPhaseList, - emit_cb); + this); } case ScriptExtension::JS: { return CreateCompiler(unit, compiler::GetTrivialPhaseList, - emit_cb); + this); } default: { UNREACHABLE(); diff --git a/ets2panda/compiler/core/compilerImpl.h b/ets2panda/compiler/core/compilerImpl.h index cee0090c00..9ed854e539 100644 --- a/ets2panda/compiler/core/compilerImpl.h +++ b/ets2panda/compiler/core/compilerImpl.h @@ -49,20 +49,35 @@ public: class CompilerImpl { public: - explicit CompilerImpl(size_t thread_count) : queue_(thread_count) {} + explicit CompilerImpl(size_t thread_count, std::vector const *plugins) + : queue_(thread_count), plugins_(plugins) + { + } NO_COPY_SEMANTIC(CompilerImpl); NO_MOVE_SEMANTIC(CompilerImpl); ~CompilerImpl() = default; pandasm::Program *Compile(const CompilationUnit &unit); + std::vector const &Plugins() + { + return *plugins_; + } + static void DumpAsm(const panda::pandasm::Program *prog); -private: panda::pandasm::Program *Emit(CompilerContext *context); + + CompileQueue *Queue() + { + return &queue_; + } + +private: static void HandleContextLiterals(CompilerContext *context); CompileQueue queue_; + std::vector const *plugins_; }; } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/checkerPhase.cpp b/ets2panda/compiler/lowering/checkerPhase.cpp index a6c865ca83..9d9c741087 100644 --- a/ets2panda/compiler/lowering/checkerPhase.cpp +++ b/ets2panda/compiler/lowering/checkerPhase.cpp @@ -18,9 +18,9 @@ #include "compiler/core/compilerContext.h" namespace panda::es2panda::compiler { -bool CheckerPhase::Perform(CompilerContext *ctx, [[maybe_unused]] parser::Program *program) +bool CheckerPhase::Perform(public_lib::Context *ctx, [[maybe_unused]] parser::Program *program) { - return ctx->Checker()->StartChecker(ctx->VarBinder(), *ctx->Options()); + return ctx->checker->StartChecker(ctx->compiler_context->VarBinder(), *ctx->compiler_context->Options()); } } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/checkerPhase.h b/ets2panda/compiler/lowering/checkerPhase.h index 86e0db579b..ef42e7004b 100644 --- a/ets2panda/compiler/lowering/checkerPhase.h +++ b/ets2panda/compiler/lowering/checkerPhase.h @@ -20,13 +20,12 @@ namespace panda::es2panda::compiler { class CheckerPhase : public Phase { - std::string const &Name() override + std::string_view Name() override { - static std::string const NAME = "checker"; - return NAME; + return "checker"; } - bool Perform(CompilerContext *ctx, parser::Program *program) override; + bool Perform(public_lib::Context *ctx, parser::Program *program) override; }; } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/generateDeclarations.cpp b/ets2panda/compiler/lowering/ets/generateDeclarations.cpp index 41393a607b..96472eae50 100644 --- a/ets2panda/compiler/lowering/ets/generateDeclarations.cpp +++ b/ets2panda/compiler/lowering/ets/generateDeclarations.cpp @@ -19,11 +19,12 @@ #include "util/declgenEts2Ts.h" namespace panda::es2panda::compiler { -bool GenerateTsDeclarationsPhase::Perform(CompilerContext *ctx, parser::Program *program) +bool GenerateTsDeclarationsPhase::Perform(public_lib::Context *ctx, parser::Program *program) { - auto *checker = ctx->Checker(); - return (ctx->Options()->ts_decl_out.empty() || - util::GenerateTsDeclarations(checker->AsETSChecker(), program, ctx->Options()->ts_decl_out)); + auto *checker = ctx->checker; + return ( + ctx->compiler_context->Options()->ts_decl_out.empty() || + util::GenerateTsDeclarations(checker->AsETSChecker(), program, ctx->compiler_context->Options()->ts_decl_out)); } } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/generateDeclarations.h b/ets2panda/compiler/lowering/ets/generateDeclarations.h index fb7fcea3fd..15ab3c61ef 100644 --- a/ets2panda/compiler/lowering/ets/generateDeclarations.h +++ b/ets2panda/compiler/lowering/ets/generateDeclarations.h @@ -22,12 +22,11 @@ namespace panda::es2panda::compiler { class GenerateTsDeclarationsPhase : public Phase { public: - std::string const &Name() override + std::string_view Name() override { - static std::string const NAME = "generate-ts-declarations"; - return NAME; + return "generate-ts-declarations"; } - bool Perform(CompilerContext *ctx, parser::Program *program) override; + bool Perform(public_lib::Context *ctx, parser::Program *program) override; }; } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index b886773d14..aaea5422ca 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -37,10 +37,9 @@ namespace panda::es2panda::compiler { -std::string const &OpAssignmentLowering::Name() +std::string_view OpAssignmentLowering::Name() { - static std::string const NAME = "op-assignment"; - return NAME; + return "op-assignment"; } struct Conversion { @@ -209,9 +208,9 @@ ir::Expression *HandleOpAssignment(checker::ETSChecker *checker, parser::ETSPars return lowering_result; } -bool OpAssignmentLowering::Perform(CompilerContext *ctx, parser::Program *program) +bool OpAssignmentLowering::Perform(public_lib::Context *ctx, parser::Program *program) { - if (ctx->Options()->compilation_mode == CompilationMode::GEN_STD_LIB) { + if (ctx->compiler_context->Options()->compilation_mode == CompilationMode::GEN_STD_LIB) { for (auto &[_, ext_programs] : program->ExternalSources()) { (void)_; for (auto *ext_prog : ext_programs) { @@ -220,8 +219,8 @@ bool OpAssignmentLowering::Perform(CompilerContext *ctx, parser::Program *progra } } - auto *const checker = ctx->Checker()->AsETSChecker(); - auto *const parser = ctx->GetParser()->AsETSParser(); + auto *const parser = ctx->parser->AsETSParser(); + checker::ETSChecker *checker = ctx->checker->AsETSChecker(); program->Ast()->TransformChildrenRecursively([checker, parser](ir::AstNode *ast) -> ir::AstNode * { if (ast->IsAssignmentExpression() && @@ -235,9 +234,9 @@ bool OpAssignmentLowering::Perform(CompilerContext *ctx, parser::Program *progra return true; } -bool OpAssignmentLowering::Postcondition(CompilerContext *ctx, const parser::Program *program) +bool OpAssignmentLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program) { - if (ctx->Options()->compilation_mode == CompilationMode::GEN_STD_LIB) { + if (ctx->compiler_context->Options()->compilation_mode == CompilationMode::GEN_STD_LIB) { for (auto &[_, ext_programs] : program->ExternalSources()) { (void)_; for (auto *ext_prog : ext_programs) { diff --git a/ets2panda/compiler/lowering/ets/opAssignment.h b/ets2panda/compiler/lowering/ets/opAssignment.h index b3c8dbd789..407d558a2e 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.h +++ b/ets2panda/compiler/lowering/ets/opAssignment.h @@ -22,9 +22,9 @@ namespace panda::es2panda::compiler { class OpAssignmentLowering : public Phase { public: - std::string const &Name() override; - bool Perform(CompilerContext *ctx, parser::Program *program) override; - bool Postcondition(CompilerContext *ctx, const parser::Program *program) override; + 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 diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index fbe3ea2305..c9e0335ac9 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -37,10 +37,9 @@ namespace panda::es2panda::compiler { -std::string const &UnionLowering::Name() +std::string_view UnionLowering::Name() { - static std::string const NAME = "union-property-access"; - return NAME; + return "union-property-access"; } ir::ClassDefinition *GetUnionFieldClass(checker::ETSChecker *checker, varbinder::VarBinder *varbinder) @@ -370,7 +369,7 @@ ir::BlockStatement *HandleBlockWithBinaryAndUnions(checker::ETSChecker *checker, return modified_ast_block; } -bool UnionLowering::Perform(CompilerContext *ctx, parser::Program *program) +bool UnionLowering::Perform(public_lib::Context *ctx, parser::Program *program) { for (auto &[_, ext_programs] : program->ExternalSources()) { (void)_; @@ -379,12 +378,12 @@ bool UnionLowering::Perform(CompilerContext *ctx, parser::Program *program) } } - checker::ETSChecker *checker = ctx->Checker()->AsETSChecker(); + checker::ETSChecker *checker = ctx->checker->AsETSChecker(); - program->Ast()->TransformChildrenRecursively([checker, ctx](ir::AstNode *ast) -> ir::AstNode * { + program->Ast()->TransformChildrenRecursively([checker](ir::AstNode *ast) -> ir::AstNode * { if (ast->IsMemberExpression() && ast->AsMemberExpression()->Object()->TsType() != nullptr && ast->AsMemberExpression()->Object()->TsType()->IsETSUnionType()) { - HandleUnionPropertyAccess(checker, ctx->VarBinder(), ast->AsMemberExpression()); + HandleUnionPropertyAccess(checker, checker->VarBinder(), ast->AsMemberExpression()); return ast; } @@ -409,14 +408,14 @@ bool UnionLowering::Perform(CompilerContext *ctx, parser::Program *program) return true; } -bool UnionLowering::Postcondition(CompilerContext *ctx, const parser::Program *program) +bool UnionLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program) { bool current = !program->Ast()->IsAnyChild([](const ir::AstNode *ast) { return ast->IsMemberExpression() && ast->AsMemberExpression()->Object()->TsType() != nullptr && ast->AsMemberExpression()->Object()->TsType()->IsETSUnionType() && ast->AsMemberExpression()->PropVar() == nullptr; }); - if (!current || ctx->Options()->compilation_mode != CompilationMode::GEN_STD_LIB) { + if (!current || ctx->compiler_context->Options()->compilation_mode != CompilationMode::GEN_STD_LIB) { return current; } diff --git a/ets2panda/compiler/lowering/ets/unionLowering.h b/ets2panda/compiler/lowering/ets/unionLowering.h index c8a4b49a90..efc0bf6bff 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.h +++ b/ets2panda/compiler/lowering/ets/unionLowering.h @@ -22,9 +22,9 @@ namespace panda::es2panda::compiler { class UnionLowering : public Phase { public: - std::string const &Name() override; - bool Perform(CompilerContext *ctx, parser::Program *program) override; - bool Postcondition(CompilerContext *ctx, const parser::Program *program) override; + 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 diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index f3b2ff83a6..19035aec00 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -19,9 +19,11 @@ #include "compiler/core/compilerContext.h" #include "lexer/token/sourceLocation.h" #include "compiler/lowering/checkerPhase.h" +#include "compiler/lowering/plugin_phase.h" #include "compiler/lowering/ets/generateDeclarations.h" #include "compiler/lowering/ets/opAssignment.h" #include "compiler/lowering/ets/unionLowering.h" +#include "public/es2panda_lib.h" namespace panda::es2panda::compiler { @@ -37,25 +39,28 @@ std::vector GetTrivialPhaseList() static GenerateTsDeclarationsPhase GENERATE_TS_DECLARATIONS_PHASE; static OpAssignmentLowering OP_ASSIGNMENT_LOWERING; 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}; +static PluginPhase PLUGINS_AFTER_LOWERINGS {"plugins-after-lowering", ES2PANDA_STATE_LOWERED, + &util::Plugin::AfterLowerings}; std::vector GetETSPhaseList() { return std::vector { - &CHECKER_PHASE, - &GENERATE_TS_DECLARATIONS_PHASE, - &OP_ASSIGNMENT_LOWERING, - &UNION_LOWERING, + &PLUGINS_AFTER_PARSE, &CHECKER_PHASE, &PLUGINS_AFTER_CHECK, &GENERATE_TS_DECLARATIONS_PHASE, + &OP_ASSIGNMENT_LOWERING, &UNION_LOWERING, &PLUGINS_AFTER_LOWERINGS, }; } -bool Phase::Apply(CompilerContext *ctx, parser::Program *program) +bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) { - const auto *options = ctx->Options(); - if (options->skip_phases.count(Name()) > 0) { + const auto *options = ctx->compiler_context->Options(); + const auto name = std::string {Name()}; + if (options->skip_phases.count(name) > 0) { return true; } - if (options->dump_before_phases.count(Name()) > 0) { + if (options->dump_before_phases.count(name) > 0) { std::cout << "Before phase " << Name() << ":" << std::endl; std::cout << program->Dump() << std::endl; } @@ -66,8 +71,8 @@ bool Phase::Apply(CompilerContext *ctx, parser::Program *program) // NOTE(tatiana): Add some error processing } if (!Precondition(ctx, program)) { - ctx->Checker()->ThrowTypeError({"Precondition check failed for ", util::StringView {Name()}}, - lexer::SourcePosition {}); + ctx->checker->ThrowTypeError({"Precondition check failed for ", util::StringView {Name()}}, + lexer::SourcePosition {}); } #endif @@ -75,7 +80,7 @@ bool Phase::Apply(CompilerContext *ctx, parser::Program *program) return false; } - if (options->dump_after_phases.count(Name()) > 0) { + if (options->dump_after_phases.count(name) > 0) { std::cout << "After phase " << Name() << ":" << std::endl; std::cout << program->Dump() << std::endl; } @@ -86,8 +91,8 @@ bool Phase::Apply(CompilerContext *ctx, parser::Program *program) // NOTE(tatiana): Add some error processing } if (!Postcondition(ctx, program)) { - ctx->Checker()->ThrowTypeError({"Postcondition check failed for ", util::StringView {Name()}}, - lexer::SourcePosition {}); + ctx->checker->ThrowTypeError({"Postcondition check failed for ", util::StringView {Name()}}, + lexer::SourcePosition {}); } #endif diff --git a/ets2panda/compiler/lowering/phase.h b/ets2panda/compiler/lowering/phase.h index 490c2fac13..d64ed04e4c 100644 --- a/ets2panda/compiler/lowering/phase.h +++ b/ets2panda/compiler/lowering/phase.h @@ -17,22 +17,25 @@ #define ES2PANDA_COMPILER_LOWERING_PHASE_H #include "parser/program/program.h" +#include "public/public.h" namespace panda::es2panda::compiler { class Phase { public: /* If Apply returns false, processing is stopped. */ - bool Apply(CompilerContext *ctx, parser::Program *program); + bool Apply(public_lib::Context *ctx, parser::Program *program); - virtual std::string const &Name() = 0; + virtual std::string_view Name() = 0; - virtual bool Precondition([[maybe_unused]] CompilerContext *ctx, [[maybe_unused]] const parser::Program *program) + virtual bool Precondition([[maybe_unused]] public_lib::Context *ctx, + [[maybe_unused]] const parser::Program *program) { return true; } - virtual bool Perform(CompilerContext *ctx, parser::Program *program) = 0; - virtual bool Postcondition([[maybe_unused]] CompilerContext *ctx, [[maybe_unused]] const parser::Program *program) + virtual bool Perform(public_lib::Context *ctx, parser::Program *program) = 0; + virtual bool Postcondition([[maybe_unused]] public_lib::Context *ctx, + [[maybe_unused]] const parser::Program *program) { return true; } diff --git a/ets2panda/compiler/lowering/plugin_phase.cpp b/ets2panda/compiler/lowering/plugin_phase.cpp new file mode 100644 index 0000000000..35fa31a61b --- /dev/null +++ b/ets2panda/compiler/lowering/plugin_phase.cpp @@ -0,0 +1,38 @@ +/** + * 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 "plugin_phase.h" + +namespace panda::es2panda::compiler { + +bool PluginPhase::Perform(public_lib::Context *ctx, [[maybe_unused]] parser::Program *program) +{ + ctx->state = context_state_; + + if (ctx->plugins == nullptr) { + return true; + } + + for (auto &plugin : *(ctx->plugins)) { + (plugin.*method_call_)(reinterpret_cast(ctx)); + if (ctx->state == ES2PANDA_STATE_ERROR) { + ctx->checker->ThrowTypeError(ctx->error_message, ctx->error_pos); + } + } + + return true; +} + +} // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/plugin_phase.h b/ets2panda/compiler/lowering/plugin_phase.h new file mode 100644 index 0000000000..4cff33ec06 --- /dev/null +++ b/ets2panda/compiler/lowering/plugin_phase.h @@ -0,0 +1,47 @@ +/** + * 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_PLUGIN_PHASE_H +#define ES2PANDA_COMPILER_PLUGIN_PHASE_H + +#include "compiler/lowering/phase.h" +#include "util/plugin.h" + +namespace panda::es2panda::compiler { + +class PluginPhase : public Phase { +public: + constexpr PluginPhase(char const *name, es2panda_ContextState context_state, + void (util::Plugin::*method_call)(es2panda_Context *) const) noexcept + : name_(name), context_state_(context_state), method_call_(method_call) + { + } + + std::string_view Name() override + { + return name_; + } + + bool Perform(public_lib::Context *ctx, parser::Program *program) override; + +private: + char const *name_; + es2panda_ContextState context_state_; + void (util::Plugin::*method_call_)(es2panda_Context *) const; +}; + +} // namespace panda::es2panda::compiler + +#endif diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index ed4d02de65..faa56e75c0 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -23,6 +23,10 @@ namespace panda::es2panda::compiler { varbinder::Scope *NearestScope(const ir::AstNode *ast) { + if (ast == nullptr) { + return nullptr; + } + while (!ast->IsScopeBearer()) { ast = ast->Parent(); ASSERT(ast != nullptr); diff --git a/ets2panda/es2panda.cpp b/ets2panda/es2panda.cpp index 458f00dd7b..4b7051f93d 100644 --- a/ets2panda/es2panda.cpp +++ b/ets2panda/es2panda.cpp @@ -16,6 +16,7 @@ #include "es2panda.h" #include "compiler/core/compilerImpl.h" +#include "util/options.h" #include #include @@ -56,10 +57,12 @@ SourceFile::SourceFile(std::string_view fn, std::string_view s, std::string_view { } -Compiler::Compiler(ScriptExtension ext) : Compiler(ext, DEFAULT_THREAD_COUNT) {} +Compiler::Compiler(ScriptExtension ext) : Compiler(ext, DEFAULT_THREAD_COUNT, {}) {} -Compiler::Compiler(ScriptExtension ext, size_t thread_count) - : compiler_(new compiler::CompilerImpl(thread_count)), ext_(ext) +Compiler::Compiler(ScriptExtension ext, size_t thread_count) : Compiler(ext, thread_count, {}) {} + +Compiler::Compiler(ScriptExtension ext, size_t thread_count, std::vector &&plugins) + : plugins_(std::move(plugins)), compiler_(new compiler::CompilerImpl(thread_count, &plugins_)), ext_(ext) { } diff --git a/ets2panda/es2panda.h b/ets2panda/es2panda.h index bd23a328c2..78ccfc73c5 100644 --- a/ets2panda/es2panda.h +++ b/ets2panda/es2panda.h @@ -18,6 +18,7 @@ #include "macros.h" #include "util/arktsconfig.h" +#include "util/plugin.h" #include "util/ustring.h" #include @@ -100,6 +101,7 @@ struct CompilerOptions { bool parse_only {}; std::string std_lib {}; std::string ts_decl_out {}; + std::vector plugins {}; std::unordered_set skip_phases {}; std::unordered_set dump_before_phases {}; std::unordered_set dump_after_phases {}; @@ -192,6 +194,7 @@ class Compiler { public: explicit Compiler(ScriptExtension ext); explicit Compiler(ScriptExtension ext, size_t thread_count); + explicit Compiler(ScriptExtension ext, size_t thread_count, std::vector &&plugins); ~Compiler(); NO_COPY_SEMANTIC(Compiler); NO_MOVE_SEMANTIC(Compiler); @@ -212,7 +215,13 @@ public: return error_; } + std::vector const &Plugins() + { + return plugins_; + } + private: + std::vector const plugins_; compiler::CompilerImpl *compiler_; Error error_; ScriptExtension ext_; diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 9e948ee8aa..52ae35ba71 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -263,6 +263,12 @@ public: variable_ = variable; } + // When no decorators are allowed, we cannot return a reference to an empty vector. + virtual const ArenaVector *DecoratorsPtr() const + { + return nullptr; + } + virtual void AddDecorators([[maybe_unused]] ArenaVector &&decorators) { UNREACHABLE(); diff --git a/ets2panda/ir/base/classDefinition.h b/ets2panda/ir/base/classDefinition.h index b952989226..9b4fca1959 100644 --- a/ets2panda/ir/base/classDefinition.h +++ b/ets2panda/ir/base/classDefinition.h @@ -150,6 +150,11 @@ public: return super_class_; } + void SetSuper(Expression *super_class) + { + super_class_ = super_class; + } + [[nodiscard]] bool IsGlobal() const noexcept { return (modifiers_ & ClassDefinitionModifiers::GLOBAL) != 0; @@ -214,6 +219,11 @@ public: return ctor_; } + void SetCtor(MethodDefinition *ctor) + { + ctor_ = ctor; + } + [[nodiscard]] ArenaVector &Implements() noexcept { return implements_; @@ -234,6 +244,11 @@ public: return type_params_; } + void SetTypeParams(ir::TSTypeParameterDeclaration *type_params) + { + type_params_ = type_params; + } + const FunctionExpression *Ctor() const; bool HasPrivateMethod() const; bool HasComputedInstanceField() const; diff --git a/ets2panda/ir/base/classElement.h b/ets2panda/ir/base/classElement.h index 034f63036d..7589b3d407 100644 --- a/ets2panda/ir/base/classElement.h +++ b/ets2panda/ir/base/classElement.h @@ -70,6 +70,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + [[nodiscard]] bool IsComputed() const noexcept { return is_computed_; @@ -87,6 +92,11 @@ public: } } + bool CanHaveDecorator([[maybe_unused]] bool in_ts) const override + { + return true; + } + [[nodiscard]] virtual PrivateFieldKind ToPrivateFieldKind(bool is_static) const = 0; protected: diff --git a/ets2panda/ir/base/methodDefinition.h b/ets2panda/ir/base/methodDefinition.h index 761e19374f..059301a44d 100644 --- a/ets2panda/ir/base/methodDefinition.h +++ b/ets2panda/ir/base/methodDefinition.h @@ -63,6 +63,16 @@ public: return kind_ == MethodDefinitionKind::EXTENSION_METHOD; } + Expression const *Key() const + { + return key_; + } + + Expression const *Value() const + { + return value_; + } + [[nodiscard]] const ArenaVector &Overloads() const noexcept { return overloads_; diff --git a/ets2panda/ir/base/spreadElement.h b/ets2panda/ir/base/spreadElement.h index 11ef4991fb..d3c047434e 100644 --- a/ets2panda/ir/base/spreadElement.h +++ b/ets2panda/ir/base/spreadElement.h @@ -58,12 +58,22 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators(ArenaVector &&decorators) override { decorators_ = std::move(decorators); } - void SetOptional(bool const optional) noexcept + bool CanHaveDecorator([[maybe_unused]] bool in_ts) const override + { + return true; + } + + void SetOptional(bool optional) noexcept { optional_ = optional; } diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index 62c59ffd9f..d832384893 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -80,6 +80,11 @@ public: functional_interface_ = functional_interface; } + ir::ScriptFunctionFlags Flags() + { + return func_flags_; + } + bool IsThrowing() const { return (func_flags_ & ir::ScriptFunctionFlags::THROWS) != 0; diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index 9cafcc56e8..3528a7646a 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -35,6 +35,26 @@ public: { } + ir::TypeNode *TypeReference() + { + return type_reference_; + } + + ir::TypeNode const *TypeReference() const + { + return type_reference_; + } + + ir::Expression *Dimension() + { + return dimension_; + } + + ir::Expression const *Dimension() const + { + return dimension_; + } + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ETSNewArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 2ee2a3d4d4..d758b3427d 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -43,6 +43,26 @@ public: explicit ETSNewMultiDimArrayInstanceExpression(ETSNewMultiDimArrayInstanceExpression const &other, ArenaAllocator *allocator); + ir::TypeNode *TypeReference() + { + return type_reference_; + } + + ir::TypeNode const *TypeReference() const + { + return type_reference_; + } + + ArenaVector &Dimensions() + { + return dimensions_; + } + + ArenaVector const &Dimension() const + { + return dimensions_; + } + [[nodiscard]] checker::Signature *Signature() noexcept { return signature_; diff --git a/ets2panda/ir/ets/etsStructDeclaration.h b/ets2panda/ir/ets/etsStructDeclaration.h index 2368350de7..5824d5a4c7 100644 --- a/ets2panda/ir/ets/etsStructDeclaration.h +++ b/ets2panda/ir/ets/etsStructDeclaration.h @@ -47,6 +47,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators(ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index bbe3c830fd..85a3fedbf0 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -93,17 +93,26 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); } + bool CanHaveDecorator([[maybe_unused]] bool in_ts) const override + { + return true; + } + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ArrayExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; [[nodiscard]] bool ConvertibleToArrayPattern(); [[nodiscard]] ValidationInfo ValidateExpression(); - 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/expressions/assignmentExpression.h b/ets2panda/ir/expressions/assignmentExpression.h index bebc40be2a..dc1542c4b4 100644 --- a/ets2panda/ir/expressions/assignmentExpression.h +++ b/ets2panda/ir/expressions/assignmentExpression.h @@ -80,7 +80,7 @@ public: return operator_; } - [[nodiscard]] lexer::TokenType SetOperatorType(lexer::TokenType token_type) noexcept + lexer::TokenType SetOperatorType(lexer::TokenType token_type) noexcept { return operator_ = token_type; } diff --git a/ets2panda/ir/expressions/identifier.h b/ets2panda/ir/expressions/identifier.h index 5cfa53c9c2..2d3e4394a8 100644 --- a/ets2panda/ir/expressions/identifier.h +++ b/ets2panda/ir/expressions/identifier.h @@ -83,6 +83,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + [[nodiscard]] bool IsOptional() const noexcept { return (flags_ & IdentifierFlags::OPTIONAL) != 0; @@ -188,6 +193,11 @@ public: // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] Identifier *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + bool CanHaveDecorator([[maybe_unused]] bool in_ts) const override + { + return true; + } + [[nodiscard]] ValidationInfo ValidateExpression(); void TransformChildren(const NodeTransformer &cb) override; diff --git a/ets2panda/ir/expressions/importExpression.h b/ets2panda/ir/expressions/importExpression.h index 884e3dbc29..5b37ae04ee 100644 --- a/ets2panda/ir/expressions/importExpression.h +++ b/ets2panda/ir/expressions/importExpression.h @@ -29,6 +29,11 @@ public: explicit ImportExpression(Expression *source) : Expression(AstNodeType::IMPORT_EXPRESSION), source_(source) {} + Expression *Source() + { + return source_; + } + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ImportExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; diff --git a/ets2panda/ir/expressions/objectExpression.h b/ets2panda/ir/expressions/objectExpression.h index 70121771fe..3499814cca 100644 --- a/ets2panda/ir/expressions/objectExpression.h +++ b/ets2panda/ir/expressions/objectExpression.h @@ -77,17 +77,26 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); } + bool CanHaveDecorator([[maybe_unused]] bool in_ts) const override + { + return true; + } + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ObjectExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; [[nodiscard]] ValidationInfo ValidateExpression(); [[nodiscard]] bool ConvertibleToObjectPattern(); - void SetDeclaration(); void SetOptional(bool optional); void TransformChildren(const NodeTransformer &cb) override; diff --git a/ets2panda/ir/statements/classDeclaration.h b/ets2panda/ir/statements/classDeclaration.h index 8984cf0651..41d4bb4f6c 100644 --- a/ets2panda/ir/statements/classDeclaration.h +++ b/ets2panda/ir/statements/classDeclaration.h @@ -41,6 +41,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators(ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/statements/variableDeclaration.h b/ets2panda/ir/statements/variableDeclaration.h index 601170366b..fac991570d 100644 --- a/ets2panda/ir/statements/variableDeclaration.h +++ b/ets2panda/ir/statements/variableDeclaration.h @@ -55,6 +55,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/ts/tsEnumDeclaration.h b/ets2panda/ir/ts/tsEnumDeclaration.h index d6d318a62b..3380a13e4a 100644 --- a/ets2panda/ir/ts/tsEnumDeclaration.h +++ b/ets2panda/ir/ts/tsEnumDeclaration.h @@ -89,6 +89,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/ts/tsInterfaceDeclaration.h b/ets2panda/ir/ts/tsInterfaceDeclaration.h index e209324087..9ede275089 100644 --- a/ets2panda/ir/ts/tsInterfaceDeclaration.h +++ b/ets2panda/ir/ts/tsInterfaceDeclaration.h @@ -120,6 +120,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/ts/tsTypeAliasDeclaration.h b/ets2panda/ir/ts/tsTypeAliasDeclaration.h index 5dc000528a..77061cb112 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.h +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.h @@ -72,6 +72,11 @@ public: return decorators_; } + const ArenaVector *DecoratorsPtr() const override + { + return &Decorators(); + } + void AddTypeParameters(ir::TSTypeParameterDeclaration *type_params) { type_params_ = type_params; diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.h b/ets2panda/ir/ts/tsTypeParameterDeclaration.h index 6e203679ad..0d9b263eba 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.h +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.h @@ -18,9 +18,9 @@ #include "varbinder/scope.h" #include "ir/expression.h" +#include "ir/ts/tsTypeParameter.h" namespace panda::es2panda::ir { -class TSTypeParameter; class TSTypeParameterDeclaration : public Expression { public: @@ -48,6 +48,14 @@ public: return params_; } + void AddParam(TSTypeParameter *param) + { + if (required_params_ == params_.size() && param->DefaultType() == nullptr) { + required_params_++; + } + params_.push_back(param); + } + size_t RequiredParams() const { return required_params_; diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index a2716bef27..e75558299c 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -51,7 +51,8 @@ public: ETSParser() = delete; NO_COPY_SEMANTIC(ETSParser); NO_MOVE_SEMANTIC(ETSParser); - ~ETSParser() = default; + + ~ETSParser() final = default; [[nodiscard]] bool IsETSParser() const noexcept override { diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index 5d0c578d0e..8247313c80 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -177,7 +177,7 @@ public: explicit ParserImpl(Program *program, const CompilerOptions &options, ParserStatus status = ParserStatus::NO_OPTS); NO_COPY_SEMANTIC(ParserImpl); NO_MOVE_SEMANTIC(ParserImpl); - ~ParserImpl() = default; + virtual ~ParserImpl() = default; void ParseScript(const SourceFile &source_file, bool gen_std_lib); diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 6a19d98166..469b5348f1 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -16,6 +16,10 @@ #include "es2panda_lib.h" #include +#include "varbinder/varbinder.h" +#include "varbinder/scope.h" +#include "varbinder/variable.h" +#include "public/public.h" #include "generated/signatures.h" #include "es2panda.h" #include "assembler/assembly-program.h" @@ -28,39 +32,221 @@ #include "compiler/core/ETSGen.h" #include "compiler/core/regSpiller.h" #include "compiler/lowering/phase.h" +#include "compiler/lowering/util.h" #include "ir/astNode.h" +#include "ir/expressions/arrowFunctionExpression.h" +#include "ir/ts/tsAsExpression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/binaryExpression.h" +#include "ir/statements/blockStatement.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/chainExpression.h" +#include "ir/statements/classDeclaration.h" +#include "ir/base/classDefinition.h" +#include "ir/base/classElement.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/base/classProperty.h" +#include "ir/statements/expressionStatement.h" +#include "ir/statements/functionDeclaration.h" +#include "ir/expressions/functionExpression.h" +#include "ir/ets/etsFunctionType.h" #include "ir/expressions/identifier.h" +#include "ir/statements/ifStatement.h" +#include "ir/module/importDeclaration.h" +#include "ir/expressions/importExpression.h" +#include "ir/module/importSpecifier.h" +#include "ir/base/methodDefinition.h" +#include "ir/ets/etsNewClassInstanceExpression.h" +#include "ir/ets/etsNewArrayInstanceExpression.h" +#include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" +#include "ir/expressions/thisExpression.h" +#include "ir/ts/tsTypeParameter.h" +#include "ir/ts/tsTypeParameterDeclaration.h" +#include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/statements/variableDeclaration.h" +#include "ir/statements/variableDeclarator.h" #include "parser/ETSparser.h" #include "parser/context/parserContext.h" #include "parser/program/program.h" #include "util/generateBin.h" +#include "util/language.h" #include "util/options.h" namespace panda::es2panda::public_lib { -struct ConfigImpl { - std::unique_ptr options; -}; -struct Context { - ConfigImpl *config = nullptr; - std::string source_file_name; - std::string input; - std::unique_ptr source_file; - std::unique_ptr allocator; - std::unique_ptr queue; - - std::unique_ptr parser_program; - std::unique_ptr parser; - std::unique_ptr checker; - std::unique_ptr analyzer; - std::unique_ptr compiler_context; - std::unique_ptr emitter; - std::unique_ptr program; - - es2panda_ContextState state = ES2PANDA_STATE_NEW; - std::string error_message; +struct TokenTypeToStr { + lexer::TokenType token; + char const *str; }; +static lexer::TokenType StrToToken(TokenTypeToStr const *table, char const *str) +{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + for (auto *tp = table; tp->str != nullptr; tp++) { + if (strcmp(str, tp->str) == 0) { + return tp->token; + } + } + UNREACHABLE(); +} + +static char const *TokenToStr(TokenTypeToStr const *table, lexer::TokenType token) +{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + for (auto *tp = table; tp->str != nullptr; tp++) { + if (tp->token == token) { + return tp->str; + } + } + UNREACHABLE(); +} + +static char const *StringViewToCString(ArenaAllocator *allocator, util::StringView const sv) +{ + // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) + std::string_view utf8 = sv.Utf8(); + if (utf8.data()[utf8.size()] == '\0') { + // Avoid superfluous allocation. + return utf8.data(); + } + char *res = reinterpret_cast(allocator->Alloc(utf8.size() + 1)); + memmove(res, utf8.cbegin(), utf8.size()); + res[utf8.size()] = '\0'; + return res; + // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) +} + +static char const *ArenaStrdup(ArenaAllocator *allocator, char const *src) +{ + size_t len = strlen(src); + char *res = reinterpret_cast(allocator->Alloc(len + 1)); + memmove(res, src, len); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + res[len] = '\0'; + return res; +} + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FOR_ALL_MODIFIER_FLAGS(_) \ + _(STATIC) \ + _(ASYNC) \ + _(PUBLIC) \ + _(PROTECTED) \ + _(PRIVATE) \ + _(DECLARE) \ + _(READONLY) \ + _(OPTIONAL) \ + _(DEFINITE) \ + _(ABSTRACT) \ + _(CONST) \ + _(FINAL) \ + _(NATIVE) \ + _(OVERRIDE) \ + _(CONSTRUCTOR) \ + _(SYNCHRONIZED) \ + _(FUNCTIONAL) \ + _(IN) \ + _(OUT) \ + _(INTERNAL) \ + _(NULL_ASSIGNABLE) \ + _(UNDEFINED_ASSIGNABLE) \ + _(EXPORT) \ + _(SETTER) \ + _(DEFAULT_EXPORT) + +static ir::ModifierFlags E2pToIrModifierFlags(es2panda_ModifierFlags e2p_flags) +{ + ir::ModifierFlags ir_flags {ir::ModifierFlags::NONE}; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DO_FLAG(FL) \ + if ((e2p_flags & ES2PANDA_MODIFIER_##FL) != 0) { \ + ir_flags |= ir::ModifierFlags::FL; \ + } + + FOR_ALL_MODIFIER_FLAGS(DO_FLAG) + +#undef DO_FLAG + + return ir_flags; +} + +static es2panda_ModifierFlags IrToE2pModifierFlags(ir::ModifierFlags ir_flags) +{ + es2panda_ModifierFlags e2p_flags {ES2PANDA_MODIFIER_NONE}; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DO_FLAG(FL) \ + if ((ir_flags & ir::ModifierFlags::FL) != 0) { \ + e2p_flags = static_cast(e2p_flags | ES2PANDA_MODIFIER_##FL); \ + } + + FOR_ALL_MODIFIER_FLAGS(DO_FLAG) + +#undef DO_FLAG + + return e2p_flags; +} + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FOR_ALL_SCRIPT_FUNCTION_FLAGS(_) \ + _(GENERATOR) \ + _(ASYNC) \ + _(ARROW) \ + _(EXPRESSION) \ + _(OVERLOAD) \ + _(CONSTRUCTOR) \ + _(METHOD) \ + _(STATIC_BLOCK) \ + _(HIDDEN) \ + _(IMPLICIT_SUPER_CALL_NEEDED) \ + _(ENUM) \ + _(EXTERNAL) \ + _(PROXY) \ + _(THROWS) \ + _(RETHROWS) \ + _(GETTER) \ + _(SETTER) \ + _(DEFAULT_PARAM_PROXY) \ + _(ENTRY_POINT) \ + _(INSTANCE_EXTENSION_METHOD) \ + _(HAS_RETURN) + +static ir::ScriptFunctionFlags E2pToIrScriptFunctionFlags(es2panda_ScriptFunctionFlags e2p_flags) +{ + ir::ScriptFunctionFlags ir_flags {ir::ScriptFunctionFlags::NONE}; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DO_FLAG(FL) \ + if ((e2p_flags & ES2PANDA_SCRIPT_FUNCTION_##FL) != 0) { \ + ir_flags |= ir::ScriptFunctionFlags::FL; \ + } + + FOR_ALL_SCRIPT_FUNCTION_FLAGS(DO_FLAG) + +#undef DO_FLAG + + return ir_flags; +} + +static es2panda_ScriptFunctionFlags IrToE2pScriptFunctionFlags(ir::ScriptFunctionFlags ir_flags) +{ + es2panda_ScriptFunctionFlags e2p_flags {ES2PANDA_SCRIPT_FUNCTION_NONE}; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DO_FLAG(FL) \ + if ((ir_flags & ir::ScriptFunctionFlags::FL) != 0) { \ + e2p_flags = static_cast(e2p_flags | ES2PANDA_SCRIPT_FUNCTION_##FL); \ + } + + FOR_ALL_SCRIPT_FUNCTION_FLAGS(DO_FLAG) + +#undef DO_FLAG + + return e2p_flags; +} + extern "C" es2panda_Config *CreateConfig(int args, char const **argv) { constexpr auto COMPILER_SIZE = 256_MB; @@ -68,7 +254,7 @@ extern "C" es2panda_Config *CreateConfig(int args, char const **argv) mem::MemConfig::Initialize(0, 0, COMPILER_SIZE, 0, 0, 0); PoolManager::Initialize(PoolType::MMAP); - auto options = std::make_unique(); + auto *options = new util::Options(); if (!options->Parse(args, argv)) { // NOTE: gogabr. report option errors properly. std::cerr << options->ErrorMsg() << std::endl; @@ -79,7 +265,7 @@ extern "C" es2panda_Config *CreateConfig(int args, char const **argv) Logger::InitializeStdLogging(Logger::LevelFromString(options->LogLevel()), mask); auto *res = new ConfigImpl; - res->options = std::move(options); + res->options = options; return reinterpret_cast(res); } @@ -88,7 +274,10 @@ extern "C" void DestroyConfig(es2panda_Config *config) PoolManager::Finalize(); mem::MemConfig::Finalize(); - delete reinterpret_cast(config); + auto *cfg = reinterpret_cast(config); + + delete cfg->options; + delete cfg; } static void CompileJob(compiler::CompilerContext *context, varbinder::FunctionScope *scope, @@ -107,32 +296,33 @@ static es2panda_Context *CreateContext(es2panda_Config *config, std::string cons { auto *cfg = reinterpret_cast(config); auto *res = new Context; - res->config = cfg; res->input = source; res->source_file_name = file_name; try { - res->source_file = std::make_unique(res->source_file_name, res->input, cfg->options->ParseModule()); - res->allocator = std::make_unique(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); - res->queue = std::make_unique(cfg->options->ThreadCount()); + res->source_file = new SourceFile(res->source_file_name, res->input, cfg->options->ParseModule()); + res->allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + res->queue = new compiler::CompileQueue(cfg->options->ThreadCount()); - auto *varbinder = res->allocator->New(res->allocator.get()); - res->parser_program = std::make_unique(res->allocator.get(), varbinder); + auto *varbinder = res->allocator->New(res->allocator); + res->parser_program = new parser::Program(res->allocator, varbinder); res->parser_program->MarkEntry(); - res->parser = std::make_unique(res->parser_program.get(), cfg->options->CompilerOptions(), - parser::ParserStatus::NO_OPTS); - res->checker = std::make_unique(); - res->analyzer = std::make_unique(res->checker.get()); - res->checker->SetAnalyzer(res->analyzer.get()); - - varbinder->SetProgram(res->parser_program.get()); - - res->compiler_context = std::make_unique( - varbinder, res->checker.get(), cfg->options->CompilerOptions(), CompileJob); - varbinder->SetCompilerContext(res->compiler_context.get()); - res->emitter = std::make_unique(res->compiler_context.get()); - res->compiler_context->SetEmitter(res->emitter.get()); - res->compiler_context->SetParser(res->parser.get()); + res->parser = + new parser::ETSParser(res->parser_program, cfg->options->CompilerOptions(), parser::ParserStatus::NO_OPTS); + res->checker = new checker::ETSChecker(); + res->analyzer = new checker::ETSAnalyzer(res->checker); + res->checker->SetAnalyzer(res->analyzer); + + varbinder->SetProgram(res->parser_program); + + res->compiler_context = + new compiler::CompilerContext(varbinder, res->checker, cfg->options->CompilerOptions(), CompileJob); + varbinder->SetCompilerContext(res->compiler_context); + res->phases = compiler::GetETSPhaseList(); + res->current_phase = 0; + res->emitter = new compiler::ETSEmitter(res->compiler_context); + res->compiler_context->SetEmitter(res->emitter); + res->compiler_context->SetParser(res->parser); res->program = nullptr; res->state = ES2PANDA_STATE_NEW; } catch (Error &e) { @@ -152,7 +342,7 @@ extern "C" es2panda_Context *CreateContextFromFile(es2panda_Config *config, char auto *res = new Context; res->error_message = "Failed to open file: "; res->error_message.append(source_file_name); - return reinterpret_cast(res); + return reinterpret_cast(res); } std::stringstream ss; ss << input_stream.rdbuf(); @@ -160,7 +350,7 @@ extern "C" es2panda_Context *CreateContextFromFile(es2panda_Config *config, char auto *res = new Context; res->error_message = "Failed to read file: "; res->error_message.append(source_file_name); - return reinterpret_cast(res); + return reinterpret_cast(res); } return CreateContext(config, ss.str(), source_file_name); } @@ -179,8 +369,9 @@ static Context *Parse(Context *ctx) return ctx; } try { - ctx->parser->ParseScript(*ctx->source_file, ctx->config->options->CompilerOptions().compilation_mode == - CompilationMode::GEN_STD_LIB); + ctx->parser->ParseScript(*ctx->source_file, + ctx->compiler_context->Options()->compilation_mode == CompilationMode::GEN_STD_LIB); + ctx->parser_program = ctx->compiler_context->VarBinder()->Program(); ctx->state = ES2PANDA_STATE_PARSED; } catch (Error &e) { std::stringstream ss; @@ -205,8 +396,13 @@ static Context *Check(Context *ctx) ASSERT(ctx->state == ES2PANDA_STATE_PARSED); try { - ctx->compiler_context->Checker()->StartChecker(ctx->compiler_context->VarBinder(), - ctx->config->options->CompilerOptions()); + do { + if (ctx->current_phase >= ctx->phases.size()) { + break; + } + + ctx->phases[ctx->current_phase]->Apply(ctx, ctx->parser_program); + } while (ctx->phases[ctx->current_phase++]->Name() != "checker"); ctx->state = ES2PANDA_STATE_CHECKED; } catch (Error &e) { std::stringstream ss; @@ -230,8 +426,8 @@ static Context *Lower(Context *ctx) ASSERT(ctx->state == ES2PANDA_STATE_CHECKED); try { - for (auto *phase : compiler::GetETSPhaseList()) { - phase->Apply(ctx->compiler_context.get(), ctx->compiler_context->VarBinder()->Program()); + while (ctx->current_phase < ctx->phases.size()) { + ctx->phases[ctx->current_phase++]->Apply(ctx, ctx->parser_program); } ctx->state = ES2PANDA_STATE_LOWERED; @@ -270,13 +466,12 @@ static Context *GenerateAsm(Context *ctx) emitter->LiteralBufferIndex() += ctx->compiler_context->ContextLiterals().size(); /* Main thread can also be used instead of idling */ - ctx->queue->Schedule(ctx->compiler_context.get()); + ctx->queue->Schedule(ctx->compiler_context); ctx->queue->Consume(); ctx->queue->Wait( [emitter](compiler::CompileJob *job) { emitter->AddProgramElement(job->GetProgramElement()); }); ASSERT(ctx->program == nullptr); - ctx->program = std::unique_ptr { - emitter->Finalize(ctx->compiler_context->DumpDebugInfo(), compiler::Signatures::ETS_GLOBAL)}; + ctx->program = emitter->Finalize(ctx->compiler_context->DumpDebugInfo(), compiler::Signatures::ETS_GLOBAL); ctx->state = ES2PANDA_STATE_ASM_GENERATED; } catch (Error &e) { @@ -302,7 +497,7 @@ Context *GenerateBin(Context *ctx) try { ASSERT(ctx->program != nullptr); - util::GenerateProgram(ctx->program.get(), ctx->config->options.get(), + util::GenerateProgram(ctx->program, ctx->config->options, [ctx](const std::string &str) { ctx->error_message = str; }); ctx->state = ES2PANDA_STATE_BIN_GENERATED; @@ -346,8 +541,18 @@ extern "C" es2panda_Context *ProceedToState(es2panda_Context *context, es2panda_ extern "C" void DestroyContext(es2panda_Context *context) { - auto *s = reinterpret_cast(context); - delete s; + auto *ctx = reinterpret_cast(context); + delete ctx->program; + delete ctx->emitter; + delete ctx->compiler_context; + delete ctx->analyzer; + delete ctx->checker; + delete ctx->parser; + delete ctx->parser_program; + delete ctx->queue; + delete ctx->allocator; + delete ctx->source_file; + delete ctx; } extern "C" es2panda_ContextState ContextState(es2panda_Context *context) @@ -362,13 +567,1942 @@ extern "C" char const *ContextErrorMessage(es2panda_Context *context) return s->error_message.c_str(); } -es2panda_Impl IMPL = {ES2PANDA_LIB_VERSION, +extern "C" es2panda_Program *ContextProgram(es2panda_Context *context) +{ + auto *ctx = reinterpret_cast(context); + return reinterpret_cast(ctx->compiler_context->VarBinder()->Program()); +} + +extern "C" es2panda_AstNode *ProgramAst(es2panda_Program *program) +{ + auto *pgm = reinterpret_cast(program); + return reinterpret_cast(pgm->Ast()); +} + +using ExternalSourceEntry = std::pair *>; + +extern "C" es2panda_ExternalSource **ProgramExternalSources(es2panda_Program *program, size_t *len_p) +{ + auto *pgm = reinterpret_cast(program); + auto *allocator = pgm->VarBinder()->Allocator(); + auto *vec = allocator->New>(allocator->Adapter()); + + for (auto &[e_name, e_programs] : pgm->ExternalSources()) { + vec->push_back(allocator->New(StringViewToCString(allocator, e_name), &e_programs)); + } + + *len_p = vec->size(); + return reinterpret_cast(vec->data()); +} + +extern "C" char const *ExternalSourceName(es2panda_ExternalSource *e_source) +{ + auto *entry = reinterpret_cast(e_source); + return entry->first; +} + +extern "C" es2panda_Program **ExternalSourcePrograms(es2panda_ExternalSource *e_source, size_t *len_p) +{ + auto *entry = reinterpret_cast(e_source); + *len_p = entry->second->size(); + return reinterpret_cast(entry->second->data()); +} + +extern "C" es2panda_Type *AstNodeType(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast); + // Need to work with other TypeAstNodes + if (node->IsExpression()) { + return reinterpret_cast(node->AsExpression()->TsType()); + } + return nullptr; +} + +extern "C" es2panda_AstNode *const *AstNodeDecorators(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast); + if (node->CanHaveDecorator(false)) { + auto *decorators = node->DecoratorsPtr(); + *size_p = decorators->size(); + return reinterpret_cast(decorators->data()); + } + *size_p = 0; + return nullptr; +} + +extern "C" es2panda_ModifierFlags AstNodeModifierFlags(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast); + return IrToE2pModifierFlags(node->Modifiers()); +} + +extern "C" void AstNodeSetDecorators(es2panda_Context *context, es2panda_AstNode *ast, es2panda_AstNode **decorators, + size_t n_decorators) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *node = reinterpret_cast(ast); + + ArenaVector decorators_vector {allocator->Adapter()}; + for (size_t i = 0; i < n_decorators; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + decorators_vector.push_back(reinterpret_cast(decorators[i])->AsDecorator()); + } + node->AddDecorators(std::move(decorators_vector)); +} + +extern "C" void AstNodeSetType(es2panda_AstNode *ast, es2panda_Type *type) +{ + auto *node = reinterpret_cast(ast); + auto *tp = reinterpret_cast(type); + // Need to work with other TypedAstNodes + if (node->IsExpression()) { + node->AsExpression()->SetTsType(tp); + } else { + UNREACHABLE(); + } +} + +extern "C" void AstNodeForEach(es2panda_AstNode *ast, void (*func)(es2panda_AstNode *, void *), void *arg) +{ + auto *node = reinterpret_cast(ast); + func(ast, arg); + node->IterateRecursively([=](ir::AstNode *child) { func(reinterpret_cast(child), arg); }); +} + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define IS(public_name, e2p_name) \ + extern "C" bool Is##public_name(es2panda_AstNode *ast) \ + { \ + auto *node = reinterpret_cast(ast); \ + return node->Is##e2p_name(); \ + } + +IS(ArrowFunctionExpression, ArrowFunctionExpression) +IS(AsExpression, TSAsExpression) +IS(AssignmentExpression, AssignmentExpression) +IS(BinaryExpression, BinaryExpression) +IS(BlockStatement, BlockStatement) +IS(CallExpression, CallExpression) +IS(ChainExpression, ChainExpression) +IS(ClassDeclaration, ClassDeclaration) +IS(ClassDefinition, ClassDefinition) +IS(ClassImplementsClause, TSClassImplements) +IS(ClassProperty, ClassProperty) +IS(ExpressionStatement, ExpressionStatement) +IS(FunctionDeclaration, FunctionDeclaration) +IS(FunctionExpression, FunctionExpression) +IS(FunctionTypeNode, TSFunctionType) +IS(Identifier, Identifier) +IS(IfStatement, IfStatement) +IS(ImportDeclaration, ImportDeclaration) +IS(ImportExpression, ImportExpression) +IS(ImportSpecifier, ImportSpecifier) +IS(MemberExpression, MemberExpression) +IS(MethodDefinition, MethodDefinition) +IS(NewClassInstanceExpression, ETSNewClassInstanceExpression) +IS(NewArrayInstanceExpression, ETSNewArrayInstanceExpression) +IS(NewMultiDimArrayInstanceExpression, ETSNewMultiDimArrayInstanceExpression) +IS(NonNullExpression, TSNonNullExpression) +IS(NumberLiteral, NumberLiteral) +IS(ObjectExpression, ObjectExpression) +IS(ParameterDeclaration, ETSParameterExpression) +IS(PrimitiveTypeNode, ETSPrimitiveType) +IS(ReturnStatement, ReturnStatement) +IS(ScriptFunction, ScriptFunction) +IS(StringLiteral, StringLiteral) +IS(ThisExpression, ThisExpression) +IS(TypeParameter, TSTypeParameter) +IS(TypeParameterDeclaration, TSTypeParameterDeclaration) +IS(TypeParameterInstantiation, TSTypeParameterInstantiation) +IS(TypeReferenceNode, ETSTypeReference) +IS(TypeReferencePart, ETSTypeReferencePart) +IS(UnionTypeNode, TSUnionType) +IS(VariableDeclaration, VariableDeclaration) +IS(VariableDeclarator, VariableDeclarator) + +#undef IS + +extern "C" es2panda_AstNode *CreateArrowFunctionExpression(es2panda_Context *context, es2panda_AstNode *script_function) +{ + auto *ctx = reinterpret_cast(context); + auto *func = reinterpret_cast(script_function)->AsScriptFunction(); + auto *allocator = ctx->allocator; + + return reinterpret_cast(allocator->New(allocator, func)); +} + +extern "C" es2panda_AstNode *ArrowFunctionExpressionScriptFunction(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsArrowFunctionExpression(); + return reinterpret_cast(node->Function()); +} + +extern "C" es2panda_AstNode *CreateAsExpression(es2panda_Context *context, es2panda_AstNode *expr, + es2panda_AstNode *type_annotation, bool is_const) +{ + auto *ctx = reinterpret_cast(context); + auto *left_expr = reinterpret_cast(expr)->AsExpression(); + auto *tp = reinterpret_cast(type_annotation)->AsExpression()->AsTypeNode(); + auto *allocator = ctx->allocator; + + return reinterpret_cast(allocator->New(left_expr, tp, is_const)); +} + +extern "C" es2panda_AstNode *AsExpressionExpr(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsTSAsExpression(); + return reinterpret_cast(node->Expr()); +} + +extern "C" es2panda_AstNode *AsExpressionTypeAnnotation(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsTSAsExpression(); + return reinterpret_cast(node->Type()); +} + +extern "C" bool AsExpressionIsConst(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsTSAsExpression(); + return node->IsConst(); +} + +extern "C" void AsExpressionSetExpr(es2panda_AstNode *ast, es2panda_AstNode *expr) +{ + auto *node = reinterpret_cast(ast)->AsTSAsExpression(); + auto *new_expr = reinterpret_cast(expr)->AsExpression(); + node->SetExpr(new_expr); +} + +extern "C" void AsExpressionSetTypeAnnotation(es2panda_AstNode *ast, es2panda_AstNode *type_annotation) +{ + auto *node = reinterpret_cast(ast)->AsTSAsExpression(); + auto *tp = reinterpret_cast(type_annotation)->AsExpression()->AsTypeNode(); + node->SetTsTypeAnnotation(tp); +} + +static constexpr std::array ASSIGNMENT_TOKEN_TYPES { + {{lexer::TokenType::PUNCTUATOR_SUBSTITUTION, "="}, + {lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL, ">>>="}, + {lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL, ">>="}, + {lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL, "<<="}, + {lexer::TokenType::PUNCTUATOR_PLUS_EQUAL, "+="}, + {lexer::TokenType::PUNCTUATOR_MINUS_EQUAL, "-="}, + {lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL, "*="}, + {lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL, "/="}, + {lexer::TokenType::PUNCTUATOR_MOD_EQUAL, "%="}, + {lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL, "&="}, + {lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL, "|="}, + {lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL, "^="}, + {lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL, "&&="}, + {lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL, "||="}, + {lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL, "\?\?="}, + {lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL, "**="}, + {lexer::TokenType::EOS, nullptr}}}; + +extern "C" es2panda_AstNode *CreateAssignmentExpression(es2panda_Context *context, es2panda_AstNode *left, + es2panda_AstNode *right, char const *operator_type) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *left_node = reinterpret_cast(left)->AsExpression(); + auto *right_node = reinterpret_cast(right)->AsExpression(); + lexer::TokenType tok = StrToToken(ASSIGNMENT_TOKEN_TYPES.data(), operator_type); + return reinterpret_cast(allocator->New(left_node, right_node, tok)); +} + +extern "C" es2panda_AstNode *AssignmentExpressionLeft(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsAssignmentExpression(); + return reinterpret_cast(node->Left()); +} + +extern "C" es2panda_AstNode *AssignmentExpressionRight(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsAssignmentExpression(); + return reinterpret_cast(node->Right()); +} + +extern "C" char const *AssignmentExpressionOperatorType(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsAssignmentExpression(); + return TokenToStr(ASSIGNMENT_TOKEN_TYPES.data(), node->OperatorType()); +} + +extern "C" void AssignmentExpressionSetOperatorType(es2panda_AstNode *ast, char const *operator_type) +{ + auto *node = reinterpret_cast(ast)->AsAssignmentExpression(); + auto tok = StrToToken(ASSIGNMENT_TOKEN_TYPES.data(), operator_type); + node->SetOperatorType(tok); +} + +static constexpr std::array BINARY_OP_TOKEN_TYPES { + {{lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT, ">>>"}, + {lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT, ">>"}, + {lexer::TokenType::PUNCTUATOR_LEFT_SHIFT, "<<"}, + {lexer::TokenType::PUNCTUATOR_PLUS, "+"}, + {lexer::TokenType::PUNCTUATOR_MINUS, "-"}, + {lexer::TokenType::PUNCTUATOR_MULTIPLY, "*"}, + {lexer::TokenType::PUNCTUATOR_DIVIDE, "/"}, + {lexer::TokenType::PUNCTUATOR_MOD, "%"}, + {lexer::TokenType::PUNCTUATOR_BITWISE_AND, "&"}, + {lexer::TokenType::PUNCTUATOR_BITWISE_OR, "|"}, + {lexer::TokenType::PUNCTUATOR_BITWISE_XOR, "^"}, + {lexer::TokenType::PUNCTUATOR_LOGICAL_AND, "&&"}, + {lexer::TokenType::PUNCTUATOR_LOGICAL_OR, "||"}, + {lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING, "??"}, + {lexer::TokenType::PUNCTUATOR_EXPONENTIATION, "**"}, + {lexer::TokenType::PUNCTUATOR_EQUAL, "=="}, + {lexer::TokenType::PUNCTUATOR_NOT_EQUAL, "/="}, + {lexer::TokenType::PUNCTUATOR_STRICT_EQUAL, "==="}, + {lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, "/=="}, + {lexer::TokenType::PUNCTUATOR_LESS_THAN, "<"}, + {lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL, "<="}, + {lexer::TokenType::PUNCTUATOR_GREATER_THAN, ">"}, + {lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL, ">="}, + {lexer::TokenType::KEYW_IN, "in"}, + {lexer::TokenType::KEYW_INSTANCEOF, "instanceof"}, + {lexer::TokenType::EOS, nullptr}}}; + +extern "C" es2panda_AstNode *CreateBinaryExpression(es2panda_Context *context, es2panda_AstNode *left, + es2panda_AstNode *right, char const *operator_type) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *left_expr = reinterpret_cast(left)->AsExpression(); + auto *right_expr = reinterpret_cast(right)->AsExpression(); + auto tok = StrToToken(BINARY_OP_TOKEN_TYPES.data(), operator_type); + + return reinterpret_cast(allocator->New(left_expr, right_expr, tok)); +} + +extern "C" es2panda_AstNode *BinaryExpressionLeft(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsBinaryExpression(); + return reinterpret_cast(node->Left()); +} + +extern "C" es2panda_AstNode *BinaryExpressionRight(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsBinaryExpression(); + return reinterpret_cast(node->Right()); +} + +extern "C" char const *BinaryExpressionOperator(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsBinaryExpression(); + return TokenToStr(BINARY_OP_TOKEN_TYPES.data(), node->OperatorType()); +} + +extern "C" void BinaryExpressionSetOperator(es2panda_AstNode *ast, char const *operator_type) +{ + auto *node = reinterpret_cast(ast)->AsBinaryExpression(); + auto op = StrToToken(BINARY_OP_TOKEN_TYPES.data(), operator_type); + node->SetOperator(op); +} + +extern "C" es2panda_AstNode *CreateBlockStatement(es2panda_Context *context, es2panda_AstNode *in_scope_of) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *parent = reinterpret_cast(in_scope_of); + auto *parent_scope = compiler::NearestScope(parent); + + auto *scope = allocator->New(allocator, parent_scope); + ArenaVector stmts {allocator->Adapter()}; + return reinterpret_cast(allocator->New(allocator, scope, std::move(stmts))); +} + +extern "C" es2panda_AstNode **BlockStatementStatements(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsBlockStatement(); + *size_p = node->Statements().size(); + return reinterpret_cast(node->Statements().data()); +} + +extern "C" void BlockStatementAddStatement(es2panda_AstNode *ast, es2panda_AstNode *statement) +{ + auto *node = reinterpret_cast(ast)->AsBlockStatement(); + auto *stmt = reinterpret_cast(statement)->AsBlockStatement(); + node->Statements().push_back(stmt); +} + +extern "C" es2panda_AstNode *CreateCallExpression(es2panda_Context *context, es2panda_AstNode *callee, + es2panda_AstNode *type_arguments, es2panda_AstNode **arguments, + size_t n_arguments, bool is_optional) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *callee_node = reinterpret_cast(callee)->AsExpression(); + + ir::TSTypeParameterInstantiation *type_args = nullptr; + if (type_arguments != nullptr) { + type_args = reinterpret_cast(type_arguments)->AsTSTypeParameterInstantiation(); + } + + ArenaVector args {allocator->Adapter()}; + for (size_t i = 0; i < n_arguments; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + args.push_back(reinterpret_cast(arguments[i])->AsExpression()); + } + return reinterpret_cast( + allocator->New(callee_node, std::move(args), type_args, is_optional)); +} + +extern "C" es2panda_AstNode const *CallExpressionCallee(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsCallExpression(); + return reinterpret_cast(node->Callee()); +} + +extern "C" es2panda_AstNode const *CallExpressionTypeArguments(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsCallExpression(); + return reinterpret_cast(node->TypeParams()); +} + +extern "C" es2panda_AstNode **CallExpressionArguments(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsCallExpression(); + *size_p = node->Arguments().size(); + return reinterpret_cast(node->Arguments().data()); +} + +extern "C" bool CallExpressionIsOptional(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsCallExpression(); + return node->IsOptional(); +} + +extern "C" void CallExpressionSetTypeArguments(es2panda_AstNode *ast, es2panda_AstNode *type_arguments) +{ + auto *node = reinterpret_cast(ast)->AsCallExpression(); + auto *type_args = reinterpret_cast(type_arguments)->AsTSTypeParameterInstantiation(); + node->SetTypeParams(type_args); +} + +extern "C" es2panda_AstNode *CreateChainExpression(es2panda_Context *context, es2panda_AstNode *child) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *child_expr = reinterpret_cast(child)->AsExpression(); + + return reinterpret_cast(allocator->New(child_expr)); +} + +extern "C" es2panda_AstNode const *ChainExpressionChild(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsChainExpression(); + return reinterpret_cast(node->GetExpression()); +} + +extern "C" es2panda_AstNode *CreateClassDeclaration(es2panda_Context *context, es2panda_AstNode *definition) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *dfn = reinterpret_cast(definition)->AsClassDefinition(); + + return reinterpret_cast(allocator->New(dfn, allocator)); +} + +extern "C" es2panda_AstNode *ClassDeclarationDefinition(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassDeclaration(); + return reinterpret_cast(node->Definition()); +} + +extern "C" es2panda_AstNode *CreateClassDefinition(es2panda_Context *context, es2panda_AstNode *in_scope_of, + es2panda_AstNode *identifier, es2panda_ModifierFlags flags) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *parent = reinterpret_cast(in_scope_of); + auto *parent_scope = compiler::NearestScope(parent); + auto *id = reinterpret_cast(identifier)->AsIdentifier(); + + auto *scope = allocator->New(allocator, parent_scope); + return reinterpret_cast( + allocator->New(allocator, scope, id, ir::ClassDefinitionModifiers::NONE, + E2pToIrModifierFlags(flags), Language::FromString("ets").value())); +} + +extern "C" es2panda_AstNode *ClassDefinitionIdentifier(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + return reinterpret_cast(node->Ident()); +} + +extern "C" es2panda_AstNode *ClassDefinitionTypeParameters(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + return reinterpret_cast(node->TypeParams()); +} + +extern "C" es2panda_AstNode *ClassDefinitionSuperClass(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + return reinterpret_cast(node->Super()); +} + +extern "C" es2panda_AstNode **ClassDefinitionImplements(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto &impl_vec = node->Implements(); + *size_p = impl_vec.size(); + return reinterpret_cast(impl_vec.data()); +} + +extern "C" es2panda_AstNode *ClassDefinitionConstructor(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + return reinterpret_cast(node->Ctor()); +} + +extern "C" es2panda_AstNode **ClassDefinitionBody(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto &body_vec = node->Body(); + *size_p = body_vec.size(); + return reinterpret_cast(body_vec.data()); +} + +extern "C" void ClassDefinitionSetIdentifier(es2panda_AstNode *ast, es2panda_AstNode *identifier) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto *id = reinterpret_cast(identifier)->AsIdentifier(); + node->SetIdent(id); +} + +extern "C" void ClassDefinitionSetTypeParameters(es2panda_AstNode *ast, es2panda_AstNode *type_params) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto *tpd = reinterpret_cast(type_params)->AsTSTypeParameterDeclaration(); + node->SetTypeParams(tpd); +} - CreateConfig, DestroyConfig, +extern "C" void ClassDefinitionSetSuperClass(es2panda_AstNode *ast, es2panda_AstNode *super_class) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto *super = reinterpret_cast(super_class)->AsExpression(); + node->SetSuper(super); +} - CreateContextFromFile, CreateContextFromString, ProceedToState, DestroyContext, +extern "C" void ClassDefinitionSetImplements(es2panda_AstNode *ast, es2panda_AstNode **implements, size_t n_implements) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto &impl_vec = node->Implements(); + impl_vec.resize(0); + for (size_t i = 0; i < n_implements; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + impl_vec.push_back(reinterpret_cast(implements[i])->AsTSClassImplements()); + } +} - ContextState, ContextErrorMessage}; +extern "C" void ClassDefinitionAddImplements(es2panda_AstNode *ast, es2panda_AstNode *implements) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto &impl_vec = node->Implements(); + impl_vec.push_back(reinterpret_cast(implements)->AsTSClassImplements()); +} + +extern "C" void ClassDefinitionSetConstructor(es2panda_AstNode *ast, es2panda_AstNode *constructor) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto *ctor = reinterpret_cast(constructor)->AsMethodDefinition(); + node->SetCtor(ctor); +} + +extern "C" void ClassDefinitionSetBody(es2panda_AstNode *ast, es2panda_AstNode **body, size_t n_elems) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto &body_vec = node->Body(); + body_vec.resize(0); + for (size_t i = 0; i < n_elems; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + body_vec.push_back(reinterpret_cast(body[i])); + } +} + +extern "C" void ClassDefinitionAddToBody(es2panda_AstNode *ast, es2panda_AstNode *body_elem) +{ + auto *node = reinterpret_cast(ast)->AsClassDefinition(); + auto *elem = reinterpret_cast(body_elem); + auto &body_vec = node->Body(); + body_vec.push_back(reinterpret_cast(elem)); +} + +extern "C" es2panda_AstNode *ClassElementKey(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassElement(); + return reinterpret_cast(node->Key()); +} + +extern "C" es2panda_AstNode *ClassElementValue(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassElement(); + return reinterpret_cast(node->Value()); +} + +extern "C" es2panda_AstNode *CreateClassImplementsClause(es2panda_Context *context, es2panda_AstNode *expression, + es2panda_AstNode *type_arguments) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *expr = reinterpret_cast(expression)->AsExpression(); + auto *targs = type_arguments == nullptr + ? nullptr + : reinterpret_cast(type_arguments)->AsTSTypeParameterInstantiation(); + + return reinterpret_cast(allocator->New(expr, targs)); +} + +extern "C" es2panda_AstNode *ClassImplementsClauseExpression(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsTSClassImplements(); + return reinterpret_cast(node->Expr()); +} + +extern "C" es2panda_AstNode const *ClassImplementsClauseTypeArguments(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsTSClassImplements(); + return reinterpret_cast(node->TypeParameters()); +} + +extern "C" es2panda_AstNode *CreateClassProperty(es2panda_Context *context, es2panda_AstNode *key, + es2panda_AstNode *value, es2panda_AstNode *type_annotation, + es2panda_ModifierFlags modifier_flags, bool is_computed) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ekey = reinterpret_cast(key)->AsExpression(); + auto *evalue = value == nullptr ? nullptr : reinterpret_cast(value)->AsExpression(); + auto *tp_ann = type_annotation == nullptr + ? nullptr + : reinterpret_cast(type_annotation)->AsExpression()->AsTypeNode(); + auto modifiers = E2pToIrModifierFlags(modifier_flags); + + return reinterpret_cast( + allocator->New(ekey, evalue, tp_ann, modifiers, allocator, is_computed)); +} + +extern "C" es2panda_AstNode *ClassPropertyTypeAnnotation(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsClassProperty(); + return reinterpret_cast(node->TypeAnnotation()); +} + +extern "C" es2panda_AstNode *CreateExpressionStatement(es2panda_Context *context, es2panda_AstNode *expression) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *expr = reinterpret_cast(expression)->AsExpression(); + + return reinterpret_cast(allocator->New(expr)); +} + +extern "C" es2panda_AstNode *ExpressionStatementExpression(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsExpressionStatement(); + return reinterpret_cast(node->GetExpression()); +} + +extern "C" es2panda_AstNode *CreateFunctionDeclaration(es2panda_Context *context, es2panda_AstNode *function) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *func = reinterpret_cast(function)->AsScriptFunction(); + + return reinterpret_cast(allocator->New(allocator, func)); +} + +extern "C" es2panda_AstNode *FunctionDeclarationFunction(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsFunctionDeclaration(); + return reinterpret_cast(node->Function()); +} + +extern "C" es2panda_AstNode *CreateFunctionExpression(es2panda_Context *context, es2panda_AstNode *function) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *func = reinterpret_cast(function)->AsScriptFunction(); + + return reinterpret_cast(allocator->New(func)); +} + +extern "C" es2panda_AstNode *FunctionExpressionFunction(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsFunctionExpression(); + return reinterpret_cast(node->Function()); +} + +extern "C" es2panda_AstNode *CreateFunctionTypeNode(es2panda_Context *context, es2panda_AstNode *in_scope_of, + es2panda_AstNode *type_params, es2panda_AstNode **params, + size_t n_params, es2panda_AstNode *return_type, + es2panda_ScriptFunctionFlags func_flags) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *parent = reinterpret_cast(in_scope_of); + auto *parent_scope = compiler::NearestScope(parent); + auto *tpar = + type_params == nullptr ? nullptr : reinterpret_cast(type_params)->AsTSTypeParameterDeclaration(); + auto *tret = + return_type == nullptr ? nullptr : reinterpret_cast(return_type)->AsExpression()->AsTypeNode(); + auto flags = E2pToIrScriptFunctionFlags(func_flags); + + auto *scope = allocator->New(allocator, parent_scope); + + ArenaVector par {allocator->Adapter()}; + for (size_t i = 0; i < n_params; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + par.push_back(reinterpret_cast(params[i])->AsExpression()); + } + + return reinterpret_cast( + allocator->New(scope, std::move(par), tpar, tret, flags)); +} + +extern "C" es2panda_AstNode const *FunctionTypeNodeTypeParams(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSFunctionType(); + return reinterpret_cast(node->TypeParams()); +} + +extern "C" es2panda_AstNode *const *FunctionTypeNodeParams(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsETSFunctionType(); + auto ¶ms = node->Params(); + *size_p = params.size(); + return reinterpret_cast(params.data()); +} + +extern "C" es2panda_AstNode *FunctionTypeNodeReturnType(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSFunctionType(); + return reinterpret_cast(node->ReturnType()); +} + +extern "C" es2panda_ScriptFunctionFlags FunctionTypeNodeFlags(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSFunctionType(); + return IrToE2pScriptFunctionFlags(node->Flags()); +} + +extern "C" es2panda_AstNode *CreateIdentifier(es2panda_Context *context, char const *name, + es2panda_AstNode *type_annotations) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *name_copy = ArenaStrdup(ctx->allocator, name); + auto *tp_ann = type_annotations == nullptr + ? nullptr + : reinterpret_cast(type_annotations)->AsExpression()->AsTypeNode(); + + auto *res = allocator->New(util::StringView {name_copy}, tp_ann, allocator); + + return reinterpret_cast(res); +} + +extern "C" char const *IdentifierName(es2panda_Context *context, es2panda_AstNode *identifier) +{ + auto *ctx = reinterpret_cast(context); + auto *id = reinterpret_cast(identifier); + ASSERT(id->IsIdentifier()); + + return StringViewToCString(ctx->allocator, id->AsIdentifier()->Name()); +} + +extern "C" es2panda_AstNode *IdentifierTypeAnnotation(es2panda_AstNode *identifier) +{ + auto *id = reinterpret_cast(identifier)->AsIdentifier(); + return reinterpret_cast(id->TypeAnnotation()); +} + +extern "C" es2panda_Variable *IdentifierVariable(es2panda_AstNode *identifier) +{ + auto *id = reinterpret_cast(identifier)->AsIdentifier(); + + return reinterpret_cast(id->Variable()); +} + +extern "C" void IdentifierSetVariable(es2panda_AstNode *identifier, es2panda_Variable *variable) +{ + auto *id = reinterpret_cast(identifier)->AsIdentifier(); + auto *var = reinterpret_cast(variable); + + id->SetVariable(var); +} + +extern "C" es2panda_AstNode *CreateIfStatement(es2panda_Context *context, es2panda_AstNode *test, + es2panda_AstNode *consequent, es2panda_AstNode *alternate) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *t = reinterpret_cast(test)->AsExpression(); + auto *conseq = reinterpret_cast(consequent)->AsStatement(); + auto *alt = reinterpret_cast(alternate)->AsStatement(); + + return reinterpret_cast(allocator->New(t, conseq, alt)); +} + +extern "C" es2panda_AstNode const *IfStatementTest(es2panda_AstNode *identifier) +{ + auto *if_stat = reinterpret_cast(identifier)->AsIfStatement(); + + return reinterpret_cast(if_stat->Test()); +} + +extern "C" es2panda_AstNode const *IfStatementConsequent(es2panda_AstNode *identifier) +{ + auto *if_stat = reinterpret_cast(identifier)->AsIfStatement(); + + return reinterpret_cast(if_stat->Consequent()); +} + +extern "C" es2panda_AstNode const *IfStatementAlternate(es2panda_AstNode *identifier) +{ + auto *if_stat = reinterpret_cast(identifier)->AsIfStatement(); + + return reinterpret_cast(if_stat->Alternate()); +} + +extern "C" es2panda_AstNode *CreateImportDeclaration(es2panda_Context *context, es2panda_AstNode *source, + es2panda_AstNode **specifiers, size_t n_specifiers) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *src = reinterpret_cast(source)->AsStringLiteral(); + + ArenaVector specs {allocator->Adapter()}; + for (size_t i = 0; i < n_specifiers; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + specs.push_back(reinterpret_cast(specifiers[i])); + } + + return reinterpret_cast(allocator->New(src, std::move(specs))); +} + +extern "C" es2panda_AstNode const *ImportDeclarationSource(es2panda_AstNode *ast) +{ + auto *decl = reinterpret_cast(ast)->AsImportDeclaration(); + + return reinterpret_cast(decl->Source()); +} + +extern "C" es2panda_AstNode *const *ImportDeclarationSpecifiers(es2panda_AstNode *ast, size_t *size_p) +{ + auto *decl = reinterpret_cast(ast)->AsImportDeclaration(); + auto &specs = decl->Specifiers(); + + *size_p = specs.size(); + + return reinterpret_cast(specs.data()); +} + +extern "C" es2panda_AstNode *CreateImportExpression(es2panda_Context *context, es2panda_AstNode *source) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *src = reinterpret_cast(source)->AsExpression(); + + return reinterpret_cast(allocator->New(src)); +} + +extern "C" es2panda_AstNode *ImportExpressionSource(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsImportExpression(); + return reinterpret_cast(node->Source()); +} + +extern "C" es2panda_AstNode *CreateImportSpecifier(es2panda_Context *context, es2panda_AstNode *imported, + es2panda_AstNode *local) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_imported = reinterpret_cast(imported)->AsIdentifier(); + auto *ir_local = reinterpret_cast(local)->AsIdentifier(); + + return reinterpret_cast(allocator->New(ir_imported, ir_local)); +} + +extern "C" es2panda_AstNode *ImportSpecifierImported(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsImportSpecifier(); + return reinterpret_cast(node->Imported()); +} + +extern "C" es2panda_AstNode *ImportSpecifierLocal(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsImportSpecifier(); + return reinterpret_cast(node->Local()); +} + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FOR_ALL_MEMBER_EXPRESSION_KINDS(_) \ + _(ELEMENT_ACCESS) \ + _(PROPERTY_ACCESS) \ + _(GETTER) \ + _(SETTER) + +static ir::MemberExpressionKind E2pToIrMemberExpressionKind(es2panda_MemberExpressionKind e2p_kind) +{ + ir::MemberExpressionKind ir_kind = ir::MemberExpressionKind::NONE; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DO_KIND(K) \ + if ((e2p_kind & ES2PANDA_MEMBER_EXPRESSION_KIND_##K) != 0) { \ + ir_kind |= ir::MemberExpressionKind::K; \ + } + + FOR_ALL_MEMBER_EXPRESSION_KINDS(DO_KIND) + +#undef DO_KIND + + return ir_kind; +} + +static es2panda_MemberExpressionKind IrToE2pMemberExpressionKind(ir::MemberExpressionKind ir_kind) +{ + es2panda_MemberExpressionKind e2p_kind = ES2PANDA_MEMBER_EXPRESSION_KIND_NONE; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DO_KIND(K) \ + if ((ir_kind & ir::MemberExpressionKind::K) != 0) { \ + e2p_kind = static_cast(e2p_kind | ES2PANDA_MEMBER_EXPRESSION_KIND_##K); \ + } + + FOR_ALL_MEMBER_EXPRESSION_KINDS(DO_KIND) + +#undef DO_KIND + + return e2p_kind; +} + +extern "C" es2panda_AstNode *CreateMemberExpression(es2panda_Context *context, es2panda_AstNode *object, + es2panda_AstNode *property, es2panda_MemberExpressionKind kind, + bool is_computed, bool is_optional) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto ir_object = reinterpret_cast(object)->AsExpression(); + auto ir_property = reinterpret_cast(property)->AsExpression(); + auto ir_kind = E2pToIrMemberExpressionKind(kind); + + return reinterpret_cast( + allocator->New(ir_object, ir_property, ir_kind, is_computed, is_optional)); +} + +extern "C" es2panda_AstNode *MemberExpressionObject(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMemberExpression(); + return reinterpret_cast(node->Object()); +} + +extern "C" es2panda_AstNode *MemberExpressionProperty(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMemberExpression(); + return reinterpret_cast(node->Property()); +} + +extern "C" es2panda_MemberExpressionKind MemberExpressionKind(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMemberExpression(); + return IrToE2pMemberExpressionKind(node->Kind()); +} + +extern "C" bool MemberExpressionIsComputed(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMemberExpression(); + return node->IsComputed(); +} + +extern "C" bool MemberExpressionIsOptional(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMemberExpression(); + return node->IsOptional(); +} + +struct MethodDefinitionKindToStrStruct { + ir::MethodDefinitionKind kind; + char const *str; +}; + +static constexpr std::array METHOD_DEFINITION_KIND_TO_STR {{ + {ir::MethodDefinitionKind::CONSTRUCTOR, "constructor"}, + {ir::MethodDefinitionKind::METHOD, "method"}, + {ir::MethodDefinitionKind::EXTENSION_METHOD, "extension method"}, + {ir::MethodDefinitionKind::GET, "get"}, + {ir::MethodDefinitionKind::SET, "set"}, +}}; + +static ir::MethodDefinitionKind StrToMethodDefinitionKind(char const *str) +{ + for (auto &elem : METHOD_DEFINITION_KIND_TO_STR) { + if (strcmp(elem.str, str) == 0) { + return elem.kind; + } + } + return ir::MethodDefinitionKind::NONE; +} + +static char const *MethodDefinitionKindToStr(ir::MethodDefinitionKind kind) +{ + for (auto &elem : METHOD_DEFINITION_KIND_TO_STR) { + if (elem.kind == kind) { + return elem.str; + } + } + return "unknown"; +} + +extern "C" es2panda_AstNode *CreateMethodDefinition(es2panda_Context *context, char const *kind, es2panda_AstNode *key, + es2panda_AstNode *value, es2panda_ModifierFlags modifiers, + bool is_computed) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto ir_kind = StrToMethodDefinitionKind(kind); + auto *ir_key = reinterpret_cast(key)->AsExpression(); + auto *ir_value = reinterpret_cast(value)->AsExpression(); + auto ir_flags = E2pToIrModifierFlags(modifiers); + + return reinterpret_cast( + allocator->New(ir_kind, ir_key, ir_value, ir_flags, allocator, is_computed)); +} + +extern "C" char const *MethodDefinitionKind(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + return MethodDefinitionKindToStr(node->Kind()); +} + +extern "C" es2panda_AstNode const *MethodDefinitionKey(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + return reinterpret_cast(node->Key()); +} + +extern "C" es2panda_AstNode const *MethodDefinitionValue(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + return reinterpret_cast(node->Value()); +} + +extern "C" es2panda_ModifierFlags MethodDefinitionModifiers(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + return IrToE2pModifierFlags(node->Modifiers()); +} + +extern "C" bool MethodDefinitionIsComputed(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + return node->IsComputed(); +} + +extern "C" es2panda_AstNode *const *MethodDefinitionOverloads(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + auto const &overloads = node->Overloads(); + *size_p = overloads.size(); + return reinterpret_cast(overloads.data()); +} + +extern "C" void MethodDefinitionSetOverloads(es2panda_AstNode *ast, es2panda_AstNode **overloads, size_t n_overloads) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + ArenaVector ir_overloads {node->Overloads().get_allocator()}; + ir_overloads.reserve(n_overloads); + for (size_t i = 0; i < n_overloads; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + ir_overloads.push_back(reinterpret_cast(overloads[i])->AsMethodDefinition()); + } + node->SetOverloads(std::move(ir_overloads)); +} + +extern "C" void MethodDefinitionAddOverload(es2panda_AstNode *ast, es2panda_AstNode *overload) +{ + auto *node = reinterpret_cast(ast)->AsMethodDefinition(); + auto *ir_overload = reinterpret_cast(overload)->AsMethodDefinition(); + node->AddOverload(ir_overload); +} + +extern "C" es2panda_AstNode *CreateNewClassInstanceExpression(es2panda_Context *context, + es2panda_AstNode *type_reference, + es2panda_AstNode **arguments, size_t n_arguments, + es2panda_AstNode *class_definition) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_typeref = reinterpret_cast(type_reference)->AsExpression(); + + ArenaVector args {allocator->Adapter()}; + for (size_t i = 0; i < n_arguments; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + args.push_back(reinterpret_cast(arguments[i])->AsExpression()); + } + + auto *ir_classdef = + class_definition == nullptr ? nullptr : reinterpret_cast(class_definition)->AsClassDefinition(); + + return reinterpret_cast( + allocator->New(ir_typeref, std::move(args), ir_classdef)); +} + +extern "C" es2panda_AstNode *NewClassInstanceExpressionTypeReference(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSNewClassInstanceExpression(); + return reinterpret_cast(node->GetTypeRef()); +} + +extern "C" es2panda_AstNode *const *NewClassInstanceExpressionArguments(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsETSNewClassInstanceExpression(); + auto const &args = node->GetArguments(); + + *size_p = args.size(); + return reinterpret_cast(args.data()); +} + +extern "C" es2panda_AstNode *NewClassInstanceExpressionClassDefinition(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSNewClassInstanceExpression(); + return reinterpret_cast(node->ClassDefinition()); +} + +extern "C" es2panda_AstNode *CreateNewArrayInstanceExpression(es2panda_Context *context, + es2panda_AstNode *type_reference, + es2panda_AstNode *dimension) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_typeref = reinterpret_cast(type_reference)->AsExpression()->AsTypeNode(); + auto *ir_dim = reinterpret_cast(dimension)->AsExpression(); + + return reinterpret_cast(allocator->New(ir_typeref, ir_dim)); +} + +extern "C" es2panda_AstNode *NewArrayInstanceExpressionTypeReference(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSNewArrayInstanceExpression(); + return reinterpret_cast(node->TypeReference()); +} + +extern "C" es2panda_AstNode *NewArrayInstanceExpressionDimension(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSNewArrayInstanceExpression(); + return reinterpret_cast(node->Dimension()); +} + +extern "C" es2panda_AstNode *CreateNewMultiDimArrayInstanceExpression(es2panda_Context *context, + es2panda_AstNode *type_reference, + es2panda_AstNode **dimensions, + size_t n_dimensions) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_typeref = reinterpret_cast(type_reference)->AsExpression()->AsTypeNode(); + + ArenaVector ir_dims {allocator->Adapter()}; + for (size_t i = 0; i < n_dimensions; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + ir_dims.push_back(reinterpret_cast(dimensions[i])->AsExpression()); + } + + return reinterpret_cast( + allocator->New(ir_typeref, std::move(ir_dims))); +} + +extern "C" es2panda_AstNode *NewMultiDimArrayInstanceExpressionTypeReference(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSNewMultiDimArrayInstanceExpression(); + return reinterpret_cast(node->TypeReference()); +} + +extern "C" es2panda_AstNode *const *NewMultiDimArrayInstanceExpressionDimensions(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsETSNewMultiDimArrayInstanceExpression(); + auto const &dims = node->Dimensions(); + + *size_p = dims.size(); + return reinterpret_cast(dims.data()); +} + +extern "C" es2panda_AstNode *CreateParameterDeclaration(es2panda_Context *context, + es2panda_AstNode *identifier_or_spread, + es2panda_AstNode *initializer) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + + auto *ir_ident_or_spread_raw = reinterpret_cast(identifier_or_spread)->AsExpression(); + ir::AnnotatedExpression *ir_ident_or_spread; + if (ir_ident_or_spread_raw->IsIdentifier()) { + ir_ident_or_spread = ir_ident_or_spread_raw->AsIdentifier(); + } else if (ir_ident_or_spread_raw->IsSpreadElement()) { + ir_ident_or_spread = ir_ident_or_spread_raw->AsSpreadElement(); + } else { + UNREACHABLE(); + } + + auto *ir_initializer = + initializer == nullptr ? nullptr : reinterpret_cast(initializer)->AsExpression(); + + return reinterpret_cast( + allocator->New(ir_ident_or_spread, ir_initializer)); +} + +extern "C" es2panda_AstNode *ParameterDeclarationIdentifierOrSpread(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSParameterExpression(); + + ir::AstNode *res; + if (node->IsRestParameter()) { + res = node->RestParameter(); + } else { + res = node->Ident(); + } + return reinterpret_cast(res); +} + +extern "C" es2panda_AstNode *ParameterDeclarationInitializer(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSParameterExpression(); + return reinterpret_cast(node->Initializer()); +} + +struct PrimitiveTypeToStrStruct { + ir::PrimitiveType type; + char const *str; +}; + +static constexpr std::array PRIMITIVE_TYPE_TO_STR {{ + {ir::PrimitiveType::BYTE, "byte"}, + {ir::PrimitiveType::INT, "int"}, + {ir::PrimitiveType::LONG, "long"}, + {ir::PrimitiveType::SHORT, "short"}, + {ir::PrimitiveType::FLOAT, "float"}, + {ir::PrimitiveType::DOUBLE, "double"}, + {ir::PrimitiveType::BOOLEAN, "boolean"}, + {ir::PrimitiveType::CHAR, "char"}, + {ir::PrimitiveType::VOID, "void"}, +}}; + +static ir::PrimitiveType StrToPrimitiveType(char const *str) +{ + for (auto &elem : PRIMITIVE_TYPE_TO_STR) { + if (strcmp(elem.str, str) == 0) { + return elem.type; + } + } + return ir::PrimitiveType::VOID; +} + +static char const *PrimitiveTypeToStr(ir::PrimitiveType type) +{ + for (auto &elem : PRIMITIVE_TYPE_TO_STR) { + if (elem.type == type) { + return elem.str; + } + } + return "unknown"; +} + +extern "C" es2panda_AstNode *CreatePrimitiveTypeNode(es2panda_Context *context, char const *type) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto tp = StrToPrimitiveType(type); + + return reinterpret_cast(allocator->New(tp)); +} + +extern "C" char const *PrimitiveTypeNodeType(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSPrimitiveType(); + return PrimitiveTypeToStr(node->GetPrimitiveType()); +} + +extern "C" es2panda_AstNode *CreateReturnStatement(es2panda_Context *context, es2panda_AstNode *argument) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_arg = argument == nullptr ? nullptr : reinterpret_cast(argument)->AsExpression(); + + return reinterpret_cast(allocator->New(ir_arg)); +} + +extern "C" es2panda_AstNode *ReturnStatementArgument(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsReturnStatement(); + return reinterpret_cast(node->Argument()); +} + +extern "C" es2panda_Type *ReturnStatementReturnType(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsReturnStatement(); + return reinterpret_cast(node->ReturnType()); +} + +extern "C" es2panda_AstNode *CreateScriptFunction(es2panda_Context *context, es2panda_AstNode *type_params, + es2panda_AstNode **params, size_t n_params, + es2panda_AstNode *return_type_annotation, + es2panda_ScriptFunctionFlags function_flags, + es2panda_ModifierFlags modifier_flags, bool is_declare, + es2panda_AstNode *in_scope_of) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_type_params = + type_params == nullptr ? nullptr : reinterpret_cast(type_params)->AsTSTypeParameterDeclaration(); + + // NOTE(gogabr): without explicit reference to scope, scopes within params will be broken + ArenaVector ir_params {allocator->Adapter()}; + for (size_t i = 0; i < n_params; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + ir_params.push_back(reinterpret_cast(params[i])->AsExpression()); + } + + auto ir_return_type_annotation = + return_type_annotation == nullptr + ? nullptr + : reinterpret_cast(return_type_annotation)->AsExpression()->AsTypeNode(); + auto ir_function_flags = E2pToIrScriptFunctionFlags(function_flags); + auto ir_modifier_flags = E2pToIrModifierFlags(modifier_flags); + + auto *outer_scope = ir_type_params == nullptr ? compiler::NearestScope(reinterpret_cast(in_scope_of)) + : ir_type_params->Scope(); + auto *parameter_scope = allocator->New(allocator, outer_scope); + auto *body_scope = allocator->New(allocator, parameter_scope); + parameter_scope->BindFunctionScope(body_scope); + body_scope->BindParamScope(parameter_scope); + + return reinterpret_cast(allocator->New( + body_scope, std::move(ir_params), ir_type_params, nullptr, ir_return_type_annotation, ir_function_flags, + ir_modifier_flags, is_declare, Language::FromString("ets").value())); +} + +extern "C" es2panda_AstNode *ScriptFunctionTypeParams(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + return reinterpret_cast(node->TypeParams()); +} + +extern "C" es2panda_AstNode *const *ScriptFunctionParams(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + auto ¶ms = node->Params(); + + *size_p = params.size(); + return reinterpret_cast(params.data()); +} + +extern "C" es2panda_AstNode *ScriptFunctionReturnTypeAnnotation(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + return reinterpret_cast(node->ReturnTypeAnnotation()); +} + +extern "C" es2panda_ScriptFunctionFlags ScriptFunctionScriptFunctionFlags(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + return IrToE2pScriptFunctionFlags(node->Flags()); +} + +extern "C" bool ScriptFunctionIsDeclare(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + return node->Declare(); +} + +extern "C" es2panda_AstNode *ScriptFunctionIdentifier(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + return reinterpret_cast(node->Id()); +} + +extern "C" es2panda_AstNode *ScriptFunctionBody(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + return reinterpret_cast(node->Body()); +} + +extern "C" void ScriptFunctionSetIdentifier(es2panda_AstNode *ast, es2panda_AstNode *identifier) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + auto *id = reinterpret_cast(identifier)->AsIdentifier(); + + node->SetIdent(id); +} + +extern "C" void ScriptFunctionSetBody(es2panda_AstNode *ast, es2panda_AstNode *body) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + auto *ir_body = reinterpret_cast(body); + + node->SetBody(ir_body); +} + +extern "C" void ScriptFunctionSetParams(es2panda_AstNode *ast, es2panda_AstNode **params, size_t n_params) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + auto &ir_params = node->Params(); + + ir_params.clear(); + for (size_t i = 0; i < n_params; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + ir_params.push_back(reinterpret_cast(params[i])->AsExpression()); + } +} + +extern "C" void ScripFunctionAddParam(es2panda_AstNode *ast, es2panda_AstNode *param) +{ + auto *node = reinterpret_cast(ast)->AsScriptFunction(); + auto *ir_param = reinterpret_cast(param)->AsExpression(); + + node->Params().push_back(ir_param); +} + +extern "C" es2panda_AstNode *CreateStringLiteral(es2panda_Context *context, char const *string) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *str = ArenaStrdup(allocator, string); + + return reinterpret_cast(allocator->New(str)); +} + +extern "C" char const *StringLiteralString(es2panda_Context *context, es2panda_AstNode *ast) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *node = reinterpret_cast(ast)->AsStringLiteral(); + return StringViewToCString(allocator, node->Str()); +} + +extern "C" es2panda_AstNode *CreateThisExpression(es2panda_Context *context) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + + return reinterpret_cast(allocator->New()); +} + +extern "C" es2panda_AstNode *CreateTypeParameter(es2panda_Context *context, es2panda_AstNode *name, + es2panda_AstNode *constraint, es2panda_AstNode *default_type) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *nm = reinterpret_cast(name)->AsIdentifier(); + auto *constr = + constraint == nullptr ? nullptr : reinterpret_cast(constraint)->AsExpression()->AsTypeNode(); + auto *dflt = + default_type == nullptr ? nullptr : reinterpret_cast(default_type)->AsExpression()->AsTypeNode(); + + return reinterpret_cast(allocator->New(nm, constr, dflt)); +} + +extern "C" es2panda_AstNode const *TypeParameterName(es2panda_AstNode *ast) +{ + auto *tp = reinterpret_cast(ast)->AsTSTypeParameter(); + return reinterpret_cast(tp->Name()); +} + +extern "C" es2panda_AstNode const *TypeParameterConstraint(es2panda_AstNode *ast) +{ + auto *tp = reinterpret_cast(ast)->AsTSTypeParameter(); + return reinterpret_cast(tp->Constraint()); +} + +extern "C" es2panda_AstNode const *TypeParameterDefaultType(es2panda_AstNode *ast) +{ + auto *tp = reinterpret_cast(ast)->AsTSTypeParameter(); + return reinterpret_cast(tp->DefaultType()); +} + +extern "C" es2panda_AstNode *CreateTypeParameterDeclaration(es2panda_Context *context, es2panda_AstNode *in_scope_of) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *parent = reinterpret_cast(in_scope_of); + auto *parent_scope = compiler::NearestScope(parent); + + auto *scope = allocator->New(allocator, parent_scope); + ArenaVector params {allocator->Adapter()}; + return reinterpret_cast( + allocator->New(scope, std::move(params), 0)); +} + +extern "C" void TypeParameterDeclarationAddTypeParameter(es2panda_AstNode *ast, es2panda_AstNode *type_parameter) +{ + auto *tpd = reinterpret_cast(ast)->AsTSTypeParameterDeclaration(); + auto *param = reinterpret_cast(type_parameter)->AsTSTypeParameter(); + + tpd->AddParam(param); +} + +extern "C" es2panda_AstNode *const *TypeParameterDeclarationTypeParameters(es2panda_AstNode *ast, size_t *size_p) +{ + auto *tpd = reinterpret_cast(ast)->AsTSTypeParameterDeclaration(); + auto const ¶ms = tpd->Params(); + *size_p = params.size(); + return reinterpret_cast(params.data()); +} + +extern "C" es2panda_AstNode *CreateTypeParameterInstantiation(es2panda_Context *context, + es2panda_AstNode **type_parameters, size_t n_params) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + + ArenaVector params {allocator->Adapter()}; + for (size_t i = 0; i < n_params; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + params.push_back(reinterpret_cast(type_parameters[i])->AsExpression()->AsTypeNode()); + } + return reinterpret_cast(allocator->New(std::move(params))); +} + +extern "C" es2panda_AstNode *const *TypeParameterInstantiationTypeParameters(es2panda_AstNode *ast, size_t *size_p) +{ + auto *tpi = reinterpret_cast(ast)->AsTSTypeParameterInstantiation(); + auto const ¶ms = tpi->Params(); + *size_p = params.size(); + return reinterpret_cast(params.data()); +} + +extern "C" es2panda_AstNode *CreateTypeReferenceNode(es2panda_Context *context, es2panda_AstNode *part) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_part = reinterpret_cast(part)->AsETSTypeReferencePart(); + + return reinterpret_cast(allocator->New(ir_part)); +} + +extern "C" es2panda_AstNode *TypeReferenceNodePart(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSTypeReference(); + return reinterpret_cast(node->Part()); +} + +extern "C" es2panda_AstNode *CreateTypeReferencePart(es2panda_Context *context, es2panda_AstNode *name, + es2panda_AstNode *type_arguments, es2panda_AstNode *previous) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ir_name = reinterpret_cast(name)->AsExpression(); + auto *ir_type_args = type_arguments == nullptr + ? nullptr + : reinterpret_cast(type_arguments)->AsTSTypeParameterInstantiation(); + auto *ir_prev = previous == nullptr ? nullptr : reinterpret_cast(previous)->AsETSTypeReferencePart(); + + return reinterpret_cast( + allocator->New(ir_name, ir_type_args, ir_prev)); +} + +extern "C" es2panda_AstNode *TypeReferencePartName(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSTypeReferencePart(); + return reinterpret_cast(node->Name()); +} + +extern "C" es2panda_AstNode *TypeReferencePartTypeArguments(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSTypeReferencePart(); + return reinterpret_cast(node->TypeParams()); +} + +extern "C" es2panda_AstNode *TypeReferencePartPrevious(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsETSTypeReferencePart(); + return reinterpret_cast(node->Previous()); +} + +extern "C" es2panda_AstNode *CreateUnionTypeNode(es2panda_Context *context, es2panda_AstNode **types, size_t n_types) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + + ArenaVector ir_types {allocator->Adapter()}; + for (size_t i = 0; i < n_types; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + ir_types.push_back(reinterpret_cast(types[i])->AsExpression()->AsTypeNode()); + } + + return reinterpret_cast(allocator->New(std::move(ir_types))); +} + +extern "C" es2panda_AstNode *const *UnionTypeNodeTypes(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsTSUnionType(); + auto &ir_types = node->Types(); + + *size_p = ir_types.size(); + return reinterpret_cast(ir_types.data()); +} + +struct VariableDeclarationKindToStrStruct { + ir::VariableDeclaration::VariableDeclarationKind kind; + char const *str; +}; + +static constexpr std::array VARIABLE_DECLARATION_KIND_TO_STR {{ + {ir::VariableDeclaration::VariableDeclarationKind::CONST, "const"}, + {ir::VariableDeclaration::VariableDeclarationKind::LET, "let"}, + {ir::VariableDeclaration::VariableDeclarationKind::VAR, "var"}, +}}; + +static ir::VariableDeclaration::VariableDeclarationKind StrToVariableDeclarationKind(char const *str) +{ + for (auto &elem : VARIABLE_DECLARATION_KIND_TO_STR) { + if (strcmp(elem.str, str) == 0) { + return elem.kind; + } + } + + // NOTE(gogabr): handle errors + UNREACHABLE(); +} + +static char const *VariableDeclarationKindToStr(ir::VariableDeclaration::VariableDeclarationKind kind) +{ + for (auto &elem : VARIABLE_DECLARATION_KIND_TO_STR) { + if (elem.kind == kind) { + return elem.str; + } + } + return "unknown"; +} + +extern "C" es2panda_AstNode *CreateVariableDeclaration(es2panda_Context *context, char const *kind, + es2panda_AstNode **declarators, size_t n_declarators, + bool is_declare) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto ir_kind = StrToVariableDeclarationKind(kind); + + ArenaVector ir_declarators {allocator->Adapter()}; + for (size_t i = 0; i < n_declarators; i++) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + ir_declarators.push_back(reinterpret_cast(declarators[i])->AsVariableDeclarator()); + } + + return reinterpret_cast( + allocator->New(ir_kind, allocator, std::move(ir_declarators), is_declare)); +} + +extern "C" char const *VariableDeclarationKind(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsVariableDeclaration(); + return VariableDeclarationKindToStr(node->Kind()); +} + +extern "C" es2panda_AstNode *const *VariableDeclarationDeclarators(es2panda_AstNode *ast, size_t *size_p) +{ + auto *node = reinterpret_cast(ast)->AsVariableDeclaration(); + auto const &declarators = node->Declarators(); + *size_p = declarators.size(); + return reinterpret_cast(declarators.data()); +} + +extern "C" bool VariableDeclarationIsDeclare(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsVariableDeclaration(); + return node->Declare(); +} + +extern "C" es2panda_AstNode *CreateVariableDeclarator(es2panda_Context *context, es2panda_AstNode *identifier, + es2panda_AstNode *initializer) +{ + auto *ctx = reinterpret_cast(context); + auto *allocator = ctx->allocator; + auto *ident = reinterpret_cast(identifier)->AsExpression(); + auto *init = initializer == nullptr ? nullptr : reinterpret_cast(initializer)->AsExpression(); + + return reinterpret_cast(allocator->New(ident, init)); +} + +extern "C" es2panda_AstNode *VariableDeclaratorIdentifier(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsVariableDeclarator(); + return reinterpret_cast(node->Id()); +} + +extern "C" es2panda_AstNode *VariableDeclaratorInitializer(es2panda_AstNode *ast) +{ + auto *node = reinterpret_cast(ast)->AsVariableDeclarator(); + return reinterpret_cast(node->Init()); +} + +es2panda_Impl IMPL = { + ES2PANDA_LIB_VERSION, + + CreateConfig, + DestroyConfig, + + CreateContextFromFile, + CreateContextFromString, + ProceedToState, + DestroyContext, + + ContextState, + ContextErrorMessage, + + ContextProgram, + ProgramAst, + ProgramExternalSources, + ExternalSourceName, + ExternalSourcePrograms, + + AstNodeType, + AstNodeSetType, + + AstNodeDecorators, + AstNodeSetDecorators, + + AstNodeModifierFlags, + + AstNodeForEach, + + IsArrowFunctionExpression, + CreateArrowFunctionExpression, + ArrowFunctionExpressionScriptFunction, + + IsAsExpression, + CreateAsExpression, + AsExpressionExpr, + AsExpressionTypeAnnotation, + AsExpressionIsConst, + AsExpressionSetExpr, + AsExpressionSetTypeAnnotation, + + IsAssignmentExpression, + CreateAssignmentExpression, + AssignmentExpressionLeft, + AssignmentExpressionRight, + AssignmentExpressionOperatorType, + AssignmentExpressionSetOperatorType, + + IsBinaryExpression, + CreateBinaryExpression, + BinaryExpressionLeft, + BinaryExpressionRight, + BinaryExpressionOperator, + BinaryExpressionSetOperator, + + IsBlockStatement, + CreateBlockStatement, + BlockStatementStatements, + BlockStatementAddStatement, + + IsCallExpression, + CreateCallExpression, + CallExpressionCallee, + CallExpressionTypeArguments, + CallExpressionArguments, + CallExpressionIsOptional, + CallExpressionSetTypeArguments, + + IsChainExpression, + CreateChainExpression, + ChainExpressionChild, + + IsClassDeclaration, + CreateClassDeclaration, + ClassDeclarationDefinition, + + IsClassDefinition, + CreateClassDefinition, + ClassDefinitionIdentifier, + ClassDefinitionTypeParameters, + ClassDefinitionSuperClass, + ClassDefinitionImplements, + ClassDefinitionConstructor, + ClassDefinitionBody, + ClassDefinitionSetIdentifier, + ClassDefinitionSetTypeParameters, + ClassDefinitionSetSuperClass, + ClassDefinitionSetImplements, + ClassDefinitionAddImplements, + ClassDefinitionSetConstructor, + ClassDefinitionSetBody, + ClassDefinitionAddToBody, + + ClassElementKey, + ClassElementValue, + + IsClassImplementsClause, + CreateClassImplementsClause, + ClassImplementsClauseExpression, + ClassImplementsClauseTypeArguments, + + IsClassProperty, + CreateClassProperty, + ClassPropertyTypeAnnotation, + + IsExpressionStatement, + CreateExpressionStatement, + ExpressionStatementExpression, + + IsFunctionDeclaration, + CreateFunctionDeclaration, + FunctionDeclarationFunction, + + IsFunctionExpression, + CreateFunctionExpression, + FunctionExpressionFunction, + + IsFunctionTypeNode, + CreateFunctionTypeNode, + FunctionTypeNodeTypeParams, + FunctionTypeNodeParams, + FunctionTypeNodeReturnType, + FunctionTypeNodeFlags, + + IsIdentifier, + CreateIdentifier, + IdentifierName, + IdentifierTypeAnnotation, + IdentifierVariable, + IdentifierSetVariable, + + IsIfStatement, + CreateIfStatement, + IfStatementTest, + IfStatementConsequent, + IfStatementAlternate, + + IsImportDeclaration, + CreateImportDeclaration, + ImportDeclarationSource, + ImportDeclarationSpecifiers, + + IsImportExpression, + CreateImportExpression, + ImportExpressionSource, + + IsImportSpecifier, + CreateImportSpecifier, + ImportSpecifierImported, + ImportSpecifierLocal, + + IsMemberExpression, + CreateMemberExpression, + MemberExpressionObject, + MemberExpressionProperty, + MemberExpressionKind, + MemberExpressionIsComputed, + MemberExpressionIsOptional, + + IsMethodDefinition, + CreateMethodDefinition, + MethodDefinitionKind, + MethodDefinitionKey, + MethodDefinitionValue, + MethodDefinitionModifiers, + MethodDefinitionIsComputed, + MethodDefinitionOverloads, + MethodDefinitionSetOverloads, + MethodDefinitionAddOverload, + + IsNewClassInstanceExpression, + CreateNewClassInstanceExpression, + NewClassInstanceExpressionTypeReference, + NewClassInstanceExpressionArguments, + NewClassInstanceExpressionClassDefinition, + + IsNewArrayInstanceExpression, + CreateNewArrayInstanceExpression, + NewArrayInstanceExpressionTypeReference, + NewArrayInstanceExpressionDimension, + + IsNewMultiDimArrayInstanceExpression, + CreateNewMultiDimArrayInstanceExpression, + NewMultiDimArrayInstanceExpressionTypeReference, + NewMultiDimArrayInstanceExpressionDimensions, + + IsNonNullExpression, + IsNumberLiteral, + IsObjectExpression, + + IsParameterDeclaration, + CreateParameterDeclaration, + ParameterDeclarationIdentifierOrSpread, + ParameterDeclarationInitializer, + + IsPrimitiveTypeNode, + CreatePrimitiveTypeNode, + PrimitiveTypeNodeType, + + IsReturnStatement, + CreateReturnStatement, + ReturnStatementArgument, + ReturnStatementReturnType, + + IsScriptFunction, + CreateScriptFunction, + ScriptFunctionTypeParams, + ScriptFunctionParams, + ScriptFunctionReturnTypeAnnotation, + ScriptFunctionScriptFunctionFlags, + ScriptFunctionIsDeclare, + ScriptFunctionIdentifier, + ScriptFunctionBody, + ScriptFunctionSetIdentifier, + ScriptFunctionSetBody, + ScriptFunctionSetParams, + ScripFunctionAddParam, + + IsStringLiteral, + CreateStringLiteral, + StringLiteralString, + + IsThisExpression, + CreateThisExpression, + + IsTypeParameter, + CreateTypeParameter, + TypeParameterName, + TypeParameterConstraint, + TypeParameterDefaultType, + + IsTypeParameterDeclaration, + CreateTypeParameterDeclaration, + TypeParameterDeclarationAddTypeParameter, + TypeParameterDeclarationTypeParameters, + + IsTypeParameterInstantiation, + CreateTypeParameterInstantiation, + TypeParameterInstantiationTypeParameters, + + IsTypeReferenceNode, + CreateTypeReferenceNode, + TypeReferenceNodePart, + + IsTypeReferencePart, + CreateTypeReferencePart, + TypeReferencePartName, + TypeReferencePartTypeArguments, + TypeReferencePartPrevious, + + IsUnionTypeNode, + CreateUnionTypeNode, + UnionTypeNodeTypes, + + IsVariableDeclaration, + CreateVariableDeclaration, + VariableDeclarationKind, + VariableDeclarationDeclarators, + VariableDeclarationIsDeclare, + + IsVariableDeclarator, + CreateVariableDeclarator, + VariableDeclaratorIdentifier, + VariableDeclaratorInitializer, +}; } // namespace panda::es2panda::public_lib diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index d20aee7772..f61653f465 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -16,17 +16,27 @@ #ifndef ES2PANDA_LIB #define ES2PANDA_LIB +// Switch off the linter for C header +// NOLINTBEGIN + +#include +#include + #ifdef __cplusplus extern "C" { #endif -// Switch off the linter for C header -// NOLINTBEGIN +#define ES2PANDA_LIB_VERSION 1 -#define ES2PANDA_LIB_VERSION 0 +typedef struct es2panda_Config es2panda_Config; +typedef struct es2panda_Context es2panda_Context; -typedef void es2panda_Config; -typedef void es2panda_Context; +typedef struct es2panda_Program es2panda_Program; +typedef struct es2panda_ExternalSource es2panda_ExternalSource; +typedef struct es2panda_AstNode es2panda_AstNode; +typedef struct es2panda_Type es2panda_Type; +typedef struct es2panda_Variable es2panda_Variable; +typedef struct es2panda_Scope es2panda_Scope; enum es2panda_ContextState { ES2PANDA_STATE_NEW, @@ -40,6 +50,74 @@ enum es2panda_ContextState { }; typedef enum es2panda_ContextState es2panda_ContextState; +// NB: has to be synchronized with astNode.h +enum es2panda_ModifierFlags { + ES2PANDA_MODIFIER_NONE = 0U, + ES2PANDA_MODIFIER_STATIC = 1U << 0U, + ES2PANDA_MODIFIER_ASYNC = 1U << 1U, + ES2PANDA_MODIFIER_PUBLIC = 1U << 2U, + ES2PANDA_MODIFIER_PROTECTED = 1U << 3U, + ES2PANDA_MODIFIER_PRIVATE = 1U << 4U, + ES2PANDA_MODIFIER_DECLARE = 1U << 5U, + ES2PANDA_MODIFIER_READONLY = 1U << 6U, + ES2PANDA_MODIFIER_OPTIONAL = 1U << 7U, + ES2PANDA_MODIFIER_DEFINITE = 1U << 8U, + ES2PANDA_MODIFIER_ABSTRACT = 1U << 9U, + ES2PANDA_MODIFIER_CONST = 1U << 10U, + ES2PANDA_MODIFIER_FINAL = 1U << 11U, + ES2PANDA_MODIFIER_NATIVE = 1U << 12U, + ES2PANDA_MODIFIER_OVERRIDE = 1U << 13U, + ES2PANDA_MODIFIER_CONSTRUCTOR = 1U << 14U, + ES2PANDA_MODIFIER_SYNCHRONIZED = 1U << 15U, + ES2PANDA_MODIFIER_FUNCTIONAL = 1U << 16U, + ES2PANDA_MODIFIER_IN = 1U << 17U, + ES2PANDA_MODIFIER_OUT = 1U << 18U, + ES2PANDA_MODIFIER_INTERNAL = 1U << 19U, + ES2PANDA_MODIFIER_NULL_ASSIGNABLE = 1U << 20U, + ES2PANDA_MODIFIER_UNDEFINED_ASSIGNABLE = 1U << 21U, + ES2PANDA_MODIFIER_EXPORT = 1U << 22U, + ES2PANDA_MODIFIER_SETTER = 1U << 23U, + ES2PANDA_MODIFIER_DEFAULT_EXPORT = 1U << 24U, +}; +typedef enum es2panda_ModifierFlags es2panda_ModifierFlags; + +// Has to be synchronized with astNode.h +enum es2panda_ScriptFunctionFlags { + ES2PANDA_SCRIPT_FUNCTION_NONE = 0, + ES2PANDA_SCRIPT_FUNCTION_GENERATOR = 1U << 0U, + ES2PANDA_SCRIPT_FUNCTION_ASYNC = 1U << 1U, + ES2PANDA_SCRIPT_FUNCTION_ARROW = 1U << 2U, + ES2PANDA_SCRIPT_FUNCTION_EXPRESSION = 1U << 3U, + ES2PANDA_SCRIPT_FUNCTION_OVERLOAD = 1U << 4U, + ES2PANDA_SCRIPT_FUNCTION_CONSTRUCTOR = 1U << 5U, + ES2PANDA_SCRIPT_FUNCTION_METHOD = 1U << 6U, + ES2PANDA_SCRIPT_FUNCTION_STATIC_BLOCK = 1U << 7U, + ES2PANDA_SCRIPT_FUNCTION_HIDDEN = 1U << 8U, + ES2PANDA_SCRIPT_FUNCTION_IMPLICIT_SUPER_CALL_NEEDED = 1U << 9U, + ES2PANDA_SCRIPT_FUNCTION_ENUM = 1U << 10U, + ES2PANDA_SCRIPT_FUNCTION_EXTERNAL = 1U << 11U, + ES2PANDA_SCRIPT_FUNCTION_PROXY = 1U << 12U, + ES2PANDA_SCRIPT_FUNCTION_THROWS = 1U << 13U, + ES2PANDA_SCRIPT_FUNCTION_RETHROWS = 1U << 14U, + ES2PANDA_SCRIPT_FUNCTION_GETTER = 1U << 15U, + ES2PANDA_SCRIPT_FUNCTION_SETTER = 1U << 16U, + ES2PANDA_SCRIPT_FUNCTION_DEFAULT_PARAM_PROXY = 1U << 17U, + ES2PANDA_SCRIPT_FUNCTION_ENTRY_POINT = 1U << 18U, + ES2PANDA_SCRIPT_FUNCTION_INSTANCE_EXTENSION_METHOD = 1U << 19U, + ES2PANDA_SCRIPT_FUNCTION_HAS_RETURN = 1U << 20U +}; +typedef enum es2panda_ScriptFunctionFlags es2panda_ScriptFunctionFlags; + +// Needs to be synchronized with memberExpression.h +enum es2panda_MemberExpressionKind { + ES2PANDA_MEMBER_EXPRESSION_KIND_NONE = 0, + ES2PANDA_MEMBER_EXPRESSION_KIND_ELEMENT_ACCESS = 1U << 0U, + ES2PANDA_MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS = 1U << 1U, + ES2PANDA_MEMBER_EXPRESSION_KIND_GETTER = 1U << 2U, + ES2PANDA_MEMBER_EXPRESSION_KIND_SETTER = 1U << 3U +}; +typedef enum es2panda_MemberExpressionKind es2panda_MemberExpressionKind; + struct es2panda_Impl { int version; @@ -53,6 +131,296 @@ struct es2panda_Impl { es2panda_ContextState (*ContextState)(es2panda_Context *context); char const *(*ContextErrorMessage)(es2panda_Context *context); + + es2panda_Program *(*ContextProgram)(es2panda_Context *context); + es2panda_AstNode *(*ProgramAst)(es2panda_Program *program); + es2panda_ExternalSource **(*ProgramExternalSources)(es2panda_Program *program, size_t *len_p); + char const *(*ExternalSourceName)(es2panda_ExternalSource *e_source); + es2panda_Program **(*ExternalSourcePrograms)(es2panda_ExternalSource *e_source, size_t *len_p); + + es2panda_Type *(*AstNodeType)(es2panda_AstNode *ast); + void (*AstNodeSetType)(es2panda_AstNode *ast, es2panda_Type *type); + + es2panda_AstNode *const *(*AstNodeDecorators)(es2panda_AstNode *ast, size_t *size_p); + void (*AstNodeSetDecorators)(es2panda_Context *context, es2panda_AstNode *ast, es2panda_AstNode **decorators, + size_t n_decorators); + + es2panda_ModifierFlags (*AstNodeModifierFlags)(es2panda_AstNode *ast); + + void (*AstNodeForEach)(es2panda_AstNode *ast, void (*func)(es2panda_AstNode *, void *), void *arg); + + bool (*IsArrowFunctionExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateArrowFunctionExpression)(es2panda_Context *context, es2panda_AstNode *script_function); + es2panda_AstNode *(*ArrowFunctionExpressionScriptFunction)(es2panda_AstNode *ast); + + bool (*IsAsExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateAsExpression)(es2panda_Context *context, es2panda_AstNode *expr, + es2panda_AstNode *type_annotation, bool is_const); + es2panda_AstNode *(*AsExpressionExpr)(es2panda_AstNode *ast); + es2panda_AstNode *(*AsExpressionTypeAnnotation)(es2panda_AstNode *ast); + bool (*AsExpressionIsConst)(es2panda_AstNode *ast); + void (*AsExpressionSetExpr)(es2panda_AstNode *ast, es2panda_AstNode *expr); + void (*AsExpressionSetTypeAnnotation)(es2panda_AstNode *ast, es2panda_AstNode *type_annotation); + + bool (*IsAssignmentExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateAssignmentExpression)(es2panda_Context *context, es2panda_AstNode *left, + es2panda_AstNode *right, char const *operator_type); + es2panda_AstNode *(*AssignmentExpressionLeft)(es2panda_AstNode *ast); + es2panda_AstNode *(*AssignmentExpressionRight)(es2panda_AstNode *ast); + char const *(*AssignmentExpressionOperatorType)(es2panda_AstNode *ast); + void (*AssignmentExpressionSetOperatorType)(es2panda_AstNode *ast, char const *operator_type); + + bool (*IsBinaryExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreatebinaryExpression)(es2panda_Context *context, es2panda_AstNode *left, + es2panda_AstNode *right, char const *operator_type); + es2panda_AstNode *(*BinaryExpressionLeft)(es2panda_AstNode *ast); + es2panda_AstNode *(*BinaryExpressionRight)(es2panda_AstNode *ast); + char const *(*BinaryExpressionOperator)(es2panda_AstNode *ast); + void (*BinaryExpressionSetOperator)(es2panda_AstNode *ast, char const *operator_type); + + bool (*IsBlockStatement)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateBlockStatement)(es2panda_Context *context, es2panda_AstNode *in_scope_of); + es2panda_AstNode **(*BlockStatementStatements)(es2panda_AstNode *ast, size_t *size_p); + void (*BlockStatementAddStatement)(es2panda_AstNode *ast, es2panda_AstNode *statement); + + bool (*IsCallExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateCallExpression)(es2panda_Context *context, es2panda_AstNode *callee, + es2panda_AstNode *type_arguments, es2panda_AstNode **arguments, + size_t n_arguments, bool optional); + es2panda_AstNode const *(*CallExpressionCallee)(es2panda_AstNode *ast); + es2panda_AstNode const *(*CallExpressionTypeArguments)(es2panda_AstNode *ast); + es2panda_AstNode **(*CallExpressionArguments)(es2panda_AstNode *ast, size_t *size_p); + bool (*CallExpressionIsOptional)(es2panda_AstNode *ast); + void (*CallExpressionSetTypeArguments)(es2panda_AstNode *ast, es2panda_AstNode *type_arguments); + + bool (*IsChainExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateChainExpression)(es2panda_Context *context, es2panda_AstNode *child); + es2panda_AstNode const *(*ChainExpressionChild)(es2panda_AstNode *ast); + + bool (*IsClassDeclaration)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateClassDeclaration)(es2panda_Context *context, es2panda_AstNode *definition); + es2panda_AstNode *(*ClassDeclarationDefinition)(es2panda_AstNode *ast); + + bool (*IsClassDefinition)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateClassDefinition)(es2panda_Context *context, es2panda_AstNode *in_scope_of, + es2panda_AstNode *identifier, es2panda_ModifierFlags flags); + es2panda_AstNode *(*ClassDefinitionIdentifier)(es2panda_AstNode *ast); + es2panda_AstNode *(*ClassDefinitionTypeParameters)(es2panda_AstNode *ast); + es2panda_AstNode *(*ClassDefinitionSuperClass)(es2panda_AstNode *ast); + es2panda_AstNode **(*ClassDefinitionImplements)(es2panda_AstNode *ast, size_t *size_p); + es2panda_AstNode *(*ClassDefinitionConstructor)(es2panda_AstNode *ast); + es2panda_AstNode **(*ClassDefinitionBody)(es2panda_AstNode *ast, size_t *size_p); + void (*ClassDefinitionSetIdentifier)(es2panda_AstNode *ast, es2panda_AstNode *identifier); + void (*ClassDefinitionSetTypeParameters)(es2panda_AstNode *ast, es2panda_AstNode *type_params); + void (*ClassDefinitionSetSuperClass)(es2panda_AstNode *ast, es2panda_AstNode *super_class); + void (*ClassDefinitionSetImplements)(es2panda_AstNode *ast, es2panda_AstNode **implements, size_t n_implements); + void (*ClassDefinitionAddImplements)(es2panda_AstNode *ast, es2panda_AstNode *implements); + void (*ClassDefinitionSetConstructor)(es2panda_AstNode *ast, es2panda_AstNode *constructor); + void (*ClassDefinitonSetBody)(es2panda_AstNode *ast, es2panda_AstNode **body, size_t n_elems); + void (*ClassDefinitonAddToBody)(es2panda_AstNode *ast, es2panda_AstNode *statement); + + es2panda_AstNode *(*ClassElementKey)(es2panda_AstNode *ast); + es2panda_AstNode *(*ClassElementValue)(es2panda_AstNode *ast); + + bool (*IsClassImplementsClause)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateClassImplementsClause)(es2panda_Context *context, es2panda_AstNode *expression, + es2panda_AstNode *type_arguments); + es2panda_AstNode *(*ClassImplementsClauseExpression)(es2panda_AstNode *ast); + es2panda_AstNode const *(*ClassImplementsClauseTypeArguments)(es2panda_AstNode *ast); + + bool (*IsClassProperty)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateClassProperty)(es2panda_Context *context, es2panda_AstNode *key, es2panda_AstNode *value, + es2panda_AstNode *type_annotation, es2panda_ModifierFlags modifier_flags, + bool is_computed); + es2panda_AstNode *(*ClassPropertyTypeAnnotation)(es2panda_AstNode *ast); + + bool (*IsExpressionStatement)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateExpressionStatement)(es2panda_Context *context, es2panda_AstNode *expression); + es2panda_AstNode *(*ExpressionStatementExpression)(es2panda_AstNode *ast); + + bool (*IsFunctionDeclaration)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateFunctionDeclaration)(es2panda_Context *context, es2panda_AstNode *function); + es2panda_AstNode *(*FunctionDeclarationFunction)(es2panda_AstNode *ast); + + bool (*IsFunctionExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateFunctionExpression)(es2panda_Context *context, es2panda_AstNode *function); + es2panda_AstNode *(*FunctionExpressionFunction)(es2panda_AstNode *ast); + + bool (*IsFunctionTypeNode)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateFunctionTypeNode)(es2panda_Context *context, es2panda_AstNode *in_scope_of, + es2panda_AstNode *type_params, es2panda_AstNode **params, + size_t n_params, es2panda_AstNode *return_type, + es2panda_ScriptFunctionFlags func_flags); + es2panda_AstNode const *(*FunctionTypeNodeTypeParams)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*FunctionTypeNodeParams)(es2panda_AstNode *ast, size_t *size_p); + es2panda_AstNode *(*FunctionTypeNodeReturnType)(es2panda_AstNode *ast); + es2panda_ScriptFunctionFlags (*FunctionTypeNodeFlags)(es2panda_AstNode *ast); + + bool (*IsIdentifier)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateIdentifier)(es2panda_Context *context, char const *name, + es2panda_AstNode *type_annotation); + char const *(*IdentifierName)(es2panda_Context *context, es2panda_AstNode *identifier); + es2panda_AstNode *(*IdentifierTypeAnnotation)(es2panda_AstNode *identifier); + es2panda_Variable *(*IdentifierVariable)(es2panda_AstNode *identifier); + void (*IdentifierSetVariable)(es2panda_AstNode *identifier, es2panda_Variable *variable); + + bool (*IsIfStatement)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateIfStatement)(es2panda_Context *context, es2panda_AstNode *test, + es2panda_AstNode *consequent, es2panda_AstNode *alternate); + es2panda_AstNode const *(*IfStatementTest)(es2panda_AstNode *ast); + es2panda_AstNode const *(*IfStatementConsequent)(es2panda_AstNode *ast); + es2panda_AstNode const *(*IfStatementAlternate)(es2panda_AstNode *ast); + + bool (*IsImportDeclaration)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateImportDeclaration)(es2panda_Context *context, es2panda_AstNode *source, + es2panda_AstNode **specifiers, size_t n_specifiers); + es2panda_AstNode const *(*ImportDeclarationSource)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*ImportDeclarationSpecifiers)(es2panda_AstNode *ast, size_t *size_p); + + bool (*IsImportExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateImportExpression)(es2panda_Context *context, es2panda_AstNode *source); + es2panda_AstNode *(*ImportExpressionSource)(es2panda_AstNode *ast); + + bool (*IsImportSpecifier)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateImportSpecifier)(es2panda_Context *context, es2panda_AstNode *imported, + es2panda_AstNode *local); + es2panda_AstNode *(*ImportSpecifierImported)(es2panda_AstNode *ast); + es2panda_AstNode *(*ImportSpecifierLocal)(es2panda_AstNode *ast); + + bool (*IsMemberExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateMemberExpression)(es2panda_Context *context, es2panda_AstNode *object, + es2panda_AstNode *property, es2panda_MemberExpressionKind kind, + bool is_computed, bool is_optional); + es2panda_AstNode *(*MemberExpressionObject)(es2panda_AstNode *ast); + es2panda_AstNode *(*MemberExpressionProperty)(es2panda_AstNode *ast); + es2panda_MemberExpressionKind (*MemberExpressionKind)(es2panda_AstNode *ast); + bool (*MemberExpressionIsComputed)(es2panda_AstNode *ast); + bool (*MemberExpressionIsOptional)(es2panda_AstNode *ast); + + bool (*IsMethodDefinition)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateMethodDefinition)(es2panda_Context *context, char const *kind, es2panda_AstNode *key, + es2panda_AstNode *value, es2panda_ModifierFlags modifiers, + bool is_computed); + char const *(*MethodDefinitionKind)(es2panda_AstNode *ast); + es2panda_AstNode const *(*MethodDefinitionKey)(es2panda_AstNode *ast); + es2panda_AstNode const *(*MethodDefinitionValue)(es2panda_AstNode *ast); + es2panda_ModifierFlags (*MethodDefinitionModifiers)(es2panda_AstNode *ast); + bool (*MethodDefinitionIsComputed)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*MethodDefinitionOverloads)(es2panda_AstNode *ast, size_t *size_p); + void (*MethodDefinitionSetOverloads)(es2panda_AstNode *ast, es2panda_AstNode **overloads, size_t n_overloads); + void (*MethodDefinitionAddOverload)(es2panda_AstNode *ast, es2panda_AstNode *overload); + + bool (*IsNewClassInstanceExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateNewClassInstanceExpression)(es2panda_Context *context, es2panda_AstNode *type_reference, + es2panda_AstNode **arguments, size_t n_arguments, + es2panda_AstNode *class_definition); + es2panda_AstNode *(*NewClassInstanceExpressionTypeReference)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*NewClassInstanceExpressionArguments)(es2panda_AstNode *ast, size_t *size_p); + es2panda_AstNode *(*NewClassInstanceExpressionClassDefinition)(es2panda_AstNode *ast); + + bool (*IsNewArrayInstanceExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateNewArrayInstanceExpression)(es2panda_Context *context, es2panda_AstNode *type_reference, + es2panda_AstNode *dimension); + es2panda_AstNode *(*NewArrayInstanceExpressionTypeReference)(es2panda_AstNode *ast); + es2panda_AstNode *(*NewArrayInstanceExpressionDimension)(es2panda_AstNode *ast); + + bool (*IsNewMultiDimArrayInstanceExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateNewMultiDimArrayInstanceExpression)(es2panda_Context *context, + es2panda_AstNode *type_reference, + es2panda_AstNode **dimensions, size_t n_dimensions); + es2panda_AstNode *(*NewMultiDimArrayInstanceExpressionTypeReference)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*NewMultiDimArrayInstanceExpressionDimensions)(es2panda_AstNode *ast, size_t *size_p); + + bool (*IsNonNullExpression)(es2panda_AstNode *ast); + bool (*IsNumberLiteral)(es2panda_AstNode *ast); + bool (*IsObjectExpression)(es2panda_AstNode *ast); + + bool (*IsParameterDeclaration)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateParameterDeclaration)(es2panda_Context *context, es2panda_AstNode *identifier_or_spread, + es2panda_AstNode *initializer); + es2panda_AstNode *(*ParameterDeclarationIdentifierOrSpread)(es2panda_AstNode *ast); + es2panda_AstNode *(*ParameterDeclarationInitializer)(es2panda_AstNode *ast); + + bool (*IsPrimitiveTypeNode)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreatePrimitiveTypeNode)(es2panda_Context *context, char const *type); + char const *(*PrimitiveTypeNodeType)(es2panda_AstNode *ast); + + bool (*IsReturnStatement)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreatereturnStatement)(es2panda_Context *context, es2panda_AstNode *argument); + es2panda_AstNode *(*ReturnStatementArgument)(es2panda_AstNode *ast); + es2panda_Type *(*ReturnStatementReturnType)(es2panda_AstNode *ast); + + bool (*IsScriptFunction)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateScriptFunction)(es2panda_Context *context, es2panda_AstNode *type_params, + es2panda_AstNode **params, size_t n_params, + es2panda_AstNode *return_type_annotation, + es2panda_ScriptFunctionFlags function_flags, + es2panda_ModifierFlags modifier_flags, bool is_declare, + es2panda_AstNode *in_scope_of); + es2panda_AstNode *(*ScriptFunctionTypeParams)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*ScriptFunctionParams)(es2panda_AstNode *ast, size_t *size_p); + es2panda_AstNode *(*ScriptFunctionReturnTypeAnnotation)(es2panda_AstNode *ast); + es2panda_ScriptFunctionFlags (*ScriptFunctionScriptFunctionFlags)(es2panda_AstNode *ast); + bool (*ScriptFunctionIsDeclare)(es2panda_AstNode *ast); + es2panda_AstNode *(*ScriptFunctionIdentifier)(es2panda_AstNode *ast); + es2panda_AstNode *(*ScriptFunctionBody)(es2panda_AstNode *ast); + void (*ScriptFunctionSetIdentifier)(es2panda_AstNode *ast, es2panda_AstNode *ident); + void (*ScriptFunctionSetBody)(es2panda_AstNode *ast, es2panda_AstNode *body); + void (*ScriptFunctionSetParams)(es2panda_AstNode *ast, es2panda_AstNode **params, size_t n_params); + void (*ScripFunctionAddParam)(es2panda_AstNode *ast, es2panda_AstNode *param); + + bool (*IsStringLiteral)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateStringLiteral)(es2panda_Context *context, char const *string); + char const *(*StringLiteralString)(es2panda_Context *context, es2panda_AstNode *ast); + + bool (*IsThisExpression)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateThisExpression)(es2panda_Context *context); + + bool (*IsTypeParameter)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateTypeParameter)(es2panda_Context *context, es2panda_AstNode *name, + es2panda_AstNode *constraint, es2panda_AstNode *defaultType); + es2panda_AstNode const *(*TypeParameterName)(es2panda_AstNode *ast); + es2panda_AstNode const *(*TypeParameterConstraint)(es2panda_AstNode *ast); + es2panda_AstNode const *(*TypeParameterDefaultType)(es2panda_AstNode *ast); + + bool (*IsTypeParameterDeclaration)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateTypeParameterDeclaration)(es2panda_Context *context, es2panda_AstNode *in_scope_of); + void (*TypeParameterDeclarationAddTypeParameter)(es2panda_AstNode *ast, es2panda_AstNode *type_parameter); + es2panda_AstNode *const *(*TypeParameterDeclarationTypeParameters)(es2panda_AstNode *ast, size_t *size_p); + + bool (*IsTypeParameterInstantiation)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateTypeParameterInstantiation)(es2panda_Context *context, es2panda_AstNode **params, + size_t n_params); + es2panda_AstNode *const *(*TypeParameterInstantiationTypeParameters)(es2panda_AstNode *ast, size_t *size_p); + + bool (*IsTypeReferenceNode)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateTypeReferenceNode)(es2panda_Context *context, es2panda_AstNode *part); + es2panda_AstNode *(*TypeRefrenceNodePart)(es2panda_AstNode *ast); + + bool (*IsTypeReferencePart)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateTypeReferencePart)(es2panda_Context *context, es2panda_AstNode *name, + es2panda_AstNode *type_arguments, es2panda_AstNode *previous); + es2panda_AstNode *(*TypeReferencePartName)(es2panda_AstNode *ast); + es2panda_AstNode *(*TypeReferencePartTypeArguments)(es2panda_AstNode *ast); + es2panda_AstNode *(*TypeReferencePartPrevious)(es2panda_AstNode *ast); + + bool (*IsUnionTypeNode)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateUnionTypeNode)(es2panda_Context *context, es2panda_AstNode **types, size_t n_types); + es2panda_AstNode *const *(*UnionTypeNodeTypes)(es2panda_AstNode *ast, size_t *size_p); + + bool (*IsVariableDeclaration)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateVariableDeclaration)(es2panda_Context *context, char const *kind, + es2panda_AstNode **declarators, size_t n_declarators, + bool is_declare); + char const *(*VariableDeclarationKind)(es2panda_AstNode *ast); + es2panda_AstNode *const *(*VariableDeclarationDeclarators)(es2panda_AstNode *ast, size_t *size_p); + bool (*VariableDeclarationIsDeclare)(es2panda_AstNode *ast); + + bool (*IsVariableDeclarator)(es2panda_AstNode *ast); + es2panda_AstNode *(*CreateVariableDeclarator)(es2panda_Context *context, es2panda_AstNode *identifier, + es2panda_AstNode *initializer); + es2panda_AstNode *(*VariableDeclaratorIdentifier)(es2panda_AstNode *ast); + es2panda_AstNode *(*VariableDeclaratorInitializer)(es2panda_AstNode *ast); }; struct es2panda_Impl const *es2panda_GetImpl(int version); diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h new file mode 100644 index 0000000000..81c04023c1 --- /dev/null +++ b/ets2panda/public/public.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2021-2022 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_PUBLIC_PUBLIC_H +#define ES2PANDA_PUBLIC_PUBLIC_H + +#include "public/es2panda_lib.h" + +#include "assembler/assembly-program.h" +#include "libpandabase/mem/arena_allocator.h" + +#include "es2panda.h" +#include "compiler/core/compileQueue.h" +#include "parser/ETSparser.h" +#include "checker/checker.h" +#include "compiler/core/emitter.h" +#include "util/options.h" + +namespace panda::es2panda::compiler { +class Phase; +} // namespace panda::es2panda::compiler + +namespace panda::es2panda::public_lib { +struct ConfigImpl { + util::Options *options; +}; + +struct Context { + ConfigImpl *config = nullptr; + std::string source_file_name; + std::string input; + SourceFile const *source_file = nullptr; + ArenaAllocator *allocator = nullptr; + compiler::CompileQueue *queue = nullptr; + std::vector const *plugins = nullptr; + std::vector phases; + size_t current_phase = 0; + + parser::Program *parser_program = nullptr; + parser::ParserImpl *parser = nullptr; + checker::Checker *checker = nullptr; + checker::SemanticAnalyzer *analyzer = nullptr; + compiler::CompilerContext *compiler_context = nullptr; + compiler::Emitter *emitter = nullptr; + pandasm::Program *program = nullptr; + + es2panda_ContextState state = ES2PANDA_STATE_NEW; + std::string error_message; + lexer::SourcePosition error_pos; +}; +} // namespace panda::es2panda::public_lib + +#endif diff --git a/ets2panda/test/CMakeLists.txt b/ets2panda/test/CMakeLists.txt index ba88fb843f..f30dfa56a4 100644 --- a/ets2panda/test/CMakeLists.txt +++ b/ets2panda/test/CMakeLists.txt @@ -76,7 +76,7 @@ if(PANDA_WITH_ETS) endforeach() panda_add_gtest( - NAME es2panda_public_tests + NAME es2panda_public_test SOURCES unit/public/es2panda_public_test.cpp LIBRARIES @@ -85,7 +85,21 @@ if(PANDA_WITH_ETS) ${CMAKE_CURRENT_SOURCE_DIR}/.. SANITIZERS ${PANDA_SANITIZERS_LIST} + ) + + panda_add_library(e2p_test_plugin SHARED unit/public/e2p_test_plugin.c) + panda_target_include_directories(e2p_test_plugin PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..") + panda_target_link_libraries(e2p_test_plugin es2panda-public) + + add_custom_target(es2panda-plugin-test + COMMENT "Test es2panda plugin functionality" + COMMAND ${CMAKE_COMMAND} -E env LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} $ --plugins=e2p_test_plugin + "${CMAKE_CURRENT_SOURCE_DIR}/unit/public/t.ets" > "${CMAKE_CURRENT_BINARY_DIR}/plugin_test.out" + COMMAND ${CMAKE_COMMAND} -E compare_files + "${CMAKE_CURRENT_BINARY_DIR}/plugin_test.out" "${CMAKE_CURRENT_SOURCE_DIR}/unit/public/plugin_test.expected.txt" ) + add_dependencies(es2panda-plugin-test es2panda e2p_test_plugin) + add_dependencies(es2panda_tests es2panda-plugin-test) add_dependencies(es2panda_tests es2panda-regression-tests) if(TARGET ets_tests) diff --git a/ets2panda/test/unit/public/e2p_test_plugin.c b/ets2panda/test/unit/public/e2p_test_plugin.c new file mode 100644 index 0000000000..2de3ca54a7 --- /dev/null +++ b/ets2panda/test/unit/public/e2p_test_plugin.c @@ -0,0 +1,57 @@ +/** + * 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. + */ + +// No linting for pure C file +// NOLINTBEGIN + +#include +#include + +#include "public/es2panda_lib.h" + +static struct es2panda_Impl const *impl = NULL; + +void e2p_test_plugin_Initialize() +{ + puts("Hi there!"); + impl = es2panda_GetImpl(ES2PANDA_LIB_VERSION); +} + +static void PrintIfIdentifier(es2panda_AstNode *node, void *arg) +{ + es2panda_Context *ctx = arg; + if (impl->IsIdentifier(node)) { + puts(impl->IdentifierName(ctx, node)); + } +} + +void e2p_test_plugin_AfterParse(es2panda_Context *ctx) +{ + puts("After parse"); + es2panda_AstNode *ast = impl->ProgramAst(impl->ContextProgram(ctx)); + impl->AstNodeForEach(ast, PrintIfIdentifier, ctx); +} + +void e2p_test_plugin_AfterCheck(es2panda_Context *ctx) +{ + puts("After check"); +} + +void e2p_test_plugin_AfterLowerings(es2panda_Context *ctx) +{ + puts("After lowerings"); +} + +// NOLINTEND diff --git a/ets2panda/test/unit/public/es2panda_public_test.cpp b/ets2panda/test/unit/public/es2panda_public_test.cpp index 03846b4edb..723fd07de0 100644 --- a/ets2panda/test/unit/public/es2panda_public_test.cpp +++ b/ets2panda/test/unit/public/es2panda_public_test.cpp @@ -53,10 +53,51 @@ TEST_F(Es2PandaLibTest, NoError) TEST_F(Es2PandaLibTest, TypeError) { es2panda_Context *ctx = - impl_->CreateContextFromString(cfg_, "function main() { let x: int = \"\" }", "no-error.ets"); - impl_->ProceedToState(ctx, ES2PANDA_STATE_ASM_GENERATED); // don't produce any object files + impl_->CreateContextFromString(cfg_, "function main() { let x: int = \"\" }", "type-error.ets"); + impl_->ProceedToState(ctx, ES2PANDA_STATE_ASM_GENERATED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_ERROR); ASSERT_EQ(std::string(impl_->ContextErrorMessage(ctx)), - "TypeError: Initializers type is not assignable to the target type[no-error.ets:1,32]"); + "TypeError: Initializers type is not assignable to the target type[type-error.ets:1,32]"); + impl_->DestroyContext(ctx); +} + +TEST_F(Es2PandaLibTest, ListIdentifiers) +{ + char const *text = R"XXX( +class C { + n: string = "oh" +} + +function main() { + let c = new C + console.log(c.n + 1) // type error, but not syntax error +} +)XXX"; + es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "list-ids.ets"); + ctx = impl_->ProceedToState(ctx, ES2PANDA_STATE_PARSED); + ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_PARSED); + + struct Arg { + es2panda_Impl const *impl = nullptr; + es2panda_Context *ctx = nullptr; + std::vector ids; + } arg; + arg.impl = impl_; + arg.ctx = ctx; + + auto func = [](es2panda_AstNode *ast, void *argp) { + auto *a = reinterpret_cast(argp); + if (a->impl->IsIdentifier(ast)) { + a->ids.emplace_back(a->impl->IdentifierName(a->ctx, ast)); + } + }; + + impl_->AstNodeForEach(impl_->ProgramAst(impl_->ContextProgram(ctx)), func, &arg); + + std::vector expected {"C", "n", "string", "constructor", "constructor", "ETSGLOBAL", + "_$init$_", "_$init$_", "main", "main", "c", "C", + "console", "log", "c", "n", ""}; + ASSERT_EQ(arg.ids, expected); + impl_->DestroyContext(ctx); } diff --git a/ets2panda/test/unit/public/plugin_test.expected.txt b/ets2panda/test/unit/public/plugin_test.expected.txt new file mode 100644 index 0000000000..f578824e84 --- /dev/null +++ b/ets2panda/test/unit/public/plugin_test.expected.txt @@ -0,0 +1,16 @@ +Hi there! +After parse +ETSGLOBAL +_$init$_ +_$init$_ +main +main +m +n +console +log +m +n + +After check +After lowerings diff --git a/ets2panda/test/unit/public/t.ets b/ets2panda/test/unit/public/t.ets new file mode 100644 index 0000000000..56969fa7e1 --- /dev/null +++ b/ets2panda/test/unit/public/t.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() { + let m: int = 1 + let n: int = 2 + console.log(m + n) +} diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 60e35b3075..f05099ad67 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -41,21 +41,31 @@ Options::~Options() delete argparser_; } -static std::unordered_set StringToStringSet(const std::string &str) +static std::vector SplitToStringVector(std::string const &str) { - std::unordered_set res; + std::vector res; std::string_view curr_str {str}; auto ix = curr_str.find(','); while (ix != std::string::npos) { if (ix != 0) { - res.insert(std::string(curr_str.substr(0, ix))); + res.emplace_back(curr_str.substr(0, ix)); } curr_str = curr_str.substr(ix + 1); ix = curr_str.find(','); } if (!curr_str.empty()) { - res.insert(std::string(curr_str)); + res.emplace_back(curr_str); + } + return res; +} + +static std::unordered_set SplitToStringSet(std::string const &str) +{ + std::vector vec = SplitToStringVector(str); + std::unordered_set res; + for (auto &elem : vec) { + res.emplace(elem); } return res; } @@ -167,6 +177,7 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg log_level("log-level", "error", "Log-level"); panda::PandArg std_lib("stdlib", "", "Path to standard library"); panda::PandArg gen_std_lib("gen-stdlib", false, "Gen standard library"); + panda::PandArg plugins("plugins", "", "Plugins"); panda::PandArg skip_phases("skip-phases", "", "Phases to skip"); panda::PandArg dump_before_phases("dump-before-phases", "", "Generate program dump before running phases in the list"); @@ -198,6 +209,7 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&log_level); argparser_->Add(&std_lib); argparser_->Add(&gen_std_lib); + argparser_->Add(&plugins); argparser_->Add(&skip_phases); argparser_->Add(&dump_before_phases); argparser_->Add(&dump_after_phases); @@ -387,9 +399,10 @@ bool Options::Parse(int argc, const char **argv) compiler_options_.std_lib = std_lib.GetValue(); compiler_options_.compilation_mode = compilation_mode; compiler_options_.is_ets_module = op_ets_module.GetValue(); - compiler_options_.skip_phases = StringToStringSet(skip_phases.GetValue()); - compiler_options_.dump_before_phases = StringToStringSet(dump_before_phases.GetValue()); - compiler_options_.dump_after_phases = StringToStringSet(dump_after_phases.GetValue()); + compiler_options_.plugins = SplitToStringVector(plugins.GetValue()); + compiler_options_.skip_phases = SplitToStringSet(skip_phases.GetValue()); + compiler_options_.dump_before_phases = SplitToStringSet(dump_before_phases.GetValue()); + compiler_options_.dump_after_phases = SplitToStringSet(dump_after_phases.GetValue()); return true; } diff --git a/ets2panda/util/plugin.cpp b/ets2panda/util/plugin.cpp new file mode 100644 index 0000000000..74c1e273fd --- /dev/null +++ b/ets2panda/util/plugin.cpp @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2021-2022 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 "plugin.h" +#include "os/library_loader.h" + +namespace panda::es2panda::util { + +std::string Plugin::FullNameForProcedure(std::string const &short_name) +{ + return std::string(name_.Utf8()) + "_" + short_name; +} + +Plugin::Plugin(util::StringView const &name) : name_ {name}, err_ {0}, h_ {nullptr} +{ + std::string so_name = + os::library_loader::DYNAMIC_LIBRARY_PREFIX + std::string(name) + os::library_loader::DYNAMIC_LIBRARY_SUFFIX; + if (auto load_res = os::library_loader::Load(so_name); load_res.HasValue()) { + h_ = std::move(load_res.Value()); + } else { + err_ = load_res.Error(); + ok_ = false; + } + + if (auto init_res = os::library_loader::ResolveSymbol(h_, FullNameForProcedure("Initialize")); + init_res.HasValue()) { + initialize_ = reinterpret_cast(init_res.Value()); + } + + if (auto ap_res = os::library_loader::ResolveSymbol(h_, FullNameForProcedure("AfterParse")); ap_res.HasValue()) { + after_parse_ = reinterpret_cast(ap_res.Value()); + } + + if (auto ac_res = os::library_loader::ResolveSymbol(h_, FullNameForProcedure("AfterCheck")); ac_res.HasValue()) { + after_check_ = reinterpret_cast(ac_res.Value()); + } + + if (auto al_res = os::library_loader::ResolveSymbol(h_, FullNameForProcedure("AfterLowerings")); + al_res.HasValue()) { + after_lowerings_ = reinterpret_cast(al_res.Value()); + } +} + +} // namespace panda::es2panda::util diff --git a/ets2panda/util/plugin.h b/ets2panda/util/plugin.h new file mode 100644 index 0000000000..74fd3c8856 --- /dev/null +++ b/ets2panda/util/plugin.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2021-2022 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_UTIL_PLUGINS_H +#define ES2PANDA_UTIL_PLUGINS_H + +#include "macros.h" +#include "os/library_loader.h" +#include "public/es2panda_lib.h" +#include "util/ustring.h" + +namespace panda::es2panda::util { + +class Plugin { +public: + explicit Plugin(util::StringView const &name); + ~Plugin() = default; + + NO_COPY_SEMANTIC(Plugin); + DEFAULT_MOVE_SEMANTIC(Plugin); + + bool IsOk() + { + return ok_; + } + + os::Error Error() + { + return err_; + } + + void Initialize() const + { + if (initialize_ != nullptr) { + initialize_(); + } + } + + void AfterParse(es2panda_Context *context) const + { + if (after_parse_ != nullptr) { + after_parse_(context); + } + } + + void AfterCheck(es2panda_Context *context) const + { + if (after_check_ != nullptr) { + after_check_(context); + } + } + + void AfterLowerings(es2panda_Context *context) const + { + if (after_lowerings_ != nullptr) { + after_lowerings_(context); + } + } + +private: + std::string FullNameForProcedure(std::string const &short_name); + + util::StringView name_; + bool ok_ {true}; + os::Error err_; + os::library_loader::LibraryHandle h_; + + void (*initialize_)() = nullptr; + void (*after_parse_)(es2panda_Context *) = nullptr; + void (*after_check_)(es2panda_Context *) = nullptr; + void (*after_lowerings_)(es2panda_Context *) = nullptr; +}; + +} // namespace panda::es2panda::util + +#endif -- Gitee