From 4c6a5bd68fb96191f9796c05c57292ffd52d12fb Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Tue, 7 Nov 2023 14:09:27 +0300 Subject: [PATCH 1/3] Support lambdas subtyping Change-Id: I6d5fcbcd395ac35ad121da684046e6d29f9266b0 Signed-off-by: Konstantin Baladurin Signed-off-by: Georgy Bronnikov --- ets2panda/checker/ETSAnalyzer.cpp | 85 +- ets2panda/checker/ETSchecker.cpp | 114 +- ets2panda/checker/ETSchecker.h | 38 +- ets2panda/checker/ets/function.cpp | 551 +++-- ets2panda/checker/ets/function_helpers.h | 11 +- ets2panda/checker/ets/helpers.cpp | 101 +- ets2panda/checker/ets/object.cpp | 35 +- ets2panda/checker/types/ets/byteType.h | 4 +- ets2panda/checker/types/ets/charType.h | 2 +- ets2panda/checker/types/ets/doubleType.h | 2 +- ets2panda/checker/types/ets/etsArrayType.cpp | 11 +- ets2panda/checker/types/ets/etsArrayType.h | 2 +- .../types/ets/etsAsyncFuncReturnType.cpp | 6 +- .../types/ets/etsAsyncFuncReturnType.h | 2 +- ets2panda/checker/types/ets/etsBigIntType.h | 2 +- ets2panda/checker/types/ets/etsBooleanType.h | 2 +- ets2panda/checker/types/ets/etsEnumType.cpp | 2 +- ets2panda/checker/types/ets/etsEnumType.h | 2 +- .../types/ets/etsExtensionFuncHelperType.cpp | 6 +- .../types/ets/etsExtensionFuncHelperType.h | 2 +- .../checker/types/ets/etsFunctionType.cpp | 96 +- ets2panda/checker/types/ets/etsFunctionType.h | 5 +- ets2panda/checker/types/ets/etsObjectType.cpp | 270 ++- ets2panda/checker/types/ets/etsObjectType.h | 39 +- ets2panda/checker/types/ets/etsStringType.h | 4 +- ets2panda/checker/types/ets/etsTupleType.cpp | 6 +- ets2panda/checker/types/ets/etsTupleType.h | 2 +- .../checker/types/ets/etsTypeParameter.cpp | 7 +- .../checker/types/ets/etsTypeParameter.h | 2 +- ets2panda/checker/types/ets/etsUnionType.cpp | 4 +- ets2panda/checker/types/ets/etsUnionType.h | 2 +- ets2panda/checker/types/ets/etsVoidType.h | 2 +- ets2panda/checker/types/ets/floatType.h | 2 +- ets2panda/checker/types/ets/intType.h | 2 +- ets2panda/checker/types/ets/longType.h | 2 +- ets2panda/checker/types/ets/shortType.h | 2 +- ets2panda/checker/types/ets/wildcardType.cpp | 2 +- ets2panda/checker/types/ets/wildcardType.h | 2 +- ets2panda/checker/types/globalTypesHolder.cpp | 26 + ets2panda/checker/types/globalTypesHolder.h | 23 + ets2panda/checker/types/signature.cpp | 44 +- ets2panda/checker/types/signature.h | 7 +- ets2panda/checker/types/ts/anyType.cpp | 2 +- ets2panda/checker/types/ts/anyType.h | 2 +- ets2panda/checker/types/ts/arrayType.cpp | 4 +- ets2panda/checker/types/ts/arrayType.h | 2 +- .../checker/types/ts/bigintLiteralType.cpp | 2 +- .../checker/types/ts/bigintLiteralType.h | 2 +- ets2panda/checker/types/ts/bigintType.cpp | 2 +- ets2panda/checker/types/ts/bigintType.h | 2 +- .../checker/types/ts/booleanLiteralType.cpp | 2 +- .../checker/types/ts/booleanLiteralType.h | 2 +- ets2panda/checker/types/ts/booleanType.cpp | 2 +- ets2panda/checker/types/ts/booleanType.h | 2 +- .../checker/types/ts/constructorType.cpp | 2 +- ets2panda/checker/types/ts/constructorType.h | 2 +- .../checker/types/ts/enumLiteralType.cpp | 2 +- ets2panda/checker/types/ts/enumLiteralType.h | 2 +- ets2panda/checker/types/ts/enumType.cpp | 2 +- ets2panda/checker/types/ts/enumType.h | 3 +- ets2panda/checker/types/ts/functionType.cpp | 2 +- ets2panda/checker/types/ts/functionType.h | 2 +- ets2panda/checker/types/ts/interfaceType.cpp | 2 +- ets2panda/checker/types/ts/interfaceType.h | 2 +- ets2panda/checker/types/ts/neverType.cpp | 2 +- ets2panda/checker/types/ts/neverType.h | 2 +- .../checker/types/ts/nonPrimitiveType.cpp | 2 +- ets2panda/checker/types/ts/nonPrimitiveType.h | 2 +- ets2panda/checker/types/ts/nullType.cpp | 2 +- ets2panda/checker/types/ts/nullType.h | 2 +- .../checker/types/ts/numberLiteralType.cpp | 2 +- .../checker/types/ts/numberLiteralType.h | 2 +- ets2panda/checker/types/ts/numberType.cpp | 2 +- ets2panda/checker/types/ts/numberType.h | 2 +- .../checker/types/ts/objectLiteralType.cpp | 2 +- .../checker/types/ts/objectLiteralType.h | 2 +- .../checker/types/ts/stringLiteralType.cpp | 2 +- .../checker/types/ts/stringLiteralType.h | 2 +- ets2panda/checker/types/ts/stringType.cpp | 2 +- ets2panda/checker/types/ts/stringType.h | 2 +- ets2panda/checker/types/ts/tupleType.cpp | 6 +- ets2panda/checker/types/ts/tupleType.h | 2 +- ets2panda/checker/types/ts/typeParameter.cpp | 2 +- ets2panda/checker/types/ts/typeParameter.h | 2 +- ets2panda/checker/types/ts/typeReference.cpp | 4 +- ets2panda/checker/types/ts/typeReference.h | 2 +- ets2panda/checker/types/ts/undefinedType.cpp | 2 +- ets2panda/checker/types/ts/undefinedType.h | 2 +- ets2panda/checker/types/ts/unionType.cpp | 4 +- ets2panda/checker/types/ts/unionType.h | 2 +- ets2panda/checker/types/ts/unknownType.cpp | 2 +- ets2panda/checker/types/ts/unknownType.h | 2 +- ets2panda/checker/types/ts/voidType.cpp | 2 +- ets2panda/checker/types/ts/voidType.h | 2 +- ets2panda/checker/types/type.cpp | 27 + ets2panda/checker/types/type.h | 7 +- ets2panda/checker/types/typeFlag.h | 2 +- ets2panda/compiler/core/ETSCompiler.cpp | 94 +- ets2panda/compiler/core/ETSCompiler.h | 3 +- ets2panda/compiler/core/ETSGen.cpp | 9 +- ets2panda/compiler/core/ETSGen.h | 27 +- ets2panda/compiler/scripts/signatures.yaml | 60 +- ets2panda/ir/ets/etsFunctionType.h | 5 + ets2panda/ir/ts/tsAsExpression.h | 5 + .../compiler/ets/FunctionType1-expected.txt | 2 +- .../compiler/ets/FunctionType3-expected.txt | 2 +- .../ets/etsObjectToString4-expected.txt | 2 +- .../ets/etsObjectToString5-expected.txt | 2 +- .../ets/function_subtyping_1-expected.txt | 997 +++++++++ .../compiler/ets/function_subtyping_1.ets | 21 + .../ets/function_subtyping_2-expected.txt | 998 +++++++++ .../compiler/ets/function_subtyping_2.ets | 21 + .../ets/function_subtyping_3-expected.txt | 998 +++++++++ .../compiler/ets/function_subtyping_3.ets | 21 + .../ets/generic_variance_1-expected.txt | 1973 +++++++++++++++++ .../test/compiler/ets/generic_variance_1.ets | 28 + .../ets/generic_variance_2-expected.txt | 1218 ++++++++++ .../test/compiler/ets/generic_variance_2.ets | 24 + .../ets/generic_variance_3-expected.txt | 1218 ++++++++++ .../test/compiler/ets/generic_variance_3.ets | 24 + .../ets/generic_variance_4-expected.txt | 1178 ++++++++++ .../test/compiler/ets/generic_variance_4.ets | 24 + .../ets/generic_variance_5-expected.txt | 1178 ++++++++++ .../test/compiler/ets/generic_variance_5.ets | 24 + .../ets/identifierReference2-expected.txt | 2 +- ...utBlockStatementDifferentType-expected.txt | 2 +- .../compiler/ets/lambdaFunction3-expected.txt | 2 +- .../compiler/ets/lambdaFunction5-expected.txt | 2 +- ...mbda_cast_infer_type_widening-expected.txt | 96 +- .../lambda_cast_infer_type_widening.ets | 4 +- ...odOverrideCovariantReturnType-expected.txt | 1 - ...ullableTypeParamToNonNullable-expected.txt | 2 +- ...ericWithNullableTypeParamToNonNullable.ets | 2 +- .../ets/overload_with_generics-expected.txt | 1209 ++++++++++ .../compiler/ets/overload_with_generics.ets | 25 + .../test/compiler/ets/override16-expected.txt | 2 +- ...unction_implicit_return_type2-expected.txt | 2 +- ...unction_implicit_return_type3-expected.txt | 2 +- .../test/parser/ets/interface-expected.txt | 4 +- ets2panda/test/parser/ets/interface.ets | 2 +- .../lambda-type-inference-neg-expected.txt | 2 +- ...a-type-inference-overloaded-1-expected.txt | 2 +- .../runtime/ets/conversion-char-boolean.ets | 2 +- .../runtime/ets/unboxingBooleanConversion.ets | 3 +- .../ets-runtime/ets-runtime-ignored.txt | 9 + .../test-lists/parser/parser-ets-ignored.txt | 14 + .../test-lists/parser/parser-js-ignored.txt | 7 +- ets2panda/util/declgenEts2Ts.cpp | 3 +- ets2panda/varbinder/ETSBinder.cpp | 59 +- ets2panda/varbinder/ETSBinder.h | 2 - 150 files changed, 12565 insertions(+), 735 deletions(-) create mode 100644 ets2panda/test/compiler/ets/function_subtyping_1-expected.txt create mode 100644 ets2panda/test/compiler/ets/function_subtyping_1.ets create mode 100644 ets2panda/test/compiler/ets/function_subtyping_2-expected.txt create mode 100644 ets2panda/test/compiler/ets/function_subtyping_2.ets create mode 100644 ets2panda/test/compiler/ets/function_subtyping_3-expected.txt create mode 100644 ets2panda/test/compiler/ets/function_subtyping_3.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_1-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_1.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_2-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_2.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_3-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_3.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_4-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_4.ets create mode 100644 ets2panda/test/compiler/ets/generic_variance_5-expected.txt create mode 100644 ets2panda/test/compiler/ets/generic_variance_5.ets create mode 100644 ets2panda/test/compiler/ets/overload_with_generics-expected.txt create mode 100644 ets2panda/test/compiler/ets/overload_with_generics.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 810934b8e5..050613b400 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -411,57 +411,50 @@ checker::Type *ETSAnalyzer::Check(ir::ETSClassLiteral *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSFunctionType *node) const { ETSChecker *checker = GetETSChecker(); - checker->CreateFunctionalInterfaceForFunctionType(node); - auto *interfaceType = - checker->CreateETSObjectType(node->FunctionalInterface()->Id()->Name(), node->FunctionalInterface(), - checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); - interfaceType->SetSuperType(checker->GlobalETSObjectType()); - - auto *invokeFunc = node->FunctionalInterface()->Body()->Body()[0]->AsMethodDefinition()->Function(); - auto *signatureInfo = checker->Allocator()->New(checker->Allocator()); - - for (auto *it : invokeFunc->Params()) { - auto *const param = it->AsETSParameterExpression(); - if (param->IsRestParameter()) { - auto *restIdent = param->Ident(); - - ASSERT(restIdent->Variable()); - signatureInfo->restVar = restIdent->Variable()->AsLocalVariable(); - - ASSERT(param->TypeAnnotation()); - signatureInfo->restVar->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - - auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); - checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); - } else { - auto *paramIdent = param->Ident(); - - ASSERT(paramIdent->Variable()); - varbinder::Variable *paramVar = paramIdent->Variable(); + auto *genericInterfaceType = checker->GlobalBuiltinFunctionType(node->Params().size()); + node->SetFunctionalInterface(genericInterfaceType->GetDeclNode()->AsTSInterfaceDeclaration()); + + auto *tsType = checker->GetCachedFunctionlInterface(node); + node->SetTsType(tsType); + if (tsType != nullptr) { + return tsType; + } + + auto *substitution = checker->NewSubstitution(); + + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + + auto const ¶ms = node->Params(); + size_t i = 0; + if (params.size() < maxParamsNum) { + for (; i < params.size(); i++) { + auto *paramType = + checker->GetTypeFromTypeAnnotation(params[i]->AsETSParameterExpression()->TypeAnnotation()); + if (paramType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + checker->Relation()->SetNode(params[i]); + auto *const boxedTypeArg = checker->PrimitiveTypeAsETSBuiltinType(paramType); + ASSERT(boxedTypeArg); + paramType = boxedTypeArg->Instantiate(checker->Allocator(), checker->Relation(), + checker->GetGlobalTypesHolder()); + } - ASSERT(param->TypeAnnotation()); - paramVar->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); - signatureInfo->params.push_back(paramVar->AsLocalVariable()); - ++signatureInfo->minArgCount; + checker::ETSChecker::EmplaceSubstituted( + substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), paramType); } } - invokeFunc->ReturnTypeAnnotation()->Check(checker); - auto *signature = - checker->Allocator()->New(signatureInfo, node->ReturnType()->GetType(checker), invokeFunc); - signature->SetOwnerVar(invokeFunc->Id()->Variable()->AsLocalVariable()); - signature->AddSignatureFlag(checker::SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); - signature->SetOwner(interfaceType); + auto *returnType = node->ReturnType()->GetType(checker); + if (returnType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + checker->Relation()->SetNode(node->ReturnType()); + auto *const boxedTypeRet = checker->PrimitiveTypeAsETSBuiltinType(returnType); + returnType = + boxedTypeRet->Instantiate(checker->Allocator(), checker->Relation(), checker->GetGlobalTypesHolder()); + } - auto *funcType = checker->CreateETSFunctionType(signature); - invokeFunc->SetSignature(signature); - invokeFunc->Id()->Variable()->SetTsType(funcType); - interfaceType->AddProperty(invokeFunc->Id()->Variable()->AsLocalVariable()); - node->FunctionalInterface()->SetTsType(interfaceType); + checker::ETSChecker::EmplaceSubstituted( + substitution, genericInterfaceType->TypeArguments()[i]->AsETSTypeParameter()->GetOriginal(), returnType); - auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); - thisVar->SetTsType(interfaceType); - checker->BuildFunctionalInterfaceName(node); + auto *interfaceType = genericInterfaceType->Substitute(checker->Relation(), substitution)->AsETSObjectType(); node->SetTsType(interfaceType); return interfaceType; @@ -1016,7 +1009,7 @@ ArenaVector &ChooseSignatures(ETSChecker *checker, checker } if (isFunctionalInterface) { return calleeType->AsETSObjectType() - ->GetOwnProperty("invoke") + ->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) ->TsType() ->AsETSFunctionType() ->CallSignatures(); diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 834464fcb7..e111deca28 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -29,6 +29,73 @@ #include "util/helpers.h" namespace panda::es2panda::checker { + +static util::StringView InitBuiltin(ETSChecker *checker, std::string_view signature) +{ + const auto varMap = checker->VarBinder()->TopScope()->Bindings(); + const auto iterator = varMap.find(signature); + ASSERT(iterator != varMap.end()); + auto *var = iterator->second; + Type *type {nullptr}; + if (var->Declaration()->Node()->IsClassDefinition()) { + type = checker->BuildBasicClassProperties(var->Declaration()->Node()->AsClassDefinition()); + } else { + ASSERT(var->Declaration()->Node()->IsTSInterfaceDeclaration()); + type = checker->BuildBasicInterfaceProperties(var->Declaration()->Node()->AsTSInterfaceDeclaration()); + } + checker->GetGlobalTypesHolder()->InitializeBuiltin(iterator->first, type); + return iterator->first; +} + +static void SetupFunctionalInterface(ETSChecker *checker, ETSObjectType *type) +{ + auto savedContext = SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, type); + checker::ScopeContext scopeCtx(checker, type->GetDeclNode()->Scope()); + checker->ResolveDeclaredMembersOfObject(type); + type->AddObjectFlag(ETSObjectFlags::FUNCTIONAL); + auto *invoke = type->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); + auto *invokeType = invoke->TsType()->AsETSFunctionType(); + ASSERT(invokeType->CallSignatures().size() == 1); + auto *signature = invokeType->CallSignatures()[0]; + signature->AddSignatureFlag(SignatureFlags::FUNCTIONAL_INTERFACE_SIGNATURE); +} + +static void SetupBuiltinMember(ETSChecker *checker, varbinder::Variable *var) +{ + auto *type = var->TsType(); + if (type == nullptr || !type->IsETSObjectType()) { + return; + } + auto *objType = type->AsETSObjectType(); + auto *declNode = var->Declaration()->Node(); + if (declNode->IsClassDefinition()) { + auto savedContext = SavedCheckerContext(checker, checker::CheckerStatus::IN_CLASS, objType); + checker::ScopeContext scopeCtx(checker, declNode->Scope()); + checker->ResolveDeclaredMembersOfObject(objType); + } else if (declNode->IsTSInterfaceDeclaration()) { + auto savedContext = SavedCheckerContext(checker, checker::CheckerStatus::IN_INTERFACE, objType); + checker::ScopeContext scopeCtx(checker, declNode->Scope()); + checker->ResolveDeclaredMembersOfObject(objType); + } +} + +// NOLINTNEXTLINE(modernize-avoid-c-arrays) +static constexpr std::string_view BUILTINS_TO_INIT[] = { + compiler::Signatures::BUILTIN_BOOLEAN_CLASS, compiler::Signatures::BUILTIN_BYTE_CLASS, + compiler::Signatures::BUILTIN_CHAR_CLASS, compiler::Signatures::BUILTIN_SHORT_CLASS, + compiler::Signatures::BUILTIN_INT_CLASS, compiler::Signatures::BUILTIN_LONG_CLASS, + compiler::Signatures::BUILTIN_FLOAT_CLASS, compiler::Signatures::BUILTIN_DOUBLE_CLASS, + compiler::Signatures::BUILTIN_FUNCTION0_CLASS, compiler::Signatures::BUILTIN_FUNCTION1_CLASS, + compiler::Signatures::BUILTIN_FUNCTION2_CLASS, compiler::Signatures::BUILTIN_FUNCTION3_CLASS, + compiler::Signatures::BUILTIN_FUNCTION4_CLASS, compiler::Signatures::BUILTIN_FUNCTION5_CLASS, + compiler::Signatures::BUILTIN_FUNCTION6_CLASS, compiler::Signatures::BUILTIN_FUNCTION7_CLASS, + compiler::Signatures::BUILTIN_FUNCTION8_CLASS, compiler::Signatures::BUILTIN_FUNCTION9_CLASS, + compiler::Signatures::BUILTIN_FUNCTION10_CLASS, compiler::Signatures::BUILTIN_FUNCTION11_CLASS, + compiler::Signatures::BUILTIN_FUNCTION12_CLASS, compiler::Signatures::BUILTIN_FUNCTION13_CLASS, + compiler::Signatures::BUILTIN_FUNCTION14_CLASS, compiler::Signatures::BUILTIN_FUNCTION15_CLASS, + compiler::Signatures::BUILTIN_FUNCTION16_CLASS, compiler::Signatures::BUILTIN_FUNCTIONN_CLASS, +}; + void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) { if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) { @@ -37,17 +104,23 @@ void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) const auto varMap = varbinder->TopScope()->Bindings(); - auto initBuiltin = [varMap](ETSChecker *checker, std::string_view signature) -> util::StringView { - const auto iterator = varMap.find(signature); - ASSERT(iterator != varMap.end()); - checker->GetGlobalTypesHolder()->InitializeBuiltin( - iterator->first, - checker->BuildClassProperties(iterator->second->Declaration()->Node()->AsClassDefinition())); - return iterator->first; - }; + auto const objectName = InitBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS); + auto const voidName = InitBuiltin(this, compiler::Signatures::BUILTIN_VOID_CLASS); + + for (auto sig : BUILTINS_TO_INIT) { + InitBuiltin(this, sig); + } - auto const objectName = initBuiltin(this, compiler::Signatures::BUILTIN_OBJECT_CLASS); - auto const voidName = initBuiltin(this, compiler::Signatures::BUILTIN_VOID_CLASS); + for (size_t id = static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS), nargs = 0; + id <= static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS); id++, nargs++) { + auto *type = GetGlobalTypesHolder()->GlobalFunctionBuiltinType(nargs)->AsETSObjectType(); + SetupFunctionalInterface(this, type); + } + + for (const auto &[name, var] : varMap) { + (void)name; + SetupBuiltinMember(this, var); + } for (const auto &[name, var] : varMap) { if (name == objectName || name == voidName) { @@ -55,7 +128,11 @@ void ETSChecker::InitializeBuiltins(varbinder::ETSBinder *varbinder) } if (var->HasFlag(varbinder::VariableFlags::BUILTIN_TYPE)) { - InitializeBuiltin(var, name); + if (var->TsType() == nullptr) { + InitializeBuiltin(var, name); + } else { + GetGlobalTypesHolder()->InitializeBuiltin(name, var->TsType()); + } } } @@ -160,9 +237,10 @@ Type *ETSChecker::CheckTypeCached(ir::Expression *expr) return expr->TsType(); } -ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)()) const +template +ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const { - auto *ret = (GetGlobalTypesHolder()->*typeFunctor)(); + auto *ret = (GetGlobalTypesHolder()->*typeFunctor)(args...); return ret != nullptr ? ret->AsETSObjectType() : nullptr; } @@ -296,6 +374,16 @@ ETSObjectType *ETSChecker::GlobalBuiltinVoidType() const return AsETSObjectType(&GlobalTypesHolder::GlobalBuiltinVoidType); } +ETSObjectType *ETSChecker::GlobalBuiltinFunctionType(size_t nargs) const +{ + return AsETSObjectType(&GlobalTypesHolder::GlobalFunctionBuiltinType, nargs); +} + +size_t ETSChecker::GlobalBuiltinFunctionTypeVariadicThreshold() const +{ + return GetGlobalTypesHolder()->VariadicFunctionTypeThreshold(); +} + ETSObjectType *ETSChecker::GlobalBuiltinDynamicType(Language lang) const { if (lang.GetId() == Language::Id::JS) { diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index e909286f93..710021b70f 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -63,6 +63,7 @@ using ArrayMap = ArenaUnorderedMap; using GlobalArraySignatureMap = ArenaUnorderedMap; using DynamicCallIntrinsicsMap = ArenaUnorderedMap>; using DynamicLambdaObjectSignatureMap = ArenaUnorderedMap; +using FunctionalInterfaceMap = ArenaUnorderedMap; class ETSChecker final : public Checker { public: @@ -75,7 +76,8 @@ public: cachedComputedAbstracts_(Allocator()->Adapter()), dynamicCallIntrinsics_(Allocator()->Adapter()), dynamicNewIntrinsics_(Allocator()->Adapter()), - dynamicLambdaSignatureCache_(Allocator()->Adapter()) + dynamicLambdaSignatureCache_(Allocator()->Adapter()), + functionalInterfaceCache_(Allocator()->Adapter()) { } @@ -118,6 +120,9 @@ public: ETSObjectType *GlobalBuiltinBoxType(const Type *contents) const; ETSObjectType *GlobalBuiltinVoidType() const; + ETSObjectType *GlobalBuiltinFunctionType(size_t nargs) const; + size_t GlobalBuiltinFunctionTypeVariadicThreshold() const; + ETSObjectType *GlobalBuiltinDynamicType(Language lang) const; const checker::WrapperDesc &PrimitiveWrapper() const; @@ -140,8 +145,10 @@ public: } // Object + ETSObjectType *BuildBasicClassProperties(ir::ClassDefinition *classDef); ETSObjectType *BuildClassProperties(ir::ClassDefinition *classDef); ETSObjectType *BuildAnonymousClassProperties(ir::ClassDefinition *classDef, ETSObjectType *superType); + ETSObjectType *BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl); ETSObjectType *BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl); ETSObjectType *GetSuperType(ETSObjectType *type); ArenaVector GetInterfaces(ETSObjectType *type); @@ -395,7 +402,7 @@ public: ArenaVector &properties); std::tuple CreateLambdaCtorImplicitParam( ArenaVector ¶ms, const lexer::SourceRange &pos, bool isStaticReference); - ir::MethodDefinition *CreateLambdaInvokeProto(); + ir::MethodDefinition *CreateLambdaInvokeProto(util::StringView invokeName); void CreateLambdaFuncDecl(ir::MethodDefinition *func, varbinder::LocalScope *scope); void ResolveProxyMethod(ir::MethodDefinition *proxyMethod, ir::ArrowFunctionExpression *lambda); void ResolveLambdaObject(ir::ClassDefinition *lambdaObject, Signature *signature, @@ -404,18 +411,18 @@ public: ir::ArrowFunctionExpression *lambda, ir::MethodDefinition *proxyMethod, bool saveThis); void ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool isStaticReference); void ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject); - void ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef); + void ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef, bool ifaceOverride); void ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, - ir::MethodDefinition *proxyMethod, bool isStatic); - ir::Statement *ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef); + ir::MethodDefinition *proxyMethod, bool isStatic, bool ifaceOverride); + ir::Statement *ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride); ir::Statement *ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, - ir::MethodDefinition *proxyMethod, bool isStatic); - void CreateFunctionalInterfaceForFunctionType(ir::ETSFunctionType *funcType); - ir::MethodDefinition *CreateInvokeFunction(ir::ETSFunctionType *funcType); + ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, bool isStatic, + bool ifaceOverride); void CheckCapturedVariables(); void CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var); void CheckCapturedVariable(ir::AstNode *node, varbinder::Variable *var); - void BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType); void CreateAsyncProxyMethods(ir::ClassDefinition *classDef); ir::MethodDefinition *CreateAsyncImplMethod(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef); ir::MethodDefinition *CreateAsyncProxy(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef, @@ -537,6 +544,7 @@ public: ETSObjectType *GetRelevantArgumentedTypeFromChild(ETSObjectType *child, ETSObjectType *target); util::StringView GetHashFromTypeArguments(const ArenaVector &typeArgTypes); util::StringView GetHashFromSubstitution(const Substitution *substitution); + util::StringView GetHashFromFunctionType(ir::ETSFunctionType *type); ETSObjectType *GetOriginalBaseType(Type *object); Type *GetTypeFromTypeAnnotation(ir::TypeNode *typeAnnotation); void AddUndefinedParamsForDefaultParams(const Signature *signature, @@ -549,9 +557,8 @@ public: Type *SelectGlobalIntegerTypeForNumeric(Type *type); const Type *TryGettingFunctionTypeFromInvokeFunction(const Type *type) const; - void GenerateGetterSetterBody(ETSChecker *checker, ArenaVector &stmts, - ArenaVector ¶ms, ir::ClassProperty *field, - varbinder::FunctionParamScope *paramScope, bool isSetter); + void GenerateGetterSetterBody(ArenaVector &stmts, ArenaVector ¶ms, + ir::ClassProperty *field, varbinder::FunctionParamScope *paramScope, bool isSetter); static ir::MethodDefinition *GenerateDefaultGetterSetter(ir::ClassProperty *field, varbinder::ClassScope *scope, bool isSetter, ETSChecker *checker); @@ -610,6 +617,9 @@ public: return ret; } + ETSObjectType *GetCachedFunctionlInterface(ir::ETSFunctionType *type); + void CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType); + private: using ClassBuilder = std::function *)>; using ClassInitializerBuilder = std::function *, @@ -688,7 +698,8 @@ private: template typename TargetType::UType GetOperand(Type *type); - ETSObjectType *AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)()) const; + template + ETSObjectType *AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const; Signature *GetMostSpecificSignature(ArenaVector &compatibleSignatures, ArenaVector &proxySignatures, const ArenaVector &arguments, @@ -713,6 +724,7 @@ private: DynamicCallIntrinsicsMap dynamicCallIntrinsics_; DynamicCallIntrinsicsMap dynamicNewIntrinsics_; DynamicLambdaObjectSignatureMap dynamicLambdaSignatureCache_; + FunctionalInterfaceMap functionalInterfaceCache_; std::recursive_mutex mtx_; }; diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index e6476c47e5..9dffd8fd25 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -20,6 +20,7 @@ #include "varbinder/variable.h" #include "varbinder/variableFlags.h" #include "checker/ETSchecker.h" +#include "checker/ets/castingContext.h" #include "checker/ets/function_helpers.h" #include "checker/ets/typeRelationContext.h" #include "checker/types/ets/etsAsyncFuncReturnType.h" @@ -143,10 +144,12 @@ bool ETSChecker::EnhanceSubstitutionForObject(const ArenaVector &typePar } if (argumentType->IsETSFunctionType() && paramObjType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE)) { - auto ¶meterSignatures = paramObjType->GetOwnProperty("invoke") - ->TsType() - ->AsETSFunctionType() - ->CallSignatures(); + auto ¶meterSignatures = + paramObjType + ->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) + ->TsType() + ->AsETSFunctionType() + ->CallSignatures(); auto &argumentSignatures = argumentType->AsETSFunctionType()->CallSignatures(); ASSERT(argumentSignatures.size() == 1); ASSERT(parameterSignatures.size() == 1); @@ -1405,83 +1408,53 @@ void ETSChecker::CheckCapturedVariables() } } -void ETSChecker::BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType) -{ - VarBinder()->AsETSBinder()->BuildFunctionalInterfaceName(funcType); -} +// Lambda creation for Lambda expressions -void ETSChecker::CreateFunctionalInterfaceForFunctionType(ir::ETSFunctionType *funcType) +// Chunk pulled out of CreateLambdaObjectForLambdaReference to appease Chinese code checker +static std::pair, bool> CreateLambdaObjectPropertiesForLambdaReference( + ETSChecker *checker, ir::ArrowFunctionExpression *lambda, varbinder::ClassScope *classScope) { - auto *identNode = Allocator()->New(util::StringView("FunctionalInterface"), Allocator()); - - auto interfaceCtx = varbinder::LexicalScope(VarBinder()); - auto *interfaceScope = interfaceCtx.GetScope(); - - ArenaVector members(Allocator()->Adapter()); - ir::MethodDefinition *invokeFunc = CreateInvokeFunction(funcType); - members.push_back(invokeFunc); - - auto methodCtx = - varbinder::LexicalScope::Enter(VarBinder(), interfaceScope->InstanceMethodScope()); - auto [_, var] = VarBinder()->NewVarDecl(invokeFunc->Start(), Allocator(), - invokeFunc->Id()->Name(), invokeFunc); - (void)_; - var->AddFlag(varbinder::VariableFlags::METHOD); - invokeFunc->Function()->Id()->SetVariable(var); + bool saveThis = false; + size_t idx = 0; + const auto &capturedVars = lambda->CapturedVars(); - if (funcType->IsThrowing()) { - invokeFunc->Function()->AddFlag(ir::ScriptFunctionFlags::THROWS); + // Create the synthetic class property nodes for the captured variables + ArenaVector properties(checker->Allocator()->Adapter()); + for (const auto *it : capturedVars) { + if (it->HasFlag(varbinder::VariableFlags::LOCAL)) { + properties.push_back(checker->CreateLambdaCapturedField(it, classScope, idx, lambda->Start())); + idx++; + } else if (!it->HasFlag(varbinder::VariableFlags::STATIC) && + !checker->Context().ContainingClass()->HasObjectFlag(ETSObjectFlags::GLOBAL)) { + saveThis = true; + } } - auto *body = Allocator()->New(std::move(members)); - - ArenaVector extends(Allocator()->Adapter()); - auto *interfaceDecl = Allocator()->New( - Allocator(), identNode, nullptr, body, std::move(extends), false, false, Language(Language::Id::ETS)); - interfaceDecl->SetScope(interfaceScope); - interfaceDecl->AddModifier(ir::ModifierFlags::FUNCTIONAL); - funcType->SetFunctionalInterface(interfaceDecl); - invokeFunc->SetParent(interfaceDecl); + // If the lambda captured a property in the current class, we have to make a synthetic class property to store + // 'this' in it + if (saveThis) { + properties.push_back(checker->CreateLambdaCapturedThis(classScope, idx, lambda->Start())); + idx++; + } - VarBinder()->AsETSBinder()->BuildFunctionType(funcType); + return {properties, saveThis}; } -ir::MethodDefinition *ETSChecker::CreateInvokeFunction(ir::ETSFunctionType *funcType) +static void HandleAsyncFuncInLambda(ETSChecker *checker, ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, ir::ClassDefinition *currentClassDef) { - auto *identNode = Allocator()->New(util::StringView("invoke"), Allocator()); - - ArenaVector params(Allocator()->Adapter()); - auto *funcParamScope = CopyParams(funcType->Params(), params); - - auto paramCtx = varbinder::LexicalScope::Enter(VarBinder(), funcParamScope, false); - auto functionCtx = varbinder::LexicalScope(VarBinder()); - auto *functionScope = functionCtx.GetScope(); - functionScope->BindParamScope(funcParamScope); - funcParamScope->BindFunctionScope(functionScope); - - ir::ModifierFlags flags = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::PUBLIC; - auto *func = Allocator()->New( - ir::FunctionSignature(nullptr, std::move(params), funcType->ReturnType()), nullptr, - ir::ScriptFunctionFlags::METHOD, flags, false, Language(Language::Id::ETS)); - - func->SetScope(functionScope); - functionScope->BindNode(func); - funcParamScope->BindNode(func); - - auto *funcExpr = Allocator()->New(func); - func->SetIdent(identNode); - - auto *method = Allocator()->New(ir::MethodDefinitionKind::METHOD, identNode, funcExpr, flags, - Allocator(), false); - - funcExpr->SetParent(method); - func->SetParent(funcExpr); - - return method; + ir::MethodDefinition *asyncImpl = checker->CreateAsyncProxy(proxyMethod, currentClassDef); + ir::ScriptFunction *asyncImplFunc = asyncImpl->Function(); + currentClassDef->Body().push_back(asyncImpl); + asyncImpl->SetParent(currentClassDef); + checker->ReplaceIdentifierReferencesInProxyMethod(asyncImplFunc->Body(), asyncImplFunc->Params(), + lambda->Function()->Params(), lambda->CapturedVars()); + Signature *implSig = checker->CreateSignature(proxyMethod->Function()->Signature()->GetSignatureInfo(), + checker->GlobalETSObjectType(), asyncImplFunc); + asyncImplFunc->SetSignature(implSig); + checker->VarBinder()->AsETSBinder()->BuildFunctionName(asyncImpl->Function()); } -// Lambda creation for Lambda expressions - void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpression *lambda, ETSObjectType *functionalInterface) { @@ -1489,33 +1462,12 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio return; } - bool saveThis = false; - size_t idx = 0; - const auto &capturedVars = lambda->CapturedVars(); - auto *currentClassDef = Context().ContainingClass()->GetDeclNode()->AsClassDefinition(); - // Create the class scope for the synthetic lambda class node auto classCtx = varbinder::LexicalScope(VarBinder()); auto *classScope = classCtx.GetScope(); - // Create the synthetic class property nodes for the captured variables - ArenaVector properties(Allocator()->Adapter()); - for (const auto *it : capturedVars) { - if (it->HasFlag(varbinder::VariableFlags::LOCAL)) { - properties.push_back(CreateLambdaCapturedField(it, classScope, idx, lambda->Start())); - idx++; - } else if (!it->HasFlag(varbinder::VariableFlags::STATIC) && - !Context().ContainingClass()->HasObjectFlag(ETSObjectFlags::GLOBAL)) { - saveThis = true; - } - } - - // If the lambda captured a property in the current class, we have to make a synthetic class property to store - // 'this' in it - if (saveThis) { - properties.push_back(CreateLambdaCapturedThis(classScope, idx, lambda->Start())); - idx++; - } + auto [properties, saveThis] = CreateLambdaObjectPropertiesForLambdaReference(this, lambda, classScope); + auto *currentClassDef = Context().ContainingClass()->GetDeclNode()->AsClassDefinition(); // Create the synthetic proxy method node for the current class definiton, which we will use in the lambda // 'invoke' method to propagate the function call to the current class @@ -1526,16 +1478,18 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio properties.push_back(ctor); // Create the synthetic invoke node for the lambda class, which will propagate the call to the proxy method - auto *invokeFunc = CreateLambdaInvokeProto(); + auto *invoke0Func = CreateLambdaInvokeProto(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); + auto *invokeFunc = CreateLambdaInvokeProto("invoke"); + properties.push_back(invoke0Func); properties.push_back(invokeFunc); // Create the declarations for the synthetic constructor and invoke method CreateLambdaFuncDecl(ctor, classScope->StaticMethodScope()); + CreateLambdaFuncDecl(invoke0Func, classScope->InstanceMethodScope()); CreateLambdaFuncDecl(invokeFunc, classScope->InstanceMethodScope()); // Create the synthetic lambda class node - ArenaVector implements(Allocator()->Adapter()); auto *identNode = Allocator()->New(util::StringView("LambdaObject"), Allocator()); auto *lambdaObject = Allocator()->New(Allocator(), identNode, std::move(properties), @@ -1553,6 +1507,7 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio // Set the parent nodes ctor->SetParent(lambdaObject); + invoke0Func->SetParent(lambdaObject); invokeFunc->SetParent(lambdaObject); classScope->BindNode(lambdaObject); @@ -1562,15 +1517,7 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio // Resolve the proxy method ResolveProxyMethod(proxyMethod, lambda); if (lambda->Function()->IsAsyncFunc()) { - ir::MethodDefinition *asyncImpl = CreateAsyncProxy(proxyMethod, currentClassDef); - ir::ScriptFunction *asyncImplFunc = asyncImpl->Function(); - currentClassDef->Body().push_back(asyncImpl); - ReplaceIdentifierReferencesInProxyMethod(asyncImplFunc->Body(), asyncImplFunc->Params(), - lambda->Function()->Params(), lambda->CapturedVars()); - Signature *implSig = CreateSignature(proxyMethod->Function()->Signature()->GetSignatureInfo(), - GlobalETSObjectType(), asyncImplFunc); - asyncImplFunc->SetSignature(implSig); - VarBinder()->AsETSBinder()->BuildFunctionName(asyncImpl->Function()); + HandleAsyncFuncInLambda(this, lambda, proxyMethod, currentClassDef); } // Resolve the lambda object @@ -1608,45 +1555,75 @@ void ETSChecker::ResolveLambdaObject(ir::ClassDefinition *lambdaObject, ETSObjec ResolveLambdaObjectCtor(lambdaObject); // Resolve the invoke function - ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis); + ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis, true); + ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis, false); } -void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, - ir::MethodDefinition *proxyMethod, bool isStatic) +static Signature *CreateInvokeSignature(ETSChecker *checker, ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, ETSObjectType *lambdaObjectType, + bool ifaceOverride) { - const auto &lambdaBody = lambdaObject->Body(); - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); - - // Set the implicit 'this' parameters type to the lambda object - auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); - thisVar->SetTsType(lambdaObjectType); + auto *allocator = checker->Allocator(); // Create the signature for the invoke function type - auto *invokeSignatureInfo = CreateSignatureInfo(); + auto *invokeSignatureInfo = checker->CreateSignatureInfo(); invokeSignatureInfo->restVar = nullptr; // Create the parameters for the invoke function, based on the lambda function's parameters - for (auto *it : lambda->Function()->Params()) { + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = lambda->Function()->Params().size(); + if (paramsNum < maxParamsNum || !ifaceOverride) { + for (auto *it : lambda->Function()->Params()) { + auto paramCtx = varbinder::LexicalScope::Enter( + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); + auto *const param = it->Clone(allocator, it->Parent())->AsETSParameterExpression(); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); + (void)_; + var->SetTsType(ifaceOverride ? checker->GlobalETSNullishObjectType() : param->Variable()->TsType()); + param->Ident()->SetVariable(var); + invokeFunc->Params().push_back(param); + invokeSignatureInfo->minArgCount++; + invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + } + } else { auto paramCtx = varbinder::LexicalScope::Enter( - VarBinder(), invokeFunc->Scope()->ParamScope(), false); + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); - auto *const param = it->AsETSParameterExpression(); - auto [_, var] = VarBinder()->AddParamDecl(param); + auto *id = checker->AllocNode("p", allocator); + auto *restElement = checker->AllocNode(ir::AstNodeType::REST_ELEMENT, allocator, id); + auto *const param = checker->AllocNode(restElement, nullptr); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); (void)_; - var->SetTsType(param->Variable()->TsType()); + var->SetTsType(checker->CreateETSArrayType(checker->GlobalETSNullishObjectType())); param->Ident()->SetVariable(var); invokeFunc->Params().push_back(param); - invokeSignatureInfo->minArgCount++; - invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + invokeSignatureInfo->restVar = var->AsLocalVariable(); } // Create the function type for the invoke method - auto *invokeSignature = - CreateSignature(invokeSignatureInfo, lambda->Function()->Signature()->ReturnType(), invokeFunc); + auto *invokeSignature = checker->CreateSignature(invokeSignatureInfo, + ifaceOverride ? checker->GlobalETSNullishObjectType() + : lambda->Function()->Signature()->ReturnType(), + invokeFunc); invokeSignature->SetOwner(lambdaObjectType); invokeSignature->AddSignatureFlag(checker::SignatureFlags::CALL); + return invokeSignature; +} + +void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, bool isStatic, bool ifaceOverride) +{ + const auto &lambdaBody = lambdaObject->Body(); + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); + + // Set the implicit 'this' parameters type to the lambda object + auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); + thisVar->SetTsType(lambdaObjectType); + + // Create the function type for the invoke method + auto *invokeSignature = CreateInvokeSignature(this, lambda, invokeFunc, lambdaObjectType, ifaceOverride); auto *invokeType = CreateETSFunctionType(invokeSignature); invokeFunc->SetSignature(invokeSignature); invokeFunc->Id()->Variable()->SetTsType(invokeType); @@ -1655,7 +1632,8 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir invokeFunc->Id()->Variable()->AsLocalVariable()); // Fill out the type information for the body of the invoke function - auto *resolvedLambdaInvokeFunctionBody = ResolveLambdaObjectInvokeFuncBody(lambdaObject, proxyMethod, isStatic); + auto *resolvedLambdaInvokeFunctionBody = + ResolveLambdaObjectInvokeFuncBody(lambdaObject, lambda, proxyMethod, isStatic, ifaceOverride); if (invokeFunc->IsAsyncFunc()) { return; } @@ -1665,8 +1643,90 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir } } +/* Pulled out to appease the Chinese checker */ + +static void AddFieldRefsToCallParameters(ETSChecker *checker, ir::ClassDefinition *lambdaObject, bool isStatic, + ArenaVector &callParams) +{ + auto *allocator = checker->Allocator(); + auto &lambdaBody = lambdaObject->Body(); + size_t counter = isStatic ? lambdaBody.size() - 3 : lambdaBody.size() - 4; + for (size_t i = 0; i < counter; i++) { + if (lambdaBody[i]->IsMethodDefinition()) { + break; + } + + auto *classProp = lambdaBody[i]->AsClassProperty(); + auto *param = allocator->New(classProp->Key()->AsIdentifier()->Name(), allocator); + param->SetVariable(classProp->Key()->AsIdentifier()->Variable()); + param->SetIgnoreBox(); + param->SetTsType(checker->MaybeBoxedType(param->Variable())); + callParams.push_back(param); + } +} + +static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSChecker *checker, + ir::ClassDefinition *lambdaObject, + ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, + bool isStatic, bool ifaceOverride) +{ + auto *allocator = checker->Allocator(); + ArenaVector callParams(allocator->Adapter()); + + AddFieldRefsToCallParameters(checker, lambdaObject, isStatic, callParams); + + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = lambda->Function()->Params().size(); + if (!ifaceOverride) { + for (auto const *const it : invokeFunc->Params()) { + auto const *const param = it->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + callParams.push_back(paramIdent); + } + } else if (paramsNum < maxParamsNum) { + // Then we add the lambda functions parameters to the call + auto nargs = invokeFunc->Params().size(); + for (size_t i = 0; i < nargs; i++) { + auto const *const param = invokeFunc->Params()[i]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + + auto *lambdaParam = lambda->Function()->Params()[i]->AsETSParameterExpression(); + auto *const paramCast = + allocator->New(paramIdent, lambdaParam->TypeAnnotation(), false); + paramCast->Check(checker); + callParams.push_back(paramCast); + } + } else { + ASSERT(invokeFunc->Params().size() == 1); + auto const *const param = invokeFunc->Params()[0]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + + for (size_t i = 0; i < paramsNum; i++) { + auto *idx = allocator->New(lexer::Number(static_cast(i))); + auto *arg = allocator->New(paramIdent, idx, ir::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + auto *lambdaParam = lambda->Function()->Params()[i]->AsETSParameterExpression(); + auto *const paramCast = allocator->New(arg, lambdaParam->TypeAnnotation(), false); + paramCast->Check(checker); + callParams.push_back(paramCast); + } + } + + return callParams; +} + ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, - ir::MethodDefinition *proxyMethod, bool isStatic) + ir::ArrowFunctionExpression *lambda, + ir::MethodDefinition *proxyMethod, bool isStatic, + bool ifaceOverride) { const auto &lambdaBody = lambdaObject->Body(); auto *proxySignature = proxyMethod->Function()->Signature(); @@ -1681,7 +1741,7 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition fieldIdent->SetTsType(fieldPropType); } else { // Otherwise, we call the proxy method through the saved 'this' field - auto *savedThis = lambdaBody[lambdaBody.size() - 3]->AsClassProperty(); + auto *savedThis = lambdaBody[lambdaBody.size() - 4]->AsClassProperty(); auto *fieldProp = savedThis->Key()->AsIdentifier()->Variable(); fieldPropType = fieldProp->TsType()->AsETSObjectType(); fieldIdent = Allocator()->New(savedThis->Key()->AsIdentifier()->Name(), Allocator()); @@ -1698,30 +1758,9 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition callee->SetTsType(proxySignature->OwnerVar()->TsType()); // Resolve the proxy method call arguments, first we add the captured fields to the call - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ArenaVector callParams(Allocator()->Adapter()); - size_t counter = isStatic ? lambdaBody.size() - 2 : lambdaBody.size() - 3; - for (size_t i = 0; i < counter; i++) { - if (lambdaBody[i]->IsMethodDefinition()) { - break; - } - - auto *classProp = lambdaBody[i]->AsClassProperty(); - auto *param = Allocator()->New(classProp->Key()->AsIdentifier()->Name(), Allocator()); - param->SetVariable(classProp->Key()->AsIdentifier()->Variable()); - param->SetIgnoreBox(); - param->SetTsType(MaybeBoxedType(param->Variable())); - callParams.push_back(param); - } - - // Then we add the lambda functions parameters to the call - for (auto const *const it : invokeFunc->Params()) { - auto const *const param = it->AsETSParameterExpression(); - auto *const paramIdent = Allocator()->New(param->Ident()->Name(), Allocator()); - paramIdent->SetVariable(param->Variable()); - paramIdent->SetTsType(param->Variable()->TsType()); - callParams.push_back(paramIdent); - } + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ArenaVector callParams = + ResolveCallParametersForLambdaFuncBody(this, lambdaObject, lambda, invokeFunc, isStatic, ifaceOverride); // Create the synthetic call expression to the proxy method auto *resolvedCall = Allocator()->New(callee, std::move(callParams), nullptr, false); @@ -1731,6 +1770,11 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition if (proxySignature->ReturnType()->IsETSVoidType()) { return Allocator()->New(resolvedCall); } + + if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); + } + return Allocator()->New(resolvedCall); } @@ -1738,7 +1782,7 @@ void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject) { const auto &lambdaBody = lambdaObject->Body(); auto *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); - auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function(); + auto *ctorFunc = lambdaBody[lambdaBody.size() - 3]->AsMethodDefinition()->Function(); // Set the implicit 'this' parameters type to the lambda object auto *thisVar = ctorFunc->Scope()->ParamScope()->Params().front(); @@ -2210,10 +2254,13 @@ void ETSChecker::CreateLambdaObjectForFunctionReference(ir::AstNode *refNode, Si return; } + /* signature has been converted through BpxPrimitives, we need to call the original one */ + auto *trueSignature = signature->Function()->Signature(); + // Create the class scope for the synthetic lambda class node auto classCtx = varbinder::LexicalScope(VarBinder()); auto *classScope = classCtx.GetScope(); - bool isStaticReference = signature->HasSignatureFlag(SignatureFlags::STATIC); + bool isStaticReference = trueSignature->HasSignatureFlag(SignatureFlags::STATIC); // Create the synthetic field where we will store the instance object which we are trying to obtain the function // reference through, if the referenced function is static, we won't need to store the instance object @@ -2229,15 +2276,17 @@ void ETSChecker::CreateLambdaObjectForFunctionReference(ir::AstNode *refNode, Si // Create the template for the synthetic invoke function which will propagate the function call to the saved // instance's referenced function, or the class static function, if this is a static reference - auto *invokeFunc = CreateLambdaInvokeProto(); + auto *invoke0Func = CreateLambdaInvokeProto(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); + auto *invokeFunc = CreateLambdaInvokeProto("invoke"); + properties.push_back(invoke0Func); properties.push_back(invokeFunc); // Create the declarations for the synthetic constructor and invoke method CreateLambdaFuncDecl(ctor, classScope->StaticMethodScope()); + CreateLambdaFuncDecl(invoke0Func, classScope->InstanceMethodScope()); CreateLambdaFuncDecl(invokeFunc, classScope->InstanceMethodScope()); // Create the synthetic lambda class node - ArenaVector implements(Allocator()->Adapter()); auto *identNode = Allocator()->New(util::StringView("LambdaObject"), Allocator()); auto *lambdaObject = Allocator()->New(Allocator(), identNode, std::move(properties), @@ -2245,14 +2294,15 @@ void ETSChecker::CreateLambdaObjectForFunctionReference(ir::AstNode *refNode, Si lambdaObject->SetScope(classScope); // Set the parent nodes ctor->SetParent(lambdaObject); + invoke0Func->SetParent(lambdaObject); invokeFunc->SetParent(lambdaObject); classScope->BindNode(lambdaObject); // Build the lambda object in the binder - VarBinder()->AsETSBinder()->BuildLambdaObject(refNode, lambdaObject, signature); + VarBinder()->AsETSBinder()->BuildLambdaObject(refNode, lambdaObject, trueSignature); // Resolve the lambda object - ResolveLambdaObject(lambdaObject, signature, functionalInterface, refNode); + ResolveLambdaObject(lambdaObject, trueSignature, functionalInterface, refNode); } ir::AstNode *ETSChecker::CreateLambdaImplicitField(varbinder::ClassScope *scope, const lexer::SourcePosition &pos) @@ -2340,11 +2390,11 @@ std::tuple ETSChecker::C return {paramCtx.GetScope(), nullptr}; } -ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto() +ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto(util::StringView invokeName) { // Create the template for the synthetic 'invoke' method, which will be used when the function type will be // called - auto *name = Allocator()->New("invoke", Allocator()); + auto *name = Allocator()->New(invokeName, Allocator()); auto *paramScope = VarBinder()->Allocator()->New(Allocator(), VarBinder()->GetScope()); auto *scope = VarBinder()->Allocator()->New(Allocator(), paramScope); @@ -2426,13 +2476,14 @@ void ETSChecker::ResolveLambdaObject(ir::ClassDefinition *lambdaObject, Signatur ResolveLambdaObjectCtor(lambdaObject, isStaticReference); // Resolve the invoke function - ResolveLambdaObjectInvoke(lambdaObject, signature); + ResolveLambdaObjectInvoke(lambdaObject, signature, true); + ResolveLambdaObjectInvoke(lambdaObject, signature, false); } void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool isStaticReference) { const auto &lambdaBody = lambdaObject->Body(); - auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function(); + auto *ctorFunc = lambdaBody[lambdaBody.size() - 3]->AsMethodDefinition()->Function(); ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); varbinder::Variable *fieldVar {}; @@ -2490,41 +2541,70 @@ void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool fieldinit->Right()->SetTsType(ctorSignature->Params()[0]->TsType()); } -void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef) +static Signature *CreateInvokeSignature(ETSChecker *checker, Signature *signatureRef, ir::ScriptFunction *invokeFunc, + ETSObjectType *lambdaObjectType, bool ifaceOverride) { - const auto &lambdaBody = lambdaObject->Body(); - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); - - // Set the implicit 'this' parameters type to the lambda object - auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); - thisVar->SetTsType(lambdaObjectType); + auto *allocator = checker->Allocator(); // Create the signature for the invoke function type - auto *invokeSignatureInfo = CreateSignatureInfo(); + auto *invokeSignatureInfo = checker->CreateSignatureInfo(); invokeSignatureInfo->restVar = nullptr; // Create the parameters for the invoke function, based on the referenced function's signature - for (auto *it : signatureRef->Params()) { + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = signatureRef->Params().size(); + if (paramsNum < maxParamsNum || !ifaceOverride) { + for (auto *it : signatureRef->Params()) { + auto paramCtx = varbinder::LexicalScope::Enter( + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); + + auto *paramIdent = allocator->New(it->Name(), allocator); + auto *param = allocator->New(paramIdent, nullptr); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); + (void)_; + var->SetTsType(ifaceOverride ? checker->GlobalETSObjectType() : it->TsType()); + paramIdent->SetVariable(var); + invokeFunc->Params().push_back(param); + invokeSignatureInfo->minArgCount++; + invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + } + } else { auto paramCtx = varbinder::LexicalScope::Enter( - VarBinder(), invokeFunc->Scope()->ParamScope(), false); + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); - auto *paramIdent = Allocator()->New(it->Name(), Allocator()); - auto *param = Allocator()->New(paramIdent, nullptr); - auto [_, var] = VarBinder()->AddParamDecl(param); + auto *id = checker->AllocNode("p", allocator); + auto *restElement = checker->AllocNode(ir::AstNodeType::REST_ELEMENT, allocator, id); + auto *const param = checker->AllocNode(restElement, nullptr); + auto [_, var] = checker->VarBinder()->AddParamDecl(param); (void)_; - var->SetTsType(it->TsType()); - paramIdent->SetVariable(var); + var->SetTsType(checker->CreateETSArrayType(checker->GlobalETSObjectType())); + param->Ident()->SetVariable(var); invokeFunc->Params().push_back(param); - invokeSignatureInfo->minArgCount++; - invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + invokeSignatureInfo->restVar = var->AsLocalVariable(); } // Create the function type for the constructor - auto *invokeSignature = CreateSignature(invokeSignatureInfo, signatureRef->ReturnType(), invokeFunc); + auto *invokeSignature = checker->CreateSignature( + invokeSignatureInfo, ifaceOverride ? checker->GlobalETSObjectType() : signatureRef->ReturnType(), invokeFunc); invokeSignature->SetOwner(lambdaObjectType); invokeSignature->AddSignatureFlag(checker::SignatureFlags::CALL); + return invokeSignature; +} + +void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride) +{ + const auto &lambdaBody = lambdaObject->Body(); + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ETSObjectType *lambdaObjectType = lambdaObject->TsType()->AsETSObjectType(); + + // Set the implicit 'this' parameters type to the lambda object + auto *thisVar = invokeFunc->Scope()->ParamScope()->Params().front(); + thisVar->SetTsType(lambdaObjectType); + + auto *invokeSignature = CreateInvokeSignature(this, signatureRef, invokeFunc, lambdaObjectType, ifaceOverride); + auto *invokeType = CreateETSFunctionType(invokeSignature); invokeFunc->SetSignature(invokeSignature); invokeFunc->Id()->Variable()->SetTsType(invokeType); @@ -2534,7 +2614,8 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Si // Fill out the type information for the body of the invoke function - auto *resolvedLambdaInvokeFunctionBody = ResolveLambdaObjectInvokeFuncBody(lambdaObject, signatureRef); + auto *resolvedLambdaInvokeFunctionBody = + ResolveLambdaObjectInvokeFuncBody(lambdaObject, signatureRef, ifaceOverride); invokeFunc->Body()->AsBlockStatement()->Statements().push_back(resolvedLambdaInvokeFunctionBody); if (resolvedLambdaInvokeFunctionBody->IsExpressionStatement()) { @@ -2542,7 +2623,80 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Si } } -ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef) +static ir::Expression *BuildParamExpression(ETSChecker *checker, ir::Identifier *paramIdent, Type *type) +{ + if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + auto *boxedType = checker->PrimitiveTypeAsETSBuiltinType(type); + auto *boxedTypeNode = checker->AllocNode(boxedType); + boxedTypeNode->SetTsType(boxedType); + auto *paramAsExpr = checker->AllocNode(paramIdent, boxedTypeNode, false); + paramAsExpr->SetTsType(boxedType); + paramAsExpr->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(type)); + return paramAsExpr; + } + checker::CastingContext ctx(checker->Relation(), paramIdent, paramIdent->TsType(), type, paramIdent->Start(), {}); + auto *const paramCast = checker->Allocator()->New(paramIdent, nullptr, false); + paramCast->SetUncheckedCast(ctx.UncheckedCast()); + paramCast->SetTsType(type); + return paramCast; +} + +static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSChecker *checker, + Signature *signatureRef, + ir::ScriptFunction *invokeFunc, + bool ifaceOverride) +{ + auto *allocator = checker->Allocator(); + ArenaVector callParams(allocator->Adapter()); + + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto paramsNum = signatureRef->Params().size(); + if (!ifaceOverride) { + for (size_t idx = 0; idx != paramsNum; idx++) { + auto *paramIdent = allocator->New(signatureRef->Params()[idx]->Name(), allocator); + paramIdent->SetVariable(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()); + paramIdent->SetTsType(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()->TsType()); + callParams.push_back(paramIdent); + } + } else if (paramsNum < maxParamsNum) { + // Then we add the lambda functions parameters to the call + auto nargs = invokeFunc->Params().size(); + for (size_t i = 0; i < nargs; i++) { + auto const *const param = invokeFunc->Params()[i]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + callParams.push_back(BuildParamExpression(checker, paramIdent, signatureRef->Params()[i]->TsType())); + } + } else { + ASSERT(invokeFunc->Params().size() == 1); + auto const *const param = invokeFunc->Params()[0]->AsETSParameterExpression(); + auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); + paramIdent->SetVariable(param->Variable()); + paramIdent->SetTsType(param->Variable()->TsType()); + + for (size_t i = 0; i < paramsNum; i++) { + auto *idx = allocator->New(lexer::Number(static_cast(i))); + auto *arg = allocator->New(paramIdent, idx, ir::MemberExpressionKind::ELEMENT_ACCESS, + true, false); + + auto *type = signatureRef->Params()[i]->TsType(); + if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + arg->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(type)); + callParams.push_back(arg); + } else { + auto *const paramCast = allocator->New(arg, nullptr, false); + paramCast->SetTsType(type); + callParams.push_back(paramCast); + } + } + } + + return callParams; +} + +ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride) { const auto &lambdaBody = lambdaObject->Body(); bool isStaticReference = signatureRef->HasSignatureFlag(SignatureFlags::STATIC); @@ -2574,14 +2728,9 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition callee->SetTsType(signatureRef->OwnerVar()->TsType()); // Create the parameters for the referenced function call - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - ArenaVector callParams(Allocator()->Adapter()); - for (size_t idx = 0; idx != signatureRef->Params().size(); idx++) { - auto *paramIdent = Allocator()->New(signatureRef->Params()[idx]->Name(), Allocator()); - paramIdent->SetVariable(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()); - paramIdent->SetTsType(invokeFunc->Params()[idx]->AsETSParameterExpression()->Variable()->TsType()); - callParams.push_back(paramIdent); - } + auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); + ArenaVector callParams = + ResolveCallParametersForLambdaFuncBody(this, signatureRef, invokeFunc, ifaceOverride); // Create the synthetic call expression to the referenced function auto *resolvedCall = Allocator()->New(callee, std::move(callParams), nullptr, false); @@ -2592,6 +2741,10 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition return Allocator()->New(resolvedCall); } + if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); + } + return Allocator()->New(resolvedCall); } @@ -2893,4 +3046,22 @@ void ETSChecker::EnsureValidCurlyBrace(ir::CallExpression *callExpr) ThrowTypeError({"No matching call signature with trailing lambda"}, callExpr->Start()); } + +ETSObjectType *ETSChecker::GetCachedFunctionlInterface(ir::ETSFunctionType *type) +{ + auto hash = GetHashFromFunctionType(type); + auto it = functionalInterfaceCache_.find(hash); + if (it == functionalInterfaceCache_.cend()) { + return nullptr; + } + return it->second; +} + +void ETSChecker::CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType) +{ + auto hash = GetHashFromFunctionType(type); + ASSERT(functionalInterfaceCache_.find(hash) == functionalInterfaceCache_.cend()); + functionalInterfaceCache_.emplace(hash, ifaceType); +} + } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/ets/function_helpers.h b/ets2panda/checker/ets/function_helpers.h index 2fa3713186..ed07549bbc 100644 --- a/ets2panda/checker/ets/function_helpers.h +++ b/ets2panda/checker/ets/function_helpers.h @@ -96,7 +96,9 @@ static const Substitution *BuildImplicitSubstitutionForArguments(ETSChecker *che } auto *argType = arg->Check(checker); argType = MaybeBoxedType(checker, argType, arg); - auto *paramType = (ix < signature->MinArgCount()) ? sigInfo->params[ix]->TsType() : sigInfo->restVar->TsType(); + auto *paramType = (ix < signature->MinArgCount()) ? sigInfo->params[ix]->TsType() + : sigInfo->restVar != nullptr ? sigInfo->restVar->TsType() + : nullptr; if (paramType == nullptr) { continue; } @@ -161,7 +163,10 @@ static Signature *MaybeSubstituteTypeParameters(ETSChecker *checker, Signature * const Substitution *substitution = (typeArguments != nullptr) ? BuildExplicitSubstitutionForArguments(checker, signature, typeArguments->Params(), pos, flags) - : BuildImplicitSubstitutionForArguments(checker, signature, arguments); + : (signature->GetSignatureInfo()->params.empty() + ? nullptr + : BuildImplicitSubstitutionForArguments(checker, signature, arguments)); + return (substitution == nullptr) ? nullptr : signature->Substitute(checker->Relation(), substitution); } @@ -260,4 +265,4 @@ static varbinder::Scope *NodeScope(ir::AstNode *ast) } // namespace panda::es2panda::checker -#endif \ No newline at end of file +#endif diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 41e52fafab..46f52f19bd 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -89,7 +89,7 @@ void ETSChecker::CheckTruthinessOfType(ir::Expression *expr) ThrowTypeError("Condition must be of possible condition type", expr->Start()); } - if (unboxedType != nullptr && unboxedType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { + if (unboxedType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { FlagExpressionWithUnboxing(type, unboxedType, expr); } expr->SetTsType(unboxedType); @@ -886,7 +886,7 @@ std::tuple ETSChecker::IsResolvedAndValue(const ir::Expression *expr IsNullLikeOrVoidExpression(expr) ? std::make_tuple(true, false) : type->ResolveConditionExpr(); const Type *tsType = expr->TsType(); - if (!tsType->ContainsUndefined() && !tsType->ContainsNull() && !tsType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { + if (!tsType->ContainsUndefined() && !tsType->ContainsNull() && !type->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { isResolve = true; isValue = true; } @@ -1780,6 +1780,10 @@ Type *ETSChecker::ETSBuiltinTypeAsConditionalType(Type *objectType) return nullptr; } + if (auto *unboxed = ETSBuiltinTypeAsPrimitiveType(objectType); unboxed != nullptr) { + return unboxed; + } + return objectType; } @@ -2294,38 +2298,6 @@ ETSObjectType *ETSChecker::GetRelevantArgumentedTypeFromChild(ETSObjectType *con return GetRelevantArgumentedTypeFromChild(child->SuperType(), target); } -static void TypeToString(std::stringstream &ss, Type *tp) -{ - if (tp->IsETSTypeParameter()) { - ss << tp->AsETSTypeParameter()->GetDeclNode()->Start().index; - ss << "."; - } - if (!tp->IsETSObjectType()) { - tp->ToString(ss); - return; - } - auto *const objType = tp->AsETSObjectType(); - ss << objType->Name(); - - if (!objType->TypeArguments().empty()) { - auto typeArgs = objType->TypeArguments(); - ss << "<"; - for (auto *ta : typeArgs) { - TypeToString(ss, ta); - ss << ";"; - } - ss << ">"; - } - - if (tp->ContainsNull()) { - ss << "|null"; - } - - if (tp->ContainsUndefined()) { - ss << "|undefined"; - } -} - void ETSChecker::EmplaceSubstituted(Substitution *substitution, ETSTypeParameter *tparam, Type *typeArg) { substitution->emplace(tparam, typeArg); @@ -2336,7 +2308,7 @@ util::StringView ETSChecker::GetHashFromTypeArguments(const ArenaVector std::stringstream ss; for (auto *it : typeArgTypes) { - TypeToString(ss, it); + it->ToString(ss, true); ss << compiler::Signatures::MANGLE_SEPARATOR; } @@ -2348,9 +2320,9 @@ util::StringView ETSChecker::GetHashFromSubstitution(const Substitution *substit std::vector fields; for (auto [k, v] : *substitution) { std::stringstream ss; - TypeToString(ss, k); + k->ToString(ss, true); ss << ":"; - TypeToString(ss, v); + v->ToString(ss, true); fields.push_back(ss.str()); } std::sort(fields.begin(), fields.end()); @@ -2363,6 +2335,29 @@ util::StringView ETSChecker::GetHashFromSubstitution(const Substitution *substit return util::UString(ss.str(), Allocator()).View(); } +util::StringView ETSChecker::GetHashFromFunctionType(ir::ETSFunctionType *type) +{ + std::stringstream ss; + for (auto *p : type->Params()) { + auto *const param = p->AsETSParameterExpression(); + GetTypeFromTypeAnnotation(param->TypeAnnotation())->ToString(ss, true); + ss << ";"; + } + + type->ReturnType()->GetType(this)->ToString(ss, true); + ss << ";"; + + if (type->IsThrowing()) { + ss << "throws;"; + } + + if (type->IsRethrowing()) { + ss << "rethrows;"; + } + + return util::UString(ss.str(), Allocator()).View(); +} + ETSObjectType *ETSChecker::GetOriginalBaseType(Type *const object) { if (object == nullptr || !object->IsETSObjectType()) { @@ -2419,6 +2414,10 @@ void ETSChecker::CheckNumberOfTypeArguments(ETSObjectType *const type, ir::TSTyp return; } + if (typeArgs == nullptr) { + return; + } + size_t minimumTypeArgs = std::count_if(typeParams.begin(), typeParams.end(), [](Type *param) { return param->AsETSTypeParameter()->GetDefaultType() == nullptr; }); @@ -2638,35 +2637,35 @@ std::string GenerateImplicitInstantiateArg(varbinder::LocalVariable *instantiate return implicitInstantiateArgument; } -void ETSChecker::GenerateGetterSetterBody(ETSChecker *checker, ArenaVector &stmts, - ArenaVector ¶ms, ir::ClassProperty *const field, - varbinder::FunctionParamScope *paramScope, bool isSetter) +void ETSChecker::GenerateGetterSetterBody(ArenaVector &stmts, ArenaVector ¶ms, + ir::ClassProperty *const field, varbinder::FunctionParamScope *paramScope, + bool isSetter) { if (!isSetter) { - stmts.push_back(checker->Allocator()->New(field->Key())); + stmts.push_back(Allocator()->New(field->Key())); return; } - auto *paramIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator()); - paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(checker->Allocator())); + auto *paramIdent = field->Key()->AsIdentifier()->Clone(Allocator()); + paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(Allocator())); paramIdent->TypeAnnotation()->SetParent(paramIdent); - auto *paramExpression = checker->AllocNode(paramIdent, nullptr); + auto *paramExpression = AllocNode(paramIdent, nullptr); paramExpression->SetRange(paramIdent->Range()); - auto *const paramVar = std::get<2>(paramScope->AddParamDecl(checker->Allocator(), paramExpression)); + auto *const paramVar = std::get<2>(paramScope->AddParamDecl(Allocator(), paramExpression)); paramIdent->SetVariable(paramVar); paramExpression->SetVariable(paramVar); params.push_back(paramExpression); - auto *assignmentExpression = checker->AllocNode( - field->Key(), paramExpression, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *assignmentExpression = + AllocNode(field->Key(), paramExpression, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); assignmentExpression->SetRange({field->Start(), field->End()}); - stmts.push_back(checker->AllocNode(assignmentExpression)); - stmts.push_back(checker->Allocator()->New(nullptr)); + stmts.push_back(AllocNode(assignmentExpression)); + stmts.push_back(Allocator()->New(nullptr)); } ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty *const field, @@ -2683,7 +2682,7 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty ArenaVector params(checker->Allocator()->Adapter()); ArenaVector stmts(checker->Allocator()->Adapter()); - checker->GenerateGetterSetterBody(checker, stmts, params, field, paramScope, isSetter); + checker->GenerateGetterSetterBody(stmts, params, field, paramScope, isSetter); auto *body = checker->AllocNode(checker->Allocator(), std::move(stmts)); auto funcFlags = isSetter ? ir::ScriptFunctionFlags::SETTER : ir::ScriptFunctionFlags::GETTER; @@ -2730,7 +2729,7 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty const Type *ETSChecker::TryGettingFunctionTypeFromInvokeFunction(const Type *type) const { if (type->IsETSObjectType() && type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { - auto const propInvoke = type->AsETSObjectType()->GetProperty(util::StringView("invoke"), + auto const propInvoke = type->AsETSObjectType()->GetProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME, PropertySearchFlags::SEARCH_INSTANCE_METHOD); ASSERT(propInvoke != nullptr); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 8c06deccbc..24e9928347 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -285,9 +285,10 @@ void ETSChecker::CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type : type->GetDeclNode()->AsTSInterfaceDeclaration()->TypeParams(); type->SetTypeArguments(CreateTypeForTypeParameters(typeParams)); type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS); + type->AddObjectFlag(ETSObjectFlags::INCOMPLETE_INSTANTIATION); } -ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) +ETSObjectType *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) { auto *var = interfaceDecl->Id()->Variable(); ASSERT(var); @@ -309,6 +310,14 @@ ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration * GetInterfacesOfInterface(interfaceType); + interfaceType->SetSuperType(GlobalETSObjectType()); + + return interfaceType; +} + +ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) +{ + auto *interfaceType = BuildBasicInterfaceProperties(interfaceDecl); checker::ScopeContext scopeCtx(this, interfaceDecl->Scope()); auto savedContext = checker::SavedCheckerContext(this, checker::CheckerStatus::IN_INTERFACE, interfaceType); @@ -317,7 +326,7 @@ ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration * return interfaceType; } -ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) +ETSObjectType *ETSChecker::BuildBasicClassProperties(ir::ClassDefinition *classDef) { if (classDef->IsFinal() && classDef->IsAbstract()) { ThrowTypeError("Cannot use both 'final' and 'abstract' modifiers.", classDef->Start()); @@ -327,7 +336,6 @@ ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) ASSERT(var); const util::StringView &className = classDef->Ident()->Name(); - auto *classScope = classDef->Scope(); checker::ETSObjectType *classType {}; if (var->TsType() == nullptr) { @@ -368,10 +376,17 @@ ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) return classType; } - checker::ScopeContext scopeCtx(this, classScope); + return classType; +} - ResolveDeclaredMembersOfObject(classType); +ETSObjectType *ETSChecker::BuildClassProperties(ir::ClassDefinition *classDef) +{ + auto *classType = BuildBasicClassProperties(classDef); + auto savedContext = checker::SavedCheckerContext(this, checker::CheckerStatus::IN_CLASS, classType); + checker::ScopeContext scopeCtx(this, classDef->Scope()); + + ResolveDeclaredMembersOfObject(classType); return classType; } @@ -1586,7 +1601,8 @@ void ETSChecker::AddElementsToModuleObject(ETSObjectType *moduleObj, const util: Type *ETSChecker::FindLeastUpperBound(Type *source, Type *target) { - ASSERT(source->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT) && target->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT)); + ASSERT(source->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT | TypeFlag::ETS_TYPE_PARAMETER)); + ASSERT(target->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT | TypeFlag::ETS_TYPE_PARAMETER)); // GetCommonClass(GenA, GenB) => LUB(GenA, GenB) auto commonClass = GetCommonClass(source, target); @@ -1695,7 +1711,12 @@ ETSObjectType *ETSChecker::GetTypeargumentedLUB(ETSObjectType *const source, ETS return source; } - ETSObjectType *templateType = source->GetDeclNode()->AsClassDefinition()->TsType()->AsETSObjectType(); + ETSObjectType *templateType; + if (source->GetDeclNode()->IsClassDefinition()) { + templateType = source->GetDeclNode()->AsClassDefinition()->TsType()->AsETSObjectType(); + } else { + templateType = source->GetDeclNode()->AsTSInterfaceDeclaration()->TsType()->AsETSObjectType(); + } auto *lubType = templateType->GetInstantiatedType(hash); diff --git a/ets2panda/checker/types/ets/byteType.h b/ets2panda/checker/types/ets/byteType.h index cd81d91cd3..3bc9deb36d 100644 --- a/ets2panda/checker/types/ets/byteType.h +++ b/ets2panda/checker/types/ets/byteType.h @@ -37,12 +37,12 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "byte"; } - void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override + void ToAssemblerType(std::stringstream &ss) const override { ss << compiler::Signatures::PRIMITIVE_BYTE; } diff --git a/ets2panda/checker/types/ets/charType.h b/ets2panda/checker/types/ets/charType.h index f917156bcf..54641c35d1 100644 --- a/ets2panda/checker/types/ets/charType.h +++ b/ets2panda/checker/types/ets/charType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "char"; } diff --git a/ets2panda/checker/types/ets/doubleType.h b/ets2panda/checker/types/ets/doubleType.h index ddf7cc3e41..57579724f2 100644 --- a/ets2panda/checker/types/ets/doubleType.h +++ b/ets2panda/checker/types/ets/doubleType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "double"; } diff --git a/ets2panda/checker/types/ets/etsArrayType.cpp b/ets2panda/checker/types/ets/etsArrayType.cpp index 9b0e9403aa..ec422c7e12 100644 --- a/ets2panda/checker/types/ets/etsArrayType.cpp +++ b/ets2panda/checker/types/ets/etsArrayType.cpp @@ -21,9 +21,16 @@ #include "checker/types/typeRelation.h" namespace panda::es2panda::checker { -void ETSArrayType::ToString(std::stringstream &ss) const +void ETSArrayType::ToString(std::stringstream &ss, bool precise) const { - element_->ToString(ss); + bool needParens = (element_->IsETSUnionType() || element_->IsETSFunctionType() || element_->IsNullish()); + if (needParens) { + ss << "("; + } + element_->ToString(ss, precise); + if (needParens) { + ss << ")"; + } ss << "[]"; if (IsNullish()) { diff --git a/ets2panda/checker/types/ets/etsArrayType.h b/ets2panda/checker/types/ets/etsArrayType.h index f4f90331b9..edd0ddde3c 100644 --- a/ets2panda/checker/types/ets/etsArrayType.h +++ b/ets2panda/checker/types/ets/etsArrayType.h @@ -38,7 +38,7 @@ public: return {false, false}; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void ToAssemblerType(std::stringstream &ss) const override; void ToAssemblerTypeWithRank(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp index 71738ebf7c..38550b5097 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp @@ -18,11 +18,11 @@ #include "checker/types/ets/etsAsyncFuncReturnType.h" namespace panda::es2panda::checker { -void ETSAsyncFuncReturnType::ToString(std::stringstream &ss) const +void ETSAsyncFuncReturnType::ToString(std::stringstream &ss, bool precise) const { - promiseType_->ToString(ss); + promiseType_->ToString(ss, precise); ss << " | "; - GetPromiseTypeArg()->ToString(ss); + GetPromiseTypeArg()->ToString(ss, precise); } void ETSAsyncFuncReturnType::Identical(TypeRelation *relation, Type *other) diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h index 339a3b1d1f..07c9ecf6bd 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h @@ -30,7 +30,7 @@ public: SetAssemblerName(compiler::Signatures::BUILTIN_OBJECT); } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ets/etsBigIntType.h b/ets2panda/checker/types/ets/etsBigIntType.h index befbfb3de9..a8b4fa3ecc 100644 --- a/ets2panda/checker/types/ets/etsBigIntType.h +++ b/ets2panda/checker/types/ets/etsBigIntType.h @@ -43,7 +43,7 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << lexer::TokenToString(lexer::TokenType::KEYW_BIGINT); } diff --git a/ets2panda/checker/types/ets/etsBooleanType.h b/ets2panda/checker/types/ets/etsBooleanType.h index 5127daf1fa..4a9f175ea8 100644 --- a/ets2panda/checker/types/ets/etsBooleanType.h +++ b/ets2panda/checker/types/ets/etsBooleanType.h @@ -36,7 +36,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "boolean"; } diff --git a/ets2panda/checker/types/ets/etsEnumType.cpp b/ets2panda/checker/types/ets/etsEnumType.cpp index 2a779b6a18..45d4cdce0f 100644 --- a/ets2panda/checker/types/ets/etsEnumType.cpp +++ b/ets2panda/checker/types/ets/etsEnumType.cpp @@ -87,7 +87,7 @@ void ETSEnumInterface::ToDebugInfoType(std::stringstream &ss) const ToDebugInfoTypeImpl(ss); } -void ETSEnumInterface::ToString(std::stringstream &ss) const +void ETSEnumInterface::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << decl_->Key()->Name(); } diff --git a/ets2panda/checker/types/ets/etsEnumType.h b/ets2panda/checker/types/ets/etsEnumType.h index 2bd8c99d3e..0ccfa56d29 100644 --- a/ets2panda/checker/types/ets/etsEnumType.h +++ b/ets2panda/checker/types/ets/etsEnumType.h @@ -60,7 +60,7 @@ public: void ToAssemblerType(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; [[nodiscard]] const ir::TSEnumDeclaration *GetDecl() const noexcept; diff --git a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp index b737bd39b4..687496405e 100644 --- a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp +++ b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.cpp @@ -27,11 +27,11 @@ namespace panda::es2panda::checker { in order to figure out a representation for case 3, we need the etsExtensionFuncHelperType */ -void ETSExtensionFuncHelperType::ToString(std::stringstream &ss) const +void ETSExtensionFuncHelperType::ToString(std::stringstream &ss, bool precise) const { - classMethodType_->ToString(ss); + classMethodType_->ToString(ss, precise); ss << " | "; - extensionFunctionType_->ToString(ss); + extensionFunctionType_->ToString(ss, precise); } void ETSExtensionFuncHelperType::AssignmentTarget(TypeRelation *relation, Type *source) diff --git a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h index a646bec143..8e4b85c913 100644 --- a/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h +++ b/ets2panda/checker/types/ets/etsExtensionFuncHelperType.h @@ -38,7 +38,7 @@ public: return extensionFunctionType_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void AssignmentTarget(TypeRelation *relation, Type *source) override; private: diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index a95e78d4d6..38b16d18e4 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -33,9 +33,9 @@ Signature *ETSFunctionType::FirstAbstractSignature() return nullptr; } -void ETSFunctionType::ToString(std::stringstream &ss) const +void ETSFunctionType::ToString(std::stringstream &ss, bool precise) const { - callSignatures_[0]->ToString(ss, nullptr); + callSignatures_[0]->ToString(ss, nullptr, false, precise); } void ETSFunctionType::Identical(TypeRelation *relation, Type *other) @@ -106,7 +106,7 @@ static Signature *ProcessSignatures(TypeRelation *relation, Signature *target, E size_t idx = 0; for (; idx != target->MinArgCount(); idx++) { - if (!relation->IsIdenticalTo(target->Params()[idx]->TsType(), it->Params()[idx]->TsType())) { + if (!relation->IsAssignableTo(target->Params()[idx]->TsType(), it->Params()[idx]->TsType())) { break; } } @@ -116,11 +116,11 @@ static Signature *ProcessSignatures(TypeRelation *relation, Signature *target, E } if (target->RestVar() != nullptr && - !relation->IsIdenticalTo(target->RestVar()->TsType(), it->RestVar()->TsType())) { + !relation->IsAssignableTo(target->RestVar()->TsType(), it->RestVar()->TsType())) { continue; } - if (!relation->IsAssignableTo(target->ReturnType(), it->ReturnType())) { + if (!relation->IsAssignableTo(it->ReturnType(), target->ReturnType())) { continue; } @@ -130,6 +130,27 @@ static Signature *ProcessSignatures(TypeRelation *relation, Signature *target, E return match; } +static ETSObjectType *SubstitutedFunctionalInterfaceForSignature(TypeRelation *relation, Signature *signature, + ETSObjectType *functionalInterface) +{ + auto &interfaceArgs = functionalInterface->TypeArguments(); + auto *checker = relation->GetChecker()->AsETSChecker(); + Substitution *substitution = checker->NewSubstitution(); + size_t i = 0; + for (auto *param : signature->Params()) { + auto *paramType = (param->TsType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) + ? checker->PrimitiveTypeAsETSBuiltinType(param->TsType()) + : param->TsType(); + substitution->emplace(interfaceArgs[i++]->AsETSTypeParameter(), paramType); + } + auto *retType = (signature->ReturnType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) + ? checker->PrimitiveTypeAsETSBuiltinType(signature->ReturnType()) + : signature->ReturnType(); + substitution->emplace(interfaceArgs[i]->AsETSTypeParameter(), retType); + + return functionalInterface->Substitute(relation, substitution); +} + void ETSFunctionType::AssignmentTarget(TypeRelation *relation, Type *source) { if (!source->IsETSFunctionType() && @@ -150,8 +171,9 @@ void ETSFunctionType::AssignmentTarget(TypeRelation *relation, Type *source) return; } - if (!target->Function()->IsThrowing()) { - if (match->Function()->IsThrowing() || match->Function()->IsRethrowing()) { + if (!(target->Function()->IsThrowing() || target->HasSignatureFlag(SignatureFlags::THROWS))) { + if (match->Function()->IsThrowing() || match->Function()->IsRethrowing() || + match->HasSignatureFlag(SignatureFlags::THROWS) || match->HasSignatureFlag(SignatureFlags::RETHROWS)) { relation->GetChecker()->ThrowTypeError( "Functions that can throw exceptions cannot be assigned to non throwing functions.", relation->GetNode()->Start()); @@ -160,12 +182,15 @@ void ETSFunctionType::AssignmentTarget(TypeRelation *relation, Type *source) ASSERT(relation->GetNode() != nullptr); if (!sourceIsFunctional) { + auto *substitutedFuncInterface = + SubstitutedFunctionalInterfaceForSignature(relation, match, callSignatures_[0]->Owner()); + if (relation->GetNode()->IsArrowFunctionExpression()) { relation->GetChecker()->AsETSChecker()->CreateLambdaObjectForLambdaReference( - relation->GetNode()->AsArrowFunctionExpression(), callSignatures_[0]->Owner()); + relation->GetNode()->AsArrowFunctionExpression(), substitutedFuncInterface); } else { relation->GetChecker()->AsETSChecker()->CreateLambdaObjectForFunctionReference(relation->GetNode(), match, - callSignatures_[0]->Owner()); + substitutedFuncInterface); } } @@ -206,19 +231,20 @@ ETSFunctionType *ETSFunctionType::Substitute(TypeRelation *relation, const Subst return anyChange ? copiedType : this; } -checker::RelationResult ETSFunctionType::CastFunctionParams(TypeRelation *relation, Type *target) +checker::RelationResult ETSFunctionType::CastFunctionParams(TypeRelation *relation, Signature *targetInvokeSig) { - auto *targetType = target->AsETSObjectType(); - auto *body = targetType->GetDeclNode()->AsTSInterfaceDeclaration()->Body(); - auto targetParams = body->AsTSInterfaceBody()->Body()[0]->AsMethodDefinition()->Function()->Params(); - for (size_t i = 0; i < targetType->TypeArguments().size(); i++) { + auto *ourSig = callSignatures_[0]; + auto &ourParams = ourSig->Params(); + auto &theirParams = targetInvokeSig->Params(); + if (ourParams.size() != theirParams.size()) { + return RelationResult::FALSE; + } + for (size_t i = 0; i < theirParams.size(); i++) { relation->Result(RelationResult::FALSE); - callSignatures_[0]->Function()->Params()[i]->TsType()->Cast( - relation, targetParams[i]->AsETSParameterExpression()->Check(relation->GetChecker()->AsETSChecker())); - if (relation->IsTrue()) { - continue; + ourParams[i]->TsType()->Cast(relation, theirParams[i]->TsType()); + if (!relation->IsTrue()) { + return RelationResult::FALSE; } - return RelationResult::FALSE; } return RelationResult::TRUE; } @@ -226,23 +252,37 @@ checker::RelationResult ETSFunctionType::CastFunctionParams(TypeRelation *relati void ETSFunctionType::Cast(TypeRelation *relation, Type *target) { ASSERT(relation->GetNode()->IsArrowFunctionExpression()); + auto *savedNode = relation->GetNode(); + conversion::Forbidden(relation); if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { auto *targetType = target->AsETSObjectType(); - auto *body = targetType->GetDeclNode()->AsTSInterfaceDeclaration()->Body()->AsTSInterfaceBody(); - auto targetParams = body->AsTSInterfaceBody()->Body()[0]->AsMethodDefinition()->Function()->Params(); - if (targetType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE) && - targetParams.size() == callSignatures_[0]->Function()->Params().size()) { - relation->Result(CastFunctionParams(relation, target)); + if (targetType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { + auto *targetInvokeVar = targetType->GetProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME, + PropertySearchFlags::SEARCH_INSTANCE_METHOD); + if (targetInvokeVar == nullptr || !targetInvokeVar->TsType()->IsETSFunctionType()) { + return; + } + auto *targetInvokeSig = targetInvokeVar->TsType()->AsETSFunctionType()->CallSignatures()[0]; + relation->Result(CastFunctionParams(relation, targetInvokeSig)); + auto *targetReturnType = targetInvokeSig->ReturnType(); + callSignatures_[0]->ReturnType()->Cast(relation, targetReturnType); } - relation->Result(RelationResult::FALSE); - auto targetReturnType = body->Body()[0]->AsMethodDefinition()->Function()->ReturnTypeAnnotation(); - callSignatures_[0]->ReturnType()->Cast(relation, targetReturnType->TsType()); if (relation->IsTrue()) { relation->GetChecker()->AsETSChecker()->CreateLambdaObjectForLambdaReference( relation->GetNode()->AsArrowFunctionExpression(), targetType->AsETSObjectType()); + relation->SetNode(savedNode); return; } } - conversion::Forbidden(relation); +} + +ETSFunctionType *ETSFunctionType::BoxPrimitives(ETSChecker *checker) +{ + auto *allocator = checker->Allocator(); + auto *ret = allocator->New(name_, allocator); + for (auto *sig : callSignatures_) { + ret->AddCallSignature(sig->BoxPrimitives(checker)); + } + return ret; } } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsFunctionType.h b/ets2panda/checker/types/ets/etsFunctionType.h index 2d79f87d3c..c275b1b730 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.h +++ b/ets2panda/checker/types/ets/etsFunctionType.h @@ -112,14 +112,15 @@ public: } Signature *FirstAbstractSignature(); - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; ETSFunctionType *Substitute(TypeRelation *relation, const Substitution *substitution) override; void Cast(TypeRelation *relation, Type *target) override; - checker::RelationResult CastFunctionParams(TypeRelation *relation, Type *target); + checker::RelationResult CastFunctionParams(TypeRelation *relation, Signature *targetInvokeSig); + ETSFunctionType *BoxPrimitives(ETSChecker *checker); private: ArenaVector callSignatures_; diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 5891c50641..28e219d850 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -281,14 +281,16 @@ ArenaMap ETSObjectType::Coll return propMap; } -void ETSObjectType::ToString(std::stringstream &ss) const +void ETSObjectType::ToString(std::stringstream &ss, bool precise) const { if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { if (IsNullish() && this != GetConstOriginalBaseType() && !name_.Is("NullType") && !IsETSNullLike() && !name_.Empty()) { ss << lexer::TokenToString(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); } - GetFunctionalInterfaceInvokeType()->ToString(ss); + GetFunctionalInterfaceInvokeType()->ToString(ss, precise); + } else if (precise) { + ss << assemblerName_; // NOTE(gogabr): need full qualified name } else { ss << name_; } @@ -296,7 +298,7 @@ void ETSObjectType::ToString(std::stringstream &ss) const if (!typeArguments_.empty()) { ss << compiler::Signatures::GENERIC_BEGIN; for (auto arg = typeArguments_.cbegin(); arg != typeArguments_.cend(); ++arg) { - (*arg)->ToString(ss); + (*arg)->ToString(ss, precise); if (next(arg) != typeArguments_.cend()) { ss << lexer::TokenToString(lexer::TokenType::PUNCTUATOR_COMMA); @@ -321,7 +323,7 @@ void ETSObjectType::ToString(std::stringstream &ss) const } } -void ETSObjectType::IdenticalUptoNullability(TypeRelation *relation, Type *other) +void ETSObjectType::IdenticalUptoNullabilityAndTypeArguments(TypeRelation *relation, Type *other) { relation->Result(false); if (!other->IsETSObjectType() || !CheckIdenticalFlags(other->AsETSObjectType()->ObjectFlags())) { @@ -339,57 +341,55 @@ void ETSObjectType::IdenticalUptoNullability(TypeRelation *relation, Type *other return; } - auto const otherTypeArguments = other->AsETSObjectType()->TypeArguments(); + if (IsNullish()) { + relation->Result(true); + return; + } - if (HasTypeFlag(TypeFlag::GENERIC) || IsNullish()) { - if (!HasTypeFlag(TypeFlag::GENERIC)) { - relation->Result(true); - return; - } - if (typeArguments_.empty() != otherTypeArguments.empty()) { - return; - } + auto const sourceTypeArguments = other->AsETSObjectType()->TypeArguments(); + if (typeArguments_.empty() != sourceTypeArguments.empty()) { + return; + } - auto const argsNumber = typeArguments_.size(); - ASSERT(argsNumber == otherTypeArguments.size()); + relation->Result(true); +} - for (size_t idx = 0U; idx < argsNumber; ++idx) { - if (typeArguments_[idx]->IsWildcardType() || otherTypeArguments[idx]->IsWildcardType()) { - continue; - } +void ETSObjectType::IdenticalUptoNullability(TypeRelation *relation, Type *other) +{ + IdenticalUptoNullabilityAndTypeArguments(relation, other); - // checking the nullishness of type args before getting their original base types - // because most probably GetOriginalBaseType will return the non-nullish version of the type - if (!typeArguments_[idx]->IsNullish() && otherTypeArguments[idx]->IsNullish()) { - return; - } + if (!relation->IsTrue() || !HasTypeFlag(TypeFlag::GENERIC)) { + return; + } + + auto const otherTypeArguments = other->AsETSObjectType()->TypeArguments(); - const auto getOriginalBaseTypeOrType = [&relation](Type *const originalType) { - auto *const baseType = relation->GetChecker()->AsETSChecker()->GetOriginalBaseType(originalType); - return baseType == nullptr ? originalType : baseType; - }; + auto const argsNumber = typeArguments_.size(); + ASSERT(argsNumber == otherTypeArguments.size()); - auto *const typeArgType = getOriginalBaseTypeOrType(typeArguments_[idx]); - auto *const otherTypeArgType = getOriginalBaseTypeOrType(otherTypeArguments[idx]); + for (size_t idx = 0U; idx < argsNumber; ++idx) { + if (typeArguments_[idx]->IsWildcardType() || otherTypeArguments[idx]->IsWildcardType()) { + continue; + } - typeArgType->Identical(relation, otherTypeArgType); - if (!relation->IsTrue()) { - return; - } + // checking the nullishness of type args before getting their original base types + // because most probably GetOriginalBaseType will return the non-nullish version of the type + if ((!typeArguments_[idx]->IsNullish() && otherTypeArguments[idx]->IsNullish()) || + (typeArguments_[idx]->IsNullish() && !otherTypeArguments[idx]->IsNullish())) { + relation->Result(false); + return; } - } else { - if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { - auto getInvokeSignature = [](const ETSObjectType *type) { - auto const propInvoke = - type->GetProperty(util::StringView("invoke"), PropertySearchFlags::SEARCH_INSTANCE_METHOD); - ASSERT(propInvoke != nullptr); - return propInvoke->TsType()->AsETSFunctionType()->CallSignatures()[0]; - }; - auto *const thisInvokeSignature = getInvokeSignature(this); - auto *const otherInvokeSignature = getInvokeSignature(other->AsETSObjectType()); + const auto getOriginalBaseTypeOrType = [&relation](Type *const originalType) { + auto *const baseType = relation->GetChecker()->AsETSChecker()->GetOriginalBaseType(originalType); + return baseType == nullptr ? originalType : baseType; + }; + + auto *const typeArgType = getOriginalBaseTypeOrType(typeArguments_[idx]); + auto *const otherTypeArgType = getOriginalBaseTypeOrType(otherTypeArguments[idx]); - relation->IsIdenticalTo(thisInvokeSignature, otherInvokeSignature); + typeArgType->Identical(relation, otherTypeArgType); + if (!relation->IsTrue()) { return; } } @@ -445,8 +445,12 @@ void ETSObjectType::AssignmentTarget(TypeRelation *const relation, Type *source) if (HasObjectFlag(ETSObjectFlags::FUNCTIONAL)) { EnsurePropertiesInstantiated(); - auto found = properties_[static_cast(PropertyType::INSTANCE_METHOD)].find("invoke"); + auto found = properties_[static_cast(PropertyType::INSTANCE_METHOD)].find( + FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); ASSERT(found != properties_[static_cast(PropertyType::INSTANCE_METHOD)].end()); + if (source->IsETSFunctionType()) { + source = source->AsETSFunctionType()->BoxPrimitives(relation->GetChecker()->AsETSChecker()); + } relation->IsAssignableTo(source, found->second->TsType()); return; } @@ -474,10 +478,14 @@ bool ETSObjectType::CastWideningNarrowing(TypeRelation *const relation, Type *co bool ETSObjectType::CastNumericObject(TypeRelation *const relation, Type *const target) { - if (this->IsNullish()) { + if (!target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | + TypeFlag::FLOAT | TypeFlag::DOUBLE | TypeFlag::ETS_BOOLEAN)) { return false; } - + IdenticalUptoNullability(relation, target); + if (relation->IsTrue()) { + return true; + } if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE)) { if (target->HasTypeFlag(TypeFlag::BYTE)) { conversion::Unboxing(relation, this); @@ -493,63 +501,42 @@ bool ETSObjectType::CastNumericObject(TypeRelation *const relation, Type *const return true; } } - TypeFlag unboxFlags = TypeFlag::NONE; - TypeFlag wideningFlags = TypeFlag::NONE; - TypeFlag narrowingFlags = TypeFlag::NONE; - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT)) { - unboxFlags = TypeFlag::SHORT; - wideningFlags = TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::CHAR; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT) && + CastWideningNarrowing(relation, target, TypeFlag::SHORT, + TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::CHAR)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { - unboxFlags = TypeFlag::CHAR; - wideningFlags = TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR) && + CastWideningNarrowing(relation, target, TypeFlag::CHAR, + TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) { - unboxFlags = TypeFlag::INT; - wideningFlags = TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) && + CastWideningNarrowing(relation, target, TypeFlag::INT, TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG)) { - unboxFlags = TypeFlag::LONG; - wideningFlags = TypeFlag::FLOAT | TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) && + CastWideningNarrowing(relation, target, TypeFlag::LONG, TypeFlag::FLOAT | TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT)) { - unboxFlags = TypeFlag::FLOAT; - wideningFlags = TypeFlag::DOUBLE; - narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT) && + CastWideningNarrowing(relation, target, TypeFlag::FLOAT, TypeFlag::DOUBLE, + TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) { - unboxFlags = TypeFlag::DOUBLE; - wideningFlags = TypeFlag::NONE; - narrowingFlags = + if (auto narrowingFlags = TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT; - if (CastWideningNarrowing(relation, target, unboxFlags, wideningFlags, narrowingFlags)) { - return true; - } + this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) && + CastWideningNarrowing(relation, target, TypeFlag::DOUBLE, TypeFlag::NONE, narrowingFlags)) { + return true; } - if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN)) { - if (target->HasTypeFlag(TypeFlag::ETS_BOOLEAN)) { - conversion::Unboxing(relation, this); - return true; - } + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN) && target->HasTypeFlag(TypeFlag::ETS_BOOLEAN)) { + conversion::Unboxing(relation, this); + return true; } if (this->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) { if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { @@ -649,23 +636,31 @@ bool ETSObjectType::DefaultObjectTypeChecks(const ETSChecker *const etsChecker, return true; } - IdenticalUptoNullability(relation, source); + IdenticalUptoNullabilityAndTypeArguments(relation, source); + if (relation->IsTrue() && HasTypeFlag(TypeFlag::GENERIC)) { + IsGenericSupertypeOf(relation, source); + } return relation->IsTrue(); } +static void IsSupertypeOfUnion(TypeRelation *relation, ETSObjectType *self, ETSUnionType *unionType) +{ + bool res = std::all_of(unionType->ConstituentTypes().begin(), unionType->ConstituentTypes().end(), + [self, relation](Type *ct) { + relation->Result(false); + self->IsSupertypeOf(relation, ct); + return relation->IsTrue(); + }); + relation->Result(res); +} + void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) { relation->Result(false); auto *const etsChecker = relation->GetChecker()->AsETSChecker(); if (source->IsETSUnionType()) { - bool res = std::all_of(source->AsETSUnionType()->ConstituentTypes().begin(), - source->AsETSUnionType()->ConstituentTypes().end(), [this, relation](Type *ct) { - relation->Result(false); - IsSupertypeOf(relation, ct); - return relation->IsTrue(); - }); - relation->Result(res); + IsSupertypeOfUnion(relation, this, source->AsETSUnionType()); return; } @@ -689,6 +684,51 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) } } +void ETSObjectType::IsGenericSupertypeOf(TypeRelation *relation, Type *source) +{ + ASSERT(HasTypeFlag(TypeFlag::GENERIC)); + + auto *sourceType = source->AsETSObjectType(); + auto const sourceTypeArguments = sourceType->TypeArguments(); + ASSERT(typeArguments_.size() == sourceTypeArguments.size()); + + ASSERT(declNode_ == sourceType->GetDeclNode()); + + auto *typeParamsDecl = GetTypeParams(); + ASSERT(typeParamsDecl != nullptr || typeArguments_.empty()); + + if (typeParamsDecl == nullptr) { + return; + } + + auto &typeParams = typeParamsDecl->Params(); + ASSERT(typeParams.size() == typeArguments_.size()); + + for (size_t idx = 0; idx < typeArguments_.size(); idx++) { + auto *typeArg = typeArguments_[idx]; + auto *sourceTypeArg = sourceTypeArguments[idx]; + auto *typeParam = typeParams[idx]; + + relation->Result(false); + + if (!(typeArg->IsWildcardType() || sourceTypeArg->IsWildcardType())) { + if (typeParam->IsOut()) { + typeArg->IsSupertypeOf(relation, sourceTypeArg); + } else if (typeParam->IsIn()) { + sourceTypeArg->IsSupertypeOf(relation, typeArg); + } else { + typeArg->Identical(relation, sourceTypeArg); + } + + if (!relation->IsTrue()) { + return; + } + } + } + + relation->Result(true); +} + Type *ETSObjectType::AsSuper(Checker *checker, varbinder::Variable *sourceVar) { if (sourceVar == nullptr) { @@ -845,7 +885,7 @@ void ETSObjectType::SetCopiedTypeProperties(TypeRelation *const relation, ETSObj copiedType->substitution_ = substitution; } -Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution) +ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution, bool cache) { if (substitution == nullptr || substitution->empty()) { return this; @@ -864,8 +904,10 @@ Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *subs } const util::StringView hash = checker->GetHashFromSubstitution(substitution); - if (auto *inst = GetInstantiatedType(hash); inst != nullptr) { - return inst; + if (cache) { + if (auto *inst = GetInstantiatedType(hash); inst != nullptr) { + return inst; + } } if (!relation->TypeInstantiationPossible(base) || IsETSNullLike()) { @@ -875,7 +917,10 @@ Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *subs auto *const copiedType = checker->CreateNewETSObjectType(name_, declNode_, flags_); SetCopiedTypeProperties(relation, copiedType, newTypeArgs, substitution); - GetInstantiationMap().try_emplace(hash, copiedType); + + if (cache) { + GetInstantiationMap().try_emplace(hash, copiedType); + } if (superType_ != nullptr) { copiedType->SetSuperType(superType_->Substitute(relation, substitution)->AsETSObjectType()); @@ -890,6 +935,11 @@ Type *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *subs return copiedType; } +ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution) +{ + return Substitute(relation, substitution, true); +} + void ETSObjectType::InstantiateProperties() const { if (baseType_ == nullptr || baseType_ == this) { diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index c59e37eb67..b54010b006 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -112,6 +112,9 @@ enum class PropertyType { COUNT, }; +/* Invoke method name in functional interfaces */ +constexpr char const *FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME = "invoke0"; + class ETSObjectType : public Type { public: using PropertyMap = ArenaUnorderedMap; @@ -392,7 +395,7 @@ public: ETSFunctionType *GetFunctionalInterfaceInvokeType() const { ASSERT(HasObjectFlag(ETSObjectFlags::FUNCTIONAL)); - auto *invoke = GetOwnProperty("invoke"); + auto *invoke = GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType()); return invoke->TsType()->AsETSFunctionType(); } @@ -414,17 +417,11 @@ public: varbinder::Scope *GetTypeArgumentScope() const { - if (HasObjectFlag(ETSObjectFlags::ENUM) || !HasTypeFlag(TypeFlag::GENERIC)) { + auto *typeParams = GetTypeParams(); + if (typeParams == nullptr) { return nullptr; } - - if (HasObjectFlag(ETSObjectFlags::CLASS)) { - ASSERT(declNode_->IsClassDefinition() && declNode_->AsClassDefinition()->TypeParams()); - return declNode_->AsClassDefinition()->TypeParams()->Scope(); - } - - ASSERT(declNode_->IsTSInterfaceDeclaration() && declNode_->AsTSInterfaceDeclaration()->TypeParams()); - return declNode_->AsTSInterfaceDeclaration()->TypeParams()->Scope(); + return typeParams->Scope(); } InstantiationMap &GetInstantiationMap() @@ -471,7 +468,7 @@ public: bool CheckIdenticalVariable(varbinder::Variable *otherVar) const; void Iterate(const PropertyTraverser &cb) const; - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; @@ -479,7 +476,8 @@ public: bool SubstituteTypeArgs(TypeRelation *relation, ArenaVector &newTypeArgs, const Substitution *substitution); void SetCopiedTypeProperties(TypeRelation *relation, ETSObjectType *copiedType, ArenaVector &newTypeArgs, const Substitution *substitution); - Type *Substitute(TypeRelation *relation, const Substitution *substitution) override; + ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution) override; + ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution, bool cache); void Cast(TypeRelation *relation, Type *target) override; bool CastNumericObject(TypeRelation *relation, Type *target); bool DefaultObjectTypeChecks(const ETSChecker *etsChecker, TypeRelation *relation, Type *source); @@ -549,6 +547,23 @@ private: void IdenticalUptoNullability(TypeRelation *relation, Type *other); bool CastWideningNarrowing(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags, TypeFlag narrowingFlags); + void IdenticalUptoNullabilityAndTypeArguments(TypeRelation *relation, Type *other); + void IsGenericSupertypeOf(TypeRelation *relation, Type *source); + + ir::TSTypeParameterDeclaration *GetTypeParams() const + { + if (HasObjectFlag(ETSObjectFlags::ENUM) || !HasTypeFlag(TypeFlag::GENERIC)) { + return nullptr; + } + + if (HasObjectFlag(ETSObjectFlags::CLASS)) { + ASSERT(declNode_->IsClassDefinition() && declNode_->AsClassDefinition()->TypeParams()); + return declNode_->AsClassDefinition()->TypeParams(); + } + + ASSERT(declNode_->IsTSInterfaceDeclaration() && declNode_->AsTSInterfaceDeclaration()->TypeParams()); + return declNode_->AsTSInterfaceDeclaration()->TypeParams(); + } ArenaAllocator *allocator_; util::StringView name_; diff --git a/ets2panda/checker/types/ets/etsStringType.h b/ets2panda/checker/types/ets/etsStringType.h index afc3c2dd9f..8b96db319e 100644 --- a/ets2panda/checker/types/ets/etsStringType.h +++ b/ets2panda/checker/types/ets/etsStringType.h @@ -43,12 +43,12 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << lexer::TokenToString(lexer::TokenType::KEYW_STRING); } - void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override + void ToAssemblerType(std::stringstream &ss) const override { ss << compiler::Signatures::BUILTIN_STRING; } diff --git a/ets2panda/checker/types/ets/etsTupleType.cpp b/ets2panda/checker/types/ets/etsTupleType.cpp index 1f79e6f997..2eea1c4084 100644 --- a/ets2panda/checker/types/ets/etsTupleType.cpp +++ b/ets2panda/checker/types/ets/etsTupleType.cpp @@ -20,12 +20,12 @@ #include "ir/ets/etsTuple.h" namespace panda::es2panda::checker { -void ETSTupleType::ToString(std::stringstream &ss) const +void ETSTupleType::ToString(std::stringstream &ss, bool precise) const { ss << "["; for (auto it = typeList_.begin(); it != typeList_.end(); it++) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != typeList_.end()) { ss << ", "; @@ -34,7 +34,7 @@ void ETSTupleType::ToString(std::stringstream &ss) const if (spreadType_ != nullptr) { ss << ", ..."; - spreadType_->ToString(ss); + spreadType_->ToString(ss, precise); ss << "[]"; } diff --git a/ets2panda/checker/types/ets/etsTupleType.h b/ets2panda/checker/types/ets/etsTupleType.h index 249dbe58cf..ac3bc3ff79 100644 --- a/ets2panda/checker/types/ets/etsTupleType.h +++ b/ets2panda/checker/types/ets/etsTupleType.h @@ -80,7 +80,7 @@ public: [[nodiscard]] Type *GetTypeAtIndex(int32_t index) const; - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ets/etsTypeParameter.cpp b/ets2panda/checker/types/ets/etsTypeParameter.cpp index 302f9ce42f..3c1f5b76c9 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.cpp +++ b/ets2panda/checker/types/ets/etsTypeParameter.cpp @@ -20,8 +20,13 @@ #include "checker/ets/conversion.h" namespace panda::es2panda::checker { -void ETSTypeParameter::ToString(std::stringstream &ss) const + +void ETSTypeParameter::ToString(std::stringstream &ss, bool precise) const { + // Need source file name to avoid clashes + if (precise) { + ss << declNode_->Range().start.index << "." << declNode_->Range().start.line << "."; + } ss << declNode_->Name()->Name(); if (IsNullish()) { diff --git a/ets2panda/checker/types/ets/etsTypeParameter.h b/ets2panda/checker/types/ets/etsTypeParameter.h index 63dabb1358..f32f0305db 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.h +++ b/ets2panda/checker/types/ets/etsTypeParameter.h @@ -61,7 +61,7 @@ public: return constraint_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index b23981aed5..7f68b971ad 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -22,10 +22,10 @@ #include "ir/astNode.h" namespace panda::es2panda::checker { -void ETSUnionType::ToString(std::stringstream &ss) const +void ETSUnionType::ToString(std::stringstream &ss, bool precise) const { for (auto it = constituentTypes_.begin(); it != constituentTypes_.end(); it++) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != constituentTypes_.end()) { ss << "|"; } diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 216c2630c2..19336608aa 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -32,7 +32,7 @@ public: return constituentTypes_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void ToAssemblerType(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; diff --git a/ets2panda/checker/types/ets/etsVoidType.h b/ets2panda/checker/types/ets/etsVoidType.h index ab280f7e2d..e6658fc53f 100644 --- a/ets2panda/checker/types/ets/etsVoidType.h +++ b/ets2panda/checker/types/ets/etsVoidType.h @@ -27,7 +27,7 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "void"; } diff --git a/ets2panda/checker/types/ets/floatType.h b/ets2panda/checker/types/ets/floatType.h index 68da05d2d0..6c9b92c1c8 100644 --- a/ets2panda/checker/types/ets/floatType.h +++ b/ets2panda/checker/types/ets/floatType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "float"; } diff --git a/ets2panda/checker/types/ets/intType.h b/ets2panda/checker/types/ets/intType.h index 2e9734ccc7..fab974a6f0 100644 --- a/ets2panda/checker/types/ets/intType.h +++ b/ets2panda/checker/types/ets/intType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "int"; } diff --git a/ets2panda/checker/types/ets/longType.h b/ets2panda/checker/types/ets/longType.h index e2887d5374..85ee2db7d3 100644 --- a/ets2panda/checker/types/ets/longType.h +++ b/ets2panda/checker/types/ets/longType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "long"; } diff --git a/ets2panda/checker/types/ets/shortType.h b/ets2panda/checker/types/ets/shortType.h index 85764fff83..7d0788b4bb 100644 --- a/ets2panda/checker/types/ets/shortType.h +++ b/ets2panda/checker/types/ets/shortType.h @@ -37,7 +37,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void ToString(std::stringstream &ss) const override + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override { ss << "short"; } diff --git a/ets2panda/checker/types/ets/wildcardType.cpp b/ets2panda/checker/types/ets/wildcardType.cpp index aab9ae80b4..7b99a7b06f 100644 --- a/ets2panda/checker/types/ets/wildcardType.cpp +++ b/ets2panda/checker/types/ets/wildcardType.cpp @@ -16,7 +16,7 @@ #include "wildcardType.h" namespace panda::es2panda::checker { -void WildcardType::ToString(std::stringstream &ss) const +void WildcardType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "wildcard"; } diff --git a/ets2panda/checker/types/ets/wildcardType.h b/ets2panda/checker/types/ets/wildcardType.h index 9db1b04df9..feb18636ec 100644 --- a/ets2panda/checker/types/ets/wildcardType.h +++ b/ets2panda/checker/types/ets/wildcardType.h @@ -23,7 +23,7 @@ class WildcardType : public Type { public: WildcardType() : Type(TypeFlag::WILDCARD) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; diff --git a/ets2panda/checker/types/globalTypesHolder.cpp b/ets2panda/checker/types/globalTypesHolder.cpp index 27115ca559..169afad7a8 100644 --- a/ets2panda/checker/types/globalTypesHolder.cpp +++ b/ets2panda/checker/types/globalTypesHolder.cpp @@ -158,6 +158,18 @@ GlobalTypesHolder::GlobalTypesHolder(ArenaAllocator *allocator) : builtinNameMap builtinNameMappings_.emplace("RegExp", GlobalTypeId::ETS_REGEXP_BUILTIN); builtinNameMappings_.emplace("Set", GlobalTypeId::ETS_SET_BUILTIN); + // ETS functional types + for (size_t id = static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS), nargs = 0; + id < static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS); id++, nargs++) { + std::stringstream ss; + ss << "Function"; + ss << nargs; + + builtinNameMappings_.emplace(util::UString(ss.str(), allocator).View(), static_cast(id)); + } + + builtinNameMappings_.emplace("FunctionN", GlobalTypeId::ETS_FUNCTIONN_CLASS); + // ETS interop js specific types builtinNameMappings_.emplace("JSRuntime", GlobalTypeId::ETS_INTEROP_JSRUNTIME_BUILTIN); builtinNameMappings_.emplace("JSValue", GlobalTypeId::ETS_INTEROP_JSVALUE_BUILTIN); @@ -613,6 +625,20 @@ Type *GlobalTypesHolder::GlobalBuiltinNeverType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_NEVER_BUILTIN)); } +size_t GlobalTypesHolder::VariadicFunctionTypeThreshold() +{ + return static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS) - + static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS); +} + +Type *GlobalTypesHolder::GlobalFunctionBuiltinType(size_t nargs) +{ + if (nargs >= VariadicFunctionTypeThreshold()) { + return globalTypes_.at(static_cast(GlobalTypeId::ETS_FUNCTIONN_CLASS)); + } + return globalTypes_.at(static_cast(GlobalTypeId::ETS_FUNCTION0_CLASS) + nargs); +} + void GlobalTypesHolder::InitializeBuiltin(const util::StringView name, Type *type) { const auto typeId = builtinNameMappings_.find(name); diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index c79d375a25..3f3fb07465 100644 --- a/ets2panda/checker/types/globalTypesHolder.h +++ b/ets2panda/checker/types/globalTypesHolder.h @@ -112,6 +112,25 @@ enum class GlobalTypeId { ETS_BIG_INT_BUILTIN, ETS_BIG_INT, + ETS_FUNCTION0_CLASS, + ETS_FUNCTION1_CLASS, + ETS_FUNCTION2_CLASS, + ETS_FUNCTION3_CLASS, + ETS_FUNCTION4_CLASS, + ETS_FUNCTION5_CLASS, + ETS_FUNCTION6_CLASS, + ETS_FUNCTION7_CLASS, + ETS_FUNCTION8_CLASS, + ETS_FUNCTION9_CLASS, + ETS_FUNCTION10_CLASS, + ETS_FUNCTION11_CLASS, + ETS_FUNCTION12_CLASS, + ETS_FUNCTION13_CLASS, + ETS_FUNCTION14_CLASS, + ETS_FUNCTION15_CLASS, + ETS_FUNCTION16_CLASS, + ETS_FUNCTIONN_CLASS, + COUNT, }; @@ -204,6 +223,10 @@ public: Type *GlobalDoubleBoxBuiltinType(); Type *GlobalBuiltinNeverType(); + // Functional types + size_t VariadicFunctionTypeThreshold(); + Type *GlobalFunctionBuiltinType(size_t nargs); + // ETS escompat layer Type *GlobalArrayBuiltinType(); Type *GlobalClassOutOfMemoryErrorBuiltinType(); diff --git a/ets2panda/checker/types/signature.cpp b/ets2panda/checker/types/signature.cpp index c9e826acf8..01feb8044b 100644 --- a/ets2panda/checker/types/signature.cpp +++ b/ets2panda/checker/types/signature.cpp @@ -15,6 +15,7 @@ #include "signature.h" +#include "typeFlag.h" #include "varbinder/scope.h" #include "ir/base/scriptFunction.h" #include "ir/ts/tsTypeParameter.h" @@ -118,12 +119,13 @@ Signature *Signature::Copy(ArenaAllocator *allocator, TypeRelation *relation, Gl return copiedSignature; } -void Signature::ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod) const +void Signature::ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod, + bool precise) const { if (!signatureInfo_->typeParams.empty()) { ss << "<"; for (auto it = signatureInfo_->typeParams.begin(); it != signatureInfo_->typeParams.end(); ++it) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != signatureInfo_->typeParams.end()) { ss << ", "; } @@ -142,7 +144,7 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << ": "; - (*it)->TsType()->ToString(ss); + (*it)->TsType()->ToString(ss, precise); if (std::next(it) != signatureInfo_->params.end()) { ss << ", "; @@ -157,7 +159,8 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << "..."; ss << signatureInfo_->restVar->Name(); ss << ": "; - signatureInfo_->restVar->TsType()->ToString(ss); + signatureInfo_->restVar->TsType()->ToString(ss, precise); + ss << "[]"; } @@ -169,7 +172,14 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << " => "; } - returnType_->ToString(ss); + returnType_->ToString(ss, precise); +} + +std::string Signature::ToString() const +{ + std::stringstream ss; + ToString(ss, nullptr); + return ss.str(); } namespace { @@ -190,9 +200,7 @@ std::size_t GetToCheckParamCount(Signature *signature, bool isEts) bool Signature::IdenticalParameter(TypeRelation *relation, Type *type1, Type *type2) { - if (!CheckFunctionalInterfaces(relation, type1, type2)) { - relation->IsIdenticalTo(type1, type2); - } + relation->IsIdenticalTo(type1, type2); return relation->IsTrue(); } @@ -340,4 +348,24 @@ void Signature::AssignmentTarget(TypeRelation *relation, Signature *source) relation->IsAssignableTo(source->RestVar()->TsType(), signatureInfo_->restVar->TsType()); } } + +Signature *Signature::BoxPrimitives(ETSChecker *checker) +{ + auto *allocator = checker->Allocator(); + auto *sigInfo = allocator->New(signatureInfo_, allocator); + for (auto param : sigInfo->params) { + if (param->TsType()->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) { + param->SetTsType(checker->PrimitiveTypeAsETSBuiltinType(param->TsType())); + } + } + auto *retType = returnType_->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) + ? checker->PrimitiveTypeAsETSBuiltinType(returnType_) + : returnType_; + + auto *resultSig = allocator->New(sigInfo, retType, func_); + resultSig->flags_ = flags_; + resultSig->SetOwner(Owner()); + resultSig->SetOwnerVar(OwnerVar()); + return resultSig; +} } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/signature.h b/ets2panda/checker/types/signature.h index 295dd1111c..ab2bc277fc 100644 --- a/ets2panda/checker/types/signature.h +++ b/ets2panda/checker/types/signature.h @@ -81,6 +81,8 @@ enum class SignatureFlags : uint32_t { THIS_RETURN_TYPE = 1U << 15U, GETTER = 1U << 16U, SETTER = 1U << 17U, + THROWS = 1U << 18U, + RETHROWS = 1U << 19U, INTERNAL_PROTECTED = INTERNAL | PROTECTED, GETTER_OR_SETTER = GETTER | SETTER, @@ -245,10 +247,13 @@ public: Signature *Copy(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); Signature *Substitute(TypeRelation *relation, const Substitution *substitution); - void ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod = false) const; + void ToString(std::stringstream &ss, const varbinder::Variable *variable, bool printAsMethod = false, + bool precise = false) const; + std::string ToString() const; void Identical(TypeRelation *relation, Signature *other); bool CheckFunctionalInterfaces(TypeRelation *relation, Type *source, Type *target); void AssignmentTarget(TypeRelation *relation, Signature *source); + Signature *BoxPrimitives(ETSChecker *checker); private: bool IdenticalParameter(TypeRelation *relation, Type *type1, Type *type2); diff --git a/ets2panda/checker/types/ts/anyType.cpp b/ets2panda/checker/types/ts/anyType.cpp index 8409060e97..db2c7f0420 100644 --- a/ets2panda/checker/types/ts/anyType.cpp +++ b/ets2panda/checker/types/ts/anyType.cpp @@ -16,7 +16,7 @@ #include "anyType.h" namespace panda::es2panda::checker { -void AnyType::ToString(std::stringstream &ss) const +void AnyType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "any"; } diff --git a/ets2panda/checker/types/ts/anyType.h b/ets2panda/checker/types/ts/anyType.h index 69c36c85f5..19633bc7a5 100644 --- a/ets2panda/checker/types/ts/anyType.h +++ b/ets2panda/checker/types/ts/anyType.h @@ -23,7 +23,7 @@ class AnyType : public Type { public: AnyType() : Type(TypeFlag::ANY) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ts/arrayType.cpp b/ets2panda/checker/types/ts/arrayType.cpp index 8c4e2ac9b7..2e34572088 100644 --- a/ets2panda/checker/types/ts/arrayType.cpp +++ b/ets2panda/checker/types/ts/arrayType.cpp @@ -19,13 +19,13 @@ #include "checker/types/ts/objectType.h" namespace panda::es2panda::checker { -void ArrayType::ToString(std::stringstream &ss) const +void ArrayType::ToString(std::stringstream &ss, bool precise) const { bool elemIsUnion = (element_->TypeFlags() == TypeFlag::UNION); if (elemIsUnion) { ss << "("; } - ElementType()->ToString(ss); + ElementType()->ToString(ss, precise); if (elemIsUnion) { ss << ")"; } diff --git a/ets2panda/checker/types/ts/arrayType.h b/ets2panda/checker/types/ts/arrayType.h index 78f6c25994..d60de37a4d 100644 --- a/ets2panda/checker/types/ts/arrayType.h +++ b/ets2panda/checker/types/ts/arrayType.h @@ -33,7 +33,7 @@ public: return element_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/bigintLiteralType.cpp b/ets2panda/checker/types/ts/bigintLiteralType.cpp index b378c83fc5..6623505258 100644 --- a/ets2panda/checker/types/ts/bigintLiteralType.cpp +++ b/ets2panda/checker/types/ts/bigintLiteralType.cpp @@ -16,7 +16,7 @@ #include "bigintLiteralType.h" namespace panda::es2panda::checker { -void BigintLiteralType::ToString(std::stringstream &ss) const +void BigintLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << value_; } diff --git a/ets2panda/checker/types/ts/bigintLiteralType.h b/ets2panda/checker/types/ts/bigintLiteralType.h index 9e02187ffe..b3797e5aff 100644 --- a/ets2panda/checker/types/ts/bigintLiteralType.h +++ b/ets2panda/checker/types/ts/bigintLiteralType.h @@ -36,7 +36,7 @@ public: return negative_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/bigintType.cpp b/ets2panda/checker/types/ts/bigintType.cpp index 91e816019d..ee84c0717a 100644 --- a/ets2panda/checker/types/ts/bigintType.cpp +++ b/ets2panda/checker/types/ts/bigintType.cpp @@ -16,7 +16,7 @@ #include "bigintType.h" namespace panda::es2panda::checker { -void BigintType::ToString(std::stringstream &ss) const +void BigintType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "bigint"; } diff --git a/ets2panda/checker/types/ts/bigintType.h b/ets2panda/checker/types/ts/bigintType.h index 17b7526c60..e9b839d3e5 100644 --- a/ets2panda/checker/types/ts/bigintType.h +++ b/ets2panda/checker/types/ts/bigintType.h @@ -23,7 +23,7 @@ class BigintType : public Type { public: BigintType() : Type(TypeFlag::BIGINT) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/booleanLiteralType.cpp b/ets2panda/checker/types/ts/booleanLiteralType.cpp index b204f0b506..36a0689342 100644 --- a/ets2panda/checker/types/ts/booleanLiteralType.cpp +++ b/ets2panda/checker/types/ts/booleanLiteralType.cpp @@ -16,7 +16,7 @@ #include "booleanLiteralType.h" namespace panda::es2panda::checker { -void BooleanLiteralType::ToString(std::stringstream &ss) const +void BooleanLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { if (value_) { ss << "true"; diff --git a/ets2panda/checker/types/ts/booleanLiteralType.h b/ets2panda/checker/types/ts/booleanLiteralType.h index 381df49bc4..4c04e0cdea 100644 --- a/ets2panda/checker/types/ts/booleanLiteralType.h +++ b/ets2panda/checker/types/ts/booleanLiteralType.h @@ -28,7 +28,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/booleanType.cpp b/ets2panda/checker/types/ts/booleanType.cpp index 3ba7501e33..3855d633b1 100644 --- a/ets2panda/checker/types/ts/booleanType.cpp +++ b/ets2panda/checker/types/ts/booleanType.cpp @@ -16,7 +16,7 @@ #include "booleanType.h" namespace panda::es2panda::checker { -void BooleanType::ToString(std::stringstream &ss) const +void BooleanType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "boolean"; } diff --git a/ets2panda/checker/types/ts/booleanType.h b/ets2panda/checker/types/ts/booleanType.h index b0b54f2233..3dc6c1ece3 100644 --- a/ets2panda/checker/types/ts/booleanType.h +++ b/ets2panda/checker/types/ts/booleanType.h @@ -23,7 +23,7 @@ class BooleanType : public Type { public: BooleanType() : Type(TypeFlag::BOOLEAN) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/constructorType.cpp b/ets2panda/checker/types/ts/constructorType.cpp index 75596cb0b9..294d1a28a5 100644 --- a/ets2panda/checker/types/ts/constructorType.cpp +++ b/ets2panda/checker/types/ts/constructorType.cpp @@ -18,7 +18,7 @@ #include "checker/types/signature.h" namespace panda::es2panda::checker { -void ConstructorType::ToString(std::stringstream &ss) const +void ConstructorType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { if (desc_->constructSignatures.size() > 1) { ss << "{ "; diff --git a/ets2panda/checker/types/ts/constructorType.h b/ets2panda/checker/types/ts/constructorType.h index 4c930cee42..02389c7292 100644 --- a/ets2panda/checker/types/ts/constructorType.h +++ b/ets2panda/checker/types/ts/constructorType.h @@ -23,7 +23,7 @@ class ConstructorType : public ObjectType { public: explicit ConstructorType(ObjectDescriptor *desc) : ObjectType(ObjectType::ObjectTypeKind::FUNCTION, desc) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; }; diff --git a/ets2panda/checker/types/ts/enumLiteralType.cpp b/ets2panda/checker/types/ts/enumLiteralType.cpp index 7cd7c05dc8..0618f2d1c9 100644 --- a/ets2panda/checker/types/ts/enumLiteralType.cpp +++ b/ets2panda/checker/types/ts/enumLiteralType.cpp @@ -19,7 +19,7 @@ #include "checker/types/ts/enumType.h" namespace panda::es2panda::checker { -void EnumLiteralType::ToString(std::stringstream &ss) const +void EnumLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << name_; } diff --git a/ets2panda/checker/types/ts/enumLiteralType.h b/ets2panda/checker/types/ts/enumLiteralType.h index 83a42455ef..19e4e8c9d5 100644 --- a/ets2panda/checker/types/ts/enumLiteralType.h +++ b/ets2panda/checker/types/ts/enumLiteralType.h @@ -47,7 +47,7 @@ public: return kind_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/enumType.cpp b/ets2panda/checker/types/ts/enumType.cpp index 0ee4cc675a..4a308dda73 100644 --- a/ets2panda/checker/types/ts/enumType.cpp +++ b/ets2panda/checker/types/ts/enumType.cpp @@ -18,7 +18,7 @@ #include "varbinder/variable.h" namespace panda::es2panda::checker { -void EnumType::ToString(std::stringstream &ss) const +void EnumType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << enumLiteralVar_->Name() << "." << enumVar_->Name(); } diff --git a/ets2panda/checker/types/ts/enumType.h b/ets2panda/checker/types/ts/enumType.h index c1a3a87882..ce3da03261 100644 --- a/ets2panda/checker/types/ts/enumType.h +++ b/ets2panda/checker/types/ts/enumType.h @@ -1,3 +1,4 @@ + /** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +41,7 @@ public: return enumVar_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/functionType.cpp b/ets2panda/checker/types/ts/functionType.cpp index 3e18974291..e8a10afe9d 100644 --- a/ets2panda/checker/types/ts/functionType.cpp +++ b/ets2panda/checker/types/ts/functionType.cpp @@ -18,7 +18,7 @@ #include "checker/types/signature.h" namespace panda::es2panda::checker { -void FunctionType::ToString(std::stringstream &ss) const +void FunctionType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { static std::unordered_set stack; diff --git a/ets2panda/checker/types/ts/functionType.h b/ets2panda/checker/types/ts/functionType.h index f1b465a54b..b8e36d821d 100644 --- a/ets2panda/checker/types/ts/functionType.h +++ b/ets2panda/checker/types/ts/functionType.h @@ -24,7 +24,7 @@ class FunctionType : public ObjectType { public: explicit FunctionType(ObjectDescriptor *desc) : ObjectType(ObjectType::ObjectTypeKind::FUNCTION, desc) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; }; diff --git a/ets2panda/checker/types/ts/interfaceType.cpp b/ets2panda/checker/types/ts/interfaceType.cpp index 69b95e8ce3..633009c8a1 100644 --- a/ets2panda/checker/types/ts/interfaceType.cpp +++ b/ets2panda/checker/types/ts/interfaceType.cpp @@ -23,7 +23,7 @@ #include namespace panda::es2panda::checker { -void InterfaceType::ToString(std::stringstream &ss) const +void InterfaceType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << name_; diff --git a/ets2panda/checker/types/ts/interfaceType.h b/ets2panda/checker/types/ts/interfaceType.h index cfd1811e49..210129214b 100644 --- a/ets2panda/checker/types/ts/interfaceType.h +++ b/ets2panda/checker/types/ts/interfaceType.h @@ -128,7 +128,7 @@ public: return properties; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; diff --git a/ets2panda/checker/types/ts/neverType.cpp b/ets2panda/checker/types/ts/neverType.cpp index e4d75b6362..8add433de8 100644 --- a/ets2panda/checker/types/ts/neverType.cpp +++ b/ets2panda/checker/types/ts/neverType.cpp @@ -16,7 +16,7 @@ #include "neverType.h" namespace panda::es2panda::checker { -void NeverType::ToString(std::stringstream &ss) const +void NeverType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "never"; } diff --git a/ets2panda/checker/types/ts/neverType.h b/ets2panda/checker/types/ts/neverType.h index 0931b3ae44..5a5fb981c3 100644 --- a/ets2panda/checker/types/ts/neverType.h +++ b/ets2panda/checker/types/ts/neverType.h @@ -23,7 +23,7 @@ class NeverType : public Type { public: NeverType() : Type(TypeFlag::NEVER) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/nonPrimitiveType.cpp b/ets2panda/checker/types/ts/nonPrimitiveType.cpp index 3c37b7cebf..3fb42a30de 100644 --- a/ets2panda/checker/types/ts/nonPrimitiveType.cpp +++ b/ets2panda/checker/types/ts/nonPrimitiveType.cpp @@ -16,7 +16,7 @@ #include "nonPrimitiveType.h" namespace panda::es2panda::checker { -void NonPrimitiveType::ToString(std::stringstream &ss) const +void NonPrimitiveType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "object"; } diff --git a/ets2panda/checker/types/ts/nonPrimitiveType.h b/ets2panda/checker/types/ts/nonPrimitiveType.h index 2047f5df57..614a658ad5 100644 --- a/ets2panda/checker/types/ts/nonPrimitiveType.h +++ b/ets2panda/checker/types/ts/nonPrimitiveType.h @@ -23,7 +23,7 @@ class NonPrimitiveType : public Type { public: NonPrimitiveType() : Type(TypeFlag::NON_PRIMITIVE) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/nullType.cpp b/ets2panda/checker/types/ts/nullType.cpp index 786aed31c6..bcd90b3f70 100644 --- a/ets2panda/checker/types/ts/nullType.cpp +++ b/ets2panda/checker/types/ts/nullType.cpp @@ -16,7 +16,7 @@ #include "nullType.h" namespace panda::es2panda::checker { -void NullType::ToString(std::stringstream &ss) const +void NullType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "null"; } diff --git a/ets2panda/checker/types/ts/nullType.h b/ets2panda/checker/types/ts/nullType.h index c46dfccb24..5d40915809 100644 --- a/ets2panda/checker/types/ts/nullType.h +++ b/ets2panda/checker/types/ts/nullType.h @@ -23,7 +23,7 @@ class NullType : public Type { public: NullType() : Type(TypeFlag::NULL_TYPE) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/numberLiteralType.cpp b/ets2panda/checker/types/ts/numberLiteralType.cpp index c4ccc26e37..3bc17ad8bc 100644 --- a/ets2panda/checker/types/ts/numberLiteralType.cpp +++ b/ets2panda/checker/types/ts/numberLiteralType.cpp @@ -20,7 +20,7 @@ #include "checker/types/ts/enumType.h" namespace panda::es2panda::checker { -void NumberLiteralType::ToString(std::stringstream &ss) const +void NumberLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << util::Helpers::ToString(value_); } diff --git a/ets2panda/checker/types/ts/numberLiteralType.h b/ets2panda/checker/types/ts/numberLiteralType.h index 360060a925..8b738425b7 100644 --- a/ets2panda/checker/types/ts/numberLiteralType.h +++ b/ets2panda/checker/types/ts/numberLiteralType.h @@ -28,7 +28,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/numberType.cpp b/ets2panda/checker/types/ts/numberType.cpp index 40916929fd..59e90af296 100644 --- a/ets2panda/checker/types/ts/numberType.cpp +++ b/ets2panda/checker/types/ts/numberType.cpp @@ -19,7 +19,7 @@ #include "checker/types/ts/enumType.h" namespace panda::es2panda::checker { -void NumberType::ToString(std::stringstream &ss) const +void NumberType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "number"; } diff --git a/ets2panda/checker/types/ts/numberType.h b/ets2panda/checker/types/ts/numberType.h index a30f48609f..eedbc33fe0 100644 --- a/ets2panda/checker/types/ts/numberType.h +++ b/ets2panda/checker/types/ts/numberType.h @@ -23,7 +23,7 @@ class NumberType : public Type { public: NumberType() : Type(TypeFlag::NUMBER) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/objectLiteralType.cpp b/ets2panda/checker/types/ts/objectLiteralType.cpp index 407454989d..0bedc56068 100644 --- a/ets2panda/checker/types/ts/objectLiteralType.cpp +++ b/ets2panda/checker/types/ts/objectLiteralType.cpp @@ -22,7 +22,7 @@ namespace panda::es2panda::checker { class TSChecker; -void ObjectLiteralType::ToString(std::stringstream &ss) const +void ObjectLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "{ "; diff --git a/ets2panda/checker/types/ts/objectLiteralType.h b/ets2panda/checker/types/ts/objectLiteralType.h index e9b5695c1c..85feba1c5c 100644 --- a/ets2panda/checker/types/ts/objectLiteralType.h +++ b/ets2panda/checker/types/ts/objectLiteralType.h @@ -24,7 +24,7 @@ public: explicit ObjectLiteralType(ObjectDescriptor *desc) : ObjectType(ObjectType::ObjectTypeKind::LITERAL, desc) {} ObjectLiteralType() : ObjectType(ObjectType::ObjectTypeKind::LITERAL) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; }; diff --git a/ets2panda/checker/types/ts/stringLiteralType.cpp b/ets2panda/checker/types/ts/stringLiteralType.cpp index 87f8cea1c1..c5e6c80e2e 100644 --- a/ets2panda/checker/types/ts/stringLiteralType.cpp +++ b/ets2panda/checker/types/ts/stringLiteralType.cpp @@ -16,7 +16,7 @@ #include "stringLiteralType.h" namespace panda::es2panda::checker { -void StringLiteralType::ToString(std::stringstream &ss) const +void StringLiteralType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "\"" << value_ << "\""; } diff --git a/ets2panda/checker/types/ts/stringLiteralType.h b/ets2panda/checker/types/ts/stringLiteralType.h index f18e1cb63b..fbca9751a9 100644 --- a/ets2panda/checker/types/ts/stringLiteralType.h +++ b/ets2panda/checker/types/ts/stringLiteralType.h @@ -28,7 +28,7 @@ public: return value_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void ToStringAsSrc(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/stringType.cpp b/ets2panda/checker/types/ts/stringType.cpp index 9afedd90b6..e0b4a9182b 100644 --- a/ets2panda/checker/types/ts/stringType.cpp +++ b/ets2panda/checker/types/ts/stringType.cpp @@ -16,7 +16,7 @@ #include "stringType.h" namespace panda::es2panda::checker { -void StringType::ToString(std::stringstream &ss) const +void StringType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "string"; } diff --git a/ets2panda/checker/types/ts/stringType.h b/ets2panda/checker/types/ts/stringType.h index d37ae5b48d..2081adda40 100644 --- a/ets2panda/checker/types/ts/stringType.h +++ b/ets2panda/checker/types/ts/stringType.h @@ -23,7 +23,7 @@ class StringType : public Type { public: StringType() : Type(TypeFlag::STRING) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/tupleType.cpp b/ets2panda/checker/types/ts/tupleType.cpp index 9e5de1369e..9efd5ccb67 100644 --- a/ets2panda/checker/types/ts/tupleType.cpp +++ b/ets2panda/checker/types/ts/tupleType.cpp @@ -30,7 +30,7 @@ Type *TupleType::ConvertToArrayType(TSChecker *checker) return checker->Allocator()->New(arrayType); } -void TupleType::ToString(std::stringstream &ss) const +void TupleType::ToString(std::stringstream &ss, bool precise) const { if (readonly_) { ss << "readonly "; @@ -39,7 +39,7 @@ void TupleType::ToString(std::stringstream &ss) const if (namedMembers_.empty()) { for (auto it = desc_->properties.begin(); it != desc_->properties.end(); it++) { - (*it)->TsType()->ToString(ss); + (*it)->TsType()->ToString(ss, precise); if ((*it)->HasFlag(varbinder::VariableFlags::OPTIONAL)) { ss << "?"; } @@ -58,7 +58,7 @@ void TupleType::ToString(std::stringstream &ss) const } ss << ": "; - (*it)->TsType()->ToString(ss); + (*it)->TsType()->ToString(ss, precise); if (std::next(it) != desc_->properties.end()) { ss << ", "; } diff --git a/ets2panda/checker/types/ts/tupleType.h b/ets2panda/checker/types/ts/tupleType.h index 53fc5c47fc..b638dce06e 100644 --- a/ets2panda/checker/types/ts/tupleType.h +++ b/ets2panda/checker/types/ts/tupleType.h @@ -87,7 +87,7 @@ public: Type *ConvertToArrayType(TSChecker *checker); - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/typeParameter.cpp b/ets2panda/checker/types/ts/typeParameter.cpp index 516b284db4..fb297bfbf3 100644 --- a/ets2panda/checker/types/ts/typeParameter.cpp +++ b/ets2panda/checker/types/ts/typeParameter.cpp @@ -16,7 +16,7 @@ #include "typeParameter.h" namespace panda::es2panda::checker { -void TypeParameter::ToString([[maybe_unused]] std::stringstream &ss) const +void TypeParameter::ToString([[maybe_unused]] std::stringstream &ss, [[maybe_unused]] bool precise) const { UNREACHABLE(); } diff --git a/ets2panda/checker/types/ts/typeParameter.h b/ets2panda/checker/types/ts/typeParameter.h index bcc320265a..3de782e2c1 100644 --- a/ets2panda/checker/types/ts/typeParameter.h +++ b/ets2panda/checker/types/ts/typeParameter.h @@ -46,7 +46,7 @@ public: default_ = type; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/typeReference.cpp b/ets2panda/checker/types/ts/typeReference.cpp index 579f22f383..4ec359bb58 100644 --- a/ets2panda/checker/types/ts/typeReference.cpp +++ b/ets2panda/checker/types/ts/typeReference.cpp @@ -16,10 +16,10 @@ #include "typeReference.h" namespace panda::es2panda::checker { -void TypeReference::ToString(std::stringstream &ss) const +void TypeReference::ToString(std::stringstream &ss, bool precise) const { if (*ref_ != nullptr) { - (*ref_)->ToString(ss); + (*ref_)->ToString(ss, precise); } } diff --git a/ets2panda/checker/types/ts/typeReference.h b/ets2panda/checker/types/ts/typeReference.h index 2b4f33fc18..4e3022e7a4 100644 --- a/ets2panda/checker/types/ts/typeReference.h +++ b/ets2panda/checker/types/ts/typeReference.h @@ -33,7 +33,7 @@ public: return *ref_; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; TypeFacts GetTypeFacts() const override; diff --git a/ets2panda/checker/types/ts/undefinedType.cpp b/ets2panda/checker/types/ts/undefinedType.cpp index 5e7f6aeae3..72e47c96e7 100644 --- a/ets2panda/checker/types/ts/undefinedType.cpp +++ b/ets2panda/checker/types/ts/undefinedType.cpp @@ -16,7 +16,7 @@ #include "undefinedType.h" namespace panda::es2panda::checker { -void UndefinedType::ToString(std::stringstream &ss) const +void UndefinedType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "undefined"; } diff --git a/ets2panda/checker/types/ts/undefinedType.h b/ets2panda/checker/types/ts/undefinedType.h index 79fbceeb63..93a0db73c9 100644 --- a/ets2panda/checker/types/ts/undefinedType.h +++ b/ets2panda/checker/types/ts/undefinedType.h @@ -23,7 +23,7 @@ class UndefinedType : public Type { public: UndefinedType() : Type(TypeFlag::UNDEFINED) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/unionType.cpp b/ets2panda/checker/types/ts/unionType.cpp index 1d3f7e92f1..352436e9cf 100644 --- a/ets2panda/checker/types/ts/unionType.cpp +++ b/ets2panda/checker/types/ts/unionType.cpp @@ -19,10 +19,10 @@ #include "checker/types/globalTypesHolder.h" namespace panda::es2panda::checker { -void UnionType::ToString(std::stringstream &ss) const +void UnionType::ToString(std::stringstream &ss, bool precise) const { for (auto it = constituentTypes_.begin(); it != constituentTypes_.end(); it++) { - (*it)->ToString(ss); + (*it)->ToString(ss, precise); if (std::next(it) != constituentTypes_.end()) { ss << " | "; } diff --git a/ets2panda/checker/types/ts/unionType.h b/ets2panda/checker/types/ts/unionType.h index 95d81fc732..93ea3ced44 100644 --- a/ets2panda/checker/types/ts/unionType.h +++ b/ets2panda/checker/types/ts/unionType.h @@ -114,7 +114,7 @@ public: mergedObjectType_ = type; } - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; diff --git a/ets2panda/checker/types/ts/unknownType.cpp b/ets2panda/checker/types/ts/unknownType.cpp index 554a3b8e0e..e3f0af57c5 100644 --- a/ets2panda/checker/types/ts/unknownType.cpp +++ b/ets2panda/checker/types/ts/unknownType.cpp @@ -16,7 +16,7 @@ #include "unknownType.h" namespace panda::es2panda::checker { -void UnknownType::ToString(std::stringstream &ss) const +void UnknownType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "unknown"; } diff --git a/ets2panda/checker/types/ts/unknownType.h b/ets2panda/checker/types/ts/unknownType.h index d1cb778f35..5a762dbe7f 100644 --- a/ets2panda/checker/types/ts/unknownType.h +++ b/ets2panda/checker/types/ts/unknownType.h @@ -23,7 +23,7 @@ class UnknownType : public Type { public: UnknownType() : Type(TypeFlag::UNKNOWN) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/ts/voidType.cpp b/ets2panda/checker/types/ts/voidType.cpp index cb2b2fe403..edab990222 100644 --- a/ets2panda/checker/types/ts/voidType.cpp +++ b/ets2panda/checker/types/ts/voidType.cpp @@ -16,7 +16,7 @@ #include "voidType.h" namespace panda::es2panda::checker { -void VoidType::ToString(std::stringstream &ss) const +void VoidType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const { ss << "void"; } diff --git a/ets2panda/checker/types/ts/voidType.h b/ets2panda/checker/types/ts/voidType.h index 47a5ceb807..e7b1b39b49 100644 --- a/ets2panda/checker/types/ts/voidType.h +++ b/ets2panda/checker/types/ts/voidType.h @@ -23,7 +23,7 @@ class VoidType : public Type { public: VoidType() : Type(TypeFlag::VOID) {} - void ToString(std::stringstream &ss) const override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; TypeFacts GetTypeFacts() const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 81affaf07a..ddf5db1e18 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -83,11 +83,37 @@ bool Type::IsLambdaObject() const return false; } +void Type::ToString(std::stringstream &ss) const +{ + ToString(ss, false); +} + void Type::ToStringAsSrc(std::stringstream &ss) const { ToString(ss); } +std::string Type::ToString() const +{ + std::stringstream ss; + ToString(ss); + return ss.str(); +} + +std::string Type::ToStringAsSrc() const +{ + std::stringstream ss; + ToStringAsSrc(ss); + return ss.str(); +} + +std::string Type::ToStringPrecise() const +{ + std::stringstream ss; + ToString(ss, true); + return ss.str(); +} + void Type::Identical(TypeRelation *relation, Type *other) { relation->Result(typeFlags_ == other->TypeFlags()); @@ -140,4 +166,5 @@ Type *Type::Substitute([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] { return this; } + } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 455ec1e227..446da59ccb 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -224,8 +224,13 @@ public: } bool IsLambdaObject() const; - virtual void ToString(std::stringstream &ss) const = 0; + virtual void ToString(std::stringstream &ss, bool precise) const = 0; + void ToString(std::stringstream &ss) const; + std::string ToString() const; + std::string ToStringPrecise() const; virtual void ToStringAsSrc(std::stringstream &ss) const; + std::string ToStringAsSrc() const; + virtual TypeFacts GetTypeFacts() const; virtual void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const {}; virtual void ToDebugInfoType([[maybe_unused]] std::stringstream &ss) const {}; diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index e4a973560d..821b89da24 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -129,7 +129,7 @@ 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 | + CONDITION_EXPRESSION_TYPE = NULLISH | CONSTANT | ETS_OBJECT | BYTE | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE | ETS_BOOLEAN | ETS_ARRAY | ETS_ENUM | ETS_STRING_ENUM }; diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index fd2476ce94..bd6143b251 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -15,8 +15,9 @@ #include "ETSCompiler.h" -#include "checker/types/ets/etsDynamicFunctionType.h" #include "compiler/base/catchTable.h" +#include "checker/types/ets/etsDynamicFunctionType.h" +#include "checker/types/ets/etsObjectType.h" #include "checker/types/ts/enumLiteralType.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" @@ -328,9 +329,7 @@ void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const etsg->InitObject(expr, expr->signature_, expr->GetArguments()); } - if (expr->GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE) { - etsg->SetAccumulatorType(expr->TsType()); - } + etsg->SetAccumulatorType(expr->TsType()); } void ETSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const @@ -659,11 +658,12 @@ void ETSCompiler::Compile(const ir::BinaryExpression *expr) const etsg->Binary(expr, expr->OperatorType(), lhs); } -static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::CallExpression *expr) +static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::CallExpression *expr, + checker::Signature *signature) { - if (expr->Signature()->RestVar() != nullptr) { + if (signature->RestVar() != nullptr) { std::size_t const argumentCount = expr->Arguments().size(); - std::size_t const parameterCount = expr->Signature()->MinArgCount(); + std::size_t const parameterCount = signature->MinArgCount(); ASSERT(argumentCount >= parameterCount); auto &arguments = const_cast &>(expr->Arguments()); @@ -678,13 +678,37 @@ static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::C } auto *arrayExpression = checker->AllocNode(std::move(elements), checker->Allocator()); arrayExpression->SetParent(const_cast(expr)); - arrayExpression->SetTsType(expr->Signature()->RestVar()->TsType()); + arrayExpression->SetTsType(signature->RestVar()->TsType()); arguments.erase(expr->Arguments().begin() + parameterCount, expr->Arguments().end()); arguments.emplace_back(arrayExpression); } } } +void ConvertArgumentsForFunctionalCall(checker::ETSChecker *const checker, const ir::CallExpression *expr) +{ + std::size_t const argumentCount = expr->Arguments().size(); + auto &arguments = const_cast &>(expr->Arguments()); + auto *signature = expr->Signature(); + + for (size_t i = 0; i < argumentCount; i++) { + auto *paramType = checker->MaybeBoxedType( + i < signature->Params().size() ? signature->Params()[i] : signature->RestVar(), checker->Allocator()); + + auto *arg = arguments[i]; + auto *cast = checker->Allocator()->New(arg, nullptr, false); + arguments[i]->SetParent(cast); + cast->SetParent(const_cast(expr)); + cast->SetTsType(paramType); + + if (paramType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + cast->AddBoxingUnboxingFlags(checker->GetBoxingFlag(paramType)); + } + + arguments[i] = cast; + } +} + void ETSCompiler::Compile(const ir::BlockExpression *expr) const { (void)expr; @@ -787,13 +811,15 @@ void ETSCompiler::CompileDynamic(const ir::CallExpression *expr, compiler::VReg etsg->StoreAccumulator(expr, dynParam2); etsg->CallDynamic(expr, calleeReg, dynParam2, expr->Signature(), expr->Arguments()); etsg->SetAccumulatorType(expr->Signature()->ReturnType()); + if (etsg->GetAccumulatorType() != expr->TsType()) { etsg->ApplyConversion(expr, expr->TsType()); } } // Helper function to avoid branching in non optional cases -void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic) const +void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic, + checker::Signature *signature, bool isReference) const { ETSGen *etsg = GetETSGen(); if (expr->Callee()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { @@ -804,14 +830,42 @@ void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calle } else if (expr->Signature()->HasSignatureFlag(checker::SignatureFlags::PRIVATE) || expr->IsETSConstructorCall() || (expr->Callee()->IsMemberExpression() && expr->Callee()->AsMemberExpression()->Object()->IsSuperExpression())) { - etsg->CallThisStatic(expr, calleeReg, expr->Signature(), expr->Arguments()); + etsg->CallThisStatic(expr, calleeReg, signature, expr->Arguments()); + } else { + etsg->CallThisVirtual(expr, calleeReg, signature, expr->Arguments()); + } + + if (isReference) { + etsg->CheckedReferenceNarrowing(expr, signature->ReturnType()); } else { - etsg->CallThisVirtual(expr, calleeReg, expr->Signature(), expr->Arguments()); + etsg->SetAccumulatorType(signature->ReturnType()); } etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->OptionalType()); } +static checker::Signature *ConvertArgumentsForFunctionReference(ETSGen *etsg, const ir::CallExpression *expr) +{ + checker::Signature *origSignature = expr->Signature(); + + auto *funcType = + origSignature->Owner() + ->GetOwnProperty(checker::FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) + ->TsType() + ->AsETSFunctionType(); + ASSERT(funcType->CallSignatures().size() == 1); + checker::Signature *signature = funcType->CallSignatures()[0]; + + if (signature->ReturnType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + expr->AddBoxingUnboxingFlags(const_cast(etsg->Checker()->AsETSChecker()) + ->GetUnboxingFlag(signature->ReturnType())); + } + + ConvertArgumentsForFunctionalCall(const_cast(etsg->Checker()->AsETSChecker()), expr); + + return signature; +} + void ETSCompiler::Compile(const ir::CallExpression *expr) const { ETSGen *etsg = GetETSGen(); @@ -829,7 +883,12 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const bool isReference = expr->Signature()->HasSignatureFlag(checker::SignatureFlags::TYPE); bool isDynamic = expr->Callee()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG); - ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr); + checker::Signature *signature = expr->Signature(); + if (isReference) { + signature = ConvertArgumentsForFunctionReference(etsg, expr); + } + + ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr, signature); if (isDynamic) { CompileDynamic(expr, calleeReg); @@ -838,24 +897,27 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const etsg->LoadThis(expr); etsg->StoreAccumulator(expr, calleeReg); } - EmitCall(expr, calleeReg, isStatic); + EmitCall(expr, calleeReg, isStatic, signature, isReference); } else if (!isReference && expr->Callee()->IsMemberExpression()) { if (!isStatic) { expr->Callee()->AsMemberExpression()->Object()->Compile(etsg); etsg->StoreAccumulator(expr, calleeReg); } - EmitCall(expr, calleeReg, isStatic); + EmitCall(expr, calleeReg, isStatic, signature, isReference); } else if (expr->Callee()->IsSuperExpression() || expr->Callee()->IsThisExpression()) { ASSERT(!isReference && expr->IsETSConstructorCall()); expr->Callee()->Compile(etsg); // ctor is not a value! etsg->SetVRegType(calleeReg, etsg->GetAccumulatorType()); - EmitCall(expr, calleeReg, isStatic); + EmitCall(expr, calleeReg, isStatic, signature, isReference); } else { ASSERT(isReference); etsg->CompileAndCheck(expr->Callee()); etsg->StoreAccumulator(expr, calleeReg); etsg->EmitMaybeOptional( - expr, [this, expr, isStatic, &calleeReg]() { this->EmitCall(expr, calleeReg, isStatic); }, + expr, + [this, expr, isStatic, &calleeReg, signature, isReference]() { + this->EmitCall(expr, calleeReg, isStatic, signature, isReference); + }, expr->IsOptional()); } } diff --git a/ets2panda/compiler/core/ETSCompiler.h b/ets2panda/compiler/core/ETSCompiler.h index 5421dde41f..4e0e04dbd3 100644 --- a/ets2panda/compiler/core/ETSCompiler.h +++ b/ets2panda/compiler/core/ETSCompiler.h @@ -38,7 +38,8 @@ private: void CompileDynamic(const ir::CallExpression *expr, compiler::VReg &calleeReg) const; void CompileCastUnboxable(const ir::TSAsExpression *expr) const; void CompileCast(const ir::TSAsExpression *expr) const; - void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic) const; + void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic, + checker::Signature *signature, bool isReference) const; ETSGen *GetETSGen() const; }; diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 9274234954..c771dc9d13 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -1753,10 +1753,6 @@ void ETSGen::CastToDynamic(const ir::AstNode *node, const checker::ETSDynamicTyp methodName = compiler::Signatures::Dynamic::NewStringBuiltin(type->Language()); break; } - if (GetAccumulatorType()->IsLambdaObject()) { - methodName = Signatures::BUILTIN_JSRUNTIME_CREATE_LAMBDA_PROXY; - break; - } [[fallthrough]]; } case checker::TypeFlag::ETS_ARRAY: { @@ -2020,6 +2016,8 @@ void ETSGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, L void ETSGen::BranchIfNullish([[maybe_unused]] const ir::AstNode *node, [[maybe_unused]] Label *ifNullish) { #ifdef PANDA_WITH_ETS + RegScope rs(this); + auto *const type = GetAccumulatorType(); if (!Checker()->MayHaveNulllikeValue(type)) { @@ -2056,6 +2054,8 @@ void ETSGen::BranchIfNullish([[maybe_unused]] const ir::AstNode *node, [[maybe_u void ETSGen::BranchIfNotNullish([[maybe_unused]] const ir::AstNode *node, [[maybe_unused]] Label *ifNotNullish) { #ifdef PANDA_WITH_ETS + RegScope rs(this); + auto *const type = GetAccumulatorType(); if (!Checker()->MayHaveNulllikeValue(type)) { @@ -2117,6 +2117,7 @@ void ETSGen::EmitNullishGuardian(const ir::AstNode *node) void ETSGen::EmitNullishException(const ir::AstNode *node) { + RegScope ra(this); VReg exception = StoreException(node); NewObject(node, exception, Signatures::BUILTIN_NULLPOINTER_EXCEPTION); CallThisStatic0(node, exception, Signatures::BUILTIN_NULLPOINTER_EXCEPTION_CTOR); diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index b1c5907351..eddd5851d0 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -213,8 +213,7 @@ public: template void ResolveConditionalResult(const ir::AstNode *node, [[maybe_unused]] Label *ifFalse) { - auto type = node->IsExpression() && !node->AsExpression()->IsUnaryExpression() ? node->AsExpression()->TsType() - : GetAccumulatorType(); + auto type = GetAccumulatorType(); if (type->IsETSBooleanType()) { return; } @@ -233,11 +232,7 @@ public: BranchIfNullish(node, ifNullish); } } - if (type->IsETSArrayType()) { - compiler::VReg objReg = AllocReg(); - StoreAccumulator(node, objReg); - LoadArrayLength(node, objReg); - } else if (type->IsETSObjectType()) { + if (type->IsETSArrayType() || type->IsETSObjectType() || type->IsETSUnionType()) { ResolveConditionalResultObject(node); } else { ResolveConditionalResultNumeric(node, ifFalse, &end); @@ -937,7 +932,7 @@ private: arguments[idx]->Compile(this); \ VReg arg##idx = AllocReg(); \ ApplyConversion(arguments[idx], nullptr); \ - ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx); + ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx) template void CallThisImpl(const ir::AstNode *const node, const VReg ctor, checker::Signature *const signature, @@ -970,11 +965,8 @@ private: break; } default: { - for (const auto *arg : arguments) { - auto ttctx = TargetTypeContext(this, arg->TsType()); - VReg argReg = AllocReg(); - arg->Compile(this); - StoreAccumulator(node, argReg); + for (size_t idx = 0; idx < arguments.size(); idx++) { + COMPILE_ARG(idx); } Rra().Emit(node, ctor, arguments.size() + 1, name, ctor); @@ -1078,11 +1070,8 @@ private: default: { VReg argStart = NextReg(); - for (const auto *arg : arguments) { - auto ttctx = TargetTypeContext(this, arg->TsType()); - VReg argReg = AllocReg(); - arg->Compile(this); - StoreAccumulator(node, argReg); + for (size_t idx = 0; idx < arguments.size(); idx++) { + COMPILE_ARG(idx); } Rra().Emit(node, argStart, arguments.size(), name, argStart); @@ -1100,7 +1089,7 @@ private: auto ttctx##idx = TargetTypeContext(this, paramType##idx); \ VReg arg##idx = AllocReg(); \ arguments[idx]->Compile(this); \ - ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx); + ApplyConversionAndStoreAccumulator(arguments[idx], arg##idx, paramType##idx) template void CallDynamicImpl(const ir::AstNode *node, VReg &obj, VReg ¶m2, checker::Signature *signature, diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index c079795062..a4b5949abc 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -296,6 +296,60 @@ builtins: - name: DoubleBox package: PKG_STD_CORE ref: BUILTIN_DOUBLE_BOX + - name: Function0 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION0 + - name: Function1 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION1 + - name: Function2 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION2 + - name: Function3 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION3 + - name: Function4 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION4 + - name: Function5 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION5 + - name: Function6 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION6 + - name: Function7 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION7 + - name: Function8 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION8 + - name: Function9 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION9 + - name: Function10 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION10 + - name: Function11 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION11 + - name: Function12 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION12 + - name: Function13 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION13 + - name: Function14 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION14 + - name: Function15 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION15 + - name: Function16 + package: PKG_STD_CORE + ref: BUILTIN_FUNCTION16 + - name: FunctionN + package: PKG_STD_CORE + ref: BUILTIN_FUNCTIONN signatures: - callee: BUILTIN_OBJECT @@ -1030,12 +1084,6 @@ signatures: return_type: BUILTIN_VOID ref: BUILTIN_JSRUNTIME_INIT_DYNAMIC_NEW_CLASS - - callee: BUILTIN_JSRUNTIME - method_name: __createLambdaProxy - params: [BUILTIN_OBJECT] - return_type: BUILTIN_JSVALUE - ref: BUILTIN_JSRUNTIME_CREATE_LAMBDA_PROXY - - callee: BUILTIN_JSRUNTIME method_name: loadModule params: [BUILTIN_STRING] diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index 42f7323db5..a3245e053f 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -93,6 +93,11 @@ public: return (funcFlags_ & ir::ScriptFunctionFlags::THROWS) != 0; } + bool IsRethrowing() const + { + return (funcFlags_ & ir::ScriptFunctionFlags::RETHROWS) != 0; + } + 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/ts/tsAsExpression.h b/ets2panda/ir/ts/tsAsExpression.h index ba4903adab..1fa6865140 100644 --- a/ets2panda/ir/ts/tsAsExpression.h +++ b/ets2panda/ir/ts/tsAsExpression.h @@ -49,6 +49,11 @@ public: return isConst_; } + void SetUncheckedCast(bool isUncheckedCast) + { + isUncheckedCast_ = isUncheckedCast; + } + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/test/compiler/ets/FunctionType1-expected.txt b/ets2panda/test/compiler/ets/FunctionType1-expected.txt index eb64020f40..a62c8dd85d 100644 --- a/ets2panda/test/compiler/ets/FunctionType1-expected.txt +++ b/ets2panda/test/compiler/ets/FunctionType1-expected.txt @@ -1001,4 +1001,4 @@ } } } -TypeError: Type '(a: int, b: int) => int' cannot be assigned to type '(a: int, b: int) => void' [FunctionType1.ets:24:12] +TypeError: Type '(a: int, b: int) => int' cannot be assigned to type '(p1: Int, p2: Int) => void' [FunctionType1.ets:24:12] diff --git a/ets2panda/test/compiler/ets/FunctionType3-expected.txt b/ets2panda/test/compiler/ets/FunctionType3-expected.txt index bbb4c6e27b..0d0d88e229 100644 --- a/ets2panda/test/compiler/ets/FunctionType3-expected.txt +++ b/ets2panda/test/compiler/ets/FunctionType3-expected.txt @@ -809,4 +809,4 @@ } } } -TypeError: Type 'string' is not compatible with type 'int' at index 2 [FunctionType3.ets:23:16] +TypeError: Type 'string' is not compatible with type 'Int' at index 2 [FunctionType3.ets:23:16] diff --git a/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt b/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt index a92c603283..37dcab16ae 100644 --- a/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt +++ b/ets2panda/test/compiler/ets/etsObjectToString4-expected.txt @@ -465,4 +465,4 @@ } } } -TypeError: Type 'int' cannot be assigned to type '() => int' [etsObjectToString4.ets:18:29] +TypeError: Type 'int' cannot be assigned to type '() => Int' [etsObjectToString4.ets:18:29] diff --git a/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt b/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt index c96da27d61..dbdd0fed4e 100644 --- a/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt +++ b/ets2panda/test/compiler/ets/etsObjectToString5-expected.txt @@ -845,4 +845,4 @@ } } } -TypeError: Type '(y: A) => A|null' cannot be assigned to type '(y: A) => A|null' [etsObjectToString5.ets:18:42] +TypeError: Type '(y: A) => A|null' cannot be assigned to type '(p1: A) => A|null' [etsObjectToString5.ets:18:42] diff --git a/ets2panda/test/compiler/ets/function_subtyping_1-expected.txt b/ets2panda/test/compiler/ets/function_subtyping_1-expected.txt new file mode 100644 index 0000000000..ca68775f5e --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_1-expected.txt @@ -0,0 +1,997 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "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": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "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": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "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 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 20, + "column": 48 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 39 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "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": 21, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/function_subtyping_1.ets b/ets2panda/test/compiler/ets/function_subtyping_1.ets new file mode 100644 index 0000000000..0b2ffc867e --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_1.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. + */ + +class A {} +class B extends A {} + +function main(): void { + let x: (p: B) => A = (p: A): B => { return new B() } +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/function_subtyping_2-expected.txt b/ets2panda/test/compiler/ets/function_subtyping_2-expected.txt new file mode 100644 index 0000000000..b49902e036 --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_2-expected.txt @@ -0,0 +1,998 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "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": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "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": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "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 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 20, + "column": 48 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 39 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "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": 21, + "column": 2 + } + } +} +TypeError: Type '(p: A) => A' cannot be assigned to type '(p1: B) => B' [function_subtyping_2.ets:20:26] diff --git a/ets2panda/test/compiler/ets/function_subtyping_2.ets b/ets2panda/test/compiler/ets/function_subtyping_2.ets new file mode 100644 index 0000000000..64860a92b8 --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_2.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. + */ + +class A {} +class B extends A {} + +function main(): void { + let x: (p: B) => B = (p: A): A => { return new B() } +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/function_subtyping_3-expected.txt b/ets2panda/test/compiler/ets/function_subtyping_3-expected.txt new file mode 100644 index 0000000000..55e50a03bc --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_3-expected.txt @@ -0,0 +1,998 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "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": "main", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "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": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 18 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "init": { + "type": "ArrowFunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "p", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "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 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 27 + }, + "end": { + "line": 20, + "column": 32 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 34 + }, + "end": { + "line": 20, + "column": 38 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 53 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 52 + }, + "end": { + "line": 20, + "column": 54 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 20, + "column": 48 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 39 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 26 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 57 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 14 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "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": 21, + "column": 2 + } + } +} +TypeError: Type '(p: B) => B' cannot be assigned to type '(p1: A) => A' [function_subtyping_3.ets:20:26] diff --git a/ets2panda/test/compiler/ets/function_subtyping_3.ets b/ets2panda/test/compiler/ets/function_subtyping_3.ets new file mode 100644 index 0000000000..4e57a855ae --- /dev/null +++ b/ets2panda/test/compiler/ets/function_subtyping_3.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. + */ + +class A {} +class B extends A {} + +function main(): void { + let x: (p: A) => A = (p: B): B => { return new B() } +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_1-expected.txt b/ets2panda/test/compiler/ets/generic_variance_1-expected.txt new file mode 100644 index 0000000000..abef87ab4c --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_1-expected.txt @@ -0,0 +1,1973 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "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": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "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": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "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": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 8 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 8 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 24, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 15 + }, + "end": { + "line": 24, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 24, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 13 + }, + "end": { + "line": 24, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "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 + } + } + } + ], + "loc": { + "start": { + "line": 24, + "column": 27 + }, + "end": { + "line": 24, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 25 + }, + "end": { + "line": 24, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 24, + "column": 21 + }, + "end": { + "line": 26, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 26, + "column": 8 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 26, + "column": 8 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x3", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 26, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 26, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 16 + }, + "end": { + "line": 26, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 15 + }, + "end": { + "line": 26, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 13 + }, + "end": { + "line": 26, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 26, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 26, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 26, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 28 + }, + "end": { + "line": 26, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 26, + "column": 27 + }, + "end": { + "line": 26, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 25 + }, + "end": { + "line": 26, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 26, + "column": 21 + }, + "end": { + "line": 27, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 9 + }, + "end": { + "line": 27, + "column": 8 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 27, + "column": 8 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x4", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 16 + }, + "end": { + "line": 27, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 15 + }, + "end": { + "line": 27, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 13 + }, + "end": { + "line": 27, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 27, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 27, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 27, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 27, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 28 + }, + "end": { + "line": 27, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 27 + }, + "end": { + "line": 27, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 27, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 25 + }, + "end": { + "line": 27, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 27, + "column": 21 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 9 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 28, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 28, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/generic_variance_1.ets b/ets2panda/test/compiler/ets/generic_variance_1.ets new file mode 100644 index 0000000000..dee382251f --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_1.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A {} +class B extends A {} + +class A1 {} +class A2 {} + +function main(): void { + let x1: A1 = new A1() + let x2: A1 = new A1() + + let x3: A2 = new A2() + let x4: A2 = new A2() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_2-expected.txt b/ets2panda/test/compiler/ets/generic_variance_2-expected.txt new file mode 100644 index 0000000000..227f565f38 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_2-expected.txt @@ -0,0 +1,1218 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "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": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "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": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "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": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A1' cannot be assigned to type 'A1' [generic_variance_2.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_2.ets b/ets2panda/test/compiler/ets/generic_variance_2.ets new file mode 100644 index 0000000000..a3bc04b211 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_2.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. + */ + +class A {} +class B extends A {} + +class A1 {} +class A2 {} + +function main(): void { + let x1: A1 = new A1() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_3-expected.txt b/ets2panda/test/compiler/ets/generic_variance_3-expected.txt new file mode 100644 index 0000000000..3bb1aa6f55 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_3-expected.txt @@ -0,0 +1,1218 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 21 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "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": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "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": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "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": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A2' cannot be assigned to type 'A2' [generic_variance_3.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_3.ets b/ets2panda/test/compiler/ets/generic_variance_3.ets new file mode 100644 index 0000000000..2b61cf9302 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_3.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. + */ + +class A {} +class B extends A {} + +class A1 {} +class A2 {} + +function main(): void { + let x1: A2 = new A2() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_4-expected.txt b/ets2panda/test/compiler/ets/generic_variance_4-expected.txt new file mode 100644 index 0000000000..a3be0edfd5 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_4-expected.txt @@ -0,0 +1,1178 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "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": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "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": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "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": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "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": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A1' cannot be assigned to type 'A1' [generic_variance_4.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_4.ets b/ets2panda/test/compiler/ets/generic_variance_4.ets new file mode 100644 index 0000000000..bc98518302 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_4.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. + */ + +class A {} +class B {} + +class A1 {} +class A2 {} + +function main(): void { + let x2: A1 = new A1() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/generic_variance_5-expected.txt b/ets2panda/test/compiler/ets/generic_variance_5-expected.txt new file mode 100644 index 0000000000..07709a6558 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_5-expected.txt @@ -0,0 +1,1178 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "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": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "in": true, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "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": 18 + }, + "end": { + "line": 19, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 18 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "out": true, + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "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": 20, + "column": 19 + }, + "end": { + "line": 20, + "column": 19 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 10 + }, + "end": { + "line": 22, + "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": 22, + "column": 10 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "x4", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 15 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 16 + }, + "end": { + "line": 23, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 15 + }, + "end": { + "line": 23, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 13 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 25 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } +} +TypeError: Type 'A2' cannot be assigned to type 'A2' [generic_variance_5.ets:23:21] diff --git a/ets2panda/test/compiler/ets/generic_variance_5.ets b/ets2panda/test/compiler/ets/generic_variance_5.ets new file mode 100644 index 0000000000..9e351ad8f9 --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_variance_5.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. + */ + +class A {} +class B {} + +class A1 {} +class A2 {} + +function main(): void { + let x4: A2 = new A2() +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/identifierReference2-expected.txt b/ets2panda/test/compiler/ets/identifierReference2-expected.txt index c0fb2875ea..100cdc5d9d 100644 --- a/ets2panda/test/compiler/ets/identifierReference2-expected.txt +++ b/ets2panda/test/compiler/ets/identifierReference2-expected.txt @@ -398,4 +398,4 @@ } } } -TypeError: Type '(v: double, u: double) => double' cannot be assigned to type '(a: int, b: int) => void' [identifierReference2.ets:16:34] +TypeError: Type '(v: double, u: double) => double' cannot be assigned to type '(p1: Int, p2: Int) => void' [identifierReference2.ets:16:34] diff --git a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt index a17df28bb3..d7fafa4654 100644 --- a/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentType-expected.txt @@ -515,4 +515,4 @@ } } } -TypeError: Type '() => String' cannot be assigned to type '() => int' [lambdaExpressionWithoutBlockStatementDifferentType.ets:17:28] +TypeError: Type '() => String' cannot be assigned to type '() => Int' [lambdaExpressionWithoutBlockStatementDifferentType.ets:17:28] diff --git a/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt b/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt index 22b2a3c2f2..1e358988d2 100644 --- a/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaFunction3-expected.txt @@ -642,4 +642,4 @@ } } } -TypeError: Type '(b: int) => void' cannot be assigned to type '(b: String) => void' [lambdaFunction3.ets:18:39] +TypeError: Type '(b: int) => void' cannot be assigned to type '(p1: String) => void' [lambdaFunction3.ets:18:39] diff --git a/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt b/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt index 5737ced2b4..b82ab2b932 100644 --- a/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt +++ b/ets2panda/test/compiler/ets/lambdaFunction5-expected.txt @@ -1705,4 +1705,4 @@ } } } -TypeError: Type 'string' is not compatible with type 'int' at index 2 [lambdaFunction5.ets:35:17] +TypeError: Type 'string' is not compatible with type 'Int' at index 2 [lambdaFunction5.ets:35:17] diff --git a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt index 545b1715cf..21e87c7c1a 100644 --- a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt +++ b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening-expected.txt @@ -289,7 +289,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "B", + "name": "A", "decorators": [], "loc": { "start": { @@ -354,9 +354,49 @@ { "type": "ReturnStatement", "argument": { - "type": "Identifier", - "name": "a", - "decorators": [], + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 41 + }, + "end": { + "line": 22, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 41 + }, + "end": { + "line": 22, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 41 + }, + "end": { + "line": 22, + "column": 44 + } + } + }, + "arguments": [], "loc": { "start": { "line": 22, @@ -364,7 +404,7 @@ }, "end": { "line": 22, - "column": 38 + "column": 44 } } }, @@ -375,7 +415,7 @@ }, "end": { "line": 22, - "column": 38 + "column": 44 } } } @@ -387,7 +427,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -398,7 +438,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -409,7 +449,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -432,33 +472,33 @@ "loc": { "start": { "line": 22, - "column": 48 + "column": 53 }, "end": { "line": 22, - "column": 49 + "column": 54 } } }, "loc": { "start": { "line": 22, - "column": 48 + "column": 53 }, "end": { "line": 22, - "column": 50 + "column": 55 } } }, "loc": { "start": { "line": 22, - "column": 48 + "column": 53 }, "end": { "line": 22, - "column": 50 + "column": 55 } } }, @@ -466,22 +506,22 @@ "loc": { "start": { "line": 22, - "column": 44 + "column": 49 }, "end": { "line": 22, - "column": 50 + "column": 55 } } }, "loc": { "start": { "line": 22, - "column": 44 + "column": 49 }, "end": { "line": 22, - "column": 50 + "column": 55 } } } @@ -497,18 +537,18 @@ "loc": { "start": { "line": 22, - "column": 54 + "column": 59 }, "end": { "line": 22, - "column": 55 + "column": 60 } } }, "loc": { "start": { "line": 22, - "column": 54 + "column": 59 }, "end": { "line": 23, @@ -519,7 +559,7 @@ "loc": { "start": { "line": 22, - "column": 54 + "column": 59 }, "end": { "line": 23, @@ -530,7 +570,7 @@ "loc": { "start": { "line": 22, - "column": 43 + "column": 48 }, "end": { "line": 23, @@ -545,7 +585,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -556,7 +596,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } } @@ -569,7 +609,7 @@ }, "end": { "line": 22, - "column": 39 + "column": 44 } } }, @@ -595,7 +635,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "A", + "name": "B", "decorators": [], "loc": { "start": { diff --git a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets index cb90f223b6..2d5c270007 100644 --- a/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets +++ b/ets2panda/test/compiler/ets/lambda_infer_type/lambda_cast_infer_type_widening.ets @@ -19,7 +19,7 @@ class A { class B extends A { main () { - let a = (a : B) => { return a} as (a : A) => A - let expected : (a : A) => A = a + let a = (a : A) => { return new B } as (a : A) => A + let expected : (a : B) => A = a } } diff --git a/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt b/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt index 186fa4c371..36610c08a0 100644 --- a/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt +++ b/ets2panda/test/compiler/ets/methodOverrideCovariantReturnType-expected.txt @@ -2084,4 +2084,3 @@ } } } -TypeError: foo(a: int): C in B cannot override foo(): A in A because overriding return type is not compatible with the other return type. [methodOverrideCovariantReturnType.ets:42:8] diff --git a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt index 218cfffdcb..50c023906d 100644 --- a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt +++ b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable-expected.txt @@ -1012,4 +1012,4 @@ } } } -TypeError: Type 'A' cannot be assigned to type 'A' [n_assignGenericWithNullableTypeParamToNonNullable.ets:21:19] +TypeError: Type 'A' cannot be assigned to type 'A' [n_assignGenericWithNullableTypeParamToNonNullable.ets:20:27] diff --git a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets index 8dab208be0..bbe9f2aa80 100644 --- a/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets +++ b/ets2panda/test/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets @@ -17,6 +17,6 @@ class A {} class B {} function main(): void { - let abn : A = new A(); // should work: non nullable B is the subtype of nullable B + let abn : A = new A(); // should not work: non nullable B is the subtype of nullable B, but T has no variance mark let ab : A = abn; // should not work: nullable B (the type of abn) is not the subtype of non nullable B } diff --git a/ets2panda/test/compiler/ets/overload_with_generics-expected.txt b/ets2panda/test/compiler/ets/overload_with_generics-expected.txt new file mode 100644 index 0000000000..8b5703c149 --- /dev/null +++ b/ets2panda/test/compiler/ets/overload_with_generics-expected.txt @@ -0,0 +1,1209 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "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": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 32 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 32 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 32 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 27 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 27 + }, + "end": { + "line": 17, + "column": 35 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 41 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 43 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 26 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 17, + "column": 42 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg1", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 31 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "arg2", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 18, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 41 + }, + "end": { + "line": 18, + "column": 50 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 41 + }, + "end": { + "line": 18, + "column": 50 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 52 + }, + "end": { + "line": 18, + "column": 56 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 52 + }, + "end": { + "line": 18, + "column": 58 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 52 + }, + "end": { + "line": 18, + "column": 58 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "A1", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 23 + }, + "end": { + "line": 18, + "column": 26 + } + } + }, + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "A2", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 27 + }, + "end": { + "line": 18, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 18, + "column": 57 + }, + "end": { + "line": 18, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 59 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 59 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 59 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 44 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 2 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 10 + }, + "end": { + "line": 21, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "arguments": [ + { + "type": "StringLiteral", + "value": "lll", + "loc": { + "start": { + "line": 22, + "column": 11 + }, + "end": { + "line": 22, + "column": 16 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 17 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 7 + }, + "end": { + "line": 23, + "column": 10 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 10 + } + } + }, + "arguments": [ + { + "type": "StringLiteral", + "value": "lll", + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 16 + } + } + }, + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 23, + "column": 18 + }, + "end": { + "line": 23, + "column": 19 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 20 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 24, + "column": 12 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 5 + }, + "end": { + "line": 24, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 14 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 25, + "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": 26, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/overload_with_generics.ets b/ets2panda/test/compiler/ets/overload_with_generics.ets new file mode 100644 index 0000000000..b0c007e32a --- /dev/null +++ b/ets2panda/test/compiler/ets/overload_with_generics.ets @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http: //www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + public static foo(arg: A1): void {} + public static foo(arg1: A1, arg2: A2): void {} +} + +function main(): int { + A.foo("lll") + A.foo("lll", 1) + return 0 +} diff --git a/ets2panda/test/compiler/ets/override16-expected.txt b/ets2panda/test/compiler/ets/override16-expected.txt index b1fa4f9c7e..cf234349f2 100644 --- a/ets2panda/test/compiler/ets/override16-expected.txt +++ b/ets2panda/test/compiler/ets/override16-expected.txt @@ -735,4 +735,4 @@ } } } -TypeError: Hiding method is not return-type-substitutable for other method. [override16.ets:23:5] +TypeError: fn(): float in B cannot override fn(): int in A because overridden method is static. [override16.ets:23:5] diff --git a/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt index b9803f021f..b6a70f9b2e 100644 --- a/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt +++ b/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt @@ -316,4 +316,4 @@ } } } -TypeError: Type '() => void' cannot be assigned to type '(i: int) => int' [function_implicit_return_type2.ets:17:27] +TypeError: Type '() => void' cannot be assigned to type '(p1: Int) => Int' [function_implicit_return_type2.ets:17:27] diff --git a/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt index 86af963d88..ef11ad3a75 100644 --- a/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt +++ b/ets2panda/test/parser/ets/function_implicit_return_type3-expected.txt @@ -465,4 +465,4 @@ } } } -TypeError: Type '(i: int) => void' cannot be assigned to type '(i: int) => int' [function_implicit_return_type3.ets:18:27] +TypeError: Type '(i: int) => void' cannot be assigned to type '(p1: Int) => Int' [function_implicit_return_type3.ets:18:27] diff --git a/ets2panda/test/parser/ets/interface-expected.txt b/ets2panda/test/parser/ets/interface-expected.txt index a84f38f68d..13e389abc2 100644 --- a/ets2panda/test/parser/ets/interface-expected.txt +++ b/ets2panda/test/parser/ets/interface-expected.txt @@ -156,7 +156,7 @@ "type": "ETSTypeReferencePart", "name": { "type": "Identifier", - "name": "Function", + "name": "FunctioN", "decorators": [], "loc": { "start": { @@ -375,4 +375,4 @@ } } } -SyntaxError: Cannot find type 'Function'. [interface.ets:17:39] +SyntaxError: Cannot find type 'FunctioN'. [interface.ets:17:39] diff --git a/ets2panda/test/parser/ets/interface.ets b/ets2panda/test/parser/ets/interface.ets index e43e384d53..80534bb52c 100644 --- a/ets2panda/test/parser/ets/interface.ets +++ b/ets2panda/test/parser/ets/interface.ets @@ -14,5 +14,5 @@ */ -interface G {} +interface G {} diff --git a/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt b/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt index b814441ff1..4ac2df4d2f 100644 --- a/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt +++ b/ets2panda/test/parser/ets/lambda-type-inference-neg-expected.txt @@ -928,4 +928,4 @@ } } } -TypeError: Reference to foo is ambiguous [lambda-type-inference-neg.ets:23:5] +TypeError: Function with this assembly signature already declared. [lambda-type-inference-neg.ets:19:1] diff --git a/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt b/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt index 5c3f1759fa..898613c8c7 100644 --- a/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt +++ b/ets2panda/test/parser/ets/lambda-type-inference-overloaded-1-expected.txt @@ -1963,4 +1963,4 @@ } } } -TypeError: Reference to foo is ambiguous [lambda-type-inference-overloaded-1.ets:32:5] +TypeError: Function with this assembly signature already declared. [lambda-type-inference-overloaded-1.ets:20:1] diff --git a/ets2panda/test/runtime/ets/conversion-char-boolean.ets b/ets2panda/test/runtime/ets/conversion-char-boolean.ets index 76f9ea8e29..2b8d23bc68 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/unboxingBooleanConversion.ets b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets index 7fb437eeda..8a865706f5 100644 --- a/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets +++ b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets @@ -23,8 +23,9 @@ function returnRefBool(a: boolean): Boolean { function main(): void { let a: Boolean = false; + let a2: Boolean = true - let b: Boolean = a && returnTrue(); + let b: Boolean = a || a2; assert b == true let c: Boolean = returnRefBool(a || returnRefBool(returnRefBool(a))); 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 e8521c7c0b..c12cc9299c 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -47,3 +47,12 @@ struct-init.ets struct-init2.ets struct_implements.ets top_level_03.ets + +# Union with undefined +OptionalCall.ets + +# Functional type with rest parameter +lambdaExpressionWithRestParameter.ets + +# Non-trivial cast sequence +castSequence.ets diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index de27323be4..803f9a2c5e 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -11,3 +11,17 @@ parser/ets/import_tests/modules/struct_module.ets parser/ets/import_tests/check_exported_default_struct.ets parser/ets/import_tests/modules/struct_default_module.ets parser/ets/import_tests/check_exported_struct.ets + +# Throwing function types are not yet supported +parser/ets/lambdaThrowsRethrows.ets +parser/ets/variable_throw_function_1.ets +compiler/ets/rethrowingCheck5.ets +compiler/ets/rethrowingConstructorCheck1.ets +compiler/ets/rethrowingConstructorCheck2.ets +compiler/ets/rethrowingConstructorCheck3.ets +compiler/ets/rethrowingFunctionCheck1.ets +compiler/ets/rethrowingFunctionCheck2.ets +compiler/ets/rethrowingFunctionCheck3.ets +compiler/ets/rethrowingMethodCheck1.ets +compiler/ets/rethrowingMethodCheck2.ets +compiler/ets/rethrowingMethodCheck3.ets diff --git a/ets2panda/test/test-lists/parser/parser-js-ignored.txt b/ets2panda/test/test-lists/parser/parser-js-ignored.txt index a0cac35d0e..f6b8c9975e 100644 --- a/ets2panda/test/test-lists/parser/parser-js-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-js-ignored.txt @@ -71,10 +71,9 @@ parser/ets/trailing_lambda_tests/trailing_lambda_define_lambda_in_body_capture_v compiler/ets/override13.ets # 15095 -compiler/ets/methodOverrideCovariantReturnType.ets -compiler/ets/override16.ets compiler/ets/override17.ets parser/ets/static_function_hide_2.ets -# 14595 -compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets +# Throwing function types +compiler/ets/throwingFunctionType2.ets +compiler/ets/throwingFunctionAsParameter2.ets diff --git a/ets2panda/util/declgenEts2Ts.cpp b/ets2panda/util/declgenEts2Ts.cpp index 89cb7e1e34..8e4d7c9c12 100644 --- a/ets2panda/util/declgenEts2Ts.cpp +++ b/ets2panda/util/declgenEts2Ts.cpp @@ -295,7 +295,8 @@ void TSDeclGen::GenEnumType(const checker::ETSEnumType *enumType) void TSDeclGen::GenObjectType(const checker::ETSObjectType *objectType) { if (objectType->HasObjectFlag(checker::ETSObjectFlags::FUNCTIONAL)) { - const auto *invoke = objectType->GetOwnProperty("invoke"); + const auto *invoke = objectType->GetOwnProperty( + checker::FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType()); GenType(invoke->TsType()); return; diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 06d08f3553..1e6c232d01 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -400,8 +400,9 @@ void ETSBinder::BuildLambdaObject(ir::AstNode *refNode, ir::ClassDefinition *lam auto boundCtx = BoundContext(GetGlobalRecordTable(), lambdaObject); const auto &lambdaBody = lambdaObject->Body(); + AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 3U]->AsMethodDefinition()->Function()); AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 2U]->AsMethodDefinition()->Function()); - AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function()); + AddLambdaFunctionThisParam(lambdaBody[lambdaBody.size() - 1U]->AsMethodDefinition()->Function()); LambdaObjects().insert({refNode, {lambdaObject, signature}}); } @@ -876,16 +877,6 @@ void ETSBinder::FormLambdaName(util::UString &name, const util::StringView &sign name.Append(replaced); } -void ETSBinder::FormFunctionalInterfaceName(util::UString &name, const util::StringView &signature) -{ - auto replaced = std::string(signature.Utf8()); - std::replace(replaced.begin(), replaced.end(), '.', '-'); - std::replace(replaced.begin(), replaced.end(), ':', '-'); - std::replace(replaced.begin(), replaced.end(), ';', '-'); - replaced.append(std::to_string(0)); - name.Append(replaced); -} - void ETSBinder::BuildLambdaObjectName(const ir::AstNode *refNode) { auto found = lambdaObjects_.find(refNode); @@ -913,51 +904,17 @@ void ETSBinder::BuildLambdaObjectName(const ir::AstNode *refNode) lambdaObject->SetAssemblerName(lambdaClass->Ident()->Name()); const auto &lambdaBody = lambdaClass->Body(); - auto *ctorFunc = lambdaBody[lambdaBody.size() - 2]->AsMethodDefinition()->Function(); + auto *ctorFunc = lambdaBody[lambdaBody.size() - 3U]->AsMethodDefinition()->Function(); auto *ctorFuncScope = ctorFunc->Scope(); ctorFuncScope->BindName(lambdaClass->Ident()->Name()); - auto *invokeFunc = lambdaBody[lambdaBody.size() - 1]->AsMethodDefinition()->Function(); - auto *invokeFuncScope = invokeFunc->Scope(); - invokeFuncScope->BindName(lambdaClass->Ident()->Name()); -} - -void ETSBinder::BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType) -{ - auto *functionalInterface = funcType->FunctionalInterface(); - auto *invokeFunc = functionalInterface->Body()->Body()[0]->AsMethodDefinition()->Function(); - util::UString functionalInterfaceName(functionalInterface->Id()->Name(), Allocator()); - std::stringstream ss; - invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), ss); - std::string signatureString = ss.str(); - util::StringView signatureName(signatureString); - FormFunctionalInterfaceName(functionalInterfaceName, signatureName); - functionalInterface->Id()->SetName(functionalInterfaceName.View()); - util::UString internalName(Program()->GetPackageName(), Allocator()); - if (!(internalName.View().Empty())) { - internalName.Append(compiler::Signatures::METHOD_SEPARATOR); - } - internalName.Append(functionalInterface->Id()->Name()); - functionalInterface->SetInternalName(internalName.View()); - - checker::ETSObjectType *functionalInterfaceType = functionalInterface->TsType()->AsETSObjectType(); - functionalInterfaceType->SetName(functionalInterface->Id()->Name()); - functionalInterfaceType->SetAssemblerName(internalName.View()); + auto *invoke0Func = lambdaBody[lambdaBody.size() - 2U]->AsMethodDefinition()->Function(); + auto *invoke0FuncScope = invoke0Func->Scope(); + invoke0FuncScope->BindName(lambdaClass->Ident()->Name()); + auto *invokeFunc = lambdaBody[lambdaBody.size() - 1U]->AsMethodDefinition()->Function(); auto *invokeFuncScope = invokeFunc->Scope(); - invokeFuncScope->BindName(functionalInterface->Id()->Name()); - - util::UString invokeInternalName(Program()->GetPackageName(), Allocator()); - if (!(invokeInternalName.View().Empty())) { - invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR); - } - invokeInternalName.Append(invokeFuncScope->Name()); - invokeInternalName.Append(compiler::Signatures::METHOD_SEPARATOR); - invokeInternalName.Append(invokeFunc->Id()->Name()); - std::stringstream invokeSignatureSs; - invokeFunc->Signature()->ToAssemblerType(GetCompilerContext(), invokeSignatureSs); - invokeInternalName.Append(invokeSignatureSs.str()); - invokeFuncScope->BindInternalName(invokeInternalName.View()); + invokeFuncScope->BindName(lambdaClass->Ident()->Name()); } void ETSBinder::InitImplicitThisParam() diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index edd27f9a43..0f70577279 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -158,8 +158,6 @@ public: void AddInvokeFunctionThisParam(ir::ScriptFunction *func); void BuildLambdaObjectName(const ir::AstNode *refNode); void FormLambdaName(util::UString &name, const util::StringView &signature); - void FormFunctionalInterfaceName(util::UString &name, const util::StringView &signature); - void BuildFunctionalInterfaceName(ir::ETSFunctionType *funcType); void SetDefaultImports(ArenaVector defaultImports) { -- Gitee From 443b25d7dcb52f7cd585ead58647ecc7f99d59ad Mon Sep 17 00:00:00 2001 From: Zelentsov Dmitry Date: Sat, 3 Feb 2024 22:29:56 +0300 Subject: [PATCH 2/3] Fix errors reported by 'EveryChildHasValidParentForAll' check of ASTVerifier. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8Y3QT?from=project-issue Tests: U-runner, CI Signed-off-by: Zelentsov Dmitry --- ets2panda/checker/ETSAnalyzer.cpp | 26 +- ets2panda/checker/ETSchecker.h | 30 +- ets2panda/checker/ets/dynamic.cpp | 200 +++++++------ ets2panda/checker/ets/enum.cpp | 233 ++++++++------- ets2panda/checker/ets/function.cpp | 278 ++++++++++-------- ets2panda/checker/ets/helpers.cpp | 71 +++-- ets2panda/checker/ets/object.cpp | 45 ++- ets2panda/checker/ets/typeCreation.cpp | 44 ++- ets2panda/compiler/core/ASTVerifier.cpp | 22 +- ets2panda/compiler/core/ETSfunction.cpp | 10 +- ets2panda/compiler/core/compilerImpl.cpp | 33 ++- .../compiler/lowering/ets/expandBrackets.cpp | 2 +- .../ets/interfacePropertyDeclarations.cpp | 20 +- .../compiler/lowering/ets/opAssignment.cpp | 119 ++++---- .../compiler/lowering/ets/tupleLowering.cpp | 30 +- .../compiler/lowering/ets/unionLowering.cpp | 10 +- .../lowering/scopesInit/scopesInitPhase.cpp | 30 +- ets2panda/ir/astNode.h | 3 +- ets2panda/ir/base/classDefinition.cpp | 8 + ets2panda/ir/base/classDefinition.h | 8 +- ets2panda/ir/base/classElement.cpp | 4 +- ets2panda/ir/base/classProperty.cpp | 12 +- ets2panda/ir/base/classProperty.h | 3 +- ets2panda/ir/base/decorator.cpp | 3 +- ets2panda/ir/base/decorator.h | 3 +- ets2panda/ir/base/metaProperty.cpp | 1 - ets2panda/ir/base/metaProperty.h | 3 +- ets2panda/ir/base/methodDefinition.cpp | 24 +- ets2panda/ir/base/methodDefinition.h | 16 +- ets2panda/ir/base/property.cpp | 5 +- ets2panda/ir/base/property.h | 3 +- ets2panda/ir/base/scriptFunction.cpp | 34 ++- ets2panda/ir/base/scriptFunction.h | 38 +-- ets2panda/ir/base/spreadElement.cpp | 1 - ets2panda/ir/base/spreadElement.h | 3 +- ets2panda/ir/base/templateElement.cpp | 1 - ets2panda/ir/base/templateElement.h | 3 +- ets2panda/ir/base/tsIndexSignature.cpp | 5 +- ets2panda/ir/base/tsIndexSignature.h | 3 +- ets2panda/ir/base/tsPropertySignature.cpp | 5 +- ets2panda/ir/base/tsPropertySignature.h | 3 +- ets2panda/ir/ets/etsClassLiteral.cpp | 3 +- ets2panda/ir/ets/etsClassLiteral.h | 3 +- ets2panda/ir/ets/etsFunctionType.cpp | 16 +- ets2panda/ir/ets/etsFunctionType.h | 3 +- ets2panda/ir/ets/etsLaunchExpression.cpp | 6 +- ets2panda/ir/ets/etsLaunchExpression.h | 3 +- .../ir/ets/etsNewArrayInstanceExpression.cpp | 9 +- .../ir/ets/etsNewArrayInstanceExpression.h | 6 +- .../ir/ets/etsNewClassInstanceExpression.cpp | 6 +- .../ir/ets/etsNewClassInstanceExpression.h | 3 +- .../etsNewMultiDimArrayInstanceExpression.cpp | 3 +- .../etsNewMultiDimArrayInstanceExpression.h | 4 +- ets2panda/ir/ets/etsPackageDeclaration.cpp | 3 +- ets2panda/ir/ets/etsPackageDeclaration.h | 3 +- ets2panda/ir/ets/etsParameterExpression.cpp | 9 +- ets2panda/ir/ets/etsParameterExpression.h | 3 +- ets2panda/ir/ets/etsPrimitiveType.cpp | 2 +- ets2panda/ir/ets/etsPrimitiveType.h | 3 +- ets2panda/ir/ets/etsStructDeclaration.cpp | 3 +- ets2panda/ir/ets/etsStructDeclaration.h | 3 +- ets2panda/ir/ets/etsTypeReference.cpp | 4 +- ets2panda/ir/ets/etsTypeReference.h | 3 +- ets2panda/ir/ets/etsTypeReferencePart.cpp | 8 +- ets2panda/ir/ets/etsTypeReferencePart.h | 3 +- ets2panda/ir/expressions/arrayExpression.cpp | 1 - ets2panda/ir/expressions/arrayExpression.h | 3 +- .../expressions/arrowFunctionExpression.cpp | 23 +- .../ir/expressions/arrowFunctionExpression.h | 3 +- .../ir/expressions/assignmentExpression.cpp | 7 +- .../ir/expressions/assignmentExpression.h | 3 +- ets2panda/ir/expressions/awaitExpression.cpp | 6 +- ets2panda/ir/expressions/awaitExpression.h | 3 +- ets2panda/ir/expressions/binaryExpression.cpp | 10 +- ets2panda/ir/expressions/binaryExpression.h | 3 +- ets2panda/ir/expressions/blockExpression.cpp | 1 - ets2panda/ir/expressions/blockExpression.h | 3 +- ets2panda/ir/expressions/callExpression.cpp | 26 +- ets2panda/ir/expressions/callExpression.h | 13 +- ets2panda/ir/expressions/chainExpression.cpp | 3 +- ets2panda/ir/expressions/chainExpression.h | 3 +- ets2panda/ir/expressions/classExpression.cpp | 3 +- ets2panda/ir/expressions/classExpression.h | 3 +- .../ir/expressions/conditionalExpression.cpp | 12 +- .../ir/expressions/conditionalExpression.h | 4 +- .../ir/expressions/functionExpression.cpp | 3 +- ets2panda/ir/expressions/functionExpression.h | 3 +- ets2panda/ir/expressions/identifier.cpp | 4 +- ets2panda/ir/expressions/identifier.h | 3 +- ets2panda/ir/expressions/importExpression.cpp | 3 +- ets2panda/ir/expressions/importExpression.h | 3 +- .../ir/expressions/literals/bigIntLiteral.cpp | 3 +- .../ir/expressions/literals/bigIntLiteral.h | 3 +- .../expressions/literals/booleanLiteral.cpp | 2 +- .../ir/expressions/literals/booleanLiteral.h | 3 +- .../ir/expressions/literals/charLiteral.cpp | 3 +- .../ir/expressions/literals/charLiteral.h | 3 +- .../ir/expressions/literals/nullLiteral.cpp | 2 +- .../ir/expressions/literals/nullLiteral.h | 3 +- .../ir/expressions/literals/numberLiteral.cpp | 2 +- .../ir/expressions/literals/numberLiteral.h | 3 +- .../ir/expressions/literals/regExpLiteral.cpp | 2 +- .../ir/expressions/literals/regExpLiteral.h | 3 +- .../ir/expressions/literals/stringLiteral.cpp | 2 +- .../ir/expressions/literals/stringLiteral.h | 3 +- .../expressions/literals/undefinedLiteral.cpp | 1 + ets2panda/ir/expressions/memberExpression.cpp | 29 +- ets2panda/ir/expressions/memberExpression.h | 7 +- ets2panda/ir/expressions/newExpression.cpp | 1 - ets2panda/ir/expressions/newExpression.h | 3 +- ets2panda/ir/expressions/objectExpression.cpp | 1 - ets2panda/ir/expressions/objectExpression.h | 3 +- .../ir/expressions/omittedExpression.cpp | 1 - ets2panda/ir/expressions/omittedExpression.h | 3 +- .../ir/expressions/sequenceExpression.cpp | 1 - ets2panda/ir/expressions/sequenceExpression.h | 3 +- ets2panda/ir/expressions/superExpression.cpp | 1 - ets2panda/ir/expressions/superExpression.h | 3 +- .../expressions/taggedTemplateExpression.cpp | 7 +- .../ir/expressions/taggedTemplateExpression.h | 3 +- ets2panda/ir/expressions/templateLiteral.cpp | 1 - ets2panda/ir/expressions/templateLiteral.h | 3 +- ets2panda/ir/expressions/thisExpression.cpp | 1 - ets2panda/ir/expressions/thisExpression.h | 3 +- ets2panda/ir/expressions/unaryExpression.cpp | 13 +- ets2panda/ir/expressions/unaryExpression.h | 3 +- ets2panda/ir/expressions/updateExpression.cpp | 6 +- ets2panda/ir/expressions/updateExpression.h | 3 +- ets2panda/ir/expressions/yieldExpression.cpp | 3 +- ets2panda/ir/expressions/yieldExpression.h | 3 +- ets2panda/ir/statements/returnStatement.cpp | 4 +- ets2panda/ir/ts/tsArrayType.cpp | 3 +- ets2panda/ir/ts/tsArrayType.h | 3 +- ets2panda/ir/ts/tsAsExpression.cpp | 51 +++- ets2panda/ir/ts/tsAsExpression.h | 19 +- ets2panda/ir/ts/tsInterfaceBody.cpp | 2 +- ets2panda/ir/ts/tsQualifiedName.cpp | 22 ++ ets2panda/ir/ts/tsQualifiedName.h | 22 +- .../ir/ts/tsTypeParameterInstantiation.cpp | 1 - .../ir/ts/tsTypeParameterInstantiation.h | 3 +- ets2panda/ir/typeNode.cpp | 1 - ets2panda/ir/typeNode.h | 3 +- ets2panda/parser/ETSparser.cpp | 149 ++++++---- ets2panda/parser/ETSparser.h | 4 + ets2panda/parser/TypedParser.cpp | 4 +- ets2panda/parser/context/parserContext.h | 2 +- ets2panda/parser/expressionParser.cpp | 2 +- ets2panda/parser/parserImpl.cpp | 20 +- ets2panda/public/es2panda_lib.cpp | 4 +- .../ets-runtime/ets-runtime-ignored.txt | 4 + .../test-lists/parser/parser-ets-ignored.txt | 3 + ets2panda/test/unit/node_creator.h | 6 +- ets2panda/util/options.cpp | 2 +- ets2panda/varbinder/ETSBinder.cpp | 4 +- 154 files changed, 1186 insertions(+), 954 deletions(-) diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 050613b400..bbddda80b3 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -259,11 +259,16 @@ void CheckGetterSetterTypeConstrains(ETSChecker *checker, ir::ScriptFunction *sc checker::Type *ETSAnalyzer::Check(ir::MethodDefinition *node) const { ETSChecker *checker = GetETSChecker(); + auto *scriptFunc = node->Function(); if (scriptFunc->IsProxy()) { return nullptr; } + if (node->Id()->Variable() == nullptr) { + node->Id()->SetVariable(scriptFunc->Id()->Variable()); + } + // NOTE: aszilagyi. make it correctly check for open function not have body if (!scriptFunc->HasBody() && !(node->IsAbstract() || node->IsNative() || node->IsDeclare() || checker->HasStatus(checker::CheckerStatus::IN_INTERFACE))) { @@ -557,7 +562,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const auto *signature = checker->ResolveConstructExpression(calleeObj, expr->GetArguments(), expr->Start()); checker->CheckObjectLiteralArguments(signature, expr->GetArguments()); - checker->AddUndefinedParamsForDefaultParams(signature, expr->arguments_, checker); + checker->AddUndefinedParamsForDefaultParams(signature, expr, expr->arguments_, checker); checker->ValidateSignatureAccessibility(calleeObj, nullptr, signature, expr->Start()); @@ -916,10 +921,19 @@ static checker::Type *InitAnonymousLambdaCallee(checker::ETSChecker *checker, ir checker::Type *calleeType) { auto *const arrowFunc = callee->AsArrowFunctionExpression()->Function(); - auto origParams = arrowFunc->Params(); - auto signature = ir::FunctionSignature(nullptr, std::move(origParams), arrowFunc->ReturnTypeAnnotation()); - auto *funcType = - checker->Allocator()->New(std::move(signature), ir::ScriptFunctionFlags::NONE); + + ArenaVector params {checker->Allocator()->Adapter()}; + checker->CopyParams(arrowFunc->Params(), params); + + auto *typeAnnotation = arrowFunc->ReturnTypeAnnotation(); + if (typeAnnotation != nullptr) { + typeAnnotation = typeAnnotation->Clone(checker->Allocator(), nullptr); + typeAnnotation->SetTsType(arrowFunc->ReturnTypeAnnotation()->TsType()); + } + + auto signature = ir::FunctionSignature(nullptr, std::move(params), typeAnnotation); + auto *funcType = checker->AllocNode(std::move(signature), ir::ScriptFunctionFlags::NONE); + funcType->SetScope(arrowFunc->Scope()->AsFunctionScope()->ParamScope()); auto *const funcIface = funcType->Check(checker); checker->Relation()->SetNode(callee); @@ -1080,7 +1094,7 @@ checker::Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, checker::Typ ResolveSignature(checker, expr, calleeType, isFunctionalInterface, isUnionTypeWithFunctionalInterface); checker->CheckObjectLiteralArguments(signature, expr->Arguments()); - checker->AddUndefinedParamsForDefaultParams(signature, expr->Arguments(), checker); + checker->AddUndefinedParamsForDefaultParams(signature, expr, expr->Arguments(), checker); if (!isFunctionalInterface) { checker::ETSObjectType *calleeObj = ChooseCalleeObj(checker, expr, calleeType, isConstructorCall); diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 710021b70f..9ce8260889 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -17,7 +17,6 @@ #define ES2PANDA_CHECKER_ETS_CHECKER_H #include "checker/checkerContext.h" -#include "varbinder/enumMemberResult.h" #include "varbinder/scope.h" #include "checker/checker.h" #include "checker/ets/primitiveWrappers.h" @@ -29,18 +28,8 @@ #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterInstantiation.h" #include "lexer/token/tokenType.h" -#include "util/enumbitops.h" #include "util/ustring.h" -#include "utils/bit_utils.h" #include "checker/resolveResult.h" -#include "macros.h" - -#include -#include -#include -#include -#include -#include namespace panda::es2panda::varbinder { class VarBinder; @@ -404,7 +393,8 @@ public: ArenaVector ¶ms, const lexer::SourceRange &pos, bool isStaticReference); ir::MethodDefinition *CreateLambdaInvokeProto(util::StringView invokeName); void CreateLambdaFuncDecl(ir::MethodDefinition *func, varbinder::LocalScope *scope); - void ResolveProxyMethod(ir::MethodDefinition *proxyMethod, ir::ArrowFunctionExpression *lambda); + void ResolveProxyMethod(ir::ClassDefinition *classDefinition, ir::MethodDefinition *proxyMethod, + ir::ArrowFunctionExpression *lambda); void ResolveLambdaObject(ir::ClassDefinition *lambdaObject, Signature *signature, ETSObjectType *functionalInterface, ir::AstNode *refNode); void ResolveLambdaObject(ir::ClassDefinition *lambdaObject, ETSObjectType *functionalInterface, @@ -547,7 +537,7 @@ public: util::StringView GetHashFromFunctionType(ir::ETSFunctionType *type); ETSObjectType *GetOriginalBaseType(Type *object); Type *GetTypeFromTypeAnnotation(ir::TypeNode *typeAnnotation); - void AddUndefinedParamsForDefaultParams(const Signature *signature, + void AddUndefinedParamsForDefaultParams(const Signature *signature, ir::AstNode *parent, ArenaVector &arguments, ETSChecker *checker); void SetArrayPreferredTypeForNestedMemberExpressions(ir::MemberExpression *expr, Type *annotationType); @@ -583,6 +573,8 @@ public: ETSEnumInterface *enumType); [[nodiscard]] ETSEnumType::Method CreateEnumValuesMethod(ir::Identifier *itemsArrayIdent, ETSEnumInterface *enumType); + [[nodiscard]] ir::StringLiteral *CreateEnumStringLiteral(ETSEnumInterface *const enumType, + const ir::TSEnumMember *const member); // Dynamic interop template @@ -645,6 +637,11 @@ private: PropertySearchFlags GetInitialSearchFlags(const ir::MemberExpression *memberExpr); const varbinder::Variable *GetTargetRef(const ir::MemberExpression *memberExpr); void BuildClass(util::StringView name, const ClassBuilder &builder); + + template + std::pair CreateScriptFunction(varbinder::FunctionScope *scope, + ClassInitializerBuilder const &builder); + template std::conditional_t CreateClassInitializer( varbinder::ClassScope *classScope, const ClassInitializerBuilder &builder, ETSObjectType *type = nullptr); @@ -653,9 +650,8 @@ private: checker::Type *type); template - ir::MethodDefinition *CreateClassMethod(varbinder::ClassScope *classScope, std::string_view methodName, - panda::es2panda::ir::ModifierFlags modifierFlags, - const MethodBuilder &builder); + ir::MethodDefinition *CreateClassMethod(varbinder::ClassScope *classScope, std::string_view name, + ir::ModifierFlags modifierFlags, const MethodBuilder &builder); template ir::ScriptFunction *CreateDynamicCallIntrinsic(ir::Expression *callee, const ArenaVector &arguments, @@ -673,6 +669,8 @@ private: Signature *invokeSignature, ir::TypeNode *retTypeAnnotation); + void ClassInitializerFromImport(ir::ETSImportDeclaration *import, varbinder::FunctionScope *scope, + ArenaVector *statements); void EmitDynamicModuleClassInitCall(); DynamicCallIntrinsicsMap *DynamicCallIntrinsics(bool isConstruct) diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index c0037fea91..cb5a6a6225 100644 --- a/ets2panda/checker/ets/dynamic.cpp +++ b/ets2panda/checker/ets/dynamic.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include "checker/ETSchecker.h" #include "varbinder/scope.h" @@ -85,7 +86,6 @@ template ir::ScriptFunction *ETSChecker::CreateDynamicCallIntrinsic(ir::Expression *callee, const ArenaVector &arguments, Language lang) { - auto *name = AllocNode("invoke", Allocator()); auto *paramScope = Allocator()->New(Allocator(), nullptr); auto *scope = Allocator()->New(Allocator(), paramScope); @@ -119,9 +119,9 @@ ir::ScriptFunction *ETSChecker::CreateDynamicCallIntrinsic(ir::Expression *calle info->params.push_back(param->Ident()->Variable()->AsLocalVariable()); } - auto *func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), nullptr, - ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::NONE, false, - Language(Language::Id::ETS)); + auto *func = AllocNode( + ir::FunctionSignature(nullptr, std::move(params), nullptr), nullptr, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::NONE}); func->SetScope(scope); scope->BindNode(func); @@ -129,6 +129,7 @@ ir::ScriptFunction *ETSChecker::CreateDynamicCallIntrinsic(ir::Expression *calle scope->BindParamScope(paramScope); paramScope->BindFunctionScope(scope); + auto *name = AllocNode("invoke", Allocator()); func->SetIdent(name); auto *signature = CreateSignature(info, dynamicType, func); @@ -197,50 +198,60 @@ template Signature *ETSChecker::ResolveDynamicCallExpression &arguments, Language lang, bool is_construct); template -std::conditional_t ETSChecker::CreateClassInitializer( - varbinder::ClassScope *classScope, const ClassInitializerBuilder &builder, ETSObjectType *type) +std::pair ETSChecker::CreateScriptFunction( + varbinder::FunctionScope *scope, ClassInitializerBuilder const &builder) { - varbinder::LocalScope *methodScope = nullptr; - if constexpr (IS_STATIC) { - methodScope = classScope->StaticMethodScope(); - } else { - methodScope = classScope->InstanceMethodScope(); - } - auto classCtx = varbinder::LexicalScope::Enter(VarBinder(), methodScope); - - ArenaVector params(Allocator()->Adapter()); - - auto *paramScope = Allocator()->New(Allocator(), classScope); - auto *scope = Allocator()->New(Allocator(), paramScope); - ArenaVector statements(Allocator()->Adapter()); + ArenaVector params(Allocator()->Adapter()); - ir::ScriptFunction *func = nullptr; - ir::Identifier *id = nullptr; + ir::ScriptFunction *func; + ir::Identifier *id; if constexpr (IS_STATIC) { builder(scope, &statements, nullptr); auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); id = AllocNode(compiler::Signatures::CCTOR, Allocator()); - func = - AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::EXPRESSION, - ir::ModifierFlags::STATIC, false, Language(Language::Id::ETS)); - func->SetScope(scope); + func = AllocNode( + ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::STATIC_BLOCK | + ir::ScriptFunctionFlags::EXPRESSION, + ir::ModifierFlags::STATIC}); } else { builder(scope, &statements, ¶ms); auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); id = AllocNode(compiler::Signatures::CTOR, Allocator()); - func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::CONSTRUCTOR | ir::ScriptFunctionFlags::EXPRESSION, - ir::ModifierFlags::PUBLIC, false, Language(Language::Id::ETS)); - func->SetScope(scope); + func = AllocNode( + ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData { + ir::ScriptFunctionFlags::CONSTRUCTOR | ir::ScriptFunctionFlags::EXPRESSION, ir::ModifierFlags::PUBLIC}); } + func->SetScope(scope); scope->BindNode(func); func->SetIdent(id); + + return std::make_pair(func, id); +} + +template +std::conditional_t ETSChecker::CreateClassInitializer( + varbinder::ClassScope *classScope, const ClassInitializerBuilder &builder, ETSObjectType *type) +{ + varbinder::LocalScope *methodScope = nullptr; + if constexpr (IS_STATIC) { + methodScope = classScope->StaticMethodScope(); + } else { + methodScope = classScope->InstanceMethodScope(); + } + auto classCtx = varbinder::LexicalScope::Enter(VarBinder(), methodScope); + + auto *paramScope = Allocator()->New(Allocator(), classScope); + auto *scope = Allocator()->New(Allocator(), paramScope); + + auto [func, id] = CreateScriptFunction(scope, builder); + paramScope->BindNode(func); scope->BindParamScope(paramScope); paramScope->BindFunctionScope(scope); @@ -263,12 +274,11 @@ std::conditional_t ET } else { type->AddConstructSignature(signature); - auto *ctor = Allocator()->New(ir::MethodDefinitionKind::CONSTRUCTOR, id, funcExpr, - ir::ModifierFlags::NONE, Allocator(), false); + auto *ctor = + AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, id->Clone(Allocator(), nullptr), + funcExpr, ir::ModifierFlags::NONE, Allocator(), false); auto *funcType = CreateETSFunctionType(signature, id->Name()); ctor->SetTsType(funcType); - funcExpr->SetParent(classScope->Node()->AsClassDeclaration()->Definition()); - func->SetParent(ctor); return ctor; } } @@ -371,10 +381,10 @@ void ETSChecker::BuildDynamicCallClass(bool isConstruct) auto *funcExpr = AllocNode(func); - auto *method = AllocNode(ir::MethodDefinitionKind::METHOD, func->Id(), funcExpr, - ir::ModifierFlags::PUBLIC | ir::ModifierFlags::NATIVE | - ir::ModifierFlags::STATIC, - Allocator(), false); + auto *method = AllocNode( + ir::MethodDefinitionKind::METHOD, func->Id()->Clone(Allocator(), nullptr), funcExpr, + ir::ModifierFlags::PUBLIC | ir::ModifierFlags::NATIVE | ir::ModifierFlags::STATIC, Allocator(), + false); VarBinder()->AsETSBinder()->BuildInternalName(func); VarBinder()->AsETSBinder()->BuildFunctionName(func); @@ -387,56 +397,69 @@ void ETSChecker::BuildDynamicCallClass(bool isConstruct) } } -ir::ClassStaticBlock *ETSChecker::CreateDynamicModuleClassInitializer( - varbinder::ClassScope *classScope, const std::vector &imports) +void ETSChecker::ClassInitializerFromImport(ir::ETSImportDeclaration *import, varbinder::FunctionScope *scope, + ArenaVector *statements) { - return CreateClassInitializer( - classScope, [this, imports](varbinder::FunctionScope *scope, ArenaVector *statements, - [[maybe_unused]] ArenaVector *params) { - for (auto *import : imports) { - auto builtin = compiler::Signatures::Dynamic::LoadModuleBuiltin(import->Language()); - auto [builtin_class_name, builtin_method_name] = util::Helpers::SplitSignature(builtin); + auto builtin = compiler::Signatures::Dynamic::LoadModuleBuiltin(import->Language()); + auto [builtin_class_name, builtin_method_name] = util::Helpers::SplitSignature(builtin); - auto *classId = AllocNode(builtin_class_name, Allocator()); - auto *methodId = AllocNode(builtin_method_name, Allocator()); - auto *callee = AllocNode(classId, methodId, - ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto *classId = AllocNode(builtin_class_name, Allocator()); + auto *methodId = AllocNode(builtin_method_name, Allocator()); + auto *callee = + AllocNode(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - ArenaVector callParams(Allocator()->Adapter()); - callParams.push_back(import->ResolvedSource()); + ArenaVector callParams(Allocator()->Adapter()); + callParams.push_back(import->ResolvedSource()); - auto *loadCall = AllocNode(callee, std::move(callParams), nullptr, false); + auto *loadCall = AllocNode(callee, std::move(callParams), nullptr, false); - auto *moduleClassId = - AllocNode(compiler::Signatures::DYNAMIC_MODULE_CLASS, Allocator()); - auto *fieldId = AllocNode(import->AssemblerName(), Allocator()); - auto *property = AllocNode( - moduleClassId, fieldId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto *moduleClassId = AllocNode(compiler::Signatures::DYNAMIC_MODULE_CLASS, Allocator()); + auto *fieldId = AllocNode(import->AssemblerName(), Allocator()); + auto *property = AllocNode(moduleClassId, fieldId, ir::MemberExpressionKind::PROPERTY_ACCESS, + false, false); - auto *initializer = - AllocNode(property, loadCall, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *initializer = + AllocNode(property, loadCall, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - { - ScopeContext ctx(this, scope); - initializer->Check(this); - } + { + ScopeContext ctx(this, scope); + initializer->Check(this); + } + statements->push_back(AllocNode(initializer)); +} - statements->push_back(AllocNode(initializer)); +ir::ClassStaticBlock *ETSChecker::CreateDynamicModuleClassInitializer( + varbinder::ClassScope *classScope, const std::vector &imports) +{ + return CreateClassInitializer( + classScope, [this, imports](varbinder::FunctionScope *scope, ArenaVector *statements, + [[maybe_unused]] ArenaVector *params) { + for (auto *import : imports) { + ClassInitializerFromImport(import, scope, statements); } }); } template -ir::MethodDefinition *ETSChecker::CreateClassMethod(varbinder::ClassScope *classScope, - const std::string_view methodName, - panda::es2panda::ir::ModifierFlags modifierFlags, - const MethodBuilder &builder) +static void AddMethodToClass(varbinder::ClassScope *classScope, varbinder::Variable *methodVar) +{ + auto *classType = classScope->Node()->AsClassDeclaration()->Definition()->TsType()->AsETSObjectType(); + if constexpr (IS_STATIC) { + classType->AddProperty(methodVar->AsLocalVariable()); + } else { + classType->AddProperty(methodVar->AsLocalVariable()); + } +} + +template +ir::MethodDefinition *ETSChecker::CreateClassMethod(varbinder::ClassScope *classScope, const std::string_view name, + ir::ModifierFlags modifierFlags, const MethodBuilder &builder) { auto classCtx = varbinder::LexicalScope::Enter(VarBinder(), classScope->StaticMethodScope()); ArenaVector params(Allocator()->Adapter()); auto *paramScope = Allocator()->New(Allocator(), classScope); auto *scope = Allocator()->New(Allocator(), paramScope); - auto *id = AllocNode(methodName, Allocator()); + auto *id = AllocNode(name, Allocator()); ArenaVector statements(Allocator()->Adapter()); Type *returnType = nullptr; @@ -446,9 +469,10 @@ ir::MethodDefinition *ETSChecker::CreateClassMethod(varbinder::ClassScope *class auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); - auto *func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::METHOD, modifierFlags, false, - Language(Language::Id::ETS)); + auto *func = AllocNode( + ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, modifierFlags}); + func->SetScope(scope); scope->BindNode(func); func->SetIdent(id); @@ -465,8 +489,9 @@ ir::MethodDefinition *ETSChecker::CreateClassMethod(varbinder::ClassScope *class func->SetSignature(signature); auto *funcExpr = AllocNode(func); - auto *method = AllocNode(ir::MethodDefinitionKind::METHOD, func->Id(), funcExpr, - modifierFlags, Allocator(), false); + auto *method = + AllocNode(ir::MethodDefinitionKind::METHOD, func->Id()->Clone(Allocator(), nullptr), + funcExpr, modifierFlags, Allocator(), false); VarBinder()->AsETSBinder()->BuildInternalName(func); VarBinder()->AsETSBinder()->BuildFunctionName(func); @@ -481,13 +506,9 @@ ir::MethodDefinition *ETSChecker::CreateClassMethod(varbinder::ClassScope *class method->SetTsType(funcType); var->AddFlag(varbinder::VariableFlags::PROPERTY); func->Id()->SetVariable(var); + method->Id()->SetVariable(var); - auto *classType = classScope->Node()->AsClassDeclaration()->Definition()->TsType()->AsETSObjectType(); - if constexpr (IS_STATIC) { - classType->AddProperty(var->AsLocalVariable()); - } else { - classType->AddProperty(var->AsLocalVariable()); - } + AddMethodToClass(classScope, var); return method; } @@ -524,12 +545,12 @@ ir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInvokeMethod(varbinder: scope->Parent()->AsFunctionParamScope(), util::UString(std::string("p") + std::to_string(idx), Allocator()).View(), invokeParam->TsType()); params->push_back(param); - callParams.push_back(param); + callParams.push_back(param->Clone(Allocator(), nullptr)); ++idx; } auto *properyId = AllocNode("jsvalue_lambda", Allocator()); - auto *callee = AllocNode(thisParam, properyId, + auto *callee = AllocNode(thisParam->Clone(Allocator(), nullptr), properyId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); auto *callLambda = AllocNode(callee, std::move(callParams), nullptr, false); @@ -538,9 +559,10 @@ ir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInvokeMethod(varbinder: callLambda->Check(this); } - auto *castToRetTypeExpr = Allocator()->New(callLambda, retTypeAnnotation, false); + auto *castToRetTypeExpr = + AllocNode(callLambda, retTypeAnnotation->Clone(Allocator(), nullptr), false); castToRetTypeExpr->SetTsType(invokeSignature->ReturnType()); - auto *retStatement = Allocator()->New(castToRetTypeExpr); + auto *retStatement = AllocNode(castToRetTypeExpr); statements->push_back(retStatement); *returnType = invokeSignature->ReturnType(); @@ -571,7 +593,9 @@ void ETSChecker::EmitDynamicModuleClassInitCall() initCall->Check(this); } - cctorBody->Statements().push_back(AllocNode(initCall)); + auto *const node = AllocNode(initCall); + node->SetParent(cctorBody); + cctorBody->Statements().push_back(node); } void ETSChecker::BuildDynamicImportClass() @@ -653,8 +677,8 @@ ir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInitializer(varbinder:: auto *fieldId = AllocNode("jsvalue_lambda", Allocator()); auto *property = AllocNode(moduleClassId, fieldId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - auto *initializer = - AllocNode(property, jsvalueParam, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *initializer = AllocNode(property, jsvalueParam->Clone(Allocator(), nullptr), + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); { ScopeContext ctx(this, scope); initializer->Check(this); diff --git a/ets2panda/checker/ets/enum.cpp b/ets2panda/checker/ets/enum.cpp index f9a116f3f2..5ab505aba6 100644 --- a/ets2panda/checker/ets/enum.cpp +++ b/ets2panda/checker/ets/enum.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "util/ustring.h" #include "varbinder/ETSBinder.h" #include "varbinder/variable.h" #include "checker/ETSchecker.h" @@ -65,16 +66,16 @@ void AppendParentNames(util::UString &qualifiedName, const ir::AstNode *const no } } -[[nodiscard]] ir::Identifier *MakeQualifiedIdentifier(panda::ArenaAllocator *const allocator, +[[nodiscard]] ir::Identifier *MakeQualifiedIdentifier(ETSChecker *const checker, const ir::TSEnumDeclaration *const enumDecl, const util::StringView &name) { - util::UString qualifiedName(util::StringView("#"), allocator); + util::UString qualifiedName(util::StringView("#"), checker->Allocator()); AppendParentNames(qualifiedName, enumDecl->Parent()); qualifiedName.Append(enumDecl->Key()->Name()); qualifiedName.Append('#'); qualifiedName.Append(name); - return allocator->New(qualifiedName.View(), allocator); + return checker->AllocNode(qualifiedName.View(), checker->Allocator()); } template @@ -88,13 +89,13 @@ template elements.push_back(elementMaker(member->AsTSEnumMember())); } - auto *const arrayExpr = checker->Allocator()->New(std::move(elements), checker->Allocator()); + auto *const arrayExpr = checker->AllocNode(std::move(elements), checker->Allocator()); arrayExpr->SetPreferredType(elementType); arrayExpr->SetTsType(checker->CreateETSArrayType(elementType)); - auto *const arrayIdent = MakeQualifiedIdentifier(checker->Allocator(), enumType->GetDecl(), name); + auto *const arrayIdent = MakeQualifiedIdentifier(checker, enumType->GetDecl(), name); - auto *const arrayClassProp = checker->Allocator()->New( + auto *const arrayClassProp = checker->AllocNode( arrayIdent, arrayExpr, nullptr, ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC | ir::ModifierFlags::CONST, checker->Allocator(), false); arrayClassProp->SetTsType(arrayExpr->TsType()); @@ -118,8 +119,8 @@ template const util::StringView &name, Type *const type) { const auto paramCtx = varbinder::LexicalScope::Enter(varbinder, scope, false); - auto *const paramIdent = checker->Allocator()->New(name, checker->Allocator()); - auto *const param = checker->Allocator()->New(paramIdent, nullptr); + auto *const paramIdent = checker->AllocNode(name, checker->Allocator()); + auto *const param = checker->AllocNode(paramIdent, nullptr); auto *const paramVar = std::get<1>(varbinder->AddParamDecl(param)); paramVar->SetTsType(type); param->Ident()->SetVariable(paramVar); @@ -128,11 +129,11 @@ template return param; } -[[nodiscard]] ir::ETSTypeReference *MakeTypeReference(panda::ArenaAllocator *allocator, const util::StringView &name) +[[nodiscard]] ir::ETSTypeReference *MakeTypeReference(ETSChecker *const checker, const util::StringView &name) { - auto *const ident = allocator->New(name, allocator); - auto *const referencePart = allocator->New(ident); - return allocator->New(referencePart); + auto *const ident = checker->AllocNode(name, checker->Allocator()); + auto *const referencePart = checker->AllocNode(ident); + return checker->AllocNode(referencePart); } [[nodiscard]] ir::ScriptFunction *MakeFunction(ETSChecker *const checker, varbinder::ETSBinder *const varbinder, @@ -145,7 +146,7 @@ template functionScope->BindParamScope(paramScope); paramScope->BindFunctionScope(functionScope); - auto *const bodyBlock = checker->Allocator()->New(checker->Allocator(), std::move(body)); + auto *const bodyBlock = checker->AllocNode(checker->Allocator(), std::move(body)); bodyBlock->SetScope(functionScope); auto flags = ir::ModifierFlags::PUBLIC; @@ -154,9 +155,9 @@ template flags |= ir::ModifierFlags::DECLARE; } - auto *const function = checker->Allocator()->New( + auto *const function = checker->AllocNode( ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), bodyBlock, - ir::ScriptFunctionFlags::METHOD, flags, isDeclare, Language(Language::Id::ETS)); + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, flags, isDeclare}); function->SetScope(functionScope); varbinder->AsETSBinder()->BuildInternalName(function); @@ -170,19 +171,21 @@ template void MakeMethodDef(ETSChecker *const checker, varbinder::ETSBinder *const varbinder, ir::Identifier *const ident, ir::ScriptFunction *const function) { - auto *const functionExpr = checker->Allocator()->New(function); - function->SetParent(functionExpr); + auto *const functionExpr = checker->AllocNode(function); + auto *const identClone = ident->Clone(checker->Allocator(), nullptr); + identClone->SetTsType(ident->TsType()); - auto *const methodDef = checker->Allocator()->New( - ir::MethodDefinitionKind::METHOD, ident, functionExpr, ir::ModifierFlags::PUBLIC, checker->Allocator(), false); + auto *const methodDef = + checker->AllocNode(ir::MethodDefinitionKind::METHOD, identClone, functionExpr, + ir::ModifierFlags::PUBLIC, checker->Allocator(), false); methodDef->SetParent(varbinder->Program()->GlobalClass()); - functionExpr->SetParent(methodDef); auto *const methodVar = std::get<1>(varbinder->NewVarDecl( methodDef->Start(), checker->Allocator(), methodDef->Id()->Name(), methodDef)); methodVar->AddFlag(varbinder::VariableFlags::STATIC | varbinder::VariableFlags::SYNTHETIC | varbinder::VariableFlags::METHOD); methodDef->Function()->Id()->SetVariable(methodVar); + methodDef->Id()->SetVariable(methodVar); } [[nodiscard]] ETSFunctionType *MakeProxyFunctionType(ETSChecker *const checker, const util::StringView &name, @@ -224,7 +227,7 @@ ir::Identifier *ETSChecker::CreateEnumNamesArray(ETSEnumInterface const *const e return MakeArray(this, VarBinder()->AsETSBinder(), enumType, "NamesArray", GlobalBuiltinETSStringType(), [this](const ir::TSEnumMember *const member) { auto *const enumNameStringLiteral = - Allocator()->New(member->Key()->AsIdentifier()->Name()); + AllocNode(member->Key()->AsIdentifier()->Name()); enumNameStringLiteral->SetTsType(GlobalBuiltinETSStringType()); return enumNameStringLiteral; }); @@ -236,7 +239,7 @@ ir::Identifier *ETSChecker::CreateEnumValuesArray(ETSEnumType *const enumType) return MakeArray( this, VarBinder()->AsETSBinder(), enumType, "ValuesArray", GlobalIntType(), [this](const ir::TSEnumMember *const member) { - auto *const enumValueLiteral = Allocator()->New(lexer::Number( + auto *const enumValueLiteral = AllocNode(lexer::Number( member->AsTSEnumMember()->Init()->AsNumberLiteral()->Number().GetValue())); enumValueLiteral->SetTsType(GlobalIntType()); return enumValueLiteral; @@ -246,17 +249,19 @@ ir::Identifier *ETSChecker::CreateEnumValuesArray(ETSEnumType *const enumType) ir::Identifier *ETSChecker::CreateEnumStringValuesArray(ETSEnumInterface *const enumType) { return MakeArray(this, VarBinder()->AsETSBinder(), enumType, "StringValuesArray", GlobalETSStringLiteralType(), - [this, isStringEnum = enumType->IsETSStringEnumType()](const ir::TSEnumMember *const member) { - auto const stringValue = - isStringEnum ? member->AsTSEnumMember()->Init()->AsStringLiteral()->Str() - : util::UString(std::to_string(member->AsTSEnumMember() - ->Init() - ->AsNumberLiteral() - ->Number() - .GetValue()), - Allocator()) - .View(); - auto *const enumValueStringLiteral = Allocator()->New(stringValue); + [this, enumType](const ir::TSEnumMember *const member) { + auto *const init = member->AsTSEnumMember()->Init(); + util::StringView stringValue; + + if (enumType->IsETSStringEnumType()) { + stringValue = init->AsStringLiteral()->Str(); + } else { + auto str = + std::to_string(init->AsNumberLiteral()->Number().GetValue()); + stringValue = util::UString(str, Allocator()).View(); + } + + auto *const enumValueStringLiteral = AllocNode(stringValue); enumValueStringLiteral->SetTsType(GlobalETSStringLiteralType()); return enumValueStringLiteral; }); @@ -264,17 +269,19 @@ ir::Identifier *ETSChecker::CreateEnumStringValuesArray(ETSEnumInterface *const ir::Identifier *ETSChecker::CreateEnumItemsArray(ETSEnumInterface *const enumType) { - auto *const enumTypeIdent = Allocator()->New(enumType->GetName(), Allocator()); - enumTypeIdent->SetTsType(enumType); - return MakeArray( this, VarBinder()->AsETSBinder(), enumType, "ItemsArray", enumType, - [this, enumTypeIdent](const ir::TSEnumMember *const member) { + [this, enumType](const ir::TSEnumMember *const member) { + auto *const enumTypeIdent = AllocNode(enumType->GetName(), Allocator()); + enumTypeIdent->SetTsType(enumType); + auto *const enumMemberIdent = - Allocator()->New(member->AsTSEnumMember()->Key()->AsIdentifier()->Name(), Allocator()); - auto *const enumMemberExpr = Allocator()->New( + AllocNode(member->AsTSEnumMember()->Key()->AsIdentifier()->Name(), Allocator()); + + auto *const enumMemberExpr = AllocNode( enumTypeIdent, enumMemberIdent, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); enumMemberExpr->SetTsType(member->AsTSEnumMember()->Key()->AsIdentifier()->Variable()->TsType()); + return enumMemberExpr; }); } @@ -289,37 +296,41 @@ ETSEnumType::Method ETSChecker::CreateEnumFromIntMethod(ir::Identifier *const na MakeFunctionParam(this, VarBinder()->AsETSBinder(), paramScope, "ordinal", GlobalIntType()); auto *const inArraySizeExpr = [this, namesArrayIdent, inputOrdinalIdent]() { - auto *const lengthIdent = Allocator()->New("length", Allocator()); - auto *const valuesArrayLengthExpr = Allocator()->New( + auto *const lengthIdent = AllocNode("length", Allocator()); + auto *const valuesArrayLengthExpr = AllocNode( namesArrayIdent, lengthIdent, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - auto *const expr = Allocator()->New(inputOrdinalIdent, valuesArrayLengthExpr, - lexer::TokenType::PUNCTUATOR_LESS_THAN); + auto *const expr = AllocNode(inputOrdinalIdent, valuesArrayLengthExpr, + lexer::TokenType::PUNCTUATOR_LESS_THAN); expr->SetOperationType(GlobalIntType()); expr->SetTsType(GlobalETSBooleanType()); return expr; }(); auto *const returnEnumStmt = [this, inputOrdinalIdent, enumType]() { - inputOrdinalIdent->SetTsType(enumType); - return Allocator()->New(inputOrdinalIdent); + auto *const identClone = inputOrdinalIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(enumType); + return AllocNode(identClone); }(); - auto *const ifOrdinalExistsStmt = Allocator()->New(inArraySizeExpr, returnEnumStmt, nullptr); + auto *const ifOrdinalExistsStmt = AllocNode(inArraySizeExpr, returnEnumStmt, nullptr); auto *const throwNoEnumStmt = [this, inputOrdinalIdent, enumType]() { - auto *const exceptionReference = MakeTypeReference(Allocator(), "Exception"); + auto *const exceptionReference = MakeTypeReference(this, "Exception"); util::UString messageString(util::StringView("No enum constant in "), Allocator()); messageString.Append(enumType->GetName()); messageString.Append(" with ordinal value "); - auto *const message = Allocator()->New(messageString.View()); + auto *const identClone = inputOrdinalIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(GlobalIntType()); + + auto *const message = AllocNode(messageString.View()); auto *const newExprArg = - Allocator()->New(message, inputOrdinalIdent, lexer::TokenType::PUNCTUATOR_PLUS); + AllocNode(message, identClone, lexer::TokenType::PUNCTUATOR_PLUS); ArenaVector newExprArgs(Allocator()->Adapter()); newExprArgs.push_back(newExprArg); - auto *const newExpr = Allocator()->New( + auto *const newExpr = AllocNode( exceptionReference, std::move(newExprArgs), GlobalBuiltinExceptionType()->GetDeclNode()->AsClassDefinition()); @@ -327,24 +338,26 @@ ETSEnumType::Method ETSChecker::CreateEnumFromIntMethod(ir::Identifier *const na ResolveConstructExpression(GlobalBuiltinExceptionType(), newExpr->GetArguments(), newExpr->Start())); newExpr->SetTsType(GlobalBuiltinExceptionType()); - return Allocator()->New(newExpr); + return AllocNode(newExpr); }(); + auto *const identClone = inputOrdinalIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(inputOrdinalIdent->TsType()); ArenaVector params(Allocator()->Adapter()); - params.push_back(inputOrdinalIdent); + params.push_back(identClone); ArenaVector body(Allocator()->Adapter()); body.push_back(ifOrdinalExistsStmt); body.push_back(throwNoEnumStmt); body.push_back(returnEnumStmt); - auto *const enumTypeAnnotation = MakeTypeReference(Allocator(), enumType->GetName()); + auto *const enumTypeAnnotation = MakeTypeReference(this, enumType->GetName()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), std::move(body), enumTypeAnnotation, enumType->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); - auto *const ident = MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::FROM_INT_METHOD_NAME); + auto *const ident = MakeQualifiedIdentifier(this, enumType->GetDecl(), ETSEnumType::FROM_INT_METHOD_NAME); function->SetIdent(ident); function->Scope()->BindInternalName(ident->Name()); @@ -362,25 +375,26 @@ ETSEnumType::Method ETSChecker::CreateEnumToStringMethod(ir::Identifier *const s auto *const inputEnumIdent = MakeFunctionParam(this, VarBinder()->AsETSBinder(), paramScope, "ordinal", enumType); auto *const returnStmt = [this, inputEnumIdent, stringValuesArrayIdent]() { - auto *const arrayAccessExpr = Allocator()->New( + auto *const arrayAccessExpr = AllocNode( stringValuesArrayIdent, inputEnumIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, true, false); arrayAccessExpr->SetTsType(GlobalETSStringLiteralType()); - return Allocator()->New(arrayAccessExpr); + return AllocNode(arrayAccessExpr); }(); ArenaVector body(Allocator()->Adapter()); body.push_back(returnStmt); + auto *const identClone = inputEnumIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(enumType); ArenaVector params(Allocator()->Adapter()); - params.push_back(inputEnumIdent); + params.push_back(identClone); - auto *const stringTypeAnnotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); + auto *const stringTypeAnnotation = MakeTypeReference(this, GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), std::move(body), stringTypeAnnotation, enumType->GetDecl()->IsDeclare()); - auto *const functionIdent = - MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::TO_STRING_METHOD_NAME); + auto *const functionIdent = MakeQualifiedIdentifier(this, enumType->GetDecl(), ETSEnumType::TO_STRING_METHOD_NAME); function->SetIdent(functionIdent); function->Scope()->BindInternalName(functionIdent->Name()); @@ -400,25 +414,26 @@ ETSEnumType::Method ETSChecker::CreateEnumGetValueMethod(ir::Identifier *const v auto *const inputEnumIdent = MakeFunctionParam(this, VarBinder()->AsETSBinder(), paramScope, "e", enumType); auto *const returnStmt = [this, inputEnumIdent, valuesArrayIdent]() { - auto *const arrayAccessExpr = Allocator()->New( + auto *const arrayAccessExpr = AllocNode( valuesArrayIdent, inputEnumIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, true, false); arrayAccessExpr->SetTsType(GlobalIntType()); - return Allocator()->New(arrayAccessExpr); + return AllocNode(arrayAccessExpr); }(); ArenaVector body(Allocator()->Adapter()); body.push_back(returnStmt); + auto *const identClone = inputEnumIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(enumType); ArenaVector params(Allocator()->Adapter()); - params.push_back(inputEnumIdent); + params.push_back(identClone); - auto *const intTypeAnnotation = Allocator()->New(ir::PrimitiveType::INT); + auto *const intTypeAnnotation = AllocNode(ir::PrimitiveType::INT); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), std::move(body), intTypeAnnotation, enumType->GetDecl()->IsDeclare()); - auto *const functionIdent = - MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::GET_VALUE_METHOD_NAME); + auto *const functionIdent = MakeQualifiedIdentifier(this, enumType->GetDecl(), ETSEnumType::GET_VALUE_METHOD_NAME); function->SetIdent(functionIdent); function->Scope()->BindInternalName(functionIdent->Name()); @@ -437,26 +452,27 @@ ETSEnumType::Method ETSChecker::CreateEnumGetNameMethod(ir::Identifier *const na auto *const inputEnumIdent = MakeFunctionParam(this, VarBinder()->AsETSBinder(), paramScope, "ordinal", enumType); auto *const returnStmt = [this, inputEnumIdent, namesArrayIdent]() { - auto *const arrayAccessExpr = Allocator()->New( + auto *const arrayAccessExpr = AllocNode( namesArrayIdent, inputEnumIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, true, false); arrayAccessExpr->SetTsType(GlobalBuiltinETSStringType()); - return Allocator()->New(arrayAccessExpr); + return AllocNode(arrayAccessExpr); }(); ArenaVector body(Allocator()->Adapter()); body.push_back(returnStmt); + auto *const identClone = inputEnumIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(enumType); ArenaVector params(Allocator()->Adapter()); - params.push_back(inputEnumIdent); + params.push_back(identClone); - auto *const stringTypeAnnotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); + auto *const stringTypeAnnotation = MakeTypeReference(this, GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), std::move(body), stringTypeAnnotation, enumType->GetDecl()->IsDeclare()); - auto *const functionIdent = - MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::GET_NAME_METHOD_NAME); + auto *const functionIdent = MakeQualifiedIdentifier(this, enumType->GetDecl(), ETSEnumType::GET_NAME_METHOD_NAME); function->SetIdent(functionIdent); function->Scope()->BindInternalName(functionIdent->Name()); @@ -472,13 +488,10 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na auto *const paramScope = VarBinder()->Allocator()->New(Allocator(), Program()->GlobalScope()); - auto *const inputNameIdent = - MakeFunctionParam(this, VarBinder()->AsETSBinder(), paramScope, "name", GlobalBuiltinETSStringType()); - varbinder::LexicalScope loopDeclScope(VarBinder()); auto *const forLoopIIdent = [this]() { - auto *const ident = Allocator()->New("i", Allocator()); + auto *const ident = AllocNode("i", Allocator()); ident->SetTsType(GlobalIntType()); auto [decl, var] = VarBinder()->NewVarDecl(ident->Start(), ident->Name()); ident->SetVariable(var); @@ -490,24 +503,23 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na }(); auto *const forLoopInitVarDecl = [this, forLoopIIdent]() { - auto *const init = Allocator()->New("0"); + auto *const init = AllocNode("0"); init->SetTsType(GlobalIntType()); - auto *const decl = - Allocator()->New(ir::VariableDeclaratorFlag::LET, forLoopIIdent, init); + auto *const decl = AllocNode(ir::VariableDeclaratorFlag::LET, forLoopIIdent, init); decl->SetTsType(GlobalIntType()); ArenaVector decls(Allocator()->Adapter()); decls.push_back(decl); - return Allocator()->New(ir::VariableDeclaration::VariableDeclarationKind::LET, - Allocator(), std::move(decls), false); + return AllocNode(ir::VariableDeclaration::VariableDeclarationKind::LET, Allocator(), + std::move(decls), false); }(); auto *const forLoopTest = [this, namesArrayIdent, forLoopIIdent]() { - auto *const lengthIdent = Allocator()->New("length", Allocator()); - auto *const arrayLengthExpr = Allocator()->New( + auto *const lengthIdent = AllocNode("length", Allocator()); + auto *const arrayLengthExpr = AllocNode( namesArrayIdent, lengthIdent, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); arrayLengthExpr->SetTsType(GlobalIntType()); - auto *const binaryExpr = Allocator()->New(forLoopIIdent, arrayLengthExpr, - lexer::TokenType::PUNCTUATOR_LESS_THAN); + auto *const binaryExpr = + AllocNode(forLoopIIdent, arrayLengthExpr, lexer::TokenType::PUNCTUATOR_LESS_THAN); binaryExpr->SetOperationType(GlobalIntType()); binaryExpr->SetTsType(GlobalETSBooleanType()); return binaryExpr; @@ -515,30 +527,34 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na auto *const forLoopUpdate = [this, forLoopIIdent]() { auto *const incrementExpr = - Allocator()->New(forLoopIIdent, lexer::TokenType::PUNCTUATOR_PLUS_PLUS, true); + AllocNode(forLoopIIdent, lexer::TokenType::PUNCTUATOR_PLUS_PLUS, true); incrementExpr->SetTsType(GlobalIntType()); return incrementExpr; }(); + auto *const inputNameIdent = + MakeFunctionParam(this, VarBinder()->AsETSBinder(), paramScope, "name", GlobalBuiltinETSStringType()); + auto *const ifStmt = [this, namesArrayIdent, forLoopIIdent, inputNameIdent]() { - auto *const namesArrayElementExpr = Allocator()->New( - namesArrayIdent, forLoopIIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, true, false); + auto *const identClone = namesArrayIdent->Clone(this->Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto *const namesArrayElementExpr = AllocNode( + identClone, forLoopIIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, true, false); namesArrayElementExpr->SetTsType(GlobalBuiltinETSStringType()); - auto *const namesEqualExpr = Allocator()->New(inputNameIdent, namesArrayElementExpr, - lexer::TokenType::PUNCTUATOR_EQUAL); + auto *const namesEqualExpr = + AllocNode(inputNameIdent, namesArrayElementExpr, lexer::TokenType::PUNCTUATOR_EQUAL); namesEqualExpr->SetOperationType(GlobalBuiltinETSStringType()); namesEqualExpr->SetTsType(GlobalETSBooleanType()); - auto *const returnStmt = Allocator()->New(forLoopIIdent); - return Allocator()->New(namesEqualExpr, returnStmt, nullptr); + auto *const returnStmt = AllocNode(forLoopIIdent); + return AllocNode(namesEqualExpr, returnStmt, nullptr); }(); varbinder::LexicalScope loopScope(VarBinder()); loopScope.GetScope()->BindDecls(loopDeclScope.GetScope()); - auto *const forLoop = - Allocator()->New(forLoopInitVarDecl, forLoopTest, forLoopUpdate, ifStmt); + auto *const forLoop = AllocNode(forLoopInitVarDecl, forLoopTest, forLoopUpdate, ifStmt); loopScope.GetScope()->BindNode(forLoop); forLoop->SetScope(loopScope.GetScope()); loopScope.GetScope()->DeclScope()->BindNode(forLoop); @@ -548,40 +564,43 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na messageString.Append(enumType->GetName()); messageString.Append('.'); - auto *const message = Allocator()->New(messageString.View()); + auto *const identClone = inputNameIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(inputNameIdent->TsType()); + auto *const message = AllocNode(messageString.View()); auto *const newExprArg = - Allocator()->New(message, inputNameIdent, lexer::TokenType::PUNCTUATOR_PLUS); + AllocNode(message, identClone, lexer::TokenType::PUNCTUATOR_PLUS); ArenaVector newExprArgs(Allocator()->Adapter()); newExprArgs.push_back(newExprArg); - auto *const exceptionReference = MakeTypeReference(Allocator(), "Exception"); + auto *const exceptionReference = MakeTypeReference(this, "Exception"); - auto *const newExpr = Allocator()->New( + auto *const newExpr = AllocNode( exceptionReference, std::move(newExprArgs), GlobalBuiltinExceptionType()->GetDeclNode()->AsClassDefinition()); newExpr->SetSignature( ResolveConstructExpression(GlobalBuiltinExceptionType(), newExpr->GetArguments(), newExpr->Start())); newExpr->SetTsType(GlobalBuiltinExceptionType()); - return Allocator()->New(newExpr); + return AllocNode(newExpr); }(); ArenaVector body(Allocator()->Adapter()); body.push_back(forLoop); body.push_back(throwStmt); + auto *const identClone = inputNameIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(inputNameIdent->TsType()); ArenaVector params(Allocator()->Adapter()); - params.push_back(inputNameIdent); + params.push_back(identClone); - auto *const enumTypeAnnotation = MakeTypeReference(Allocator(), enumType->GetName()); + auto *const enumTypeAnnotation = MakeTypeReference(this, enumType->GetName()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), std::move(body), enumTypeAnnotation, enumType->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); - auto *const functionIdent = - MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::VALUE_OF_METHOD_NAME); + auto *const functionIdent = MakeQualifiedIdentifier(this, enumType->GetDecl(), ETSEnumType::VALUE_OF_METHOD_NAME); function->SetIdent(functionIdent); function->Scope()->BindInternalName(functionIdent->Name()); @@ -599,20 +618,18 @@ ETSEnumType::Method ETSChecker::CreateEnumValuesMethod(ir::Identifier *const ite auto *const paramScope = VarBinder()->Allocator()->New(Allocator(), Program()->GlobalScope()); - auto *const returnStmt = Allocator()->New(itemsArrayIdent); + auto *const returnStmt = AllocNode(itemsArrayIdent); ArenaVector body(Allocator()->Adapter()); body.push_back(returnStmt); ArenaVector params(Allocator()->Adapter()); - auto *const enumArrayTypeAnnotation = - Allocator()->New(MakeTypeReference(Allocator(), enumType->GetName())); + auto *const enumArrayTypeAnnotation = AllocNode(MakeTypeReference(this, enumType->GetName())); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), std::move(body), enumArrayTypeAnnotation, enumType->GetDecl()->IsDeclare()); - auto *const functionIdent = - MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::VALUES_METHOD_NAME); + auto *const functionIdent = MakeQualifiedIdentifier(this, enumType->GetDecl(), ETSEnumType::VALUES_METHOD_NAME); function->SetIdent(functionIdent); function->Scope()->BindInternalName(functionIdent->Name()); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 9dffd8fd25..ecb64e3308 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1490,10 +1490,10 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio CreateLambdaFuncDecl(invokeFunc, classScope->InstanceMethodScope()); // Create the synthetic lambda class node - auto *identNode = Allocator()->New(util::StringView("LambdaObject"), Allocator()); + auto *identNode = AllocNode(util::StringView("LambdaObject"), Allocator()); auto *lambdaObject = - Allocator()->New(Allocator(), identNode, std::move(properties), - ir::ClassDefinitionModifiers::DECLARATION, Language(Language::Id::ETS)); + AllocNode(Allocator(), identNode, std::move(properties), + ir::ClassDefinitionModifiers::DECLARATION, Language(Language::Id::ETS)); lambda->SetResolvedLambda(lambdaObject); lambda->SetTsType(functionalInterface); lambdaObject->SetScope(classScope); @@ -1515,7 +1515,7 @@ void ETSChecker::CreateLambdaObjectForLambdaReference(ir::ArrowFunctionExpressio VarBinder()->AsETSBinder()->BuildLambdaObject(lambda, lambdaObject, proxyMethod->Function()->Signature()); // Resolve the proxy method - ResolveProxyMethod(proxyMethod, lambda); + ResolveProxyMethod(currentClassDef, proxyMethod, lambda); if (lambda->Function()->IsAsyncFunc()) { HandleAsyncFuncInLambda(this, lambda, proxyMethod, currentClassDef); } @@ -1631,15 +1631,20 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, ir lambdaObjectType->AddProperty( invokeFunc->Id()->Variable()->AsLocalVariable()); - // Fill out the type information for the body of the invoke function - auto *resolvedLambdaInvokeFunctionBody = - ResolveLambdaObjectInvokeFuncBody(lambdaObject, lambda, proxyMethod, isStatic, ifaceOverride); if (invokeFunc->IsAsyncFunc()) { return; } + + // Fill out the type information for the body of the invoke function + auto *resolvedLambdaInvokeFunctionBody = + ResolveLambdaObjectInvokeFuncBody(lambdaObject, lambda, proxyMethod, isStatic, ifaceOverride); + resolvedLambdaInvokeFunctionBody->SetParent(invokeFunc->Body()); invokeFunc->Body()->AsBlockStatement()->Statements().push_back(resolvedLambdaInvokeFunctionBody); + if (resolvedLambdaInvokeFunctionBody->IsExpressionStatement()) { - invokeFunc->Body()->AsBlockStatement()->Statements().push_back(Allocator()->New(nullptr)); + auto *const returnStatement = Allocator()->New(nullptr); + returnStatement->SetParent(invokeFunc->Body()); + invokeFunc->Body()->AsBlockStatement()->Statements().push_back(returnStatement); } } @@ -1735,7 +1740,7 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition // If the proxy method is static, we should call it through the owner class itself if (isStatic) { - fieldIdent = Allocator()->New(proxySignature->Owner()->Name(), Allocator()); + fieldIdent = AllocNode(proxySignature->Owner()->Name(), Allocator()); fieldPropType = proxySignature->Owner(); fieldIdent->SetVariable(proxySignature->Owner()->Variable()); fieldIdent->SetTsType(fieldPropType); @@ -1750,9 +1755,9 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition } // Set the type information for the proxy function call - auto *funcIdent = Allocator()->New(proxyMethod->Function()->Id()->Name(), Allocator()); - auto *callee = Allocator()->New(fieldIdent, funcIdent, - ir::MemberExpressionKind::ELEMENT_ACCESS, false, false); + auto *funcIdent = AllocNode(proxyMethod->Function()->Id()->Name(), Allocator()); + auto *callee = + AllocNode(fieldIdent, funcIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, false, false); callee->SetPropVar(proxySignature->OwnerVar()->AsLocalVariable()); callee->SetObjectType(fieldPropType); callee->SetTsType(proxySignature->OwnerVar()->TsType()); @@ -1763,19 +1768,19 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition ResolveCallParametersForLambdaFuncBody(this, lambdaObject, lambda, invokeFunc, isStatic, ifaceOverride); // Create the synthetic call expression to the proxy method - auto *resolvedCall = Allocator()->New(callee, std::move(callParams), nullptr, false); + auto *resolvedCall = AllocNode(callee, std::move(callParams), nullptr, false); resolvedCall->SetTsType(proxySignature->ReturnType()); resolvedCall->SetSignature(proxySignature); if (proxySignature->ReturnType()->IsETSVoidType()) { - return Allocator()->New(resolvedCall); + return AllocNode(resolvedCall); } if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); } - return Allocator()->New(resolvedCall); + return AllocNode(resolvedCall); } void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject) @@ -1825,15 +1830,16 @@ void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject) } } -void ETSChecker::ResolveProxyMethod(ir::MethodDefinition *proxyMethod, ir::ArrowFunctionExpression *lambda) +void ETSChecker::ResolveProxyMethod(ir::ClassDefinition *const classDefinition, ir::MethodDefinition *proxyMethod, + ir::ArrowFunctionExpression *lambda) { + auto *const varbinder = VarBinder()->AsETSBinder(); auto *func = proxyMethod->Function(); bool isStatic = func->IsStatic(); auto *currentClassType = Context().ContainingClass(); // Build the proxy method in the binder - VarBinder()->AsETSBinder()->BuildProxyMethod( - func, currentClassType->GetDeclNode()->AsClassDefinition()->InternalName(), isStatic); + varbinder->BuildProxyMethod(func, currentClassType->GetDeclNode()->AsClassDefinition()->InternalName(), isStatic); // If the proxy method is not static, set the implicit 'this' parameters type to the current class if (!isStatic) { @@ -1855,13 +1861,28 @@ void ETSChecker::ResolveProxyMethod(ir::MethodDefinition *proxyMethod, ir::Arrow signature->SetOwner(currentClassType); // Add the proxy method to the current class methods + auto *const variable = func->Id()->Variable()->AsLocalVariable(); if (isStatic) { - currentClassType->AddProperty(func->Id()->Variable()->AsLocalVariable()); + currentClassType->AddProperty(variable); } else { - currentClassType->AddProperty( - func->Id()->Variable()->AsLocalVariable()); + currentClassType->AddProperty(variable); + } + varbinder->BuildFunctionName(func); + + if (lambda->Function()->IsAsyncFunc()) { + ir::MethodDefinition *asyncImpl = CreateAsyncProxy(proxyMethod, classDefinition); + ir::ScriptFunction *asyncImplFunc = asyncImpl->Function(); + + classDefinition->Body().emplace_back(asyncImpl); + asyncImpl->SetParent(classDefinition); + + ReplaceIdentifierReferencesInProxyMethod(asyncImplFunc->Body(), asyncImplFunc->Params(), + lambda->Function()->Params(), lambda->CapturedVars()); + Signature *implSig = CreateSignature(proxyMethod->Function()->Signature()->GetSignatureInfo(), + GlobalETSObjectType(), asyncImplFunc); + asyncImplFunc->SetSignature(implSig); + varbinder->BuildFunctionName(asyncImplFunc); } - VarBinder()->AsETSBinder()->BuildFunctionName(func); } size_t ETSChecker::ComputeProxyMethods(ir::ClassDefinition *klass) @@ -1912,8 +1933,8 @@ ir::ScriptFunction *ETSChecker::CreateProxyFunc(ir::ArrowFunctionExpression *lam funcFlags |= ir::ScriptFunctionFlags::ASYNC; } auto *func = Allocator()->New( - ir::FunctionSignature(nullptr, std::move(params), lambda->Function()->ReturnTypeAnnotation()), body, funcFlags, - GetFlagsForProxyLambda(isStatic), false, Language(Language::Id::ETS)); + ir::FunctionSignature(nullptr, std::move(params), lambda->Function()->ReturnTypeAnnotation()), body, + ir::ScriptFunction::ScriptFunctionData {funcFlags, GetFlagsForProxyLambda(isStatic)}); func->SetScope(scope); if (!func->IsAsyncFunc()) { @@ -1945,23 +1966,22 @@ ir::MethodDefinition *ETSChecker::CreateProxyMethodForLambda(ir::ClassDefinition auto *func = CreateProxyFunc(lambda, captured, isStatic); // Create the synthetic proxy method - auto *funcExpr = Allocator()->New(func); + auto *funcExpr = AllocNode(func); util::UString funcName(util::StringView("lambda$invoke$"), Allocator()); funcName.Append(std::to_string(ComputeProxyMethods(klass))); - auto *identNode = Allocator()->New(funcName.View(), Allocator()); + auto *identNode = AllocNode(funcName.View(), Allocator()); func->SetIdent(identNode); - auto *proxy = Allocator()->New(ir::MethodDefinitionKind::METHOD, identNode, funcExpr, - GetFlagsForProxyLambda(isStatic), Allocator(), false); + + auto *identClone = identNode->Clone(Allocator(), nullptr); + auto *proxy = AllocNode(ir::MethodDefinitionKind::METHOD, identClone, funcExpr, + GetFlagsForProxyLambda(isStatic), Allocator(), false); + klass->Body().push_back(proxy); proxy->SetParent(klass); // Add the proxy method to the current class declarations CreateLambdaFuncDecl(proxy, klass->Scope()->AsClassScope()->InstanceMethodScope()); - // Set the parent nodes - func->SetParent(funcExpr); - funcExpr->SetParent(proxy); - // Create the signature template for the proxy method to be able to save this signatures pointer in the binder // lambdaObjects_ to be able to compute the lambda object invoke functions internal name later auto *proxySignatureInfo = CreateSignatureInfo(); @@ -2017,16 +2037,18 @@ void ETSChecker::ReplaceIdentifierReferencesInProxyMethod( ir::AstNode *node, const ArenaVector &proxyParams, std::unordered_map &mergedTargetReferences) { - if (node->IsMemberExpression()) { - auto *memberExpr = node->AsMemberExpression(); - if (memberExpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS) { - ReplaceIdentifierReferenceInProxyMethod(memberExpr->Object(), proxyParams, mergedTargetReferences); - return; + if (node != nullptr) { + if (node->IsMemberExpression()) { + auto *memberExpr = node->AsMemberExpression(); + if (memberExpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS) { + ReplaceIdentifierReferenceInProxyMethod(memberExpr->Object(), proxyParams, mergedTargetReferences); + return; + } } + node->Iterate([this, &proxyParams, &mergedTargetReferences](ir::AstNode *childNode) { + ReplaceIdentifierReferenceInProxyMethod(childNode, proxyParams, mergedTargetReferences); + }); } - node->Iterate([this, &proxyParams, &mergedTargetReferences](ir::AstNode *childNode) { - ReplaceIdentifierReferenceInProxyMethod(childNode, proxyParams, mergedTargetReferences); - }); } void ETSChecker::ReplaceIdentifierReferenceInProxyMethod( @@ -2070,12 +2092,12 @@ varbinder::FunctionParamScope *ETSChecker::CreateProxyMethodParams(ir::ArrowFunc // "this" should be binded with the parameter of the proxy method if (this->HasStatus(checker::CheckerStatus::IN_INSTANCE_EXTENSION_METHOD) && lambda->CapturedVars()[i]->Name() == varbinder::VarBinder::MANDATORY_PARAM_THIS) { - paramIdent = Allocator()->New(varbinder::VarBinder::MANDATORY_PARAM_THIS, Allocator()); + paramIdent = AllocNode(varbinder::VarBinder::MANDATORY_PARAM_THIS, Allocator()); } else { - paramIdent = Allocator()->New(capturedVar->Name(), Allocator()); + paramIdent = AllocNode(capturedVar->Name(), Allocator()); } - auto *param = Allocator()->New(paramIdent, nullptr); + auto *param = AllocNode(paramIdent, nullptr); auto [_, var] = VarBinder()->AddParamDecl(param); (void)_; var->SetTsType(capturedVar->TsType()); @@ -2090,16 +2112,15 @@ varbinder::FunctionParamScope *ETSChecker::CreateProxyMethodParams(ir::ArrowFunc // Then add the lambda function parameters to the proxy method's parameter vector, and set the type from the // already computed types for the lambda parameters - for (auto const *const it : params) { - auto *const oldParamExprIdent = it->AsETSParameterExpression()->Ident(); - auto *const paramIdent = Allocator()->New(oldParamExprIdent->Name(), Allocator()); - auto *param = Allocator()->New(paramIdent, nullptr); - auto [_, var] = VarBinder()->AddParamDecl(param); + for (auto *const it : params) { + auto *const oldParameter = it->AsETSParameterExpression(); + auto *newParameter = oldParameter->Clone(Allocator(), nullptr); + auto [_, var] = VarBinder()->AddParamDecl(newParameter); (void)_; - var->SetTsType(oldParamExprIdent->Variable()->TsType()); - param->SetVariable(var); - param->SetTsType(oldParamExprIdent->Variable()->TsType()); - proxyParams.push_back(param); + var->SetTsType(oldParameter->Variable()->TsType()); + newParameter->SetVariable(var); + newParameter->SetTsType(oldParameter->Variable()->TsType()); + proxyParams.push_back(newParameter); } return paramCtx.GetScope(); @@ -2179,12 +2200,13 @@ ir::MethodDefinition *ETSChecker::CreateLambdaImplicitCtor(ArenaVectorNew(Allocator(), std::move(statements)); + auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); auto *func = - Allocator()->New(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::CONSTRUCTOR, false, Language(Language::Id::ETS)); + AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::CONSTRUCTOR}); func->SetScope(scope); + // Set the scopes scope->BindNode(func); funcParamScope->BindNode(func); @@ -2192,15 +2214,13 @@ ir::MethodDefinition *ETSChecker::CreateLambdaImplicitCtor(ArenaVectorBindFunctionScope(scope); // Create the name for the synthetic constructor - auto *funcExpr = Allocator()->New(func); - auto *key = Allocator()->New("constructor", Allocator()); + auto *funcExpr = AllocNode(func); + auto *key = AllocNode("constructor", Allocator()); func->SetIdent(key); - auto *ctor = Allocator()->New(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, - ir::ModifierFlags::NONE, Allocator(), false); - // Set the parent nodes - func->SetParent(funcExpr); - funcExpr->SetParent(ctor); + auto *keyClone = key->Clone(Allocator(), nullptr); + auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, keyClone, funcExpr, + ir::ModifierFlags::NONE, Allocator(), false); return ctor; } @@ -2215,8 +2235,8 @@ varbinder::FunctionParamScope *ETSChecker::CreateLambdaCtorImplicitParams(ArenaV // captured variables for (auto *it : properties) { auto *field = it->AsClassProperty()->Key()->AsIdentifier(); - auto *paramField = Allocator()->New(field->Name(), Allocator()); - auto *param = Allocator()->New(paramField, nullptr); + auto *paramField = field->Clone(Allocator(), nullptr); + auto *param = AllocNode(paramField, nullptr); auto [_, var] = VarBinder()->AddParamDecl(param); (void)_; auto *type = MaybeBoxedType(field->Variable()); @@ -2234,15 +2254,15 @@ ir::Statement *ETSChecker::CreateLambdaCtorFieldInit(util::StringView name, varb // Create synthetic field initializers for the lambda class fields // The node structure is the following: this.field0 = field0, where the left hand side refers to the lambda // classes field, and the right hand side is refers to the constructors parameter - auto *thisExpr = Allocator()->New(); - auto *fieldAccessExpr = Allocator()->New(name, Allocator()); - auto *leftHandSide = Allocator()->New( - thisExpr, fieldAccessExpr, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - auto *rightHandSide = Allocator()->New(name, Allocator()); + auto *thisExpr = AllocNode(); + auto *fieldAccessExpr = AllocNode(name, Allocator()); + auto *leftHandSide = AllocNode(thisExpr, fieldAccessExpr, + ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto *rightHandSide = AllocNode(name, Allocator()); rightHandSide->SetVariable(var); - auto *initializer = Allocator()->New(leftHandSide, rightHandSide, - lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - return Allocator()->New(initializer); + auto *initializer = + AllocNode(leftHandSide, rightHandSide, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + return AllocNode(initializer); } // Lambda creation for Function references @@ -2341,11 +2361,11 @@ ir::MethodDefinition *ETSChecker::CreateLambdaImplicitCtor(const lexer::SourceRa statements.push_back(CreateLambdaCtorFieldInit(util::StringView("field0"), var)); } - auto *body = Allocator()->New(Allocator(), std::move(statements)); + auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); auto *func = - Allocator()->New(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::CONSTRUCTOR, false, Language(Language::Id::ETS)); + AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::CONSTRUCTOR}); func->SetScope(scope); // Bind the scopes scope->BindNode(func); @@ -2354,15 +2374,13 @@ ir::MethodDefinition *ETSChecker::CreateLambdaImplicitCtor(const lexer::SourceRa funcParamScope->BindFunctionScope(scope); // Create the synthetic constructor - auto *funcExpr = Allocator()->New(func); - auto *key = Allocator()->New("constructor", Allocator()); + auto *funcExpr = AllocNode(func); + auto *key = AllocNode("constructor", Allocator()); func->SetIdent(key); - auto *ctor = Allocator()->New(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, - ir::ModifierFlags::NONE, Allocator(), false); - // Set the parent nodes - func->SetParent(funcExpr); - funcExpr->SetParent(ctor); + auto *keyClone = key->Clone(Allocator(), nullptr); + auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, keyClone, funcExpr, + ir::ModifierFlags::NONE, Allocator(), false); return ctor; } @@ -2377,8 +2395,8 @@ std::tuple ETSChecker::C // since when initializing the lambda class, we don't need to save the instance object which we tried to get the // function reference through if (!isStaticReference) { - auto *paramIdent = Allocator()->New("field0", Allocator()); - auto *param = Allocator()->New(paramIdent, nullptr); + auto *paramIdent = AllocNode("field0", Allocator()); + auto *param = AllocNode(paramIdent, nullptr); paramIdent->SetRange(pos); auto [_, var] = VarBinder()->AddParamDecl(param); (void)_; @@ -2394,18 +2412,17 @@ ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto(util::StringView invok { // Create the template for the synthetic 'invoke' method, which will be used when the function type will be // called - auto *name = Allocator()->New(invokeName, Allocator()); auto *paramScope = VarBinder()->Allocator()->New(Allocator(), VarBinder()->GetScope()); auto *scope = VarBinder()->Allocator()->New(Allocator(), paramScope); ArenaVector params(Allocator()->Adapter()); ArenaVector statements(Allocator()->Adapter()); - auto *body = Allocator()->New(Allocator(), std::move(statements)); + auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); - auto *func = Allocator()->New(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC, false, - Language(Language::Id::ETS)); + auto *func = AllocNode( + ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC}); func->SetScope(scope); scope->BindNode(func); @@ -2413,14 +2430,14 @@ ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto(util::StringView invok scope->BindParamScope(paramScope); paramScope->BindFunctionScope(scope); - auto *funcExpr = Allocator()->New(func); + auto *name = AllocNode(invokeName, Allocator()); func->SetIdent(name); - auto *method = Allocator()->New(ir::MethodDefinitionKind::METHOD, name, funcExpr, - ir::ModifierFlags::PUBLIC, Allocator(), false); + auto *funcExpr = AllocNode(func); - funcExpr->SetParent(method); - func->SetParent(funcExpr); + auto *nameClone = name->Clone(Allocator(), nullptr); + auto *method = AllocNode(ir::MethodDefinitionKind::METHOD, nameClone, funcExpr, + ir::ModifierFlags::PUBLIC, Allocator(), false); return method; } @@ -2429,9 +2446,11 @@ void ETSChecker::CreateLambdaFuncDecl(ir::MethodDefinition *func, varbinder::Loc { // Add the function declarations to the lambda class scope auto ctx = varbinder::LexicalScope::Enter(VarBinder(), scope); - auto [_, var] = - VarBinder()->NewVarDecl(func->Start(), Allocator(), func->Id()->Name(), func); - (void)_; + varbinder::Variable *var = scope->FindLocal(func->Id()->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION); + if (var == nullptr) { + var = std::get<1>( + VarBinder()->NewVarDecl(func->Start(), Allocator(), func->Id()->Name(), func)); + } var->AddFlag(varbinder::VariableFlags::METHOD); func->Function()->Id()->SetVariable(var); } @@ -2558,8 +2577,8 @@ static Signature *CreateInvokeSignature(ETSChecker *checker, Signature *signatur auto paramCtx = varbinder::LexicalScope::Enter( checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); - auto *paramIdent = allocator->New(it->Name(), allocator); - auto *param = allocator->New(paramIdent, nullptr); + auto *paramIdent = checker->AllocNode(it->Name(), allocator); + auto *param = checker->AllocNode(paramIdent, nullptr); auto [_, var] = checker->VarBinder()->AddParamDecl(param); (void)_; var->SetTsType(ifaceOverride ? checker->GlobalETSObjectType() : it->TsType()); @@ -2613,13 +2632,15 @@ void ETSChecker::ResolveLambdaObjectInvoke(ir::ClassDefinition *lambdaObject, Si invokeFunc->Id()->Variable()->AsLocalVariable()); // Fill out the type information for the body of the invoke function - auto *resolvedLambdaInvokeFunctionBody = ResolveLambdaObjectInvokeFuncBody(lambdaObject, signatureRef, ifaceOverride); - + resolvedLambdaInvokeFunctionBody->SetParent(invokeFunc->Body()); invokeFunc->Body()->AsBlockStatement()->Statements().push_back(resolvedLambdaInvokeFunctionBody); + if (resolvedLambdaInvokeFunctionBody->IsExpressionStatement()) { - invokeFunc->Body()->AsBlockStatement()->Statements().push_back(Allocator()->New(nullptr)); + auto *const returnStatement = Allocator()->New(nullptr); + returnStatement->SetParent(invokeFunc->Body()); + invokeFunc->Body()->AsBlockStatement()->Statements().push_back(returnStatement); } } @@ -2705,7 +2726,7 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition // If this is a static function reference, we have to call the referenced function through the class itself if (isStaticReference) { - fieldIdent = Allocator()->New(signatureRef->Owner()->Name(), Allocator()); + fieldIdent = AllocNode(signatureRef->Owner()->Name(), Allocator()); fieldPropType = signatureRef->Owner(); fieldIdent->SetVariable(signatureRef->Owner()->Variable()); fieldIdent->SetTsType(fieldPropType); @@ -2714,15 +2735,15 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition // reference auto *fieldProp = lambdaBody[0]->AsClassProperty()->Key()->AsIdentifier()->Variable(); fieldPropType = fieldProp->TsType()->AsETSObjectType(); - fieldIdent = Allocator()->New("field0", Allocator()); + fieldIdent = AllocNode("field0", Allocator()); fieldIdent->SetVariable(fieldProp); fieldIdent->SetTsType(fieldPropType); } // Set the type information for the function reference call - auto *funcIdent = Allocator()->New(signatureRef->Function()->Id()->Name(), Allocator()); - auto *callee = Allocator()->New(fieldIdent, funcIdent, - ir::MemberExpressionKind::ELEMENT_ACCESS, false, false); + auto *funcIdent = AllocNode(signatureRef->Function()->Id()->Name(), Allocator()); + auto *callee = + AllocNode(fieldIdent, funcIdent, ir::MemberExpressionKind::ELEMENT_ACCESS, false, false); callee->SetPropVar(signatureRef->OwnerVar()->AsLocalVariable()); callee->SetObjectType(fieldPropType); callee->SetTsType(signatureRef->OwnerVar()->TsType()); @@ -2733,19 +2754,19 @@ ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition ResolveCallParametersForLambdaFuncBody(this, signatureRef, invokeFunc, ifaceOverride); // Create the synthetic call expression to the referenced function - auto *resolvedCall = Allocator()->New(callee, std::move(callParams), nullptr, false); + auto *resolvedCall = AllocNode(callee, std::move(callParams), nullptr, false); resolvedCall->SetTsType(signatureRef->ReturnType()); resolvedCall->SetSignature(signatureRef); if (signatureRef->ReturnType()->IsETSVoidType()) { - return Allocator()->New(resolvedCall); + return AllocNode(resolvedCall); } if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); } - return Allocator()->New(resolvedCall); + return AllocNode(resolvedCall); } bool ETSChecker::AreOverrideEquivalent(Signature *const s1, Signature *const s2) @@ -2813,11 +2834,11 @@ ir::MethodDefinition *ETSChecker::CreateAsyncImplMethod(ir::MethodDefinition *as varbinder::FunctionParamScope *paramScope = CopyParams(asyncFunc->Params(), params); // Set impl method return type "Object" because it may return Promise as well as Promise parameter's type - auto *objectId = Allocator()->New(compiler::Signatures::BUILTIN_OBJECT_CLASS, Allocator()); + auto *objectId = AllocNode(compiler::Signatures::BUILTIN_OBJECT_CLASS, Allocator()); objectId->SetReference(); VarBinder()->AsETSBinder()->LookupTypeReference(objectId, false); auto *returnTypeAnn = - Allocator()->New(Allocator()->New(objectId, nullptr, nullptr)); + AllocNode(AllocNode(objectId, nullptr, nullptr)); objectId->SetParent(returnTypeAnn->Part()); returnTypeAnn->Part()->SetParent(returnTypeAnn); auto *asyncFuncRetTypeAnn = asyncFunc->ReturnTypeAnnotation(); @@ -2837,8 +2858,6 @@ ir::MethodDefinition *ETSChecker::CreateAsyncImplMethod(ir::MethodDefinition *as asyncFunc->SetBody(nullptr); returnTypeAnn->SetParent(implMethod->Function()); implMethod->SetParent(asyncMethod->Parent()); - std::for_each(implMethod->Function()->Params().begin(), implMethod->Function()->Params().end(), - [implMethod](ir::Expression *param) { param->SetParent(implMethod->Function()); }); return implMethod; } @@ -2886,28 +2905,24 @@ ir::MethodDefinition *ETSChecker::CreateMethod(const util::StringView &name, ir: varbinder::FunctionParamScope *paramScope, ir::TypeNode *returnType, ir::AstNode *body) { - auto *nameId = Allocator()->New(name, Allocator()); + auto *nameId = AllocNode(name, Allocator()); auto *scope = VarBinder()->Allocator()->New(Allocator(), paramScope); - ir::ScriptFunction *func = - Allocator()->New(ir::FunctionSignature(nullptr, std::move(params), returnType), body, flags, - modifiers, false, Language(Language::Id::ETS)); + auto *const func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), returnType), + body, ir::ScriptFunction::ScriptFunctionData {flags, modifiers}); func->SetScope(scope); func->SetIdent(nameId); - body->SetParent(func); - if (body->IsBlockStatement()) { + if (body != nullptr && body->IsBlockStatement()) { body->AsBlockStatement()->SetScope(scope); } scope->BindNode(func); paramScope->BindNode(func); scope->BindParamScope(paramScope); paramScope->BindFunctionScope(scope); - auto *funcExpr = Allocator()->New(func); - auto *method = Allocator()->New(ir::MethodDefinitionKind::METHOD, nameId, funcExpr, modifiers, - Allocator(), false); - funcExpr->SetParent(method); - func->SetParent(funcExpr); - nameId->SetParent(method); + auto *funcExpr = AllocNode(func); + auto *nameClone = nameId->Clone(Allocator(), nullptr); + auto *method = AllocNode(ir::MethodDefinitionKind::METHOD, nameClone, funcExpr, modifiers, + Allocator(), false); return method; } @@ -2935,6 +2950,10 @@ varbinder::FunctionParamScope *ETSChecker::CopyParams(const ArenaVectorIterate([this, oldNode, newScope](ir::AstNode *child) { auto *scope = NodeScope(child); if (scope != nullptr) { @@ -2995,7 +3014,7 @@ void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr) ArenaVector params(Allocator()->Adapter()); auto *funcNode = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), trailingBlock, - ir::ScriptFunctionFlags::ARROW, false, Language(Language::Id::ETS)); + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::ARROW}); funcNode->SetScope(funcScope); funcScope->BindNode(funcNode); funcParamScope->BindNode(funcNode); @@ -3021,8 +3040,9 @@ ArenaVector ETSChecker::ExtendArgumentsWithFakeLamda(ir::CallE auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(funcScope); - auto *funcNode = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::ARROW, false, Language(Language::Id::ETS)); + auto *funcNode = + AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::ARROW}); funcNode->SetScope(funcScope); funcScope->BindNode(funcNode); auto *arrowFuncNode = AllocNode(Allocator(), funcNode); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 46f52f19bd..7c56e88c6d 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1123,10 +1123,11 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T if (init->IsArrowFunctionExpression()) { typeAnnotation = init->AsArrowFunctionExpression()->CreateTypeAnnotation(this); } else { - typeAnnotation = init->AsTSAsExpression()->TypeAnnotation(); + typeAnnotation = init->AsTSAsExpression()->TypeAnnotation()->Clone(Allocator(), nullptr); } ident->SetTsTypeAnnotation(typeAnnotation); typeAnnotation->SetParent(ident); + annotationType = GetTypeFromTypeAnnotation(typeAnnotation); bindingVar->SetTsType(annotationType); } @@ -2500,7 +2501,9 @@ void ETSChecker::InferTypesForLambda(ir::ScriptFunction *lambda, ir::ETSFunction const auto *const calleeParam = calleeType->Params()[i]->AsETSParameterExpression()->Ident(); auto *const lambdaParam = lambda->Params()[i]->AsETSParameterExpression()->Ident(); if (lambdaParam->TypeAnnotation() == nullptr) { - lambdaParam->SetTsTypeAnnotation(calleeParam->TypeAnnotation()); + auto *const typeAnnotation = calleeParam->TypeAnnotation()->Clone(Allocator(), lambdaParam); + lambdaParam->SetTsTypeAnnotation(typeAnnotation); + typeAnnotation->SetParent(lambdaParam); } } if (lambda->ReturnTypeAnnotation() == nullptr) { @@ -2555,7 +2558,7 @@ bool ETSChecker::TypeInference(Signature *signature, const ArenaVector &arguments, ETSChecker *checker) { @@ -2563,28 +2566,36 @@ void ETSChecker::AddUndefinedParamsForDefaultParams(const Signature *const signa return; } + // Just to avoid extra nested levels + auto const addDefaultLiteral = [&arguments, checker, parent](ir::TypeNode const *const typeAnnotation) -> void { + if (typeAnnotation->IsETSPrimitiveType()) { + if (typeAnnotation->AsETSPrimitiveType()->GetPrimitiveType() == ir::PrimitiveType::BOOLEAN) { + arguments.push_back(checker->Allocator()->New(false)); + } else { + arguments.push_back(checker->Allocator()->New(lexer::Number(0))); + } + arguments.back()->SetParent(parent); + } else { + // A proxy-function is called, so default reference parameters + // are initialized with null instead of undefined + auto *const nullLiteral = checker->Allocator()->New(); + nullLiteral->SetTsType(checker->GlobalETSNullType()); + nullLiteral->SetParent(parent); + arguments.push_back(nullLiteral); + } + }; + uint32_t num = 0; - for (size_t i = arguments.size(); i != signature->Function()->Params().size() - 1; i++) { + for (size_t i = arguments.size(); i != signature->Function()->Params().size() - 1U; ++i) { if (auto const *const param = signature->Function()->Params()[i]->AsETSParameterExpression(); !param->IsRestParameter()) { - auto const *const typeAnn = param->Ident()->TypeAnnotation(); - if (typeAnn->IsETSPrimitiveType()) { - if (typeAnn->AsETSPrimitiveType()->GetPrimitiveType() == ir::PrimitiveType::BOOLEAN) { - arguments.push_back(checker->Allocator()->New(false)); - } else { - arguments.push_back(checker->Allocator()->New(lexer::Number(0))); - } - } else { - // A proxy-function is called, so default reference parameters - // are initialized with null instead of undefined - auto *const nullLiteral = checker->Allocator()->New(); - nullLiteral->SetTsType(checker->GlobalETSNullType()); - arguments.push_back(nullLiteral); - } + addDefaultLiteral(param->Ident()->TypeAnnotation()); num |= (1U << (arguments.size() - 1)); } } + arguments.push_back(checker->Allocator()->New(lexer::Number(num))); + arguments.back()->SetParent(parent); } bool ETSChecker::ExtensionETSFunctionType(checker::Type *type) @@ -2642,25 +2653,25 @@ void ETSChecker::GenerateGetterSetterBody(ArenaVector &stmts, A bool isSetter) { if (!isSetter) { - stmts.push_back(Allocator()->New(field->Key())); + auto *clone = field->Key()->Clone(Allocator(), nullptr)->AsExpression(); + stmts.push_back(AllocNode(clone)); return; } - auto *paramIdent = field->Key()->AsIdentifier()->Clone(Allocator()); - paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(Allocator())); - paramIdent->TypeAnnotation()->SetParent(paramIdent); + auto *paramIdent = field->Key()->AsIdentifier()->Clone(Allocator(), nullptr); + auto *const typeAnnotation = field->TypeAnnotation()->Clone(Allocator(), paramIdent); + paramIdent->SetTsTypeAnnotation(typeAnnotation); auto *paramExpression = AllocNode(paramIdent, nullptr); paramExpression->SetRange(paramIdent->Range()); auto *const paramVar = std::get<2>(paramScope->AddParamDecl(Allocator(), paramExpression)); - - paramIdent->SetVariable(paramVar); paramExpression->SetVariable(paramVar); params.push_back(paramExpression); - auto *assignmentExpression = - AllocNode(field->Key(), paramExpression, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *assignmentExpression = AllocNode( + field->Key()->Clone(Allocator(), nullptr)->AsExpression(), paramExpression->Clone(Allocator(), nullptr), + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); assignmentExpression->SetRange({field->Start(), field->End()}); @@ -2686,16 +2697,16 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty auto *body = checker->AllocNode(checker->Allocator(), std::move(stmts)); auto funcFlags = isSetter ? ir::ScriptFunctionFlags::SETTER : ir::ScriptFunctionFlags::GETTER; - auto *const returnTypeAnn = isSetter ? nullptr : field->TypeAnnotation(); + auto *const returnTypeAnn = isSetter ? nullptr : field->TypeAnnotation()->Clone(checker->Allocator(), nullptr); auto *func = checker->AllocNode(ir::FunctionSignature(nullptr, std::move(params), returnTypeAnn), body, - funcFlags, flags, true, Language(Language::Id::ETS)); + ir::ScriptFunction::ScriptFunctionData {funcFlags, flags, true}); func->SetRange(field->Range()); func->SetScope(functionScope); body->SetScope(functionScope); - auto *methodIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator()); + auto *methodIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator(), nullptr); auto *decl = checker->Allocator()->New( checker->Allocator(), field->Key()->AsIdentifier()->Name(), field->Key()->AsIdentifier()->Variable()->Declaration()->Node()); @@ -2712,7 +2723,7 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty method->Id()->SetMutator(); method->SetRange(field->Range()); - method->Function()->SetIdent(method->Id()); + method->Function()->SetIdent(method->Id()->Clone(checker->Allocator(), nullptr)); method->Function()->AddModifier(method->Modifiers()); method->SetVariable(var); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 24e9928347..2dda693b09 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -450,34 +450,51 @@ static void ResolveDeclaredMethodsOfObject(ETSChecker *checker, ETSObjectType *t { for (auto &[_, it] : scope->InstanceMethodScope()->Bindings()) { (void)_; - auto *node = it->Declaration()->Node()->AsMethodDefinition(); + auto *method = it->Declaration()->Node()->AsMethodDefinition(); + auto *function = method->Function(); - if (node->Function()->IsProxy()) { + function->Id()->SetVariable(method->Id()->Variable()); + for (ir::MethodDefinition *const overload : method->Overloads()) { + overload->Function()->Id()->SetVariable(overload->Id()->Variable()); + } + + if (function->IsProxy()) { continue; } - it->AddFlag(checker->GetAccessFlagFromNode(node)); - auto *funcType = checker->BuildMethodSignature(node); + it->AddFlag(checker->GetAccessFlagFromNode(method)); + auto *funcType = checker->BuildMethodSignature(method); it->SetTsType(funcType); funcType->SetVariable(it); - node->SetTsType(funcType); + method->SetTsType(funcType); type->AddProperty(it->AsLocalVariable()); } for (auto &[_, it] : scope->StaticMethodScope()->Bindings()) { (void)_; - if (!it->Declaration()->Node()->IsMethodDefinition() || - it->Declaration()->Node()->AsMethodDefinition()->Function()->IsProxy()) { + if (!it->Declaration()->Node()->IsMethodDefinition()) { continue; } - auto *node = it->Declaration()->Node()->AsMethodDefinition(); - it->AddFlag(checker->GetAccessFlagFromNode(node)); - auto *funcType = checker->BuildMethodSignature(node); + + auto *method = it->Declaration()->Node()->AsMethodDefinition(); + auto *function = method->Function(); + + function->Id()->SetVariable(method->Id()->Variable()); + for (ir::MethodDefinition *const overload : method->Overloads()) { + overload->Function()->Id()->SetVariable(overload->Id()->Variable()); + } + + if (function->IsProxy()) { + continue; + } + + it->AddFlag(checker->GetAccessFlagFromNode(method)); + auto *funcType = checker->BuildMethodSignature(method); it->SetTsType(funcType); funcType->SetVariable(it); - node->SetTsType(funcType); + method->SetTsType(funcType); - if (node->IsConstructor()) { + if (method->IsConstructor()) { type->AddConstructSignature(funcType->CallSignatures()); continue; } @@ -861,6 +878,7 @@ void ETSChecker::CreateAsyncProxyMethods(ir::ClassDefinition *classDef) } } for (auto *it : asyncImpls) { + it->SetParent(classDef); it->Check(this); classDef->Body().push_back(it); } @@ -1507,6 +1525,7 @@ void ETSChecker::TransformProperties(ETSObjectType *classType) ir::MethodDefinition *getter = GenerateDefaultGetterSetter(classProp, scope->AsClassScope(), false, this); classDef->Body().push_back(getter); + getter->SetParent(classDef); classType->AddProperty(getter->Variable()->AsLocalVariable()); auto *const methodScope = scope->AsClassScope()->InstanceMethodScope(); @@ -1524,6 +1543,7 @@ void ETSChecker::TransformProperties(ETSObjectType *classType) if (!classProp->IsReadonly()) { ir::MethodDefinition *const setter = GenerateDefaultGetterSetter(classProp, scope->AsClassScope(), true, this); + setter->SetParent(classDef); classType->AddProperty(setter->Variable()->AsLocalVariable()); prevDecl->Node()->AsMethodDefinition()->AddOverload(setter); @@ -1537,6 +1557,7 @@ void ETSChecker::TransformProperties(ETSObjectType *classType) if (!classProp->IsReadonly()) { ir::MethodDefinition *const setter = GenerateDefaultGetterSetter(classProp, scope->AsClassScope(), true, this); + setter->SetParent(classDef); classType->AddProperty(setter->Variable()->AsLocalVariable()); getter->AddOverload(setter); diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index ea39dcd47c..ff45c96a13 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -389,28 +389,40 @@ ETSEnumType *ETSChecker::CreateETSEnumType(ir::TSEnumDeclaration const *const en auto *const namesArrayIdent = CreateEnumNamesArray(enumType); - auto const getNameMethod = CreateEnumGetNameMethod(namesArrayIdent, enumType); + auto *identClone = namesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto const getNameMethod = CreateEnumGetNameMethod(identClone, enumType); enumType->SetGetNameMethod(getNameMethod); - auto const valueOfMethod = CreateEnumValueOfMethod(namesArrayIdent, enumType); + identClone = namesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto const valueOfMethod = CreateEnumValueOfMethod(identClone, enumType); enumType->SetValueOfMethod(valueOfMethod); - auto const fromIntMethod = CreateEnumFromIntMethod(namesArrayIdent, enumType); + identClone = namesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto const fromIntMethod = CreateEnumFromIntMethod(identClone, enumType); enumType->SetFromIntMethod(fromIntMethod); auto *const valuesArrayIdent = CreateEnumValuesArray(enumType); - auto const getValueMethod = CreateEnumGetValueMethod(valuesArrayIdent, enumType); + identClone = valuesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(valuesArrayIdent->TsType()); + auto const getValueMethod = CreateEnumGetValueMethod(identClone, enumType); enumType->SetGetValueMethod(getValueMethod); auto *const stringValuesArrayIdent = CreateEnumStringValuesArray(enumType); - auto const toStringMethod = CreateEnumToStringMethod(stringValuesArrayIdent, enumType); + identClone = stringValuesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(stringValuesArrayIdent->TsType()); + auto const toStringMethod = CreateEnumToStringMethod(identClone, enumType); enumType->SetToStringMethod(toStringMethod); auto *const itemsArrayIdent = CreateEnumItemsArray(enumType); - auto const valuesMethod = CreateEnumValuesMethod(itemsArrayIdent, enumType); + identClone = itemsArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(itemsArrayIdent->TsType()); + auto const valuesMethod = CreateEnumValuesMethod(identClone, enumType); enumType->SetValuesMethod(valuesMethod); for (auto *const member : enumType->GetMembers()) { @@ -444,24 +456,34 @@ ETSStringEnumType *ETSChecker::CreateETSStringEnumType(ir::TSEnumDeclaration con auto *const namesArrayIdent = CreateEnumNamesArray(enumType); - auto const getNameMethod = CreateEnumGetNameMethod(namesArrayIdent, enumType); + auto *identClone = namesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto const getNameMethod = CreateEnumGetNameMethod(identClone, enumType); enumType->SetGetNameMethod(getNameMethod); - auto const valueOfMethod = CreateEnumValueOfMethod(namesArrayIdent, enumType); + identClone = namesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto const valueOfMethod = CreateEnumValueOfMethod(identClone, enumType); enumType->SetValueOfMethod(valueOfMethod); - auto const fromIntMethod = CreateEnumFromIntMethod(namesArrayIdent, enumType); + identClone = namesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(namesArrayIdent->TsType()); + auto const fromIntMethod = CreateEnumFromIntMethod(identClone, enumType); enumType->SetFromIntMethod(fromIntMethod); auto *const stringValuesArrayIdent = CreateEnumStringValuesArray(enumType); - auto const toStringMethod = CreateEnumToStringMethod(stringValuesArrayIdent, enumType); + identClone = stringValuesArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(stringValuesArrayIdent->TsType()); + auto const toStringMethod = CreateEnumToStringMethod(identClone, enumType); enumType->SetToStringMethod(toStringMethod); enumType->SetGetValueMethod(toStringMethod); auto *const itemsArrayIdent = CreateEnumItemsArray(enumType); - auto const valuesMethod = CreateEnumValuesMethod(itemsArrayIdent, enumType); + identClone = itemsArrayIdent->Clone(Allocator(), nullptr); + identClone->SetTsType(itemsArrayIdent->TsType()); + auto const valuesMethod = CreateEnumValuesMethod(identClone, enumType); enumType->SetValuesMethod(valuesMethod); for (auto *const member : enumType->GetMembers()) { diff --git a/ets2panda/compiler/core/ASTVerifier.cpp b/ets2panda/compiler/core/ASTVerifier.cpp index 405acad229..921d856a99 100644 --- a/ets2panda/compiler/core/ASTVerifier.cpp +++ b/ets2panda/compiler/core/ASTVerifier.cpp @@ -219,7 +219,8 @@ public: ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) { - const auto isEtsScript = ast->IsETSScript(); + const auto isEtsScript = + ast->IsETSScript() || (ast->IsBlockStatement() && ast->AsBlockStatement()->IsProgram()); const auto hasParent = ast->Parent() != nullptr; if (!isEtsScript && !hasParent) { ctx.AddInvariantError("NodeHasParent", "NULL_PARENT", *ast); @@ -361,16 +362,33 @@ public: ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) { + ASSERT(ast != nullptr); + auto result = ASTVerifier::CheckResult::SUCCESS; if (ast->IsETSScript()) { return result; } + ast->Iterate([&](const ir::AstNode *node) { - if (ast != node->Parent()) { + if (ir::AstNode const *parent = node->Parent(); ast != parent) { + // NOTE: Temporary suppress. + // Should be removed after special lowering for lambda-functions will be implemented: #14376 + if ((ast->IsScriptFunction() || ast->IsETSFunctionType()) && parent != nullptr && + parent->IsScriptFunction()) { + return; + } + + // NOTE: Temporary suppress. + // Should be removed after new ENUMs support will be implemented: #14443 + if (ast->IsClassDeclaration() && parent != nullptr && parent->IsETSNewClassInstanceExpression()) { + return; + } + ctx.AddInvariantError("EveryChildHasValidParent", "INCORRECT_PARENT_REF", *node); result = ASTVerifier::CheckResult::FAILED; } }); + return result; } diff --git a/ets2panda/compiler/core/ETSfunction.cpp b/ets2panda/compiler/core/ETSfunction.cpp index 75739a159d..8ad11cb7e0 100644 --- a/ets2panda/compiler/core/ETSfunction.cpp +++ b/ets2panda/compiler/core/ETSfunction.cpp @@ -146,13 +146,11 @@ void ETSFunction::CompileSourceBlock(ETSGen *etsg, const ir::BlockStatement *blo void ETSFunction::CompileFunction(ETSGen *etsg) { - const auto *decl = etsg->RootNode()->AsScriptFunction(); - - if (decl->IsDeclare()) { - return; + if (const auto *decl = etsg->RootNode()->AsScriptFunction(); !decl->IsDeclare()) { + if (auto *const body = decl->Body(); body != nullptr && body->IsBlockStatement()) { + CompileSourceBlock(etsg, body->AsBlockStatement()); + } } - - CompileSourceBlock(etsg, etsg->RootNode()->AsScriptFunction()->Body()->AsBlockStatement()); } void ETSFunction::Compile(ETSGen *etsg) diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index a5bc7da17f..dfc46cabf3 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -110,11 +110,15 @@ static void Verify(const parser::Program &program, const CompilerContext &contex using NamedProgram = std::tuple; ArenaVector toCheck {program.Allocator()->Adapter()}; toCheck.push_back(std::make_tuple(program.SourceFilePath(), &program)); + + // collect list of checks for (const auto &externalSource : program.ExternalSources()) { for (const auto *external : externalSource.second) { toCheck.push_back(std::make_tuple(external->SourceFilePath(), external)); } } + + // check for (const auto &it : toCheck) { const auto &sourceName = std::get<0>(it); const auto &linkedProgram = std::get<1>(it); @@ -123,6 +127,20 @@ static void Verify(const parser::Program &program, const CompilerContext &contex verificationCtx.IntroduceNewInvariants(phase->Name()); } } + +static void Report(const CompilerContext &context, ASTVerifierContext &verificationCtx) +{ + if (!context.Options()->verifierWarnings.empty()) { + if (auto errors = verificationCtx.DumpWarningsJSON(); errors != "[]") { + LOG(ERROR, ES2PANDA) << errors; + } + } + if (!context.Options()->verifierErrors.empty()) { + if (auto errors = verificationCtx.DumpAssertsJSON(); errors != "[]") { + ASSERT_PRINT(false, errors); + } + } +} #endif using EmitCb = std::function; @@ -169,21 +187,14 @@ static pandasm::Program *CreateCompiler(const CompilationUnit &unit, const Phase return nullptr; } #ifndef NDEBUG - Verify(program, context, phase, verificationCtx); + if (unit.ext == ScriptExtension::ETS) { + Verify(program, context, phase, verificationCtx); + } #endif } #ifndef NDEBUG - if (!context.Options()->verifierWarnings.empty()) { - if (auto errors = verificationCtx.DumpWarningsJSON(); errors != "[]") { - LOG(ERROR, ES2PANDA) << errors; - } - } - if (!context.Options()->verifierErrors.empty()) { - if (auto errors = verificationCtx.DumpAssertsJSON(); errors != "[]") { - ASSERT_PRINT(false, errors); - } - } + Report(context, verificationCtx); #endif emitter.GenAnnotation(); diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp index d8936fe26a..f5915b3187 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.cpp +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -61,7 +61,7 @@ bool ExpandBracketsPhase::Perform(public_lib::Context *ctx, parser::Program *pro " throw new TypeError(\"Index fractional part should not be different from 0.0\");" "};" "(@@E5);", - parser::DEFAULT_SOURCE_FILE, ident, dimension, exprType, ident->Clone(allocator), newExpression); + parser::DEFAULT_SOURCE_FILE, ident, dimension, exprType, ident->Clone(allocator, nullptr), newExpression); sequenceExpr->SetParent(newExpression->Parent()); InitScopesPhaseETS::RunExternalNode(sequenceExpr, ctx->compilerContext->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(sequenceExpr, scope); diff --git a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp index 97b56809eb..35a6278c38 100644 --- a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp +++ b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp @@ -45,8 +45,8 @@ static ir::MethodDefinition *GenerateGetterOrSetter(checker::ETSChecker *const c ArenaVector params(checker->Allocator()->Adapter()); if (isSetter) { - auto paramIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator()); - paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(checker->Allocator())); + auto paramIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator(), nullptr); + paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(checker->Allocator(), nullptr)); paramIdent->TypeAnnotation()->SetParent(paramIdent); auto *const paramExpression = checker->AllocNode(paramIdent, nullptr); @@ -61,17 +61,17 @@ static ir::MethodDefinition *GenerateGetterOrSetter(checker::ETSChecker *const c auto signature = ir::FunctionSignature(nullptr, std::move(params), isSetter ? nullptr : field->TypeAnnotation()); - auto *func = - isSetter - ? checker->AllocNode(std::move(signature), nullptr, ir::ScriptFunctionFlags::SETTER, - flags, true, Language(Language::Id::ETS)) - : checker->AllocNode(std::move(signature), nullptr, ir::ScriptFunctionFlags::GETTER, - flags, true, Language(Language::Id::ETS)); + auto *func = isSetter ? checker->AllocNode( + std::move(signature), nullptr, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::SETTER, flags, true}) + : checker->AllocNode( + std::move(signature), nullptr, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::GETTER, flags, true}); func->SetRange(field->Range()); func->SetScope(functionScope); - auto methodIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator()); + auto methodIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator(), nullptr); auto *decl = checker->Allocator()->New(field->Key()->AsIdentifier()->Name()); auto var = functionScope->AddDecl(checker->Allocator(), decl, ScriptExtension::ETS); @@ -86,7 +86,7 @@ static ir::MethodDefinition *GenerateGetterOrSetter(checker::ETSChecker *const c method->Id()->SetMutator(); method->SetRange(field->Range()); - method->Function()->SetIdent(method->Id()); + method->Function()->SetIdent(method->Id()->Clone(checker->Allocator(), nullptr)); method->Function()->AddModifier(method->Modifiers()); paramScope->BindNode(func); functionScope->BindNode(func); diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index 9b4bfa606b..8253e18c6a 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -71,8 +71,21 @@ static lexer::TokenType OpEqualToOp(const lexer::TokenType opEqual) UNREACHABLE(); } -void AdjustBoxingUnboxingFlags(ir::Expression *newExpr, const ir::Expression *oldExpr) +void AdjustBoxingUnboxingFlags(ir::Expression *loweringResult, const ir::Expression *oldExpr) { + ir::AssignmentExpression *newAssignment = nullptr; + if (loweringResult->IsAssignmentExpression()) { + newAssignment = loweringResult->AsAssignmentExpression(); + } else if (loweringResult->IsBlockExpression() && !loweringResult->AsBlockExpression()->Statements().empty()) { + auto *statement = loweringResult->AsBlockExpression()->Statements().back(); + if (statement->IsExpressionStatement() && + statement->AsExpressionStatement()->GetExpression()->IsAssignmentExpression()) { + newAssignment = statement->AsExpressionStatement()->GetExpression()->AsAssignmentExpression(); + } + } else { + UNREACHABLE(); + } + // NOTE: gogabr. make sure that the checker never puts both a boxing and an unboxing flag on the same node. // Then this function will become unnecessary. const ir::BoxingUnboxingFlags oldBoxingFlag {oldExpr->GetBoxingUnboxingFlags() & @@ -80,11 +93,47 @@ void AdjustBoxingUnboxingFlags(ir::Expression *newExpr, const ir::Expression *ol const ir::BoxingUnboxingFlags oldUnboxingFlag {oldExpr->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG}; - if (newExpr->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - newExpr->SetBoxingUnboxingFlags(oldBoxingFlag); - } else if (newExpr->TsType()->IsETSObjectType()) { - newExpr->SetBoxingUnboxingFlags(oldUnboxingFlag); + if (newAssignment->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + newAssignment->SetBoxingUnboxingFlags(oldBoxingFlag); + } else if (newAssignment->TsType()->IsETSObjectType()) { + newAssignment->SetBoxingUnboxingFlags(oldUnboxingFlag); + } +} + +static ir::OpaqueTypeNode *CreateProxyTypeNode(checker::ETSChecker *checker, ir::Expression *expr) +{ + auto *lcType = expr->TsType(); + if (auto *lcTypeAsPrimitive = checker->ETSBuiltinTypeAsPrimitiveType(lcType); lcTypeAsPrimitive != nullptr) { + lcType = lcTypeAsPrimitive; + } + return checker->AllocNode(lcType); +} + +static std::string GenerateStringForLoweredAssignment(lexer::TokenType opEqual, bool hasProperty, ir::Expression *expr) +{ + std::string leftHand = "@@I5"; + std::string rightHand = "@@I7"; + + if (hasProperty) { + auto const kind = expr->AsMemberExpression()->Kind(); + if (kind == ir::MemberExpressionKind::PROPERTY_ACCESS) { + leftHand += ".@@I6"; + rightHand += ".@@I8"; + } else if (kind == ir::MemberExpressionKind::ELEMENT_ACCESS) { + leftHand += "[@@I6]"; + rightHand += "[@@I8]"; + } else { + UNREACHABLE(); + } } + + return leftHand + " = (" + rightHand + ' ' + std::string {lexer::TokenToString(OpEqualToOp(opEqual))} + + " (@@E9)) as @@T10"; +} + +static ir::Identifier *GetClone(ArenaAllocator *allocator, ir::Identifier *node) +{ + return node != nullptr ? node->Clone(allocator, nullptr) : nullptr; } ir::Expression *HandleOpAssignment(public_lib::Context *ctx, checker::ETSChecker *checker, parser::ETSParser *parser, @@ -136,71 +185,25 @@ ir::Expression *HandleOpAssignment(public_lib::Context *ctx, checker::ETSChecker UNREACHABLE(); } - // Create proxy TypeNode for left hand of assignment expression - auto *lcType = left->TsType(); - if (auto *lcTypeAsPrimitive = checker->ETSBuiltinTypeAsPrimitiveType(lcType); lcTypeAsPrimitive != nullptr) { - lcType = lcTypeAsPrimitive; - } - auto *exprType = checker->AllocNode(lcType); + auto *exprType = CreateProxyTypeNode(checker, left); // Generate ArkTS code string for new lowered assignment expression: - std::string leftHand = "@@I5"; - std::string rightHand = "@@I7"; - - if (ident2 != nullptr) { - if (auto const kind = left->AsMemberExpression()->Kind(); kind == ir::MemberExpressionKind::PROPERTY_ACCESS) { - leftHand += ".@@I6"; - rightHand += ".@@I8"; - } else if (kind == ir::MemberExpressionKind::ELEMENT_ACCESS) { - leftHand += "[@@I6]"; - rightHand += "[@@I8]"; - } else { - UNREACHABLE(); - } - } - - newAssignmentStatements += leftHand + " = (" + rightHand + ' ' + - std::string {lexer::TokenToString(OpEqualToOp(opEqual))} + " (@@E9)) as @@T10"; - // std::cout << "Lowering statements: " << new_assignment_statements << std::endl; + newAssignmentStatements += GenerateStringForLoweredAssignment(opEqual, ident2 != nullptr, left); // Parse ArkTS code string and create and process corresponding AST node(s) auto expressionCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); - auto *loweringResult = parser->CreateFormattedExpression( - newAssignmentStatements, parser::DEFAULT_SOURCE_FILE, ident1, object, ident2, property, - ident1->Clone(allocator), ident2 != nullptr ? ident2->Clone(allocator) : nullptr, ident1->Clone(allocator), - ident2 != nullptr ? ident2->Clone(allocator) : nullptr, right, exprType); + auto *loweringResult = + parser->CreateFormattedExpression(newAssignmentStatements, parser::DEFAULT_SOURCE_FILE, ident1, object, ident2, + property, GetClone(allocator, ident1), GetClone(allocator, ident2), + GetClone(allocator, ident1), GetClone(allocator, ident2), right, exprType); loweringResult->SetParent(assignment->Parent()); InitScopesPhaseETS::RunExternalNode(loweringResult, ctx->compilerContext->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(loweringResult, scope); loweringResult->Check(checker); - // Adjust [un]boxing flag - ir::AssignmentExpression *newAssignment; - if (loweringResult->IsAssignmentExpression()) { - newAssignment = loweringResult->AsAssignmentExpression(); - } else if (loweringResult->IsBlockExpression() && !loweringResult->AsBlockExpression()->Statements().empty() && - loweringResult->AsBlockExpression()->Statements().back()->IsExpressionStatement() && - loweringResult->AsBlockExpression() - ->Statements() - .back() - ->AsExpressionStatement() - ->GetExpression() - ->IsAssignmentExpression()) { - newAssignment = loweringResult->AsBlockExpression() - ->Statements() - .back() - ->AsExpressionStatement() - ->GetExpression() - ->AsAssignmentExpression(); - } else { - UNREACHABLE(); - } - - // NOTE(gogabr): make sure that the checker never puts both a boxing and an unboxing flag on the same node. - // Then this code will become unnecessary. - AdjustBoxingUnboxingFlags(newAssignment, assignment); + AdjustBoxingUnboxingFlags(loweringResult, assignment); return loweringResult; } diff --git a/ets2panda/compiler/lowering/ets/tupleLowering.cpp b/ets2panda/compiler/lowering/ets/tupleLowering.cpp index 5d81de89d9..67132fed09 100644 --- a/ets2panda/compiler/lowering/ets/tupleLowering.cpp +++ b/ets2panda/compiler/lowering/ets/tupleLowering.cpp @@ -81,13 +81,16 @@ static ir::Expression *ConvertTupleUpdate(checker::ETSChecker *const checker, ir // Clone argument of update expression (conversion flag might be added to it, so we need to duplicate it to not make // conversions on 'line 3', that belongs to 'line 1' ) auto *const memberExpr = argument->AsMemberExpression(); - auto *const argumentClone = - checker->AllocNode(memberExpr->Object(), memberExpr->Property(), memberExpr->Kind(), - memberExpr->IsComputed(), memberExpr->IsOptional()); - argumentClone->SetPropVar(memberExpr->PropVar()); - argumentClone->SetParent(memberExpr->Parent()); + auto *const argumentClone = memberExpr->Clone(checker->Allocator(), memberExpr->Parent()); + argumentClone->Object()->SetTsType(memberExpr->Object()->TsType()); + if (argumentClone->Object()->IsIdentifier()) { + argumentClone->Object()->AsIdentifier()->SetVariable(memberExpr->Object()->AsIdentifier()->Variable()); + } + argumentClone->Property()->SetTsType(memberExpr->Property()->TsType()); + if (argumentClone->Property()->IsIdentifier()) { + argumentClone->Property()->AsIdentifier()->SetVariable(memberExpr->Property()->AsIdentifier()->Variable()); + } argumentClone->SetTsType(memberExpr->TsType()); - argumentClone->SetObjectType(memberExpr->ObjType()); // -------------- // Generate temporary symbols @@ -113,20 +116,29 @@ static ir::Expression *ConvertTupleUpdate(checker::ETSChecker *const checker, ir // -------------- // make node: let gensym2 = (gensym)++; - auto *gensymUpdate = checker->AllocNode(gensym, update->OperatorType(), update->IsPrefix()); + auto *identClone = gensym->Clone(checker->Allocator(), nullptr); + identClone->SetTsType(tmpVar->TsType()); + auto *gensymUpdate = + checker->AllocNode(identClone, update->OperatorType(), update->IsPrefix()); auto *const gensym2Assignment = checker->AllocNode(gensym2, gensymUpdate, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); // -------------- // make node: tuple[n] = (gensym as ) as ; - auto *gensymAs = checker->AllocNode(gensym, tupleTypeAtIdxNode, false); + identClone = gensym->Clone(checker->Allocator(), nullptr); + identClone->SetTsType(tmpVar->TsType()); + auto *gensymAs = checker->AllocNode( + identClone, tupleTypeAtIdxNode->Clone(checker->Allocator(), nullptr), false); auto *gensymAsTupleTypeAtIdx = checker->AllocNode(gensymAs, tupleElementTypeNode, false); auto *const tupleAssignment = checker->AllocNode( argument, gensymAsTupleTypeAtIdx, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); // -------------- // make node: gensym2 as ; - auto *const finalTupleNode = checker->AllocNode(gensym2, tupleTypeAtIdxNode, false); + identClone = gensym2->Clone(checker->Allocator(), nullptr); + identClone->SetTsType(tmpVar2->TsType()); + auto *const finalTupleNode = checker->AllocNode( + identClone, tupleTypeAtIdxNode->Clone(checker->Allocator(), nullptr), false); // -------------- // Construct sequence expression order diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index ef64447b69..f6b9c5f394 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -167,7 +167,7 @@ ir::TSAsExpression *HandleUnionCastToPrimitive(checker::ETSChecker *checker, ir: ir::BinaryExpression *GenInstanceofExpr(checker::ETSChecker *checker, ir::Expression *unionNode, checker::Type *constituentType) { - auto *const lhsExpr = unionNode->Clone(checker->Allocator())->AsExpression(); + auto *const lhsExpr = unionNode->Clone(checker->Allocator(), nullptr)->AsExpression(); lhsExpr->Check(checker); lhsExpr->SetBoxingUnboxingFlags(unionNode->GetBoxingUnboxingFlags()); auto *rhsType = constituentType; @@ -240,7 +240,6 @@ ir::BlockStatement *GenBlockStmtForAssignmentBinary(checker::ETSChecker *checker stmts.push_back(stmt); auto *const localBlockStmt = checker->AllocNode(checker->Allocator(), std::move(stmts)); localBlockStmt->SetScope(localCtx.GetScope()); - stmt->SetParent(localBlockStmt); localBlockStmt->SetRange(stmt->Range()); localCtx.GetScope()->BindNode(localBlockStmt); return localBlockStmt; @@ -329,12 +328,7 @@ ir::BlockStatement *ReplaceBinaryExprInStmt(checker::ETSChecker *checker, ir::Ex clonedBinary->Check(checker); auto *const consequent = GenBlockStmtForAssignmentBinary( checker, varDeclId->AsIdentifier(), ProcessOperandsInBinaryExpr(checker, clonedBinary, uType)); - instanceofTree = checker->Allocator()->New(test, consequent, instanceofTree); - test->SetParent(instanceofTree); - consequent->SetParent(instanceofTree); - if (instanceofTree->Alternate() != nullptr) { - instanceofTree->Alternate()->SetParent(instanceofTree); - } + instanceofTree = checker->AllocNode(test, consequent, instanceofTree); } ASSERT(instanceofTree != nullptr); // Replacing a binary expression with an identifier diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index 736ba8c6cd..3c4e61f971 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -400,7 +400,7 @@ void ScopesInitPhase::VisitFunctionExpression(ir::FunctionExpression *funcExpr) auto id = funcExpr->Id(); auto *funcParamScope = func->Scope()->ParamScope(); funcParamScope->BindName(Allocator(), id->Name()); - func->SetIdent(id); + func->SetIdent(id->Clone(Allocator(), nullptr)); } } @@ -734,16 +734,22 @@ void InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecif Iterate(importSpec); } -void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) +// Auxiliary method to avoid extra nested levels and too large function size +void AddOverload(ir::MethodDefinition *overload, varbinder::Variable *variable) noexcept { - const auto methodName = method->Id(); + auto *currentNode = variable->Declaration()->Node(); + currentNode->AsMethodDefinition()->AddOverload(overload); + overload->Id()->SetVariable(variable); +} +void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) +{ ASSERT(VarBinder()->GetScope()->IsClassScope()); - if (method->AsMethodDefinition()->Function()->IsDefaultParamProxy()) { return; } + const auto methodName = method->Id(); auto *const clsScope = VarBinder()->GetScope()->AsClassScope(); if (clsScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION) != nullptr) { @@ -758,18 +764,10 @@ void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) } auto *found = targetScope->FindLocal(methodName->Name(), varbinder::ResolveBindingOptions::BINDINGS); - auto addOverload = [](ir::MethodDefinition *overload, varbinder::Variable *of) { - auto *currentNode = of->Declaration()->Node(); - currentNode->AsMethodDefinition()->AddOverload(overload); - overload->Id()->SetVariable(of); - overload->SetParent(currentNode); - }; - if (found == nullptr) { auto classCtx = varbinder::LexicalScope::Enter(VarBinder(), targetScope); - auto [_, var] = VarBinder()->NewVarDecl(methodName->Start(), Allocator(), - methodName->Name(), method); - (void)_; + [[maybe_unused]] auto [_, var] = VarBinder()->NewVarDecl( + methodName->Start(), Allocator(), methodName->Name(), method); var->SetScope(clsScope); var->AddFlag(varbinder::VariableFlags::METHOD); methodName->SetVariable(var); @@ -782,13 +780,13 @@ void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) if (methodName->Name().Is(compiler::Signatures::MAIN) && clsScope->Parent()->IsGlobalScope()) { ThrowSyntaxError("Main overload is not enabled", methodName->Start()); } - addOverload(method, found); + AddOverload(method, found); method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); // default params proxy for (auto *overload : method->Overloads()) { ASSERT(overload->Function()->IsDefaultParamProxy()); - addOverload(overload, found); + AddOverload(overload, found); } method->ClearOverloads(); } diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 4b20f93db3..3075935b3a 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -484,9 +484,8 @@ public: [[nodiscard]] ir::BlockStatement *GetTopStatement(); [[nodiscard]] const ir::BlockStatement *GetTopStatement() const; - // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] virtual AstNode *Clone([[maybe_unused]] ArenaAllocator *const allocator, - [[maybe_unused]] AstNode *const parent = nullptr) + [[maybe_unused]] AstNode *const parent) { UNREACHABLE(); } diff --git a/ets2panda/ir/base/classDefinition.cpp b/ets2panda/ir/base/classDefinition.cpp index cfb7ac8dc8..94b77be1b6 100644 --- a/ets2panda/ir/base/classDefinition.cpp +++ b/ets2panda/ir/base/classDefinition.cpp @@ -117,6 +117,14 @@ void ClassDefinition::Iterate(const NodeTraverser &cb) const } } +void ClassDefinition::SetIdent(ir::Identifier *ident) noexcept +{ + ident_ = ident; + if (ident_ != nullptr) { + ident_->SetParent(this); + } +} + void ClassDefinition::Dump(ir::AstDumper *dumper) const { auto propFilter = [](AstNode *prop) -> bool { diff --git a/ets2panda/ir/base/classDefinition.h b/ets2panda/ir/base/classDefinition.h index 49d1237bf1..7161da9007 100644 --- a/ets2panda/ir/base/classDefinition.h +++ b/ets2panda/ir/base/classDefinition.h @@ -123,10 +123,7 @@ public: return ident_; } - void SetIdent(ir::Identifier *ident) noexcept - { - ident_ = ident; - } + void SetIdent(ir::Identifier *ident) noexcept; [[nodiscard]] const util::StringView &PrivateId() const noexcept { @@ -156,6 +153,9 @@ public: void SetSuper(Expression *superClass) { superClass_ = superClass; + if (superClass_ != nullptr) { + superClass_->SetParent(this); + } } [[nodiscard]] bool IsGlobal() const noexcept diff --git a/ets2panda/ir/base/classElement.cpp b/ets2panda/ir/base/classElement.cpp index 62b0ebb100..8e41ec34c7 100644 --- a/ets2panda/ir/base/classElement.cpp +++ b/ets2panda/ir/base/classElement.cpp @@ -22,12 +22,12 @@ namespace panda::es2panda::ir { Identifier *ClassElement::Id() noexcept { - return key_->IsIdentifier() ? key_->AsIdentifier() : nullptr; + return key_ != nullptr && key_->IsIdentifier() ? key_->AsIdentifier() : nullptr; } const Identifier *ClassElement::Id() const noexcept { - return key_->IsIdentifier() ? key_->AsIdentifier() : nullptr; + return key_ != nullptr && key_->IsIdentifier() ? key_->AsIdentifier() : nullptr; } bool ClassElement::IsPrivateElement() const noexcept diff --git a/ets2panda/ir/base/classProperty.cpp b/ets2panda/ir/base/classProperty.cpp index 9d97cafada..12c6583b73 100644 --- a/ets2panda/ir/base/classProperty.cpp +++ b/ets2panda/ir/base/classProperty.cpp @@ -17,15 +17,10 @@ #include "checker/ETSchecker.h" #include "checker/TSchecker.h" -#include "checker/types/ets/etsObjectType.h" #include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "ir/srcDump.h" -#include "ir/base/decorator.h" -#include "ir/typeNode.h" -#include "ir/expression.h" -#include "ir/expressions/identifier.h" namespace panda::es2panda::ir { void ClassProperty::TransformChildren(const NodeTransformer &cb) @@ -136,12 +131,11 @@ checker::Type *ClassProperty::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const key = key_->Clone(allocator)->AsExpression(); - auto *const value = value_->Clone(allocator)->AsExpression(); - auto *const typeAnnotation = typeAnnotation_->Clone(allocator, this); + auto *const key = key_->Clone(allocator, nullptr)->AsExpression(); + auto *const value = value_->Clone(allocator, nullptr)->AsExpression(); + auto *const typeAnnotation = typeAnnotation_->Clone(allocator, nullptr); if (auto *const clone = allocator->New(key, value, typeAnnotation, flags_, allocator, isComputed_); clone != nullptr) { diff --git a/ets2panda/ir/base/classProperty.h b/ets2panda/ir/base/classProperty.h index 25ac075f90..0f2c7d5ba3 100644 --- a/ets2panda/ir/base/classProperty.h +++ b/ets2panda/ir/base/classProperty.h @@ -51,8 +51,7 @@ public: return isStatic ? PrivateFieldKind::STATIC_FIELD : PrivateFieldKind::FIELD; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ClassProperty *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ClassProperty *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/base/decorator.cpp b/ets2panda/ir/base/decorator.cpp index eed3b5f6db..4ae382fa25 100644 --- a/ets2panda/ir/base/decorator.cpp +++ b/ets2panda/ir/base/decorator.cpp @@ -65,10 +65,9 @@ checker::Type *Decorator::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) Decorator *Decorator::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const expr = expr_ != nullptr ? expr_->Clone(allocator)->AsExpression() : nullptr; + auto *const expr = expr_ != nullptr ? expr_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(expr); clone != nullptr) { if (expr != nullptr) { diff --git a/ets2panda/ir/base/decorator.h b/ets2panda/ir/base/decorator.h index dfbcc9027c..779e08c90c 100644 --- a/ets2panda/ir/base/decorator.h +++ b/ets2panda/ir/base/decorator.h @@ -36,8 +36,7 @@ public: return expr_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] Decorator *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] Decorator *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/base/metaProperty.cpp b/ets2panda/ir/base/metaProperty.cpp index a5208db90f..bf4cb3a214 100644 --- a/ets2panda/ir/base/metaProperty.cpp +++ b/ets2panda/ir/base/metaProperty.cpp @@ -71,7 +71,6 @@ checker::Type *MetaProperty::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) MetaProperty *MetaProperty::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(kind_); clone != nullptr) { diff --git a/ets2panda/ir/base/metaProperty.h b/ets2panda/ir/base/metaProperty.h index c5eb1bb844..369b6ba66b 100644 --- a/ets2panda/ir/base/metaProperty.h +++ b/ets2panda/ir/base/metaProperty.h @@ -43,8 +43,7 @@ public: void TransformChildren(const NodeTransformer &cb) override; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] MetaProperty *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] MetaProperty *Clone(ArenaAllocator *allocator, AstNode *parent) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/base/methodDefinition.cpp b/ets2panda/ir/base/methodDefinition.cpp index 9ab31f5844..3f6be2a26a 100644 --- a/ets2panda/ir/base/methodDefinition.cpp +++ b/ets2panda/ir/base/methodDefinition.cpp @@ -15,7 +15,6 @@ #include "methodDefinition.h" -#include "varbinder/scope.h" #include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" @@ -52,7 +51,7 @@ PrivateFieldKind MethodDefinition::ToPrivateFieldKind(bool const isStatic) const } } -void MethodDefinition::Iterate(const NodeTraverser &cb) const +void MethodDefinition::ResolveReferences(const NodeTraverser &cb) const { cb(key_); cb(value_); @@ -66,6 +65,22 @@ void MethodDefinition::Iterate(const NodeTraverser &cb) const } } +void MethodDefinition::Iterate(const NodeTraverser &cb) const +{ + cb(key_); + cb(value_); + + for (auto *it : overloads_) { + if (it->Parent() == this) { + cb(it); + } + } + + for (auto *it : decorators_) { + cb(it); + } +} + void MethodDefinition::TransformChildren(const NodeTransformer &cb) { key_ = cb(key_)->AsExpression(); @@ -192,11 +207,10 @@ checker::Type *MethodDefinition::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) MethodDefinition *MethodDefinition::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const key = key_ != nullptr ? key_->Clone(allocator)->AsExpression() : nullptr; - auto *const value = value_ != nullptr ? value_->Clone(allocator)->AsExpression() : nullptr; + auto *const key = key_ != nullptr ? key_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(kind_, key, value, flags_, allocator, isComputed_); clone != nullptr) { diff --git a/ets2panda/ir/base/methodDefinition.h b/ets2panda/ir/base/methodDefinition.h index d3a314df0b..bf0f208af9 100644 --- a/ets2panda/ir/base/methodDefinition.h +++ b/ets2panda/ir/base/methodDefinition.h @@ -45,6 +45,7 @@ public: kind_(kind), overloads_(allocator->Adapter()) { + ASSERT(key_ != nullptr && value_ != nullptr); } // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields @@ -65,16 +66,6 @@ public: return kind_ == MethodDefinitionKind::EXTENSION_METHOD; } - Expression const *Key() const - { - return key_; - } - - Expression const *Value() const - { - return value_; - } - [[nodiscard]] const OverloadsT &Overloads() const noexcept { return overloads_; @@ -104,12 +95,13 @@ public: const ScriptFunction *Function() const; PrivateFieldKind ToPrivateFieldKind(bool isStatic) const override; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] MethodDefinition *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] MethodDefinition *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; + void ResolveReferences(const NodeTraverser &cb) const; + void Dump(ir::AstDumper *dumper) const override; void Dump(ir::SrcDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/ets2panda/ir/base/property.cpp b/ets2panda/ir/base/property.cpp index c6811cba02..d70ba1108c 100644 --- a/ets2panda/ir/base/property.cpp +++ b/ets2panda/ir/base/property.cpp @@ -31,11 +31,10 @@ Property::Property([[maybe_unused]] Tag const tag, Property const &other, Expres value_ = value; } -// NOLINTNEXTLINE(google-default-arguments) Property *Property::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const key = key_ != nullptr ? key_->Clone(allocator)->AsExpression() : nullptr; - auto *const value = value_ != nullptr ? value_->Clone(allocator)->AsExpression() : nullptr; + auto *const key = key_ != nullptr ? key_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(Tag {}, *this, key, value); clone != nullptr) { if (key != nullptr) { diff --git a/ets2panda/ir/base/property.h b/ets2panda/ir/base/property.h index d643644cfb..ccfdde132f 100644 --- a/ets2panda/ir/base/property.h +++ b/ets2panda/ir/base/property.h @@ -102,8 +102,7 @@ public: return kind == PropertyKind::GET || kind == PropertyKind::SET; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] Property *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] Property *Clone(ArenaAllocator *allocator, AstNode *parent) override; bool ConvertibleToPatternProperty(); ValidationInfo ValidateExpression(); diff --git a/ets2panda/ir/base/scriptFunction.cpp b/ets2panda/ir/base/scriptFunction.cpp index b033e6749c..8c99eda9f0 100644 --- a/ets2panda/ir/base/scriptFunction.cpp +++ b/ets2panda/ir/base/scriptFunction.cpp @@ -15,7 +15,6 @@ #include "scriptFunction.h" -#include "varbinder/scope.h" #include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" @@ -24,6 +23,27 @@ namespace panda::es2panda::ir { +ScriptFunction::ScriptFunction(FunctionSignature &&signature, AstNode *body, ScriptFunctionData &&data) + : AstNode(AstNodeType::SCRIPT_FUNCTION, data.flags), + irSignature_(std::move(signature)), + body_(body), + funcFlags_(data.funcFlags), + declare_(data.declare), + lang_(data.lang) +{ + for (auto *param : irSignature_.Params()) { + param->SetParent(this); + } + + if (auto *returnType = irSignature_.ReturnType(); returnType != nullptr) { + returnType->SetParent(this); + } + + if (auto *typeParams = irSignature_.TypeParams(); typeParams != nullptr) { + typeParams->SetParent(this); + } +} + std::size_t ScriptFunction::FormalParamsLength() const noexcept { std::size_t length = 0U; @@ -39,6 +59,12 @@ std::size_t ScriptFunction::FormalParamsLength() const noexcept return length; } +void ScriptFunction::SetIdent(Identifier *id) noexcept +{ + id_ = id; + id_->SetParent(this); +} + void ScriptFunction::TransformChildren(const NodeTransformer &cb) { if (id_ != nullptr) { @@ -61,6 +87,12 @@ void ScriptFunction::Iterate(const NodeTraverser &cb) const } } +void ScriptFunction::SetReturnTypeAnnotation(TypeNode *node) noexcept +{ + irSignature_.SetReturnType(node); + node->SetParent(this); +} + void ScriptFunction::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "ScriptFunction"}, diff --git a/ets2panda/ir/base/scriptFunction.h b/ets2panda/ir/base/scriptFunction.h index 36e35e5461..3104009fe1 100644 --- a/ets2panda/ir/base/scriptFunction.h +++ b/ets2panda/ir/base/scriptFunction.h @@ -36,31 +36,25 @@ class TypeNode; class ScriptFunction : public AstNode { public: + // Need to reduce the number of constructor parameters to pass OHOS CI code check + struct ScriptFunctionData { + ir::ScriptFunctionFlags funcFlags = ir::ScriptFunctionFlags::NONE; + ir::ModifierFlags flags = ir::ModifierFlags::NONE; + bool declare = false; + panda::es2panda::Language lang {Language::Id::ETS}; + }; + ScriptFunction() = delete; ~ScriptFunction() override = default; NO_COPY_SEMANTIC(ScriptFunction); NO_MOVE_SEMANTIC(ScriptFunction); - explicit ScriptFunction(FunctionSignature &&signature, AstNode *body, ir::ScriptFunctionFlags funcFlags, - bool declare, Language lang) - : AstNode(AstNodeType::SCRIPT_FUNCTION), - irSignature_(std::move(signature)), - body_(body), - funcFlags_(funcFlags), - declare_(declare), - lang_(lang) - { - } + explicit ScriptFunction(FunctionSignature &&signature, AstNode *body, ScriptFunctionData &&data); explicit ScriptFunction(FunctionSignature &&signature, AstNode *body, ir::ScriptFunctionFlags funcFlags, - ir::ModifierFlags flags, bool declare, Language lang) - : AstNode(AstNodeType::SCRIPT_FUNCTION, flags), - irSignature_(std::move(signature)), - body_(body), - funcFlags_(funcFlags), - declare_(declare), - lang_(lang) + bool declare, Language lang) + : ScriptFunction(std::move(signature), body, {funcFlags, {}, declare, lang}) { } @@ -129,10 +123,7 @@ public: return irSignature_.ReturnType(); } - void SetReturnTypeAnnotation(TypeNode *node) noexcept - { - irSignature_.SetReturnType(node); - } + void SetReturnTypeAnnotation(TypeNode *node) noexcept; [[nodiscard]] bool IsEntryPoint() const noexcept { @@ -254,10 +245,7 @@ public: return funcFlags_; } - void SetIdent(Identifier *id) noexcept - { - id_ = id; - } + void SetIdent(Identifier *id) noexcept; void SetSignature(checker::Signature *signature) noexcept { diff --git a/ets2panda/ir/base/spreadElement.cpp b/ets2panda/ir/base/spreadElement.cpp index f66d003679..c9d519118e 100644 --- a/ets2panda/ir/base/spreadElement.cpp +++ b/ets2panda/ir/base/spreadElement.cpp @@ -42,7 +42,6 @@ SpreadElement::SpreadElement([[maybe_unused]] Tag const tag, SpreadElement const } } -// NOLINTNEXTLINE(google-default-arguments) SpreadElement *SpreadElement::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/base/spreadElement.h b/ets2panda/ir/base/spreadElement.h index 939f60c975..40c8b0dbe6 100644 --- a/ets2panda/ir/base/spreadElement.h +++ b/ets2panda/ir/base/spreadElement.h @@ -78,8 +78,7 @@ public: optional_ = optional; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] SpreadElement *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] SpreadElement *Clone(ArenaAllocator *allocator, AstNode *parent) override; ValidationInfo ValidateExpression(); [[nodiscard]] bool ConvertibleToRest(bool isDeclaration, bool allowPattern = true); diff --git a/ets2panda/ir/base/templateElement.cpp b/ets2panda/ir/base/templateElement.cpp index 8816ba413c..09a61236ab 100644 --- a/ets2panda/ir/base/templateElement.cpp +++ b/ets2panda/ir/base/templateElement.cpp @@ -58,7 +58,6 @@ checker::Type *TemplateElement::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) TemplateElement *TemplateElement::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(raw_, cooked_); clone != nullptr) { diff --git a/ets2panda/ir/base/templateElement.h b/ets2panda/ir/base/templateElement.h index 85154cdd14..45f96e6202 100644 --- a/ets2panda/ir/base/templateElement.h +++ b/ets2panda/ir/base/templateElement.h @@ -44,8 +44,7 @@ public: return cooked_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TemplateElement *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TemplateElement *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/base/tsIndexSignature.cpp b/ets2panda/ir/base/tsIndexSignature.cpp index c85adb93c7..a878eeb13a 100644 --- a/ets2panda/ir/base/tsIndexSignature.cpp +++ b/ets2panda/ir/base/tsIndexSignature.cpp @@ -72,11 +72,10 @@ checker::Type *TSIndexSignature::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) TSIndexSignature *TSIndexSignature::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const param = param_ != nullptr ? param_->Clone(allocator)->AsExpression() : nullptr; - auto *const typeAnnotation = typeAnnotation_->Clone(allocator); + auto *const param = param_ != nullptr ? param_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const typeAnnotation = typeAnnotation_->Clone(allocator, nullptr); if (auto *const clone = allocator->New(param, typeAnnotation, readonly_); clone != nullptr) { if (parent != nullptr) { diff --git a/ets2panda/ir/base/tsIndexSignature.h b/ets2panda/ir/base/tsIndexSignature.h index cff8d5fd21..9b1b1c1d29 100644 --- a/ets2panda/ir/base/tsIndexSignature.h +++ b/ets2panda/ir/base/tsIndexSignature.h @@ -60,8 +60,7 @@ public: [[nodiscard]] TSIndexSignatureKind Kind() const noexcept; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TSIndexSignature *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TSIndexSignature *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/base/tsPropertySignature.cpp b/ets2panda/ir/base/tsPropertySignature.cpp index 4dd052b5d6..49c0ac995c 100644 --- a/ets2panda/ir/base/tsPropertySignature.cpp +++ b/ets2panda/ir/base/tsPropertySignature.cpp @@ -74,11 +74,10 @@ checker::Type *TSPropertySignature::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) TSPropertySignature *TSPropertySignature::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const key = key_ != nullptr ? key_->Clone(allocator)->AsExpression() : nullptr; - auto *const typeAnnotation = TypeAnnotation()->Clone(allocator); + auto *const key = key_ != nullptr ? key_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const typeAnnotation = TypeAnnotation()->Clone(allocator, nullptr); if (auto *const clone = allocator->New(key, typeAnnotation, computed_, optional_, readonly_); clone != nullptr) { diff --git a/ets2panda/ir/base/tsPropertySignature.h b/ets2panda/ir/base/tsPropertySignature.h index c3a0f73429..8171be38e4 100644 --- a/ets2panda/ir/base/tsPropertySignature.h +++ b/ets2panda/ir/base/tsPropertySignature.h @@ -63,8 +63,7 @@ public: return readonly_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TSPropertySignature *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TSPropertySignature *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsClassLiteral.cpp b/ets2panda/ir/ets/etsClassLiteral.cpp index ad0eabe305..787e96b377 100644 --- a/ets2panda/ir/ets/etsClassLiteral.cpp +++ b/ets2panda/ir/ets/etsClassLiteral.cpp @@ -62,10 +62,9 @@ checker::Type *ETSClassLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ETSClassLiteral *ETSClassLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const expr = expr_ != nullptr ? expr_->Clone(allocator) : nullptr; + auto *const expr = expr_ != nullptr ? expr_->Clone(allocator, nullptr) : nullptr; if (auto *const clone = allocator->New(expr); clone != nullptr) { if (expr != nullptr) { diff --git a/ets2panda/ir/ets/etsClassLiteral.h b/ets2panda/ir/ets/etsClassLiteral.h index 592f3536fd..d52bf955f6 100644 --- a/ets2panda/ir/ets/etsClassLiteral.h +++ b/ets2panda/ir/ets/etsClassLiteral.h @@ -38,8 +38,7 @@ public: explicit ETSClassLiteral(ir::TypeNode *const expr) : Expression(AstNodeType::ETS_CLASS_LITERAL), expr_(expr) {} - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSClassLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSClassLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields friend class checker::ETSAnalyzer; diff --git a/ets2panda/ir/ets/etsFunctionType.cpp b/ets2panda/ir/ets/etsFunctionType.cpp index 0eec9494ff..7ff4c9b59d 100644 --- a/ets2panda/ir/ets/etsFunctionType.cpp +++ b/ets2panda/ir/ets/etsFunctionType.cpp @@ -97,20 +97,20 @@ checker::Type *ETSFunctionType::GetType(checker::ETSChecker *checker) return Check(checker); } -// NOLINTNEXTLINE(google-default-arguments) ETSFunctionType *ETSFunctionType::Clone(ArenaAllocator *const allocator, AstNode *const parent) { ArenaVector paramsClone(allocator->Adapter()); for (auto *const param : signature_.Params()) { - paramsClone.emplace_back(param->Clone(allocator)->AsExpression()); + paramsClone.emplace_back(param->Clone(allocator, nullptr)->AsExpression()); } - auto *const typeParamsClone = signature_.TypeParams() != nullptr - ? signature_.TypeParams()->Clone(allocator)->AsTSTypeParameterDeclaration() - : nullptr; + auto *const typeParamsClone = + signature_.TypeParams() != nullptr + ? signature_.TypeParams()->Clone(allocator, nullptr)->AsTSTypeParameterDeclaration() + : nullptr; auto *const returnTypeClone = - signature_.ReturnType() != nullptr ? signature_.ReturnType()->Clone(allocator)->AsTypeNode() : nullptr; + signature_.ReturnType() != nullptr ? signature_.ReturnType()->Clone(allocator, nullptr)->AsTypeNode() : nullptr; if (auto *const clone = allocator->New( FunctionSignature(typeParamsClone, std::move(paramsClone), returnTypeClone), funcFlags_); @@ -123,6 +123,10 @@ ETSFunctionType *ETSFunctionType::Clone(ArenaAllocator *const allocator, AstNode returnTypeClone->SetParent(clone); } + for (auto *param : clone->Params()) { + param->SetParent(clone); + } + if (parent != nullptr) { clone->SetParent(parent); } diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index a3245e053f..6dbe855484 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -114,8 +114,7 @@ public: v->Accept(this); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSFunctionType *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSFunctionType *Clone(ArenaAllocator *allocator, AstNode *parent) override; private: varbinder::Scope *scope_ {}; diff --git a/ets2panda/ir/ets/etsLaunchExpression.cpp b/ets2panda/ir/ets/etsLaunchExpression.cpp index a492c7c3f2..0ac08f6185 100644 --- a/ets2panda/ir/ets/etsLaunchExpression.cpp +++ b/ets2panda/ir/ets/etsLaunchExpression.cpp @@ -75,18 +75,20 @@ bool ETSLaunchExpression::IsStaticCall() const return expr_->Signature()->HasSignatureFlag(checker::SignatureFlags::STATIC); } -// NOLINTNEXTLINE(google-default-arguments) ETSLaunchExpression *ETSLaunchExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const expr = expr_ != nullptr ? expr_->Clone(allocator) : nullptr; + auto *const expr = expr_ != nullptr ? expr_->Clone(allocator, nullptr) : nullptr; if (auto *const clone = allocator->New(expr); clone != nullptr) { if (expr != nullptr) { expr->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/ets/etsLaunchExpression.h b/ets2panda/ir/ets/etsLaunchExpression.h index 5f41d342c8..eee51886e9 100644 --- a/ets2panda/ir/ets/etsLaunchExpression.h +++ b/ets2panda/ir/ets/etsLaunchExpression.h @@ -44,8 +44,7 @@ public: friend class checker::ETSAnalyzer; friend class compiler::ETSCompiler; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSLaunchExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSLaunchExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp index 71277d9384..a5687be6b4 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -72,24 +72,27 @@ checker::Type *ETSNewArrayInstanceExpression::Check(checker::ETSChecker *checker return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ETSNewArrayInstanceExpression *ETSNewArrayInstanceExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const typeRef = typeReference_ != nullptr ? typeReference_->Clone(allocator) : nullptr; - auto *const dimension = dimension_ != nullptr ? dimension_->Clone(allocator)->AsExpression() : nullptr; + auto *const typeRef = typeReference_ != nullptr ? typeReference_->Clone(allocator, nullptr) : nullptr; + auto *const dimension = dimension_ != nullptr ? dimension_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(allocator, typeRef, dimension); clone != nullptr) { if (typeRef != nullptr) { typeRef->SetParent(clone); } + if (dimension != nullptr) { dimension->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index e1f121eaee..5e3dcaee5a 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -72,10 +72,12 @@ public: void SetDimension(ir::Expression *dimension) { dimension_ = dimension; + if (dimension_ != nullptr) { + dimension_->SetParent(this); + } } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSNewArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSNewArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp index c85d7639ca..0a6c95d214 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp @@ -96,15 +96,15 @@ ETSNewClassInstanceExpression::ETSNewClassInstanceExpression(ETSNewClassInstance ArenaAllocator *const allocator) : Expression(static_cast(other)), arguments_(allocator->Adapter()), signature_(other.signature_) { - typeReference_ = other.typeReference_->Clone(allocator, this)->AsExpression(); - classDef_ = other.classDef_->Clone(allocator, this)->AsClassDefinition(); + typeReference_ = + other.typeReference_ != nullptr ? other.typeReference_->Clone(allocator, this)->AsExpression() : nullptr; + classDef_ = other.classDef_ != nullptr ? other.classDef_->Clone(allocator, this)->AsClassDefinition() : nullptr; for (auto *const argument : other.arguments_) { arguments_.emplace_back(argument->Clone(allocator, this)->AsExpression()); } } -// NOLINTNEXTLINE(google-default-arguments) ETSNewClassInstanceExpression *ETSNewClassInstanceExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.h b/ets2panda/ir/ets/etsNewClassInstanceExpression.h index 6cbef0d123..4df829352a 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.h @@ -85,8 +85,7 @@ public: signature_ = signature; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSNewClassInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSNewClassInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp index 4b2bc1500d..e9de7f927b 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp @@ -90,7 +90,6 @@ ETSNewMultiDimArrayInstanceExpression::ETSNewMultiDimArrayInstanceExpression( } } -// NOLINTNEXTLINE(google-default-arguments) ETSNewMultiDimArrayInstanceExpression *ETSNewMultiDimArrayInstanceExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { @@ -98,6 +97,8 @@ ETSNewMultiDimArrayInstanceExpression *ETSNewMultiDimArrayInstanceExpression::Cl if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 825aae727d..993a655807 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -81,9 +81,7 @@ public: return signature_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSNewMultiDimArrayInstanceExpression *Clone(ArenaAllocator *allocator, - AstNode *parent = nullptr) override; + [[nodiscard]] ETSNewMultiDimArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsPackageDeclaration.cpp b/ets2panda/ir/ets/etsPackageDeclaration.cpp index 27a44e419c..1af22f1a87 100644 --- a/ets2panda/ir/ets/etsPackageDeclaration.cpp +++ b/ets2panda/ir/ets/etsPackageDeclaration.cpp @@ -64,10 +64,9 @@ checker::Type *ETSPackageDeclaration::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ETSPackageDeclaration *ETSPackageDeclaration::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto const name = name_ != nullptr ? name_->Clone(allocator, this)->AsExpression() : nullptr; + auto const name = name_ != nullptr ? name_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(name); clone != nullptr) { if (name != nullptr) { name->SetParent(clone); diff --git a/ets2panda/ir/ets/etsPackageDeclaration.h b/ets2panda/ir/ets/etsPackageDeclaration.h index 88d51f0c08..98463a9102 100644 --- a/ets2panda/ir/ets/etsPackageDeclaration.h +++ b/ets2panda/ir/ets/etsPackageDeclaration.h @@ -33,8 +33,7 @@ public: { } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSPackageDeclaration *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSPackageDeclaration *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsParameterExpression.cpp b/ets2panda/ir/ets/etsParameterExpression.cpp index 7b808c79c3..ec2682f776 100644 --- a/ets2panda/ir/ets/etsParameterExpression.cpp +++ b/ets2panda/ir/ets/etsParameterExpression.cpp @@ -32,6 +32,7 @@ ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identO : Expression(AstNodeType::ETS_PARAMETER_EXPRESSION), initializer_(initializer) { ASSERT(identOrSpread != nullptr); + identOrSpread->SetParent(this); if (identOrSpread->IsIdentifier()) { ident_ = identOrSpread->AsIdentifier(); @@ -187,12 +188,12 @@ checker::Type *ETSParameterExpression::Check(checker::ETSChecker *const checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ETSParameterExpression *ETSParameterExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const identOrSpread = spread_ != nullptr ? spread_->Clone(allocator)->AsAnnotatedExpression() - : ident_->Clone(allocator)->AsAnnotatedExpression(); - auto *const initializer = initializer_ != nullptr ? initializer_->Clone(allocator)->AsExpression() : nullptr; + auto *const identOrSpread = spread_ != nullptr ? spread_->Clone(allocator, nullptr)->AsAnnotatedExpression() + : ident_->Clone(allocator, nullptr)->AsAnnotatedExpression(); + auto *const initializer = + initializer_ != nullptr ? initializer_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(identOrSpread, initializer); clone != nullptr) { identOrSpread->SetParent(clone); diff --git a/ets2panda/ir/ets/etsParameterExpression.h b/ets2panda/ir/ets/etsParameterExpression.h index aedc3e7166..ec6fde41a5 100644 --- a/ets2panda/ir/ets/etsParameterExpression.h +++ b/ets2panda/ir/ets/etsParameterExpression.h @@ -78,8 +78,7 @@ public: extraValue_ = value; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSParameterExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSParameterExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void Iterate(const NodeTraverser &cb) const override; void TransformChildren(const NodeTransformer &cb) override; diff --git a/ets2panda/ir/ets/etsPrimitiveType.cpp b/ets2panda/ir/ets/etsPrimitiveType.cpp index bfc3562cfa..be255ddd3a 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.cpp +++ b/ets2panda/ir/ets/etsPrimitiveType.cpp @@ -132,7 +132,6 @@ checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *c } } -// NOLINTNEXTLINE(google-default-arguments) ETSPrimitiveType *ETSPrimitiveType::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(type_); clone != nullptr) { @@ -140,6 +139,7 @@ ETSPrimitiveType *ETSPrimitiveType::Clone(ArenaAllocator *const allocator, AstNo clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/ets/etsPrimitiveType.h b/ets2panda/ir/ets/etsPrimitiveType.h index b2ad1451df..2fb0d55172 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.h +++ b/ets2panda/ir/ets/etsPrimitiveType.h @@ -46,8 +46,7 @@ public: v->Accept(this); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSPrimitiveType *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSPrimitiveType *Clone(ArenaAllocator *allocator, AstNode *parent) override; private: PrimitiveType type_; diff --git a/ets2panda/ir/ets/etsStructDeclaration.cpp b/ets2panda/ir/ets/etsStructDeclaration.cpp index 37026f4a62..873c13499f 100644 --- a/ets2panda/ir/ets/etsStructDeclaration.cpp +++ b/ets2panda/ir/ets/etsStructDeclaration.cpp @@ -75,10 +75,9 @@ checker::Type *ETSStructDeclaration::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ETSStructDeclaration *ETSStructDeclaration::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const def = def_ != nullptr ? def_->Clone(allocator, this)->AsClassDefinition() : nullptr; + auto *const def = def_ != nullptr ? def_->Clone(allocator, nullptr)->AsClassDefinition() : nullptr; if (auto *const clone = allocator->New(def, allocator); clone != nullptr) { for (auto *const decorator : decorators_) { diff --git a/ets2panda/ir/ets/etsStructDeclaration.h b/ets2panda/ir/ets/etsStructDeclaration.h index b7d6176e72..f16200a8dd 100644 --- a/ets2panda/ir/ets/etsStructDeclaration.h +++ b/ets2panda/ir/ets/etsStructDeclaration.h @@ -67,8 +67,7 @@ public: return true; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSStructDeclaration *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSStructDeclaration *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/ets/etsTypeReference.cpp b/ets2panda/ir/ets/etsTypeReference.cpp index b65b9a68d6..0ef5afa775 100644 --- a/ets2panda/ir/ets/etsTypeReference.cpp +++ b/ets2panda/ir/ets/etsTypeReference.cpp @@ -107,10 +107,9 @@ checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker) return type; } -// NOLINTNEXTLINE(google-default-arguments) ETSTypeReference *ETSTypeReference::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const partClone = part_ != nullptr ? part_->Clone(allocator)->AsETSTypeReferencePart() : nullptr; + auto *const partClone = part_ != nullptr ? part_->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr; if (auto *const clone = allocator->New(partClone); clone != nullptr) { if (partClone != nullptr) { @@ -123,6 +122,7 @@ ETSTypeReference *ETSTypeReference::Clone(ArenaAllocator *const allocator, AstNo clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/ets/etsTypeReference.h b/ets2panda/ir/ets/etsTypeReference.h index d67d7f49ac..dfcecf74bb 100644 --- a/ets2panda/ir/ets/etsTypeReference.h +++ b/ets2panda/ir/ets/etsTypeReference.h @@ -53,8 +53,7 @@ public: v->Accept(this); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSTypeReference *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSTypeReference *Clone(ArenaAllocator *allocator, AstNode *parent) override; private: ir::ETSTypeReferencePart *part_; diff --git a/ets2panda/ir/ets/etsTypeReferencePart.cpp b/ets2panda/ir/ets/etsTypeReferencePart.cpp index 792e942e8c..21cb3dbbf7 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.cpp +++ b/ets2panda/ir/ets/etsTypeReferencePart.cpp @@ -110,13 +110,12 @@ checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) return checker->GetReferencedTypeFromBase(baseType, name_); } -// NOLINTNEXTLINE(google-default-arguments) ETSTypeReferencePart *ETSTypeReferencePart::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const nameClone = name_ != nullptr ? name_->Clone(allocator)->AsExpression() : nullptr; + auto *const nameClone = name_ != nullptr ? name_->Clone(allocator, nullptr)->AsExpression() : nullptr; auto *const typeParamsClone = - typeParams_ != nullptr ? typeParams_->Clone(allocator)->AsTSTypeParameterInstantiation() : nullptr; - auto *const prevClone = prev_ != nullptr ? prev_->Clone(allocator)->AsETSTypeReferencePart() : nullptr; + typeParams_ != nullptr ? typeParams_->Clone(allocator, nullptr)->AsTSTypeParameterInstantiation() : nullptr; + auto *const prevClone = prev_ != nullptr ? prev_->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr; if (auto *const clone = allocator->New(nameClone, typeParamsClone, prevClone); clone != nullptr) { if (nameClone != nullptr) { @@ -135,6 +134,7 @@ ETSTypeReferencePart *ETSTypeReferencePart::Clone(ArenaAllocator *const allocato clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/ets/etsTypeReferencePart.h b/ets2panda/ir/ets/etsTypeReferencePart.h index ab785f6f9c..4493d56307 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.h +++ b/ets2panda/ir/ets/etsTypeReferencePart.h @@ -70,8 +70,7 @@ public: v->Accept(this); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSTypeReferencePart *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ETSTypeReferencePart *Clone(ArenaAllocator *allocator, AstNode *parent) override; private: ir::Expression *name_; diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index 294f8f23ae..653b922f98 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -53,7 +53,6 @@ ArrayExpression::ArrayExpression([[maybe_unused]] Tag const tag, ArrayExpression } } -// NOLINTNEXTLINE(google-default-arguments) ArrayExpression *ArrayExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index 34e834a776..90dfd3e7aa 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -119,8 +119,7 @@ public: return true; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ArrayExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ArrayExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; [[nodiscard]] bool ConvertibleToArrayPattern(); [[nodiscard]] ValidationInfo ValidateExpression(); diff --git a/ets2panda/ir/expressions/arrowFunctionExpression.cpp b/ets2panda/ir/expressions/arrowFunctionExpression.cpp index 3e4f53a46e..63676ae387 100644 --- a/ets2panda/ir/expressions/arrowFunctionExpression.cpp +++ b/ets2panda/ir/expressions/arrowFunctionExpression.cpp @@ -26,7 +26,6 @@ #include "ir/ets/etsTypeReference.h" #include "ir/ets/etsTypeReferencePart.h" #include "ir/expressions/identifier.h" -#include "ir/expressions/thisExpression.h" #include "ir/statements/variableDeclarator.h" namespace panda::es2panda::ir { @@ -86,7 +85,6 @@ ArrowFunctionExpression::ArrowFunctionExpression(ArrowFunctionExpression const & } } -// NOLINTNEXTLINE(google-default-arguments) ArrowFunctionExpression *ArrowFunctionExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(*this, allocator); clone != nullptr) { @@ -105,11 +103,9 @@ ir::TypeNode *ArrowFunctionExpression::CreateReturnNodeFromType(checker::ETSChec Construct a synthetic Node with the correct ts_type_. */ ASSERT(returnType != nullptr); - ir::TypeNode *returnNode = nullptr; - auto *ident = checker->Allocator()->New(util::StringView(""), checker->Allocator()); - ir::ETSTypeReferencePart *part = checker->Allocator()->New(ident); - returnNode = checker->Allocator()->New(part); - part->SetParent(returnNode); + auto *ident = checker->AllocNode(util::StringView(""), checker->Allocator()); + auto *const part = checker->AllocNode(ident); + auto *returnNode = checker->AllocNode(part); returnNode->SetTsType(returnType); return returnNode; } @@ -135,14 +131,15 @@ ir::TypeNode *ArrowFunctionExpression::CreateTypeAnnotation(checker::ETSChecker */ returnNode = CreateReturnNodeFromType(checker, Function()->Signature()->ReturnType()); } else { - returnNode = Function()->ReturnTypeAnnotation(); + returnNode = Function()->ReturnTypeAnnotation()->Clone(checker->Allocator(), nullptr); + returnNode->SetTsType(Function()->ReturnTypeAnnotation()->TsType()); } - auto origParams = Function()->Params(); - auto signature = ir::FunctionSignature(nullptr, std::move(origParams), returnNode); - auto *funcType = - checker->Allocator()->New(std::move(signature), ir::ScriptFunctionFlags::NONE); - returnNode->SetParent(funcType); + ArenaVector params {checker->Allocator()->Adapter()}; + checker->CopyParams(Function()->Params(), params); + + auto signature = ir::FunctionSignature(nullptr, std::move(params), returnNode); + auto *funcType = checker->AllocNode(std::move(signature), ir::ScriptFunctionFlags::NONE); return funcType; } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/arrowFunctionExpression.h b/ets2panda/ir/expressions/arrowFunctionExpression.h index c1358a1722..79bc5b379f 100644 --- a/ets2panda/ir/expressions/arrowFunctionExpression.h +++ b/ets2panda/ir/expressions/arrowFunctionExpression.h @@ -83,8 +83,7 @@ public: propagateThis_ = true; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ArrowFunctionExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ArrowFunctionExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/assignmentExpression.cpp b/ets2panda/ir/expressions/assignmentExpression.cpp index b4a288a823..bebb7e2b2e 100644 --- a/ets2panda/ir/expressions/assignmentExpression.cpp +++ b/ets2panda/ir/expressions/assignmentExpression.cpp @@ -174,16 +174,17 @@ AssignmentExpression::AssignmentExpression([[maybe_unused]] Tag const tag, Assig } } -// NOLINTNEXTLINE(google-default-arguments) AssignmentExpression *AssignmentExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const left = left_ != nullptr ? left_->Clone(allocator)->AsExpression() : nullptr; - auto *const right = right_ != nullptr ? right_->Clone(allocator)->AsExpression() : nullptr; + auto *const left = left_ != nullptr ? left_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const right = right_ != nullptr ? right_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(Tag {}, *this, left, right); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/assignmentExpression.h b/ets2panda/ir/expressions/assignmentExpression.h index ae8eea3397..4077716d10 100644 --- a/ets2panda/ir/expressions/assignmentExpression.h +++ b/ets2panda/ir/expressions/assignmentExpression.h @@ -112,8 +112,7 @@ public: return target_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] AssignmentExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] AssignmentExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; [[nodiscard]] bool ConvertibleToAssignmentPattern(bool mustBePattern = true); diff --git a/ets2panda/ir/expressions/awaitExpression.cpp b/ets2panda/ir/expressions/awaitExpression.cpp index 5048bd86c4..bd59fee269 100644 --- a/ets2panda/ir/expressions/awaitExpression.cpp +++ b/ets2panda/ir/expressions/awaitExpression.cpp @@ -66,18 +66,20 @@ checker::Type *AwaitExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) AwaitExpression *AwaitExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const argument = argument_ != nullptr ? argument_->Clone(allocator)->AsExpression() : nullptr; + auto *const argument = argument_ != nullptr ? argument_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(argument); clone != nullptr) { if (argument != nullptr) { argument->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/awaitExpression.h b/ets2panda/ir/expressions/awaitExpression.h index ab1160ad37..5754b7b976 100644 --- a/ets2panda/ir/expressions/awaitExpression.h +++ b/ets2panda/ir/expressions/awaitExpression.h @@ -41,8 +41,7 @@ public: return argument_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] AwaitExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] AwaitExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/binaryExpression.cpp b/ets2panda/ir/expressions/binaryExpression.cpp index 69de433333..dbbfc271d0 100644 --- a/ets2panda/ir/expressions/binaryExpression.cpp +++ b/ets2panda/ir/expressions/binaryExpression.cpp @@ -75,25 +75,29 @@ checker::Type *BinaryExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) BinaryExpression *BinaryExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const left = left_ != nullptr ? left_->Clone(allocator)->AsExpression() : nullptr; - auto *const right = right_ != nullptr ? right_->Clone(allocator)->AsExpression() : nullptr; + auto *const left = left_ != nullptr ? left_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const right = right_ != nullptr ? right_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(left, right, operator_); clone != nullptr) { if (operationType_ != nullptr) { clone->SetOperationType(operationType_); } + if (right != nullptr) { right->SetParent(clone); } + if (left != nullptr) { left->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/binaryExpression.h b/ets2panda/ir/expressions/binaryExpression.h index c4222f4db9..82b484185e 100644 --- a/ets2panda/ir/expressions/binaryExpression.h +++ b/ets2panda/ir/expressions/binaryExpression.h @@ -142,8 +142,7 @@ public: return operationType_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] BinaryExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] BinaryExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/blockExpression.cpp b/ets2panda/ir/expressions/blockExpression.cpp index 63b795532e..eaf53644da 100644 --- a/ets2panda/ir/expressions/blockExpression.cpp +++ b/ets2panda/ir/expressions/blockExpression.cpp @@ -40,7 +40,6 @@ BlockExpression::BlockExpression([[maybe_unused]] Tag const tag, BlockExpression } } -// NOLINTNEXTLINE(google-default-arguments) BlockExpression *BlockExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/expressions/blockExpression.h b/ets2panda/ir/expressions/blockExpression.h index 6c6329ccd2..0180304f97 100644 --- a/ets2panda/ir/expressions/blockExpression.h +++ b/ets2panda/ir/expressions/blockExpression.h @@ -41,8 +41,7 @@ public: return statements_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] BlockExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] BlockExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/callExpression.cpp b/ets2panda/ir/expressions/callExpression.cpp index 577a4393b3..630e59b951 100644 --- a/ets2panda/ir/expressions/callExpression.cpp +++ b/ets2panda/ir/expressions/callExpression.cpp @@ -108,27 +108,43 @@ CallExpression::CallExpression(CallExpression const &other, ArenaAllocator *cons isTrailingBlockInNewLine_(other.isTrailingBlockInNewLine_) { callee_ = other.callee_->Clone(allocator, this)->AsExpression(); - typeParams_ = other.typeParams_->Clone(allocator, this); + typeParams_ = other.typeParams_ != nullptr ? other.typeParams_->Clone(allocator, this) : nullptr; for (auto *const argument : other.arguments_) { arguments_.emplace_back(argument->Clone(allocator, this)->AsExpression()); } - if (other.trailingBlock_ != nullptr) { - trailingBlock_ = other.trailingBlock_->Clone(allocator, this)->AsBlockStatement(); - } + trailingBlock_ = + other.trailingBlock_ != nullptr ? other.trailingBlock_->Clone(allocator, this)->AsBlockStatement() : nullptr; } -// NOLINTNEXTLINE(google-default-arguments) CallExpression *CallExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(*this, allocator); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); } + +void CallExpression::SetTypeParams(TSTypeParameterInstantiation *const typeParams) noexcept +{ + typeParams_ = typeParams; + if (typeParams_ != nullptr) { + typeParams_->SetParent(this); + } +} + +void CallExpression::SetTrailingBlock(ir::BlockStatement *const block) noexcept +{ + trailingBlock_ = block; + if (trailingBlock_ != nullptr) { + trailingBlock_->SetParent(this); + } +} } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/callExpression.h b/ets2panda/ir/expressions/callExpression.h index cd2e29cb97..92c87a41e8 100644 --- a/ets2panda/ir/expressions/callExpression.h +++ b/ets2panda/ir/expressions/callExpression.h @@ -116,10 +116,7 @@ public: signature_ = signature; } - void SetTypeParams(TSTypeParameterInstantiation *const typeParams) noexcept - { - typeParams_ = typeParams; - } + void SetTypeParams(TSTypeParameterInstantiation *typeParams) noexcept; [[nodiscard]] checker::Type *UncheckedType() const noexcept { @@ -131,10 +128,7 @@ public: uncheckedType_ = type; } - void SetTrailingBlock(ir::BlockStatement *const block) noexcept - { - trailingBlock_ = block; - } + void SetTrailingBlock(ir::BlockStatement *const block) noexcept; [[nodiscard]] ir::BlockStatement *TrailingBlock() const noexcept { @@ -151,8 +145,7 @@ public: return isTrailingBlockInNewLine_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] CallExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] CallExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/chainExpression.cpp b/ets2panda/ir/expressions/chainExpression.cpp index 7513d034fe..83f5181212 100644 --- a/ets2panda/ir/expressions/chainExpression.cpp +++ b/ets2panda/ir/expressions/chainExpression.cpp @@ -76,10 +76,9 @@ checker::Type *ChainExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ChainExpression *ChainExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const expression = expression_ != nullptr ? expression_->Clone(allocator)->AsExpression() : nullptr; + auto *const expression = expression_ != nullptr ? expression_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(expression); clone != nullptr) { if (expression != nullptr) { diff --git a/ets2panda/ir/expressions/chainExpression.h b/ets2panda/ir/expressions/chainExpression.h index 9c124c9c91..0ee4506fc9 100644 --- a/ets2panda/ir/expressions/chainExpression.h +++ b/ets2panda/ir/expressions/chainExpression.h @@ -45,8 +45,7 @@ public: return expression_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ChainExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ChainExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/classExpression.cpp b/ets2panda/ir/expressions/classExpression.cpp index 6caf00999f..7d8e14ddff 100644 --- a/ets2panda/ir/expressions/classExpression.cpp +++ b/ets2panda/ir/expressions/classExpression.cpp @@ -62,10 +62,9 @@ checker::Type *ClassExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ClassExpression *ClassExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const def = def_ != nullptr ? def_->Clone(allocator)->AsClassDefinition() : nullptr; + auto *const def = def_ != nullptr ? def_->Clone(allocator, nullptr)->AsClassDefinition() : nullptr; if (auto *const clone = allocator->New(def); clone != nullptr) { if (parent != nullptr) { diff --git a/ets2panda/ir/expressions/classExpression.h b/ets2panda/ir/expressions/classExpression.h index 3277ec23ae..2073d0690d 100644 --- a/ets2panda/ir/expressions/classExpression.h +++ b/ets2panda/ir/expressions/classExpression.h @@ -36,8 +36,7 @@ public: return def_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ClassExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ClassExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/conditionalExpression.cpp b/ets2panda/ir/expressions/conditionalExpression.cpp index c75255d971..839f243ca1 100644 --- a/ets2panda/ir/expressions/conditionalExpression.cpp +++ b/ets2panda/ir/expressions/conditionalExpression.cpp @@ -82,26 +82,30 @@ checker::Type *ConditionalExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ConditionalExpression *ConditionalExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const test = test_ != nullptr ? test_->Clone(allocator)->AsExpression() : nullptr; - auto *const consequent = consequent_ != nullptr ? consequent_->Clone(allocator)->AsExpression() : nullptr; - auto *const alternate = alternate_ != nullptr ? alternate_->Clone(allocator)->AsExpression() : nullptr; + auto *const test = test_ != nullptr ? test_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const consequent = consequent_ != nullptr ? consequent_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const alternate = alternate_ != nullptr ? alternate_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(test, consequent, alternate); clone != nullptr) { if (test != nullptr) { test->SetParent(clone); } + if (consequent != nullptr) { consequent->SetParent(clone); } + if (alternate != nullptr) { alternate->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/conditionalExpression.h b/ets2panda/ir/expressions/conditionalExpression.h index f7e3bb822a..466228c481 100644 --- a/ets2panda/ir/expressions/conditionalExpression.h +++ b/ets2panda/ir/expressions/conditionalExpression.h @@ -64,10 +64,10 @@ public: void SetTest(Expression *const test) noexcept { test_ = test; + test_->SetParent(this); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ConditionalExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ConditionalExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/functionExpression.cpp b/ets2panda/ir/expressions/functionExpression.cpp index 243a94df42..d677d21281 100644 --- a/ets2panda/ir/expressions/functionExpression.cpp +++ b/ets2panda/ir/expressions/functionExpression.cpp @@ -62,10 +62,9 @@ checker::Type *FunctionExpression::Check([[maybe_unused]] checker::ETSChecker *c return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) FunctionExpression *FunctionExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const func = func_->Clone(allocator)->AsScriptFunction(); + auto *const func = func_->Clone(allocator, nullptr)->AsScriptFunction(); if (auto *const clone = allocator->New(func); clone != nullptr) { func->SetParent(clone); diff --git a/ets2panda/ir/expressions/functionExpression.h b/ets2panda/ir/expressions/functionExpression.h index ae284499ce..ce81316c51 100644 --- a/ets2panda/ir/expressions/functionExpression.h +++ b/ets2panda/ir/expressions/functionExpression.h @@ -58,8 +58,7 @@ public: return exprName_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] FunctionExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] FunctionExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index 03d77fb781..7376be7a24 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -15,7 +15,6 @@ #include "identifier.h" -#include "varbinder/scope.h" #include "checker/ETSchecker.h" #include "checker/TSchecker.h" #include "compiler/core/pandagen.h" @@ -36,13 +35,14 @@ Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, } } -// NOLINTNEXTLINE(google-default-arguments) Identifier *Identifier::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); diff --git a/ets2panda/ir/expressions/identifier.h b/ets2panda/ir/expressions/identifier.h index b91b01311f..48196b964b 100644 --- a/ets2panda/ir/expressions/identifier.h +++ b/ets2panda/ir/expressions/identifier.h @@ -190,8 +190,7 @@ public: decorators_ = std::move(decorators); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] Identifier *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] Identifier *Clone(ArenaAllocator *allocator, AstNode *parent) override; bool CanHaveDecorator([[maybe_unused]] bool inTs) const override { diff --git a/ets2panda/ir/expressions/importExpression.cpp b/ets2panda/ir/expressions/importExpression.cpp index 21a048c903..37a2df2530 100644 --- a/ets2panda/ir/expressions/importExpression.cpp +++ b/ets2panda/ir/expressions/importExpression.cpp @@ -61,10 +61,9 @@ checker::Type *ImportExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ImportExpression *ImportExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const source = source_ != nullptr ? source_->Clone(allocator)->AsExpression() : nullptr; + auto *const source = source_ != nullptr ? source_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(source); clone != nullptr) { if (source != nullptr) { diff --git a/ets2panda/ir/expressions/importExpression.h b/ets2panda/ir/expressions/importExpression.h index 4ac17ab188..bb3a5fab15 100644 --- a/ets2panda/ir/expressions/importExpression.h +++ b/ets2panda/ir/expressions/importExpression.h @@ -34,8 +34,7 @@ public: return source_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ImportExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ImportExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp index 9b72a6a358..2dd72386fb 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp +++ b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp @@ -56,13 +56,14 @@ checker::Type *BigIntLiteral::Check([[maybe_unused]] checker::ETSChecker *checke return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) BigIntLiteral *BigIntLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(src_); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/bigIntLiteral.h b/ets2panda/ir/expressions/literals/bigIntLiteral.h index 6ac3d77385..217e99057d 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.h +++ b/ets2panda/ir/expressions/literals/bigIntLiteral.h @@ -35,8 +35,7 @@ public: return src_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] BigIntLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] BigIntLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/booleanLiteral.cpp b/ets2panda/ir/expressions/literals/booleanLiteral.cpp index 40bfa7bc65..d6c73467be 100644 --- a/ets2panda/ir/expressions/literals/booleanLiteral.cpp +++ b/ets2panda/ir/expressions/literals/booleanLiteral.cpp @@ -56,13 +56,13 @@ checker::Type *BooleanLiteral::Check([[maybe_unused]] checker::ETSChecker *check return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) BooleanLiteral *BooleanLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(boolean_); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/booleanLiteral.h b/ets2panda/ir/expressions/literals/booleanLiteral.h index 88f62c6bf7..f3ede215ba 100644 --- a/ets2panda/ir/expressions/literals/booleanLiteral.h +++ b/ets2panda/ir/expressions/literals/booleanLiteral.h @@ -34,8 +34,7 @@ public: return boolean_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] BooleanLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] BooleanLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/charLiteral.cpp b/ets2panda/ir/expressions/literals/charLiteral.cpp index ce4be05ffc..6ae2efc53f 100644 --- a/ets2panda/ir/expressions/literals/charLiteral.cpp +++ b/ets2panda/ir/expressions/literals/charLiteral.cpp @@ -59,13 +59,14 @@ checker::Type *CharLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) CharLiteral *CharLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(char_); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/charLiteral.h b/ets2panda/ir/expressions/literals/charLiteral.h index 629e1a0d03..003e922b4a 100644 --- a/ets2panda/ir/expressions/literals/charLiteral.h +++ b/ets2panda/ir/expressions/literals/charLiteral.h @@ -40,8 +40,7 @@ public: return char_ == other.char_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] CharLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] CharLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/nullLiteral.cpp b/ets2panda/ir/expressions/literals/nullLiteral.cpp index 74c0e57816..6c45263aba 100644 --- a/ets2panda/ir/expressions/literals/nullLiteral.cpp +++ b/ets2panda/ir/expressions/literals/nullLiteral.cpp @@ -55,13 +55,13 @@ checker::Type *NullLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) NullLiteral *NullLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/nullLiteral.h b/ets2panda/ir/expressions/literals/nullLiteral.h index 4fb46bb414..40a5f7b299 100644 --- a/ets2panda/ir/expressions/literals/nullLiteral.h +++ b/ets2panda/ir/expressions/literals/nullLiteral.h @@ -28,8 +28,7 @@ public: explicit NullLiteral() : Literal(AstNodeType::NULL_LITERAL) {} - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] NullLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] NullLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/numberLiteral.cpp b/ets2panda/ir/expressions/literals/numberLiteral.cpp index dc7e40501b..3a832b8da0 100644 --- a/ets2panda/ir/expressions/literals/numberLiteral.cpp +++ b/ets2panda/ir/expressions/literals/numberLiteral.cpp @@ -74,13 +74,13 @@ checker::Type *NumberLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) NumberLiteral *NumberLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(number_); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/numberLiteral.h b/ets2panda/ir/expressions/literals/numberLiteral.h index 0abcbbce6d..7a4412d2f3 100644 --- a/ets2panda/ir/expressions/literals/numberLiteral.h +++ b/ets2panda/ir/expressions/literals/numberLiteral.h @@ -49,8 +49,7 @@ public: [[nodiscard]] bool HasFloatingPoint() const; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] NumberLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] NumberLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/regExpLiteral.cpp b/ets2panda/ir/expressions/literals/regExpLiteral.cpp index e14f0fad2d..c05a8ede16 100644 --- a/ets2panda/ir/expressions/literals/regExpLiteral.cpp +++ b/ets2panda/ir/expressions/literals/regExpLiteral.cpp @@ -57,13 +57,13 @@ checker::Type *RegExpLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) RegExpLiteral *RegExpLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(pattern_, flags_, flagsStr_); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/regExpLiteral.h b/ets2panda/ir/expressions/literals/regExpLiteral.h index 9666670fe7..9e21afa71f 100644 --- a/ets2panda/ir/expressions/literals/regExpLiteral.h +++ b/ets2panda/ir/expressions/literals/regExpLiteral.h @@ -44,8 +44,7 @@ public: return flags_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] RegExpLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] RegExpLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/stringLiteral.cpp b/ets2panda/ir/expressions/literals/stringLiteral.cpp index 11bc091825..8fb5ab112e 100644 --- a/ets2panda/ir/expressions/literals/stringLiteral.cpp +++ b/ets2panda/ir/expressions/literals/stringLiteral.cpp @@ -87,13 +87,13 @@ checker::Type *StringLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) StringLiteral *StringLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(str_); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/literals/stringLiteral.h b/ets2panda/ir/expressions/literals/stringLiteral.h index 081eed374f..3183fd6cd3 100644 --- a/ets2panda/ir/expressions/literals/stringLiteral.h +++ b/ets2panda/ir/expressions/literals/stringLiteral.h @@ -41,8 +41,7 @@ public: return str_ == other.str_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] StringLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] StringLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/literals/undefinedLiteral.cpp b/ets2panda/ir/expressions/literals/undefinedLiteral.cpp index 5ba4fd860a..3195df4ce8 100644 --- a/ets2panda/ir/expressions/literals/undefinedLiteral.cpp +++ b/ets2panda/ir/expressions/literals/undefinedLiteral.cpp @@ -63,6 +63,7 @@ UndefinedLiteral *UndefinedLiteral::Clone(ArenaAllocator *allocator, AstNode *pa if (parent != nullptr) { clone->SetParent(parent); } + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index ae0ec9e0bf..ec8b9340a2 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -24,18 +24,11 @@ namespace panda::es2panda::ir { MemberExpression::MemberExpression([[maybe_unused]] Tag const tag, MemberExpression const &other, - Expression *const object, Expression *const property) + ArenaAllocator *allocator) : MemberExpression(other) { - object_ = object; - if (object_ != nullptr) { - object_->SetParent(this); - } - - property_ = property; - if (property_ != nullptr) { - property_->SetParent(this); - } + object_ = other.object_ != nullptr ? other.object_->Clone(allocator, this)->AsExpression() : nullptr; + property_ = other.property_ != nullptr ? other.property_->Clone(allocator, this)->AsExpression() : nullptr; } bool MemberExpression::IsPrivateReference() const noexcept @@ -394,24 +387,14 @@ checker::Type *MemberExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) MemberExpression *MemberExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - 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(object, property, kind_, computed_, MaybeOptionalExpression::IsOptional()); - clone != nullptr) { - if (object != nullptr) { - object->SetParent(clone); - } - if (property != nullptr) { - property->SetParent(clone); - } + if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/memberExpression.h b/ets2panda/ir/expressions/memberExpression.h index b59a73b409..581b342eb2 100644 --- a/ets2panda/ir/expressions/memberExpression.h +++ b/ets2panda/ir/expressions/memberExpression.h @@ -69,7 +69,7 @@ public: { } - explicit MemberExpression(Tag tag, MemberExpression const &other, Expression *object, Expression *property); + explicit MemberExpression(Tag tag, MemberExpression const &other, ArenaAllocator *allocator); // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields friend class compiler::JSCompiler; @@ -172,8 +172,7 @@ public: [[nodiscard]] bool IsPrivateReference() const noexcept; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] MemberExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] MemberExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; @@ -200,7 +199,9 @@ protected: ignoreBox_ = other.ignoreBox_; propVar_ = other.propVar_; // Note! Probably, we need to do 'Instantiate(...)' but we haven't access to 'Relation()' here... + uncheckedType_ = other.uncheckedType_; objType_ = other.objType_; + tupleConvertedType_ = other.tupleConvertedType_; } private: diff --git a/ets2panda/ir/expressions/newExpression.cpp b/ets2panda/ir/expressions/newExpression.cpp index f56cdeb805..8fb67ccc9f 100644 --- a/ets2panda/ir/expressions/newExpression.cpp +++ b/ets2panda/ir/expressions/newExpression.cpp @@ -36,7 +36,6 @@ NewExpression::NewExpression([[maybe_unused]] Tag const tag, NewExpression const } } -// NOLINTNEXTLINE(google-default-arguments) NewExpression *NewExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/expressions/newExpression.h b/ets2panda/ir/expressions/newExpression.h index a1d974cd3f..883e310a29 100644 --- a/ets2panda/ir/expressions/newExpression.h +++ b/ets2panda/ir/expressions/newExpression.h @@ -53,8 +53,7 @@ public: return arguments_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] NewExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] NewExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index 6ebf574910..4ba78c48b3 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -65,7 +65,6 @@ ObjectExpression::ObjectExpression([[maybe_unused]] Tag const tag, ObjectExpress } } -// NOLINTNEXTLINE(google-default-arguments) ObjectExpression *ObjectExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/expressions/objectExpression.h b/ets2panda/ir/expressions/objectExpression.h index 0beef0b780..758a46c161 100644 --- a/ets2panda/ir/expressions/objectExpression.h +++ b/ets2panda/ir/expressions/objectExpression.h @@ -96,8 +96,7 @@ public: return true; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ObjectExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ObjectExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; [[nodiscard]] ValidationInfo ValidateExpression(); [[nodiscard]] bool ConvertibleToObjectPattern(); diff --git a/ets2panda/ir/expressions/omittedExpression.cpp b/ets2panda/ir/expressions/omittedExpression.cpp index 0ab3d1f332..abbfdd6774 100644 --- a/ets2panda/ir/expressions/omittedExpression.cpp +++ b/ets2panda/ir/expressions/omittedExpression.cpp @@ -55,7 +55,6 @@ checker::Type *OmittedExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) OmittedExpression *OmittedExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(); clone != nullptr) { diff --git a/ets2panda/ir/expressions/omittedExpression.h b/ets2panda/ir/expressions/omittedExpression.h index 4f1f340b78..b29553d7c4 100644 --- a/ets2panda/ir/expressions/omittedExpression.h +++ b/ets2panda/ir/expressions/omittedExpression.h @@ -30,8 +30,7 @@ public: void TransformChildren(const NodeTransformer &cb) override; - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] OmittedExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] OmittedExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/expressions/sequenceExpression.cpp b/ets2panda/ir/expressions/sequenceExpression.cpp index 3830204255..d4f37ffaef 100644 --- a/ets2panda/ir/expressions/sequenceExpression.cpp +++ b/ets2panda/ir/expressions/sequenceExpression.cpp @@ -32,7 +32,6 @@ SequenceExpression::SequenceExpression([[maybe_unused]] Tag const tag, SequenceE } } -// NOLINTNEXTLINE(google-default-arguments) SequenceExpression *SequenceExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/expressions/sequenceExpression.h b/ets2panda/ir/expressions/sequenceExpression.h index 98c53be093..4c46022aad 100644 --- a/ets2panda/ir/expressions/sequenceExpression.h +++ b/ets2panda/ir/expressions/sequenceExpression.h @@ -47,8 +47,7 @@ public: return sequence_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] SequenceExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] SequenceExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/superExpression.cpp b/ets2panda/ir/expressions/superExpression.cpp index 02e8244316..8707b2b35e 100644 --- a/ets2panda/ir/expressions/superExpression.cpp +++ b/ets2panda/ir/expressions/superExpression.cpp @@ -57,7 +57,6 @@ checker::Type *SuperExpression::Check([[maybe_unused]] checker::ETSChecker *chec return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) SuperExpression *SuperExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(); clone != nullptr) { diff --git a/ets2panda/ir/expressions/superExpression.h b/ets2panda/ir/expressions/superExpression.h index 29d12a994d..a3d33a1f18 100644 --- a/ets2panda/ir/expressions/superExpression.h +++ b/ets2panda/ir/expressions/superExpression.h @@ -28,8 +28,7 @@ public: explicit SuperExpression() : Expression(AstNodeType::SUPER_EXPRESSION) {} - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] SuperExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] SuperExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/taggedTemplateExpression.cpp b/ets2panda/ir/expressions/taggedTemplateExpression.cpp index 238deecd37..bd0bce7063 100644 --- a/ets2panda/ir/expressions/taggedTemplateExpression.cpp +++ b/ets2panda/ir/expressions/taggedTemplateExpression.cpp @@ -81,12 +81,11 @@ checker::Type *TaggedTemplateExpression::Check([[maybe_unused]] checker::ETSChec return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) TaggedTemplateExpression *TaggedTemplateExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const tag = tag_ != nullptr ? tag_->Clone(allocator)->AsExpression() : nullptr; - auto *const quasi = quasi_ != nullptr ? quasi_->Clone(allocator) : nullptr; - auto *const typeParams = typeParams_ != nullptr ? typeParams_->Clone(allocator) : nullptr; + auto *const tag = tag_ != nullptr ? tag_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const quasi = quasi_ != nullptr ? quasi_->Clone(allocator, nullptr) : nullptr; + auto *const typeParams = typeParams_ != nullptr ? typeParams_->Clone(allocator, nullptr) : nullptr; if (auto *const clone = allocator->New(tag, quasi, typeParams); clone != nullptr) { if (tag != nullptr) { diff --git a/ets2panda/ir/expressions/taggedTemplateExpression.h b/ets2panda/ir/expressions/taggedTemplateExpression.h index d8853db8a9..2f70a9451a 100644 --- a/ets2panda/ir/expressions/taggedTemplateExpression.h +++ b/ets2panda/ir/expressions/taggedTemplateExpression.h @@ -50,8 +50,7 @@ public: return typeParams_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TaggedTemplateExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TaggedTemplateExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/templateLiteral.cpp b/ets2panda/ir/expressions/templateLiteral.cpp index 732c96706b..30e37189f8 100644 --- a/ets2panda/ir/expressions/templateLiteral.cpp +++ b/ets2panda/ir/expressions/templateLiteral.cpp @@ -39,7 +39,6 @@ TemplateLiteral::TemplateLiteral([[maybe_unused]] Tag const tag, TemplateLiteral } } -// NOLINTNEXTLINE(google-default-arguments) TemplateLiteral *TemplateLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { diff --git a/ets2panda/ir/expressions/templateLiteral.h b/ets2panda/ir/expressions/templateLiteral.h index 046ea69c4f..0b7b587116 100644 --- a/ets2panda/ir/expressions/templateLiteral.h +++ b/ets2panda/ir/expressions/templateLiteral.h @@ -48,8 +48,7 @@ public: return expressions_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TemplateLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TemplateLiteral *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/thisExpression.cpp b/ets2panda/ir/expressions/thisExpression.cpp index 9598cea01a..7ab66d905c 100644 --- a/ets2panda/ir/expressions/thisExpression.cpp +++ b/ets2panda/ir/expressions/thisExpression.cpp @@ -63,7 +63,6 @@ checker::Type *ThisExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) ThisExpression *ThisExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const clone = allocator->New(); clone != nullptr) { diff --git a/ets2panda/ir/expressions/thisExpression.h b/ets2panda/ir/expressions/thisExpression.h index 51ab041129..c1db0af614 100644 --- a/ets2panda/ir/expressions/thisExpression.h +++ b/ets2panda/ir/expressions/thisExpression.h @@ -28,8 +28,7 @@ public: explicit ThisExpression() : Expression(AstNodeType::THIS_EXPRESSION) {} - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ThisExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] ThisExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/unaryExpression.cpp b/ets2panda/ir/expressions/unaryExpression.cpp index 835456d9c4..5759906507 100644 --- a/ets2panda/ir/expressions/unaryExpression.cpp +++ b/ets2panda/ir/expressions/unaryExpression.cpp @@ -15,19 +15,12 @@ #include "unaryExpression.h" -#include "varbinder/variable.h" -#include "checker/types/typeFlag.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" #include "ir/astDump.h" #include "ir/srcDump.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/literals/bigIntLiteral.h" -#include "ir/expressions/literals/numberLiteral.h" -#include "ir/expressions/callExpression.h" -#include "ir/expressions/memberExpression.h" namespace panda::es2panda::ir { void UnaryExpression::TransformChildren(const NodeTransformer &cb) @@ -71,18 +64,20 @@ checker::Type *UnaryExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) UnaryExpression *UnaryExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const argument = argument_ != nullptr ? argument_->Clone(allocator)->AsExpression() : nullptr; + auto *const argument = argument_ != nullptr ? argument_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(argument, operator_); clone != nullptr) { if (argument != nullptr) { argument->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/unaryExpression.h b/ets2panda/ir/expressions/unaryExpression.h index bbb261d3a0..af060bca82 100644 --- a/ets2panda/ir/expressions/unaryExpression.h +++ b/ets2panda/ir/expressions/unaryExpression.h @@ -58,8 +58,7 @@ public: return argument_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] UnaryExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] UnaryExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/updateExpression.cpp b/ets2panda/ir/expressions/updateExpression.cpp index 5453e7543c..3e498d2bff 100644 --- a/ets2panda/ir/expressions/updateExpression.cpp +++ b/ets2panda/ir/expressions/updateExpression.cpp @@ -78,18 +78,20 @@ checker::Type *UpdateExpression::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) UpdateExpression *UpdateExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const argument = argument_ != nullptr ? argument_->Clone(allocator)->AsExpression() : nullptr; + auto *const argument = argument_ != nullptr ? argument_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(argument, operator_, prefix_); clone != nullptr) { if (argument != nullptr) { argument->SetParent(clone); } + if (parent != nullptr) { clone->SetParent(parent); } + + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/expressions/updateExpression.h b/ets2panda/ir/expressions/updateExpression.h index 312a73df33..51539cccf5 100644 --- a/ets2panda/ir/expressions/updateExpression.h +++ b/ets2panda/ir/expressions/updateExpression.h @@ -62,8 +62,7 @@ public: return prefix_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] UpdateExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] UpdateExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/yieldExpression.cpp b/ets2panda/ir/expressions/yieldExpression.cpp index 36ce163da7..3c8400649d 100644 --- a/ets2panda/ir/expressions/yieldExpression.cpp +++ b/ets2panda/ir/expressions/yieldExpression.cpp @@ -67,10 +67,9 @@ checker::Type *YieldExpression::Check([[maybe_unused]] checker::ETSChecker *chec return checker->GetAnalyzer()->Check(this); } -// NOLINTNEXTLINE(google-default-arguments) YieldExpression *YieldExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const argument = argument_ != nullptr ? argument_->Clone(allocator)->AsExpression() : nullptr; + auto *const argument = argument_ != nullptr ? argument_->Clone(allocator, nullptr)->AsExpression() : nullptr; if (auto *const clone = allocator->New(argument, delegate_); clone != nullptr) { if (argument != nullptr) { diff --git a/ets2panda/ir/expressions/yieldExpression.h b/ets2panda/ir/expressions/yieldExpression.h index 793843063c..c7e2f278f9 100644 --- a/ets2panda/ir/expressions/yieldExpression.h +++ b/ets2panda/ir/expressions/yieldExpression.h @@ -46,8 +46,7 @@ public: return argument_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] YieldExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] YieldExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/statements/returnStatement.cpp b/ets2panda/ir/statements/returnStatement.cpp index e6973d5d36..59a5277ddd 100644 --- a/ets2panda/ir/statements/returnStatement.cpp +++ b/ets2panda/ir/statements/returnStatement.cpp @@ -96,6 +96,8 @@ void ReturnStatement::SetReturnType(checker::ETSChecker *checker, checker::Type void ReturnStatement::SetArgument(Expression *arg) { argument_ = arg; - arg->SetParent(this); + if (argument_ != nullptr) { + argument_->SetParent(this); + } } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index b4c9d27cae..328476307b 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -78,10 +78,9 @@ checker::Type *TSArrayType::GetType(checker::ETSChecker *checker) return checker->CreateETSArrayType(elementType); } -// NOLINTNEXTLINE(google-default-arguments) TSArrayType *TSArrayType::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const elementTypeClone = elementType_ != nullptr ? elementType_->Clone(allocator) : nullptr; + auto *const elementTypeClone = elementType_ != nullptr ? elementType_->Clone(allocator, nullptr) : nullptr; if (auto *const clone = allocator->New(elementTypeClone); clone != nullptr) { if (elementTypeClone != nullptr) { diff --git a/ets2panda/ir/ts/tsArrayType.h b/ets2panda/ir/ts/tsArrayType.h index 12752a3004..131d10a5d0 100644 --- a/ets2panda/ir/ts/tsArrayType.h +++ b/ets2panda/ir/ts/tsArrayType.h @@ -53,8 +53,7 @@ public: v->Accept(this); } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TSArrayType *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TSArrayType *Clone(ArenaAllocator *allocator, AstNode *parent) override; private: TypeNode *elementType_; diff --git a/ets2panda/ir/ts/tsAsExpression.cpp b/ets2panda/ir/ts/tsAsExpression.cpp index 051d18b7a5..c28ff0e5cc 100644 --- a/ets2panda/ir/ts/tsAsExpression.cpp +++ b/ets2panda/ir/ts/tsAsExpression.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 @@ -15,30 +15,24 @@ #include "tsAsExpression.h" -#include "varbinder/scope.h" #include "checker/TSchecker.h" -#include "checker/ets/castingContext.h" -#include "checker/types/ets/etsUnionType.h" +#include "checker/ETSchecker.h" #include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/literal.h" -#include "ir/expressions/memberExpression.h" -#include "ir/expressions/objectExpression.h" -#include "ir/expressions/unaryExpression.h" -#include "ir/typeNode.h" -#include "ir/ets/etsFunctionType.h" namespace panda::es2panda::ir { -Expression *TSAsExpression::Expr() +Expression *TSAsExpression::Expr() noexcept { return expression_; } -void TSAsExpression::SetExpr(Expression *expr) +void TSAsExpression::SetExpr(Expression *expr) noexcept { expression_ = expr; - SetStart(expression_->Start()); + if (expression_ != nullptr) { + SetStart(expression_->Start()); + expression_->SetParent(this); + } } void TSAsExpression::TransformChildren(const NodeTransformer &cb) @@ -82,4 +76,33 @@ checker::Type *TSAsExpression::Check(checker::ETSChecker *const checker) { return checker->GetAnalyzer()->Check(this); } + +TSAsExpression *TSAsExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) +{ + auto *const expression = expression_ != nullptr ? expression_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *typeAnnotation = TypeAnnotation(); + if (typeAnnotation != nullptr) { + typeAnnotation = typeAnnotation->Clone(allocator, nullptr); + } + + if (auto *const clone = allocator->New(expression, typeAnnotation, isConst_); clone != nullptr) { + if (expression != nullptr) { + expression->SetParent(clone); + } + + if (typeAnnotation != nullptr) { + typeAnnotation->SetParent(clone); + } + + clone->SetTsType(TsType()); + if (parent != nullptr) { + clone->SetParent(parent); + } + + clone->SetRange(Range()); + return clone; + } + + throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); +} } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsAsExpression.h b/ets2panda/ir/ts/tsAsExpression.h index 1fa6865140..7639332ad4 100644 --- a/ets2panda/ir/ts/tsAsExpression.h +++ b/ets2panda/ir/ts/tsAsExpression.h @@ -29,6 +29,12 @@ class ETSCompiler; namespace panda::es2panda::ir { class TSAsExpression : public AnnotatedExpression { public: + TSAsExpression() = delete; + ~TSAsExpression() override = default; + + NO_COPY_SEMANTIC(TSAsExpression); + NO_MOVE_SEMANTIC(TSAsExpression); + explicit TSAsExpression(Expression *expression, TypeNode *typeAnnotation, bool isConst) : AnnotatedExpression(AstNodeType::TS_AS_EXPRESSION, typeAnnotation), expression_(expression), isConst_(isConst) { @@ -36,20 +42,23 @@ public: // NOTE (vivienvoros): these friend relationships can be removed once there are getters for private fields friend class checker::ETSAnalyzer; friend class compiler::ETSCompiler; - const Expression *Expr() const + + [[nodiscard]] const Expression *Expr() const noexcept { return expression_; } - Expression *Expr(); - void SetExpr(Expression *expr); + [[nodiscard]] Expression *Expr() noexcept; + void SetExpr(Expression *expr) noexcept; - bool IsConst() const + [[nodiscard]] bool IsConst() const noexcept { return isConst_; } - void SetUncheckedCast(bool isUncheckedCast) + [[nodiscard]] TSAsExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; + + void SetUncheckedCast(bool isUncheckedCast) noexcept { isUncheckedCast_ = isUncheckedCast; } diff --git a/ets2panda/ir/ts/tsInterfaceBody.cpp b/ets2panda/ir/ts/tsInterfaceBody.cpp index ecdb207672..34392b2882 100644 --- a/ets2panda/ir/ts/tsInterfaceBody.cpp +++ b/ets2panda/ir/ts/tsInterfaceBody.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2022 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 diff --git a/ets2panda/ir/ts/tsQualifiedName.cpp b/ets2panda/ir/ts/tsQualifiedName.cpp index d3c4751114..65fe1b15bb 100644 --- a/ets2panda/ir/ts/tsQualifiedName.cpp +++ b/ets2panda/ir/ts/tsQualifiedName.cpp @@ -24,6 +24,14 @@ #include "ir/expressions/identifier.h" namespace panda::es2panda::ir { +TSQualifiedName::TSQualifiedName([[maybe_unused]] Tag const tag, TSQualifiedName const &other, + ArenaAllocator *allocator) + : Expression(static_cast(other)) +{ + left_ = other.left_ != nullptr ? other.left_->Clone(allocator, this)->AsExpression() : nullptr; + right_ = other.right_ != nullptr ? other.right_->Clone(allocator, this)->AsIdentifier() : nullptr; +} + void TSQualifiedName::Iterate(const NodeTraverser &cb) const { cb(left_); @@ -132,4 +140,18 @@ const ir::TSQualifiedName *TSQualifiedName::ResolveLeftMostQualifiedName() const { return ResolveLeftMostQualifiedNameImpl(this); } + +TSQualifiedName *TSQualifiedName::Clone(ArenaAllocator *const allocator, AstNode *const parent) +{ + if (auto *const clone = allocator->New(Tag {}, *this, allocator); clone != nullptr) { + if (parent != nullptr) { + clone->SetParent(parent); + } + + clone->SetRange(Range()); + return clone; + } + + throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); +} } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsQualifiedName.h b/ets2panda/ir/ts/tsQualifiedName.h index a59bf6aa3a..ff2e145f8f 100644 --- a/ets2panda/ir/ts/tsQualifiedName.h +++ b/ets2panda/ir/ts/tsQualifiedName.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2024 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 @@ -20,28 +20,38 @@ namespace panda::es2panda::ir { class TSQualifiedName : public Expression { + struct Tag {}; + public: + TSQualifiedName() = delete; + ~TSQualifiedName() override = default; + + NO_COPY_SEMANTIC(TSQualifiedName); + NO_MOVE_SEMANTIC(TSQualifiedName); + explicit TSQualifiedName(Expression *left, Identifier *right) : Expression(AstNodeType::TS_QUALIFIED_NAME), left_(left), right_(right) { } - const Expression *Left() const + explicit TSQualifiedName(Tag tag, TSQualifiedName const &other, ArenaAllocator *allocator); + + [[nodiscard]] const Expression *Left() const noexcept { return left_; } - Expression *Left() + [[nodiscard]] Expression *Left() noexcept { return left_; } - const Identifier *Right() const + [[nodiscard]] const Identifier *Right() const noexcept { return right_; } - Identifier *Right() + [[nodiscard]] Identifier *Right() noexcept { return right_; } @@ -51,6 +61,8 @@ public: ir::TSQualifiedName *ResolveLeftMostQualifiedName(); const ir::TSQualifiedName *ResolveLeftMostQualifiedName() const; + [[nodiscard]] TSQualifiedName *Clone(ArenaAllocator *allocator, AstNode *parent) override; + 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/ts/tsTypeParameterInstantiation.cpp b/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp index ef538c9bcf..84496dcd92 100644 --- a/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp +++ b/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp @@ -35,7 +35,6 @@ TSTypeParameterInstantiation::TSTypeParameterInstantiation([[maybe_unused]] Tag } } -// NOLINTNEXTLINE(google-default-arguments) TSTypeParameterInstantiation *TSTypeParameterInstantiation::Clone(ArenaAllocator *const allocator, AstNode *const parent) { diff --git a/ets2panda/ir/ts/tsTypeParameterInstantiation.h b/ets2panda/ir/ts/tsTypeParameterInstantiation.h index be57a1c502..e6c02c9e58 100644 --- a/ets2panda/ir/ts/tsTypeParameterInstantiation.h +++ b/ets2panda/ir/ts/tsTypeParameterInstantiation.h @@ -42,8 +42,7 @@ public: return params_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TSTypeParameterInstantiation *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TSTypeParameterInstantiation *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/typeNode.cpp b/ets2panda/ir/typeNode.cpp index be22e10ee7..c90e0234ae 100644 --- a/ets2panda/ir/typeNode.cpp +++ b/ets2panda/ir/typeNode.cpp @@ -20,7 +20,6 @@ namespace panda::es2panda::ir { -// NOLINTNEXTLINE(google-default-arguments) TypeNode *TypeNode::Clone(ArenaAllocator *const allocator, AstNode *const parent) { if (auto *const type = TsType(); type != nullptr) { diff --git a/ets2panda/ir/typeNode.h b/ets2panda/ir/typeNode.h index 7933f9b5e4..72f4ceb540 100644 --- a/ets2panda/ir/typeNode.h +++ b/ets2panda/ir/typeNode.h @@ -47,8 +47,7 @@ public: return nullptr; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] TypeNode *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + [[nodiscard]] TypeNode *Clone(ArenaAllocator *allocator, AstNode *parent) override; protected: explicit TypeNode(AstNodeType const type) : Expression(type) {} diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index b91b25f816..ee9438be7f 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -648,7 +648,7 @@ ir::ScriptFunction *ETSParser::AddInitMethod(ArenaVector &globalP auto *initBody = AllocNode(Allocator(), std::move(statements)); initFunc = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), - initBody, functionFlags, false, GetContext().GetLanguge()); + initBody, functionFlags, false, GetContext().GetLanguage()); } initFunc->SetIdent(initIdent); @@ -656,8 +656,9 @@ ir::ScriptFunction *ETSParser::AddInitMethod(ArenaVector &globalP auto *funcExpr = AllocNode(initFunc); - auto *initMethod = AllocNode(ir::MethodDefinitionKind::METHOD, initIdent, funcExpr, - functionModifiers, Allocator(), false); + auto *initMethod = AllocNode(ir::MethodDefinitionKind::METHOD, + initIdent->Clone(Allocator(), nullptr)->AsExpression(), + funcExpr, functionModifiers, Allocator(), false); return std::make_pair(initFunc, initMethod); }; @@ -1017,9 +1018,6 @@ void ETSParser::CreateCCtor(ArenaVector &properties, const lexer: } ArenaVector params(Allocator()->Adapter()); - - auto *id = AllocNode(compiler::Signatures::CCTOR, Allocator()); - ArenaVector statements(Allocator()->Adapter()); // Add the call to special '_$init$_' method containing all the top-level variable initializations (as assignments) @@ -1044,10 +1042,12 @@ void ETSParser::CreateCCtor(ArenaVector &properties, const lexer: } } + auto *id = AllocNode(compiler::Signatures::CCTOR, Allocator()); auto *body = AllocNode(Allocator(), std::move(statements)); - auto *func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::HIDDEN, - ir::ModifierFlags::STATIC, false, GetContext().GetLanguge()); + auto *func = AllocNode( + ir::FunctionSignature(nullptr, std::move(params), nullptr), body, + ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::HIDDEN, + ir::ModifierFlags::STATIC, false, GetContext().GetLanguage()}); func->SetIdent(id); auto *funcExpr = AllocNode(func); @@ -1387,16 +1387,16 @@ lexer::SourcePosition ETSParser::InitializeGlobalVariable(ir::Identifier *fieldN ident->SetReference(); ident->SetRange(fieldName->Range()); - auto *assignmentExpression = - AllocNode(ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto *assignmentExpression = AllocNode( + ident, initializer->Clone(Allocator(), nullptr)->AsExpression(), lexer::TokenType::PUNCTUATOR_SUBSTITUTION); endLoc = initializer->End(); assignmentExpression->SetRange({fieldName->Start(), endLoc}); - assignmentExpression->SetParent(funcBody); auto expressionStatement = AllocNode(assignmentExpression); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { endLoc = Lexer()->GetToken().End(); } + expressionStatement->SetParent(funcBody); expressionStatement->SetRange({startLoc, endLoc}); funcBody->AsBlockStatement()->Statements().emplace_back(expressionStatement); @@ -1440,7 +1440,8 @@ ir::MethodDefinition *ETSParser::ParseClassMethodDefinition(ir::Identifier *meth if (className != nullptr) { func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD); } - auto *method = AllocNode(methodKind, methodName, funcExpr, modifiers, Allocator(), false); + auto *method = AllocNode(methodKind, methodName->Clone(Allocator(), nullptr)->AsExpression(), + funcExpr, modifiers, Allocator(), false); method->SetRange(funcExpr->Range()); fieldMap_.insert({methodName->Name(), method}); @@ -1489,7 +1490,7 @@ ir::ScriptFunction *ETSParser::ParseFunction(ParserStatus newStatus, ir::Identif functionContext.AddFlag(throwMarker); auto *funcNode = AllocNode(std::move(signature), body, functionContext.Flags(), false, - GetContext().GetLanguge()); + GetContext().GetLanguage()); funcNode->SetRange({startLoc, endLoc}); return funcNode; @@ -1505,6 +1506,9 @@ ir::MethodDefinition *ETSParser::ParseClassMethod(ClassElementDescriptor *desc, } ir::ScriptFunction *func = ParseFunction(desc->newStatus); + if (propName->IsIdentifier()) { + func->SetIdent(propName->AsIdentifier()->Clone(Allocator(), nullptr)); + } auto *funcExpr = AllocNode(func); funcExpr->SetRange(func->Range()); @@ -1517,8 +1521,9 @@ ir::MethodDefinition *ETSParser::ParseClassMethod(ClassElementDescriptor *desc, *propEnd = func->End(); func->AddFlag(ir::ScriptFunctionFlags::METHOD); - auto *method = AllocNode(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(), - desc->isComputed); + auto *method = + AllocNode(desc->methodKind, propName->Clone(Allocator(), nullptr)->AsExpression(), + funcExpr, desc->modifiers, Allocator(), desc->isComputed); method->SetRange(funcExpr->Range()); return method; @@ -1745,7 +1750,6 @@ ir::MethodDefinition *ETSParser::ParseClassGetterSetterMethod(const ArenaVector< lexer::SourcePosition propEnd = methodName->End(); ir::MethodDefinition *method = ParseClassMethod(&desc, properties, methodName, &propEnd); - method->Function()->SetIdent(methodName); method->Function()->AddModifier(desc.modifiers); method->SetRange({desc.propStart, propEnd}); if (desc.methodKind == ir::MethodDefinitionKind::GET) { @@ -1772,7 +1776,7 @@ ir::MethodDefinition *ETSParser::ParseInterfaceGetterSetterMethod(const ir::Modi method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER); } - method->Function()->SetIdent(method->Id()); + method->Function()->SetIdent(method->Id()->Clone(Allocator(), nullptr)); method->Function()->AddModifier(method->Modifiers()); return method; @@ -1964,7 +1968,7 @@ ir::TSInterfaceDeclaration *ETSParser::ParseInterfaceBody(ir::Identifier *name, const auto isExternal = (GetContext().Status() & ParserStatus::IN_EXTERNAL); auto *interfaceDecl = AllocNode( - Allocator(), name, typeParamDecl, body, std::move(extends), isStatic, isExternal, GetContext().GetLanguge()); + Allocator(), name, typeParamDecl, body, std::move(extends), isStatic, isExternal, GetContext().GetLanguage()); Lexer()->NextToken(); GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE; @@ -2065,7 +2069,7 @@ ir::ClassDefinition *ETSParser::ParseClassDefinition(ir::ClassDefinitionModifier auto *classDefinition = AllocNode( util::StringView(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass, - std::move(properties), modifiers, flags, GetContext().GetLanguge()); + std::move(properties), modifiers, flags, GetContext().GetLanguage()); classDefinition->SetRange(bodyRange); @@ -2133,6 +2137,7 @@ ir::ClassProperty *ETSParser::ParseInterfaceField() typeAnnotation = ParseTypeAnnotation(&options); name->SetTsTypeAnnotation(typeAnnotation); + typeAnnotation->SetParent(name); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) { ThrowSyntaxError("Initializers are not allowed on interface propertys."); @@ -2144,7 +2149,8 @@ ir::ClassProperty *ETSParser::ParseInterfaceField() fieldModifiers |= ir::ModifierFlags::DECLARE; } - auto *field = AllocNode(name, nullptr, typeAnnotation, fieldModifiers, Allocator(), false); + auto *field = AllocNode(name, nullptr, typeAnnotation->Clone(Allocator(), nullptr), + fieldModifiers, Allocator(), false); field->SetEnd(Lexer()->GetToken().End()); return field; @@ -2181,8 +2187,9 @@ ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, i functionContext.AddFlag(throwMarker); - auto *func = AllocNode(std::move(signature), body, functionContext.Flags(), flags, true, - GetContext().GetLanguge()); + auto *func = AllocNode( + std::move(signature), body, + ir::ScriptFunction::ScriptFunctionData {functionContext.Flags(), flags, true, GetContext().GetLanguage()}); if ((flags & ir::ModifierFlags::STATIC) == 0 && body == nullptr) { func->AddModifier(ir::ModifierFlags::ABSTRACT); @@ -2196,8 +2203,9 @@ ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, i func->AddFlag(ir::ScriptFunctionFlags::METHOD); func->SetIdent(name); - auto *method = - AllocNode(ir::MethodDefinitionKind::METHOD, name, funcExpr, flags, Allocator(), false); + auto *method = AllocNode(ir::MethodDefinitionKind::METHOD, + name->Clone(Allocator(), nullptr)->AsExpression(), funcExpr, flags, + Allocator(), false); method->SetRange(funcExpr->Range()); ConsumeSemicolon(method); @@ -3718,7 +3726,10 @@ void ETSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpr Lexer()->NextToken(); // eat ':' TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - param->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); + if (auto *typeAnnotation = ParseTypeAnnotation(&options); typeAnnotation != nullptr) { + typeAnnotation->SetParent(param); + param->SetTsTypeAnnotation(typeAnnotation); + } } if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { @@ -4196,6 +4207,53 @@ ir::Expression *ETSParser::ParsePotentialAsExpression(ir::Expression *primaryExp return asExpression; } +// Extracted from 'ParseNewExpression()' to reduce function's size +ir::ClassDefinition *ETSParser::CreateClassDefinitionForNewExpression(ArenaVector &arguments, + ir::TypeNode *typeReference, + ir::TypeNode *baseTypeReference) +{ + lexer::SourcePosition endLoc = typeReference->End(); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { + if (baseTypeReference != nullptr) { + ThrowSyntaxError("Can not use 'new' on primitive types.", baseTypeReference->Start()); + } + + Lexer()->NextToken(); + + while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + ir::Expression *argument = ParseExpression(); + arguments.push_back(argument); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { + Lexer()->NextToken(); + continue; + } + } + + endLoc = Lexer()->GetToken().End(); + Lexer()->NextToken(); + } + + ir::ClassDefinition *classDefinition {}; + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + ArenaVector implements(Allocator()->Adapter()); + auto modifiers = ir::ClassDefinitionModifiers::ANONYMOUS | ir::ClassDefinitionModifiers::HAS_SUPER; + auto [ctor, properties, bodyRange] = ParseClassBody(modifiers); + + auto newIdent = AllocNode("#0", Allocator()); + classDefinition = AllocNode( + "#0", newIdent, nullptr, nullptr, std::move(implements), ctor, // remove name + typeReference->Clone(Allocator(), nullptr), std::move(properties), modifiers, ir::ModifierFlags::NONE, + Language(Language::Id::ETS)); + + classDefinition->SetRange(bodyRange); + } + + return classDefinition; +} + ir::Expression *ETSParser::ParseNewExpression() { lexer::SourcePosition start = Lexer()->GetToken().Start(); @@ -4242,43 +4300,8 @@ ir::Expression *ETSParser::ParseNewExpression() } ArenaVector arguments(Allocator()->Adapter()); - lexer::SourcePosition endLoc = typeReference->End(); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { - if (baseTypeReference != nullptr) { - ThrowSyntaxError("Can not use 'new' on primitive types.", baseTypeReference->Start()); - } - - Lexer()->NextToken(); - - while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - ir::Expression *argument = ParseExpression(); - arguments.push_back(argument); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { - Lexer()->NextToken(); - continue; - } - } - - endLoc = Lexer()->GetToken().End(); - Lexer()->NextToken(); - } - - ir::ClassDefinition *classDefinition {}; - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { - ArenaVector implements(Allocator()->Adapter()); - auto modifiers = ir::ClassDefinitionModifiers::ANONYMOUS | ir::ClassDefinitionModifiers::HAS_SUPER; - auto [ctor, properties, bodyRange] = ParseClassBody(modifiers); - - auto newIdent = AllocNode("#0", Allocator()); - classDefinition = AllocNode( - "#0", newIdent, nullptr, nullptr, std::move(implements), ctor, // remove name - typeReference, std::move(properties), modifiers, ir::ModifierFlags::NONE, Language(Language::Id::ETS)); - - classDefinition->SetRange(bodyRange); - } + ir::ClassDefinition *classDefinition = + CreateClassDefinitionForNewExpression(arguments, typeReference, baseTypeReference); auto *newExprNode = AllocNode(typeReference, std::move(arguments), classDefinition); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 4b4afef511..01e8b64204 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -266,6 +266,10 @@ private: ir::AstNode *ParseInnerRest(const ArenaVector &properties, ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags memberModifiers, ir::Identifier *identNode, const lexer::SourcePosition &startLoc); + + ir::ClassDefinition *CreateClassDefinitionForNewExpression(ArenaVector &arguments, + ir::TypeNode *typeReference, + ir::TypeNode *baseTypeReference); ir::Expression *ParseNewExpression() override; ir::Expression *ParseAsyncExpression(); ir::Expression *ParseAwaitExpression(); diff --git a/ets2panda/parser/TypedParser.cpp b/ets2panda/parser/TypedParser.cpp index a3018356f2..9851f05a72 100644 --- a/ets2panda/parser/TypedParser.cpp +++ b/ets2panda/parser/TypedParser.cpp @@ -462,7 +462,7 @@ ir::Statement *TypedParser::ParseInterfaceDeclaration(bool isStatic) const auto isExternal = (GetContext().Status() & ParserStatus::IN_EXTERNAL); auto *interfaceDecl = AllocNode( - Allocator(), id, typeParamDecl, body, std::move(extends), isStatic, isExternal, GetContext().GetLanguge()); + Allocator(), id, typeParamDecl, body, std::move(extends), isStatic, isExternal, GetContext().GetLanguage()); interfaceDecl->SetRange({interfaceStart, Lexer()->GetToken().End()}); Lexer()->NextToken(); @@ -880,7 +880,7 @@ ir::ClassDefinition *TypedParser::ParseClassDefinition(ir::ClassDefinitionModifi auto *classDefinition = AllocNode( privateBinding.View(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass, - std::move(properties), modifiers, flags, GetContext().GetLanguge()); + std::move(properties), modifiers, flags, GetContext().GetLanguage()); classDefinition->SetRange(bodyRange); diff --git a/ets2panda/parser/context/parserContext.h b/ets2panda/parser/context/parserContext.h index 926fc510f0..5a3c4ce511 100644 --- a/ets2panda/parser/context/parserContext.h +++ b/ets2panda/parser/context/parserContext.h @@ -98,7 +98,7 @@ public: program_ = program; } - Language GetLanguge() const + Language GetLanguage() const { return lang_; } diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 5eaa24e774..ab8912e19f 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -325,7 +325,7 @@ ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowF funcNode = AllocNode( ir::FunctionSignature(typeParamDecl, std::move(desc->params), returnTypeAnnotation), body, - arrowFunctionContext->Flags(), false, context_.GetLanguge()); + arrowFunctionContext->Flags(), false, context_.GetLanguage()); funcNode->SetRange({desc->startLoc, endLoc}); auto *arrowFuncNode = AllocNode(Allocator(), funcNode); diff --git a/ets2panda/parser/parserImpl.cpp b/ets2panda/parser/parserImpl.cpp index 5f4d6b623c..675bdf760b 100644 --- a/ets2panda/parser/parserImpl.cpp +++ b/ets2panda/parser/parserImpl.cpp @@ -466,7 +466,11 @@ ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc, *propEnd = func->End(); func->AddFlag(ir::ScriptFunctionFlags::METHOD); - auto *method = AllocNode(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(), + + auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression() + ? propName->Clone(Allocator(), nullptr)->AsExpression() + : propName; + auto *method = AllocNode(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(), desc->isComputed); method->SetRange(funcExpr->Range()); @@ -569,8 +573,9 @@ ir::ClassElement *ParserImpl::ParseClassStaticBlock() auto *body = AllocNode(Allocator(), std::move(statements)); auto *func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK, - ir::ModifierFlags::STATIC, false, context_.GetLanguge()); + ir::ScriptFunction::ScriptFunctionData { + ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK, + ir::ModifierFlags::STATIC, false, context_.GetLanguage()}); auto *funcExpr = AllocNode(func); auto *staticBlock = AllocNode(funcExpr, Allocator()); @@ -656,7 +661,7 @@ ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionMo auto *func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, ir::ScriptFunctionFlags::CONSTRUCTOR | ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED, - false, context_.GetLanguge()); + false, context_.GetLanguage()); auto *funcExpr = AllocNode(func); auto *key = AllocNode("constructor", Allocator()); @@ -665,7 +670,8 @@ ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionMo func->SetIdent(key); } - auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, + auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, + key->Clone(Allocator(), nullptr)->AsExpression(), funcExpr, ir::ModifierFlags::NONE, Allocator(), false); ctor->SetRange({startLoc, lexer_->GetToken().End()}); @@ -763,7 +769,7 @@ ir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifie ArenaVector implements(Allocator()->Adapter()); auto *classDefinition = AllocNode( privateBinding.View(), identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass, - std::move(properties), modifiers, flags, GetContext().GetLanguge()); + std::move(properties), modifiers, flags, GetContext().GetLanguage()); classDefinition->SetRange(bodyRange); @@ -912,7 +918,7 @@ ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus) functionContext.AddFlag(throw_marker); auto *funcNode = AllocNode(std::move(signature), body, functionContext.Flags(), - isDeclare && letDeclare, context_.GetLanguge()); + isDeclare && letDeclare, context_.GetLanguage()); funcNode->SetRange({startLoc, endLoc}); return funcNode; diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 4386ff754f..47c1e4c1ed 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -2023,8 +2023,8 @@ extern "C" es2panda_AstNode *CreateScriptFunction(es2panda_Context *context, es2 auto irModifierFlags = E2pToIrModifierFlags(modifierFlags); ir::FunctionSignature sig(irTypeParams, std::move(irParams), irReturnTypeAnnotation); - auto func = allocator->New(std::move(sig), nullptr, irFunctionFlags, irModifierFlags, isDeclare, - Language::FromString("ets").value()); + auto func = allocator->New( + std::move(sig), nullptr, ir::ScriptFunction::ScriptFunctionData {irFunctionFlags, irModifierFlags, isDeclare}); return reinterpret_cast(func); } 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 c12cc9299c..fa05377005 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -48,6 +48,10 @@ struct-init2.ets struct_implements.ets top_level_03.ets +# lowering 'expandBrackets' should be repaired #15594 +array-new.ets +array-new-catched.ets + # Union with undefined OptionalCall.ets diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index 803f9a2c5e..278ddb2e5c 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -12,6 +12,9 @@ parser/ets/import_tests/check_exported_default_struct.ets parser/ets/import_tests/modules/struct_default_module.ets parser/ets/import_tests/check_exported_struct.ets +# lowering 'expandBrackets' should be repaired #15594 +parser/ets/array_new.ets + # Throwing function types are not yet supported parser/ets/lambdaThrowsRethrows.ets parser/ets/variable_throw_function_1.ets diff --git a/ets2panda/test/unit/node_creator.h b/ets2panda/test/unit/node_creator.h index f345b56f28..4a054bcb10 100644 --- a/ets2panda/test/unit/node_creator.h +++ b/ets2panda/test/unit/node_creator.h @@ -65,7 +65,9 @@ public: auto varDecl = CreateVarDecl(true, name); ArenaVector tmp {alloc_->Adapter()}; tmp.emplace_back(varDecl); - return alloc_->New(alloc_, std::move(tmp)); + auto *newBlock = alloc_->New(alloc_, std::move(tmp)); + varDecl->SetParent(newBlock); + return newBlock; } ir::ForUpdateStatement *CreateForUpdate() @@ -82,4 +84,4 @@ public: private: ArenaAllocator *const alloc_; }; -} // namespace panda::es2panda::gtests \ No newline at end of file +} // namespace panda::es2panda::gtests diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 7961ee7c14..4f5e5c1db2 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -190,7 +190,7 @@ bool Options::Parse(int argc, const char **argv) "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll," "ImportExportAccessValid"); panda::PandArg verifierErrors( - "verifier-errors", "ForLoopCorrectlyInitializedForAll", + "verifier-errors", "ForLoopCorrectlyInitializedForAll,NodeHasParentForAll,EveryChildHasValidParentForAll", "Print errors and stop compilation if AST tree is incorrect. " "Possible values: " "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll," diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 1e6c232d01..cb13eb13ff 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -275,9 +275,9 @@ void ETSBinder::BuildMethodDefinition(ir::MethodDefinition *methodDef) void ETSBinder::ResolveMethodDefinition(ir::MethodDefinition *methodDef) { - auto *func = methodDef->Function(); - ResolveReferences(methodDef); + methodDef->ResolveReferences([this](auto *childNode) { ResolveReference(childNode); }); + auto *func = methodDef->Function(); if (methodDef->IsStatic() || func->IsStaticBlock()) { return; } -- Gitee From b3fa8538b162ba016a6f7adc6bfcb09530797c36 Mon Sep 17 00:00:00 2001 From: Zelentsov Dmitry Date: Tue, 6 Feb 2024 12:43:51 +0300 Subject: [PATCH 3/3] Modify 'ExpandBrackets` lowering to produce valid AST structure. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I91D6U?from=project-issue Tests: U-Runner, CI and AST-verifier Signed-off-by: Zelentsov Dmitry --- ets2panda/checker/ETSAnalyzer.cpp | 19 +- ets2panda/checker/ets/object.cpp | 2 +- ets2panda/compiler/core/ETSCompiler.cpp | 20 +- ets2panda/compiler/core/ETSGen.h | 6 +- .../compiler/lowering/ets/expandBrackets.cpp | 179 ++++++++++++++---- .../compiler/lowering/ets/expandBrackets.h | 13 +- ets2panda/compiler/lowering/util.cpp | 11 +- .../ir/ets/etsNewArrayInstanceExpression.cpp | 5 +- .../ir/ets/etsNewArrayInstanceExpression.h | 35 ++-- .../etsNewMultiDimArrayInstanceExpression.h | 16 +- ets2panda/ir/expressions/blockExpression.h | 20 ++ ets2panda/parser/ETSparser.cpp | 2 +- ets2panda/public/es2panda_lib.cpp | 3 +- .../parser/ets/array_new_failed-expected.txt | 2 +- .../runtime/ets/multi-array-new-catched-1.ets | 28 +++ .../runtime/ets/multi-array-new-catched-2.ets | 32 ++++ .../test/runtime/ets/multi-array-new.ets | 25 +++ .../ets-runtime/ets-runtime-ignored.txt | 4 - .../test-lists/parser/parser-ets-ignored.txt | 3 - 19 files changed, 321 insertions(+), 104 deletions(-) create mode 100644 ets2panda/test/runtime/ets/multi-array-new-catched-1.ets create mode 100644 ets2panda/test/runtime/ets/multi-array-new-catched-2.ets create mode 100644 ets2panda/test/runtime/ets/multi-array-new.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index bbddda80b3..575ac4b87c 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -500,8 +500,8 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { ETSChecker *checker = GetETSChecker(); - auto *elementType = expr->typeReference_->GetType(checker); - checker->ValidateArrayIndex(expr->dimension_, true); + auto *elementType = expr->TypeReference()->GetType(checker); + checker->ValidateArrayIndex(expr->Dimension(), true); if (!elementType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) && !elementType->IsNullish() && elementType->ToAssemblerName().str() != "Ball") { @@ -510,10 +510,9 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const auto *calleeObj = elementType->AsETSObjectType(); if (!calleeObj->HasObjectFlag(checker::ETSObjectFlags::ABSTRACT)) { // A workaround check for new Interface[...] in test cases - expr->defaultConstructorSignature_ = - checker->CollectParameterlessConstructor(calleeObj->ConstructSignatures(), expr->Start()); - checker->ValidateSignatureAccessibility(calleeObj, nullptr, expr->defaultConstructorSignature_, - expr->Start()); + expr->SetSignature( + checker->CollectParameterlessConstructor(calleeObj->ConstructSignatures(), expr->Start())); + checker->ValidateSignatureAccessibility(calleeObj, nullptr, expr->Signature(), expr->Start()); } } } @@ -589,15 +588,15 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { ETSChecker *checker = GetETSChecker(); - auto *elementType = expr->typeReference_->GetType(checker); + auto *elementType = expr->TypeReference()->GetType(checker); - for (auto *dim : expr->dimensions_) { - checker->ValidateArrayIndex(dim); + for (auto *dim : expr->Dimensions()) { + checker->ValidateArrayIndex(dim, true); elementType = checker->CreateETSArrayType(elementType); } expr->SetTsType(elementType); - expr->signature_ = checker->CreateBuiltinArraySignature(elementType->AsETSArrayType(), expr->dimensions_.size()); + expr->SetSignature(checker->CreateBuiltinArraySignature(elementType->AsETSArrayType(), expr->Dimensions().size())); return expr->TsType(); } diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 2dda693b09..33675378ce 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -1030,7 +1030,7 @@ void ETSChecker::ValidateArrayIndex(ir::Expression *const expr, bool relaxed) double value = num.GetDouble(); double intpart; if (std::modf(value, &intpart) != 0.0) { - ThrowTypeError("Index fracional part should not be different from 0.0", expr->Start()); + ThrowTypeError("Index fractional part should be zero.", expr->Start()); } return; } diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index bd6143b251..f786bafc9b 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -16,14 +16,12 @@ #include "ETSCompiler.h" #include "compiler/base/catchTable.h" -#include "checker/types/ets/etsDynamicFunctionType.h" -#include "checker/types/ets/etsObjectType.h" -#include "checker/types/ts/enumLiteralType.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/ETSGen.h" #include "compiler/core/switchBuilder.h" #include "compiler/function/functionBuilder.h" +#include "checker/types/ets/etsDynamicFunctionType.h" namespace panda::es2panda::compiler { @@ -217,14 +215,14 @@ void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const compiler::RegScope rs(etsg); compiler::TargetTypeContext ttctx(etsg, etsg->Checker()->GlobalIntType()); - expr->dimension_->Compile(etsg); + expr->Dimension()->Compile(etsg); compiler::VReg arr = etsg->AllocReg(); compiler::VReg dim = etsg->AllocReg(); - etsg->ApplyConversionAndStoreAccumulator(expr, dim, expr->dimension_->TsType()); + etsg->ApplyConversionAndStoreAccumulator(expr, dim, expr->Dimension()->TsType()); etsg->NewArray(expr, arr, dim, expr->TsType()); - if (expr->defaultConstructorSignature_ != nullptr) { + if (expr->Signature() != nullptr) { compiler::VReg countReg = etsg->AllocReg(); auto *startLabel = etsg->AllocLabel(); auto *endLabel = etsg->AllocLabel(); @@ -237,10 +235,10 @@ void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const etsg->LoadAccumulator(expr, countReg); etsg->StoreAccumulator(expr, indexReg); - const compiler::TargetTypeContext ttctx2(etsg, expr->typeReference_->TsType()); - ArenaVector arguments(expr->allocator_->Adapter()); - etsg->InitObject(expr, expr->defaultConstructorSignature_, arguments); - etsg->StoreArrayElement(expr, arr, indexReg, expr->typeReference_->TsType()); + const compiler::TargetTypeContext ttctx2(etsg, expr->TypeReference()->TsType()); + ArenaVector arguments(GetCodeGen()->Allocator()->Adapter()); + etsg->InitObject(expr, expr->Signature(), arguments); + etsg->StoreArrayElement(expr, arr, indexReg, expr->TypeReference()->TsType()); etsg->IncrementImmediateRegister(expr, countReg, checker::TypeFlag::INT, static_cast(1)); etsg->JumpTo(expr, startLabel); @@ -335,7 +333,7 @@ void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const void ETSCompiler::Compile(const ir::ETSNewMultiDimArrayInstanceExpression *expr) const { ETSGen *etsg = GetETSGen(); - etsg->InitObject(expr, expr->signature_, expr->dimensions_); + etsg->InitObject(expr, expr->Signature(), expr->Dimensions()); etsg->SetAccumulatorType(expr->TsType()); } diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index eddd5851d0..cf83270296 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -554,7 +554,7 @@ public: void CallBigIntBinaryOperator(const ir::Expression *node, VReg lhs, VReg rhs, util::StringView signature); void CallBigIntBinaryComparison(const ir::Expression *node, VReg lhs, VReg rhs, util::StringView signature); void BuildTemplateString(const ir::TemplateLiteral *node); - void InitObject(const ir::AstNode *node, checker::Signature *signature, + void InitObject(const ir::AstNode *node, checker::Signature const *signature, const ArenaVector &arguments) { CallImpl(node, signature, arguments); @@ -976,7 +976,7 @@ private: } template - bool ResolveStringFromNullishBuiltin(const ir::AstNode *node, checker::Signature *signature, + bool ResolveStringFromNullishBuiltin(const ir::AstNode *node, checker::Signature const *signature, const ArenaVector &arguments) { if (signature->InternalName() != Signatures::BUILTIN_STRING_FROM_NULLISH_CTOR) { @@ -1027,7 +1027,7 @@ private: } template - void CallImpl(const ir::AstNode *node, checker::Signature *signature, + void CallImpl(const ir::AstNode *node, checker::Signature const *signature, const ArenaVector &arguments) { RegScope rs(this); diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp index f5915b3187..d8640ce673 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.cpp +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -18,57 +18,164 @@ #include "checker/ETSchecker.h" #include "compiler/lowering/util.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" -#include "ir/statements/blockStatement.h" -#include "ir/expressions/memberExpression.h" #include "parser/ETSparser.h" #include "varbinder/ETSBinder.h" +#include "varbinder/scope.h" namespace panda::es2panda::compiler { -bool ExpandBracketsPhase::Perform(public_lib::Context *ctx, parser::Program *program) +// NOLINTBEGIN(modernize-avoid-c-arrays) +static constexpr char const FORMAT_NEW_MULTI_DIM_ARRAY_EXPRESSION[] = + "let @@I1: @@T2 = (@@E3);" + "if (!isSafeInteger(@@I4)) {" + " throw new TypeError(\"Fractional part of index expression should be zero.\");" + "};"; +static constexpr char const FORMAT_NEW_ARRAY_EXPRESSION[] = + "let @@I1: @@T2 = (@@E3);" + "if (!isSafeInteger(@@I4)) {" + " throw new TypeError(\"Fractional part of index expression should be zero.\");" + "};" + "(@@E5);"; +static constexpr char const CAST_NEW_DIMENSION_EXPRESSION[] = "@@I1 as int"; +static constexpr char const CAST_OLD_DIMENSION_EXPRESSION[] = "(@@E1) as int"; +// NOLINTEND(modernize-avoid-c-arrays) + +ir::Expression *ExpandBracketsPhase::ProcessNewArrayInstanceExpression( + parser::ETSParser *parser, checker::ETSChecker *checker, + ir::ETSNewArrayInstanceExpression *newInstanceExpression) const { - auto *const checker = ctx->checker->AsETSChecker(); - auto *const allocator = checker->Allocator(); - auto *const parser = ctx->parser->AsETSParser(); + auto *dimension = newInstanceExpression->Dimension(); + auto *dimType = dimension->TsType(); + if (auto *unboxed = checker->ETSBuiltinTypeAsPrimitiveType(dimType); unboxed != nullptr) { + dimType = unboxed; + } + if (!dimType->HasTypeFlag(checker::TypeFlag::ETS_FLOATING_POINT)) { + return newInstanceExpression; + } - program->Ast()->TransformChildrenRecursively([ctx, parser, checker, allocator](ir::AstNode *ast) -> ir::AstNode * { - if (!ast->IsETSNewArrayInstanceExpression()) { - return ast; - } - auto *newExpression = ast->AsETSNewArrayInstanceExpression(); - auto *dimension = newExpression->Dimension(); + auto *scope = NearestScope(newInstanceExpression); + if (scope == nullptr) { + scope = checker->VarBinder()->VarScope() != nullptr ? checker->VarBinder()->VarScope() + : checker->VarBinder()->TopScope(); + } + auto expressionCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); + + auto *ident = Gensym(checker->Allocator()); + auto *exprType = checker->AllocNode(dimType); + auto *const newInstanceParent = newInstanceExpression->Parent(); + + auto *blockExpression = parser->CreateFormattedExpression( + FORMAT_NEW_ARRAY_EXPRESSION, parser::DEFAULT_SOURCE_FILE, ident, exprType, dimension, + ident->Clone(checker->Allocator(), nullptr), newInstanceExpression); + blockExpression->SetParent(newInstanceParent); + + auto *castedDimension = parser->CreateFormattedExpression( + CAST_NEW_DIMENSION_EXPRESSION, parser::DEFAULT_SOURCE_FILE, ident->Clone(checker->Allocator(), nullptr)); + newInstanceExpression->SetDimension(castedDimension); + + newInstanceExpression->SetTsType(nullptr); + InitScopesPhaseETS::RunExternalNode(blockExpression, checker->VarBinder()); + checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(blockExpression, scope); + blockExpression->Check(checker); + + return blockExpression; +} + +ir::Expression *ExpandBracketsPhase::ProcessNewMultiDimArrayInstanceExpression( + parser::ETSParser *parser, checker::ETSChecker *checker, + ir::ETSNewMultiDimArrayInstanceExpression *newInstanceExpression) const +{ + ir::BlockExpression *returnExpression = nullptr; + + auto *scope = NearestScope(newInstanceExpression); + if (scope == nullptr) { + scope = checker->VarBinder()->VarScope() != nullptr ? checker->VarBinder()->VarScope() + : checker->VarBinder()->TopScope(); + } + auto expressionCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); + + for (std::size_t i = 0U; i < newInstanceExpression->Dimensions().size(); ++i) { + auto *dimension = newInstanceExpression->Dimensions()[i]; auto *dimType = dimension->TsType(); if (auto *unboxed = checker->ETSBuiltinTypeAsPrimitiveType(dimType); unboxed != nullptr) { dimType = unboxed; } if (!dimType->HasTypeFlag(checker::TypeFlag::ETS_FLOATING_POINT)) { - return ast; + continue; + } + + if (dimension->IsNumberLiteral()) { + auto *castedDimension = parser->CreateFormattedExpression(CAST_OLD_DIMENSION_EXPRESSION, + parser::DEFAULT_SOURCE_FILE, dimension); + castedDimension->SetParent(newInstanceExpression); + newInstanceExpression->Dimensions()[i] = castedDimension; + } else { + auto *ident = Gensym(checker->Allocator()); + auto *exprType = checker->AllocNode(dimType); + + auto *blockExpression = + parser + ->CreateFormattedExpression(FORMAT_NEW_MULTI_DIM_ARRAY_EXPRESSION, parser::DEFAULT_SOURCE_FILE, + ident, exprType, dimension, ident->Clone(checker->Allocator(), nullptr)) + ->AsBlockExpression(); + + if (returnExpression == nullptr) { + returnExpression = blockExpression; + } else { + returnExpression->AddStatements(blockExpression->Statements()); + } + + auto *castedDimension = + parser->CreateFormattedExpression(CAST_NEW_DIMENSION_EXPRESSION, parser::DEFAULT_SOURCE_FILE, + ident->Clone(checker->Allocator(), nullptr)); + castedDimension->SetParent(newInstanceExpression); + newInstanceExpression->Dimensions()[i] = castedDimension; } + } + + if (returnExpression != nullptr) { + return CreateNewMultiDimArrayInstanceExpression(checker, newInstanceExpression, returnExpression, scope); + } + + return newInstanceExpression; +} + +// NOTE: Just to reduce the size of 'ProcessNewMultiDimArrayInstanceExpression' method +ir::Expression *ExpandBracketsPhase::CreateNewMultiDimArrayInstanceExpression( + checker::ETSChecker *checker, ir::ETSNewMultiDimArrayInstanceExpression *newInstanceExpression, + ir::BlockExpression *blockExpression, varbinder::Scope *scope) const +{ + blockExpression->SetParent(newInstanceExpression->Parent()); + newInstanceExpression->SetTsType(nullptr); + blockExpression->AddStatement(checker->AllocNode(newInstanceExpression)); + + InitScopesPhaseETS::RunExternalNode(blockExpression, checker->VarBinder()); + checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(blockExpression, scope); + blockExpression->Check(checker); - auto *castedDimension = - parser->CreateFormattedExpression("@@E1 as int", parser::DEFAULT_SOURCE_FILE, dimension); - castedDimension->Check(checker); - castedDimension->SetParent(dimension->Parent()); - newExpression->SetDimension(castedDimension); - - auto *const scope = NearestScope(newExpression); - auto expressionCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); - auto *ident = Gensym(allocator); - auto *exprType = checker->AllocNode(dimType); - auto *sequenceExpr = parser->CreateFormattedExpression( - "let @@I1 = (@@E2) as @@T3;" - "if (!isSafeInteger(@@I4)) {" - " throw new TypeError(\"Index fractional part should not be different from 0.0\");" - "};" - "(@@E5);", - parser::DEFAULT_SOURCE_FILE, ident, dimension, exprType, ident->Clone(allocator, nullptr), newExpression); - sequenceExpr->SetParent(newExpression->Parent()); - InitScopesPhaseETS::RunExternalNode(sequenceExpr, ctx->compilerContext->VarBinder()); - checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(sequenceExpr, scope); - sequenceExpr->Check(checker); - - return sequenceExpr; + return blockExpression; +} + +bool ExpandBracketsPhase::Perform(public_lib::Context *ctx, parser::Program *program) +{ + auto *const parser = ctx->parser->AsETSParser(); + ASSERT(parser != nullptr); + auto *const checker = ctx->checker->AsETSChecker(); + ASSERT(checker != nullptr); + + program->Ast()->TransformChildrenRecursively([this, parser, checker](ir::AstNode *const ast) -> ir::AstNode * { + if (ast->IsETSNewArrayInstanceExpression()) { + return ProcessNewArrayInstanceExpression(parser, checker, ast->AsETSNewArrayInstanceExpression()); + } + + if (ast->IsETSNewMultiDimArrayInstanceExpression()) { + return ProcessNewMultiDimArrayInstanceExpression(parser, checker, + ast->AsETSNewMultiDimArrayInstanceExpression()); + } + + return ast; }); + return true; } diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.h b/ets2panda/compiler/lowering/ets/expandBrackets.h index 406d7f2832..6b47d2eb6f 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.h +++ b/ets2panda/compiler/lowering/ets/expandBrackets.h @@ -28,8 +28,19 @@ public: } bool Perform(public_lib::Context *ctx, parser::Program *program) override; -}; +private: + ir::Expression *ProcessNewArrayInstanceExpression(parser::ETSParser *parser, checker::ETSChecker *checker, + ir::ETSNewArrayInstanceExpression *newInstanceExpression) const; + + ir::Expression *ProcessNewMultiDimArrayInstanceExpression( + parser::ETSParser *parser, checker::ETSChecker *checker, + ir::ETSNewMultiDimArrayInstanceExpression *newInstanceExpression) const; + + ir::Expression *CreateNewMultiDimArrayInstanceExpression( + checker::ETSChecker *checker, ir::ETSNewMultiDimArrayInstanceExpression *newInstanceExpression, + ir::BlockExpression *blockExpression, varbinder::Scope *scope) const; +}; } // namespace panda::es2panda::compiler #endif diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index cab0d07614..a558ce5136 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -13,8 +13,6 @@ * limitations under the License. */ -#include - #include "util.h" #include "ir/expressions/identifier.h" @@ -23,16 +21,11 @@ namespace panda::es2panda::compiler { varbinder::Scope *NearestScope(const ir::AstNode *ast) { - if (ast == nullptr) { - return nullptr; - } - - while (!ast->IsScopeBearer()) { + while (ast != nullptr && !ast->IsScopeBearer()) { ast = ast->Parent(); - ASSERT(ast != nullptr); } - return ast->Scope(); + return ast == nullptr ? nullptr : ast->Scope(); } ir::Identifier *Gensym(ArenaAllocator *const allocator) diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp index a5687be6b4..4f3f013c77 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -78,8 +78,7 @@ ETSNewArrayInstanceExpression *ETSNewArrayInstanceExpression::Clone(ArenaAllocat auto *const typeRef = typeReference_ != nullptr ? typeReference_->Clone(allocator, nullptr) : nullptr; auto *const dimension = dimension_ != nullptr ? dimension_->Clone(allocator, nullptr)->AsExpression() : nullptr; - if (auto *const clone = allocator->New(allocator, typeRef, dimension); - clone != nullptr) { + if (auto *const clone = allocator->New(typeRef, dimension); clone != nullptr) { if (typeRef != nullptr) { typeRef->SetParent(clone); } @@ -92,7 +91,9 @@ ETSNewArrayInstanceExpression *ETSNewArrayInstanceExpression::Clone(ArenaAllocat clone->SetParent(parent); } + clone->defaultConstructorSignature_ = defaultConstructorSignature_; clone->SetRange(Range()); + return clone; } diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index 5e3dcaee5a..bf744f17b4 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -37,39 +37,44 @@ public: NO_COPY_SEMANTIC(ETSNewArrayInstanceExpression); NO_MOVE_SEMANTIC(ETSNewArrayInstanceExpression); - explicit ETSNewArrayInstanceExpression(ArenaAllocator *allocator, ir::TypeNode *const typeReference, - ir::Expression *const dimension) + explicit ETSNewArrayInstanceExpression(ir::TypeNode *const typeReference, ir::Expression *const dimension) : Expression(AstNodeType::ETS_NEW_ARRAY_INSTANCE_EXPRESSION), typeReference_(typeReference), - dimension_(dimension), - allocator_(allocator) + dimension_(dimension) { } - // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields - friend class checker::ETSAnalyzer; - friend class compiler::ETSCompiler; - ir::TypeNode *TypeReference() + [[nodiscard]] ir::TypeNode *TypeReference() noexcept { return typeReference_; } - ir::TypeNode const *TypeReference() const + [[nodiscard]] ir::TypeNode const *TypeReference() const noexcept { return typeReference_; } - ir::Expression *Dimension() + [[nodiscard]] ir::Expression *Dimension() noexcept { return dimension_; } - ir::Expression const *Dimension() const + [[nodiscard]] ir::Expression const *Dimension() const noexcept { return dimension_; } - void SetDimension(ir::Expression *dimension) + [[nodiscard]] checker::Signature *Signature() const noexcept + { + return defaultConstructorSignature_; + } + + [[nodiscard]] checker::Signature *Signature() noexcept + { + return defaultConstructorSignature_; + } + + void SetDimension(ir::Expression *dimension) noexcept { dimension_ = dimension; if (dimension_ != nullptr) { @@ -77,6 +82,11 @@ public: } } + void SetSignature(checker::Signature *signature) noexcept + { + defaultConstructorSignature_ = signature; + } + [[nodiscard]] ETSNewArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; @@ -97,7 +107,6 @@ private: ir::TypeNode *typeReference_; ir::Expression *dimension_; checker::Signature *defaultConstructorSignature_ {}; - ArenaAllocator *allocator_; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 993a655807..2f284625dc 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -44,29 +44,26 @@ public: dimensions_(std::move(dimensions)) { } - // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields - friend class checker::ETSAnalyzer; - friend class compiler::ETSCompiler; explicit ETSNewMultiDimArrayInstanceExpression(ETSNewMultiDimArrayInstanceExpression const &other, ArenaAllocator *allocator); - ir::TypeNode *TypeReference() + [[nodiscard]] ir::TypeNode *TypeReference() noexcept { return typeReference_; } - ir::TypeNode const *TypeReference() const + [[nodiscard]] ir::TypeNode const *TypeReference() const noexcept { return typeReference_; } - ArenaVector &Dimensions() + [[nodiscard]] ArenaVector &Dimensions() noexcept { return dimensions_; } - ArenaVector const &Dimension() const + [[nodiscard]] ArenaVector const &Dimensions() const noexcept { return dimensions_; } @@ -81,6 +78,11 @@ public: return signature_; } + void SetSignature(checker::Signature *signature) noexcept + { + signature_ = signature; + } + [[nodiscard]] ETSNewMultiDimArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; diff --git a/ets2panda/ir/expressions/blockExpression.h b/ets2panda/ir/expressions/blockExpression.h index 0180304f97..1fd672f964 100644 --- a/ets2panda/ir/expressions/blockExpression.h +++ b/ets2panda/ir/expressions/blockExpression.h @@ -41,6 +41,26 @@ public: return statements_; } + void AddStatements(ArenaVector const &statements) + { + std::copy_if(statements.begin(), statements.end(), std::back_inserter(statements_), + [this](ir::Statement *statement) { + if (statement != nullptr) { + statement->SetParent(this); + return true; + }; + return false; + }); + } + + void AddStatement(ir::Statement *statement) + { + if (statement != nullptr) { + statement->SetParent(this); + statements_.emplace_back(statement); + } + } + [[nodiscard]] BlockExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index ee9438be7f..92e289060e 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -4278,7 +4278,7 @@ ir::Expression *ETSParser::ParseNewExpression() ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET); if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { - auto *arrInstance = AllocNode(Allocator(), typeReference, dimension); + auto *arrInstance = AllocNode(typeReference, dimension); arrInstance->SetRange({start, endLoc}); return arrInstance; } diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 47c1e4c1ed..a5ab58c8a1 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -1833,8 +1833,7 @@ extern "C" es2panda_AstNode *CreateNewArrayInstanceExpression(es2panda_Context * auto *irTyperef = reinterpret_cast(typeReference)->AsExpression()->AsTypeNode(); auto *irDim = reinterpret_cast(dimension)->AsExpression(); - return reinterpret_cast( - allocator->New(allocator, irTyperef, irDim)); + return reinterpret_cast(allocator->New(irTyperef, irDim)); } extern "C" es2panda_AstNode *NewArrayInstanceExpressionTypeReference(es2panda_AstNode *ast) diff --git a/ets2panda/test/parser/ets/array_new_failed-expected.txt b/ets2panda/test/parser/ets/array_new_failed-expected.txt index 7a1d50898a..9d3ca1198d 100644 --- a/ets2panda/test/parser/ets/array_new_failed-expected.txt +++ b/ets2panda/test/parser/ets/array_new_failed-expected.txt @@ -371,4 +371,4 @@ } } } -TypeError: Index fracional part should not be different from 0.0 [array_new_failed.ets:17:19] +TypeError: Index fractional part should be zero. [array_new_failed.ets:17:19] diff --git a/ets2panda/test/runtime/ets/multi-array-new-catched-1.ets b/ets2panda/test/runtime/ets/multi-array-new-catched-1.ets new file mode 100644 index 0000000000..5a129195b9 --- /dev/null +++ b/ets2panda/test/runtime/ets/multi-array-new-catched-1.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main(): void { + let A: Array = new Array(); + let a: Number[][][]; + + let catched = false; + try { + a = new Number[A.length + 2.][4][A.length + 3.00001]; + } catch (e: TypeError) { + catched = true; + } + + assert catched +} diff --git a/ets2panda/test/runtime/ets/multi-array-new-catched-2.ets b/ets2panda/test/runtime/ets/multi-array-new-catched-2.ets new file mode 100644 index 0000000000..eefeb31395 --- /dev/null +++ b/ets2panda/test/runtime/ets/multi-array-new-catched-2.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 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 baz(): number { + return 5.1 +} + +function main(): void { + let A: Array = new Array(); + let a: Number[][][]; + + let catched = false; + try { + a = new Number[baz()][4][A.length + 3.0000]; + } catch (e: TypeError) { + catched = true; + } + + assert catched +} diff --git a/ets2panda/test/runtime/ets/multi-array-new.ets b/ets2panda/test/runtime/ets/multi-array-new.ets new file mode 100644 index 0000000000..fe46e6e25d --- /dev/null +++ b/ets2panda/test/runtime/ets/multi-array-new.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main(): void { + let A: Array = new Array(); + let a: Number[][][]; + + a = new Number[A.length + 2.][4.00][A.length + 3.0000]; + + assert a.length == 2 + assert a[1].length == 4 + assert a[0][3].length == 3 +} 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 fa05377005..c12cc9299c 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -48,10 +48,6 @@ struct-init2.ets struct_implements.ets top_level_03.ets -# lowering 'expandBrackets' should be repaired #15594 -array-new.ets -array-new-catched.ets - # Union with undefined OptionalCall.ets diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index 278ddb2e5c..803f9a2c5e 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -12,9 +12,6 @@ parser/ets/import_tests/check_exported_default_struct.ets parser/ets/import_tests/modules/struct_default_module.ets parser/ets/import_tests/check_exported_struct.ets -# lowering 'expandBrackets' should be repaired #15594 -parser/ets/array_new.ets - # Throwing function types are not yet supported parser/ets/lambdaThrowsRethrows.ets parser/ets/variable_throw_function_1.ets -- Gitee