diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 810934b8e53e9efea986fc479d2259ee75030a99..575ac4b87c9e17684944a0f7f6d3a46485b4241a 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))) { @@ -411,57 +416,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()); + auto *genericInterfaceType = checker->GlobalBuiltinFunctionType(node->Params().size()); + node->SetFunctionalInterface(genericInterfaceType->GetDeclNode()->AsTSInterfaceDeclaration()); - 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(); + auto *tsType = checker->GetCachedFunctionlInterface(node); + node->SetTsType(tsType); + if (tsType != nullptr) { + return tsType; + } - ASSERT(param->TypeAnnotation()); - signatureInfo->restVar->SetTsType(checker->GetTypeFromTypeAnnotation(param->TypeAnnotation())); + auto *substitution = checker->NewSubstitution(); - auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType(); - checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); - } else { - auto *paramIdent = param->Ident(); + auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); - ASSERT(paramIdent->Variable()); - varbinder::Variable *paramVar = paramIdent->Variable(); + 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; @@ -502,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") { @@ -512,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()); } } } @@ -564,7 +561,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()); @@ -591,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(); } @@ -923,10 +920,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); @@ -1016,7 +1022,7 @@ ArenaVector &ChooseSignatures(ETSChecker *checker, checker } if (isFunctionalInterface) { return calleeType->AsETSObjectType() - ->GetOwnProperty("invoke") + ->GetOwnProperty(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME) ->TsType() ->AsETSFunctionType() ->CallSignatures(); @@ -1087,7 +1093,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.cpp b/ets2panda/checker/ETSchecker.cpp index 834464fcb7aeca39c4c8fd21343bc27fcfbbeafd..e111deca283261984ec8a3535eb1ddf976042dc0 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 e909286f9379778b42a2def9136e029356ee7fb0..9ce82608899595f5101c8b014123f93eb1208a53 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; @@ -63,6 +52,7 @@ using ArrayMap = ArenaUnorderedMap; using GlobalArraySignatureMap = ArenaUnorderedMap; using DynamicCallIntrinsicsMap = ArenaUnorderedMap>; using DynamicLambdaObjectSignatureMap = ArenaUnorderedMap; +using FunctionalInterfaceMap = ArenaUnorderedMap; class ETSChecker final : public Checker { public: @@ -75,7 +65,8 @@ public: cachedComputedAbstracts_(Allocator()->Adapter()), dynamicCallIntrinsics_(Allocator()->Adapter()), dynamicNewIntrinsics_(Allocator()->Adapter()), - dynamicLambdaSignatureCache_(Allocator()->Adapter()) + dynamicLambdaSignatureCache_(Allocator()->Adapter()), + functionalInterfaceCache_(Allocator()->Adapter()) { } @@ -118,6 +109,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 +134,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,27 +391,28 @@ 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 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, 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,9 +534,10 @@ 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, + void AddUndefinedParamsForDefaultParams(const Signature *signature, ir::AstNode *parent, ArenaVector &arguments, ETSChecker *checker); void SetArrayPreferredTypeForNestedMemberExpressions(ir::MemberExpression *expr, Type *annotationType); @@ -549,9 +547,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); @@ -576,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 @@ -610,6 +609,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 *, @@ -635,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); @@ -643,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, @@ -663,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) @@ -688,7 +696,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 +722,7 @@ private: DynamicCallIntrinsicsMap dynamicCallIntrinsics_; DynamicCallIntrinsicsMap dynamicNewIntrinsics_; DynamicLambdaObjectSignatureMap dynamicLambdaSignatureCache_; + FunctionalInterfaceMap functionalInterfaceCache_; std::recursive_mutex mtx_; }; diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index c0037fea918477ea3dbf1bd09d75bdbb005f7310..cb5a6a6225b3fd1187218ed79d4d700b9ed3445e 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 f9a116f3f27bc4e043e692519b5df6cf72ed1623..5ab505aba65a1c719b16f5828b8c4ceab722153a 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 e6476c47e5aa9b87ce662392da988ef5231198fc..ecb64e33082fc109d444c05cef5cdbf88062cbd5 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,20 +1478,22 @@ 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 *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); @@ -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); @@ -1560,17 +1515,9 @@ 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()) { - 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); @@ -1654,19 +1631,107 @@ 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, proxyMethod, isStatic); 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); + } +} + +/* 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(); @@ -1675,13 +1740,13 @@ 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); } 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()); @@ -1690,55 +1755,39 @@ 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()); // 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); + 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); } - return Allocator()->New(resolvedCall); + + if (ifaceOverride && resolvedCall->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + resolvedCall->AddBoxingUnboxingFlags(GetBoxingFlag(resolvedCall->TsType())); + } + + return AllocNode(resolvedCall); } 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(); @@ -1781,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) { @@ -1811,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) @@ -1868,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()) { @@ -1901,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(); @@ -1973,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( @@ -2026,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()); @@ -2046,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(); @@ -2135,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); @@ -2148,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; } @@ -2171,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()); @@ -2190,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 @@ -2210,10 +2274,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 +2296,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 +2314,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) @@ -2291,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); @@ -2304,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; } @@ -2327,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)_; @@ -2340,22 +2408,21 @@ 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 *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); @@ -2363,14 +2430,14 @@ ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto() 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; } @@ -2379,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); } @@ -2426,13 +2495,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 +2560,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 = 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()); + 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); @@ -2533,16 +2632,92 @@ 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); - + 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); + } +} + +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) +ir::Statement *ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, Signature *signatureRef, + bool ifaceOverride) { const auto &lambdaBody = lambdaObject->Body(); bool isStaticReference = signatureRef->HasSignatureFlag(SignatureFlags::STATIC); @@ -2551,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); @@ -2560,39 +2735,38 @@ 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()); // 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); + 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) @@ -2660,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(); @@ -2684,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; } @@ -2733,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; } @@ -2782,6 +2950,10 @@ varbinder::FunctionParamScope *ETSChecker::CopyParams(const ArenaVectorIterate([this, oldNode, newScope](ir::AstNode *child) { auto *scope = NodeScope(child); if (scope != nullptr) { @@ -2842,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); @@ -2868,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); @@ -2893,4 +3066,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 2fa371318630e76ce3d4e8517f1553beae6ce3a5..ed07549bbcc60c750621e49475c24c1e1c002a13 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 41e52fafab41dfa69f6e896b7839b31b51e0f803..7c56e88c6ddd4975300e54e020d0a19cb7ac4066 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; } @@ -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); } @@ -1780,6 +1781,10 @@ Type *ETSChecker::ETSBuiltinTypeAsConditionalType(Type *objectType) return nullptr; } + if (auto *unboxed = ETSBuiltinTypeAsPrimitiveType(objectType); unboxed != nullptr) { + return unboxed; + } + return objectType; } @@ -2294,38 +2299,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 +2309,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 +2321,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 +2336,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 +2415,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; }); @@ -2501,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) { @@ -2556,7 +2558,7 @@ bool ETSChecker::TypeInference(Signature *signature, const ArenaVector &arguments, ETSChecker *checker) { @@ -2564,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) @@ -2638,35 +2648,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())); + auto *clone = field->Key()->Clone(Allocator(), nullptr)->AsExpression(); + stmts.push_back(AllocNode(clone)); return; } - auto *paramIdent = field->Key()->AsIdentifier()->Clone(checker->Allocator()); - paramIdent->SetTsTypeAnnotation(field->TypeAnnotation()->Clone(checker->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 = checker->AllocNode(paramIdent, nullptr); + auto *paramExpression = AllocNode(paramIdent, nullptr); paramExpression->SetRange(paramIdent->Range()); - auto *const paramVar = std::get<2>(paramScope->AddParamDecl(checker->Allocator(), paramExpression)); - - paramIdent->SetVariable(paramVar); + auto *const paramVar = std::get<2>(paramScope->AddParamDecl(Allocator(), paramExpression)); paramExpression->SetVariable(paramVar); params.push_back(paramExpression); - auto *assignmentExpression = checker->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()}); - 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,20 +2693,20 @@ 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; - 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()); @@ -2713,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); @@ -2730,7 +2740,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 8c06deccbc40e0c84799fcc304c753c462a02968..33675378cef53811dbf68fff6053b2abadb264f5 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; } @@ -435,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 *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; } - auto *node = it->Declaration()->Node()->AsMethodDefinition(); - 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); - if (node->IsConstructor()) { + if (method->IsConstructor()) { type->AddConstructSignature(funcType->CallSignatures()); continue; } @@ -846,6 +878,7 @@ void ETSChecker::CreateAsyncProxyMethods(ir::ClassDefinition *classDef) } } for (auto *it : asyncImpls) { + it->SetParent(classDef); it->Check(this); classDef->Body().push_back(it); } @@ -997,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; } @@ -1492,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(); @@ -1509,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); @@ -1522,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); @@ -1586,7 +1622,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 +1732,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/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index ea39dcd47ced2ae9e31fc730999c79875efd611f..ff45c96a13bd38d41d479b11396eed04a1ab21ba 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/checker/types/ets/byteType.h b/ets2panda/checker/types/ets/byteType.h index cd81d91cd3ad250330121d70bbc1c1ab71291f73..3bc9deb36dd38b0e039c69f375ce295f8d674020 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 f917156bcf5ac851bc61ddd2a9deee84ed26b184..54641c35d1adf14cf2b36cecb725d1cd928d257d 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 ddf7cc3e41102344f620e13423eda07d67a6e84e..57579724f2d938e407d4b610d81bbc1f1670c06f 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 9b0e9403aad8cc4a0cc7699c4f027367add94ac6..ec422c7e122d602b5d9933e8d8d8b193614fcec7 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 f4f90331b9512aa7c8c929e2e8e97343351801fd..edd0ddde3cc1b5ee5b644d51fa1734b04bb57d03 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 71738ebf7c2dc0c640b06f6131719ec5cdb720a7..38550b5097f8b59db27275de1d8b2e18a919890b 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 339a3b1d1fb36f9f48d27b22f7d6d134ec4624af..07c9ecf6bddbb8c94178daeedd7b1e3f6ffcf549 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 befbfb3de9cd9d965fcc3e063ca4b651f7e752d8..a8b4fa3ecc77596201f4d274022b90c89ce9aea5 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 5127daf1fa56668d143014f3d97f68952eac3dae..4a9f175ea84b921e6c0619d505f8a81f74b39d92 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 2a779b6a18f7a7ceb2b72012f9e26405c332b9ad..45d4cdce0fd15559ebe2becb0b29a5364f123a85 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 2bd8c99d3e2bc35d51ff9ace55572753de6a8cdb..0ccfa56d29af6b23bb2c0d48f7030c901a77a4d3 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 b737bd39b44a2bd56258300b4b978e9b461de704..687496405eb080f15abc45929e7c006fbb0b5f95 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 a646bec1436f1f39ebeb5565437e90ccb2e4eec7..8e4b85c913247c57eba4ff8da4518da96a5d76c9 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 a95e78d4d676aa7e15057237e54a14afa5da5893..38b16d18e45145f78602eb60f817deaf71c0dcf1 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 2d79f87d3c7e77db11b32a4b48956b62ba212c36..c275b1b7300db574d3a85f5fedf8b0ed165f4d44 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 5891c506419167fd360e3a1807ec48e13b105b0c..28e219d850b37e14320776c3cc121aef2315bc4e 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 c59e37eb679af296ad1c42556dfef7ddd35f646d..b54010b006e47c53985afcc3587dbfc67125310a 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 afc3c2dd9f195b96c20f502cc49e7aea94894c18..8b96db319e315fabe4d34a751764ca4d6780d753 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 1f79e6f99724de0d5f1c2820f9543ee17b0e1085..2eea1c4084deb2c23262ec2ea462bca7b14d4beb 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 249dbe58cfb3991dfd171a6c4a632c3d61f7946d..ac3bc3ff7949a615dff26058d46ea180788e8e32 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 302f9ce42f07b11e4d28b92ba3813ebca9ab2544..3c1f5b76c9458da6a58eb72d74d4bae294bca91a 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 63dabb1358eb560a44e56b955f5b8b66028ecff8..f32f0305db571acec465052aa4120bb74c423f7e 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 b23981aed59051ab16f3c0313bcc6b9101fdcd90..7f68b971ade1125d3432cc7e7b8260157c1372d7 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 216c2630c2289fd3b71898320fbf8e60904d083d..19336608aa1991995246ac535912f7fdac4bc4c4 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 ab280f7e2d669cbe6b4c9e2ff96b5a32e7828c63..e6658fc53f0db8ae73440c5c0d99cdbfe986ab6e 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 68da05d2d0d860f364b4cd27373bbc2b31f13489..6c9b92c1c809707acc1b81f72d5c5ab56dc95145 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 2e9734ccc7560d47e08498d6195d39d3d0fad5f0..fab974a6f0192cdc2223b6b18ebaaf30c70aa628 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 e2887d5374200ef53bd5bed45c731a889bad27df..85ee2db7d372550e1dd606492b49e4d319b7bbdd 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 85764fff8368b50c13502fd89826f17bc27afa42..7d0788b4bbae52eecba3e3dbf92aec088e85d244 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 aab9ae80b4bb640f13301f32e514d0ce03a64363..7b99a7b06f2d4b82704665042ef99eea52ef851c 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 9db1b04df9994ae3cda0054eafb0d581e9b8f9c9..feb18636ec67a10f19e6c309bae7d62c02999be3 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 27115ca55964d3b87dbe05ed8f7ee85ea9c57e63..169afad7a8913ecd6d5c1945808307a42a79b3e6 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 c79d375a2512aff489471fa4b5f8d7435c8e0535..3f3fb0746558b7986f34d9e0c4f09cf244b5d368 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 c9e826acf84026e034c63489ca0a42aa53838a12..01feb8044bcfe7a35b34d05f82e35a2e1090b3e4 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 295dd1111c72bc314a60d4850aa44811c78aa7d7..ab2bc277fcc51a5cf498cc0ebbe2afbfa3cab70f 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 8409060e97205aca44075ab32a21ba5bd9d42e36..db2c7f04207d3c58643f4aec71d2d552bc3ad81d 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 69c36c85f551be9052bfd885ea95122dda26c0a1..19633bc7a504bea3a6da49ae9c6c6c93a7f05d0c 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 8c4e2ac9b752354e21737cf0b8795727369a01e1..2e3457208810c901a93e1f9999627e44b7951c1a 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 78f6c259941b962ce68e4557492ce96c924604af..d60de37a4d12828ca1cef9a07178a7826f310f8b 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 b378c83fc57c839369b1177dc9438abfb3e14f5e..66235052588ea9eef635d77296915368afb7c58e 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 9e02187ffe506f858727b9249d8ad19e5929550e..b3797e5affa0355623896e14f0af58f8c3bdfb12 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 91e816019d653586ad6d32c38f9a45e4c43af992..ee84c0717acc6695430e86467b7b0c739f7aa987 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 17b7526c605661d7c0e351c262ba3533d2dd3bf4..e9b839d3e59fcbcaecc8fe478fbf098ba2b26dbe 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 b204f0b5060976567a27cbab45f638097d667f2f..36a06893425d149f434b237533f82f9759dace14 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 381df49bc45d8cb5be675fc8aa13bb9a7e4aa752..4c04e0cdeaad4ce53f6920d420da70c6623c6f6b 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 3ba7501e333db432fb04e7319481ba6117c59a60..3855d633b11b092e6c9ff21103b1955713b32635 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 b0b54f22330367a8bc95403c58d799f91a7b2991..3dc6c1ece33ef757e992d0621cd87e4efd3066a7 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 75596cb0b99b9ae81bfd987dbc11dba0456e40a5..294d1a28a53b0ece3a182ac941f44bcf9bf7e1b5 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 4c930cee425ce0e369eee677a3dd9dc3867c3c02..02389c7292771e2085257e0811229b28518e810d 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 7cd7c05dc8b3871300b5406a97c0396361974757..0618f2d1c936919c2ef5e7a83da3b3ad4a366095 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 83a42455efe5a1222ce4c5ccdf7c09c7e9743cd9..19e4e8c9d57cadc99f37ca5d1104850c86b7434f 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 0ee4cc675ac9f14d20d1b3c4cdbd58a2b9985384..4a308dda73ebdb778f83e2de770b6392400a17cb 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 c1a3a87882a5bc3c5bdf0281e80adf3ab3004b46..ce3da03261a2a763a6f50932e7c02f91dd17f0e6 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 3e1897429192a54666fe25d69b6bf804bba72e03..e8a10afe9dfc80a9a85d51e8f396a63fdd8a55c0 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 f1b465a54bf29dc70687363036581e95c8d9aac3..b8e36d821d176a95143ad032041d23f8e2e35a14 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 69b95e8ce3fa99201b78e0f45c3a71547cc09dff..633009c8a1c9f2b5e79eaab173cc0403cb14ba17 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 cfd1811e4929f73ca6f38afac6c946a4cb988514..210129214b984fe945987e091c35f8e085787f50 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 e4d75b636209194b65062c0225ef856e279dea7e..8add433de854dccac13d148fd0bebbedf0b54a98 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 0931b3ae44735a9a18df449e57b1441a0eeadc54..5a5fb981c3a982b714a97ba72fd49d2ce1e28af6 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 3c37b7cebf616752f57400ba6cc60ba93c148969..3fb42a30de6324a6b176b4ff3ae39bdfc5ad4bdc 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 2047f5df5758e9cd93c2800663f26de5396ced43..614a658ad564cf7c55c325a8f8d1f4696ef6c73b 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 786aed31c6edb2cabe6bd3db889c555825a3d8b1..bcd90b3f70038cf0d1c66ee21e1ea09d1edaf72b 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 c46dfccb24b06b26942881de22e734eceee7cb84..5d40915809a2715623aef50ba5be3ca4a3d65764 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 c4ccc26e3705309d897f318bbac4628356679e73..3bc17ad8bc4dd1b17666589524f270b38b8d2557 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 360060a925771989c3b636a9040115dd3a9389a2..8b738425b7050e7b511e90faae139d7f4682dbee 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 40916929fd36efa53f8b84f08efbe1e07bbe1ae9..59e90af296985c0e3b1b05ba9410273267f83779 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 a30f48609f8154c91348d1be2bb20ac4500146a9..eedbc33fe040eabef099597cbce2d85f20aeae76 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 407454989dfb19651344006e86e4656fa6563514..0bedc56068b34e87c19d40531bcd7328d496f7e4 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 e9b5695c1c07ce046180a7f0065239b2ee4f9b4f..85feba1c5c619c84a79b76959af7d53fe5c00f57 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 87f8cea1c18409ef9dd31e402f2db895f0c60722..c5e6c80e2eb2e28c8078a65b4c7ba6222faef9e6 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 f18e1cb63b8ebf23dbd2fb2601218702e417efbb..fbca9751a9e5a2a35ee265061110194e777c20c5 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 9afedd90b61d6c8d86aaf6e5c4b509396400cf26..e0b4a9182b3c4126bfdccd7b5a93eef6d5a047b8 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 d37ae5b48ddb3c422b038f2f695a29695190e829..2081adda400843413e3de57ae4ce57a608010320 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 9e5de1369e137b31bd658a38e5643fe8e3e93637..9efd5ccb6702a871fa7eccd0ead6a5468e12aac1 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 53fc5c47fc0be3cff90c570ee9d979580c334e1e..b638dce06ed1547ba3aba42a06a636e45212b371 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 516b284db4679e82910212114d6e052f7dc768f5..fb297bfbf3e0b084f597349723097fc5c66e5e95 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 bcc320265a19204985bc0ccded22d64afd7e2069..3de782e2c18d1fa29dd8f8ad8d0114090c5f8c44 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 579f22f3838cc9aa565200f24009ec7d24c1aaf8..4ec359bb587777c14d2c2a2196b55cf97e1f3e94 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 2b4f33fc18a92457104961ce9bf913d338cfd55b..4e3022e7a4e4571faa36f7668c862f3b59e1e952 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 5e7f6aeae367b58dcb5b91a96ca5eed5d8ce0f2b..72e47c96e7eb9ea7fa9eb026aecf498c20502337 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 79fbceeb63fae48f11ea7afbfa30d14e1b2dfab7..93a0db73c9402ef96b07458da936078a89059ff9 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 1d3f7e92f11954b0e50ec4e6f9b5c1927c967afd..352436e9cf46da823c024a422e2ea598e25f52b8 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 95d81fc732b3c82d4557f25c8228426fa784852c..93ea3ced44b52f0b537393e7b2799c4df40b2bb6 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 554a3b8e0e9bcce45ce7c0046b22995f7f33428f..e3f0af57c5e82629d3883d7f398bdb27e921823a 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 d1cb778f354f361ec36f7636d52fd1c7c03324d9..5a762dbe7fc0c8a60f361cb6f0180fca01d09f97 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 cb2b2fe4035c380b6b3c7762c0f8786476310eef..edab990222dce37ae37ffc8e40a6332da7c60321 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 47a5ceb8074dc66413fa602c01150f09e195b00c..e7b1b39b494094e641090c7720c6ab61ebc75194 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 81affaf07a021118950650f48d0f34bb840b6f0d..ddf5db1e185d990fa5b8f9333c320e53ab80e4ec 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 455ec1e227c8a225cbe77ce5efe4b679d154adb3..446da59ccb17f117b85ffcdcee396a8f811f8808 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 e4a973560db05f2f57ddb73cdd31c2478d82762e..821b89da24cd27a8cfb27add951990a8d3c0aa8d 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/ASTVerifier.cpp b/ets2panda/compiler/core/ASTVerifier.cpp index 405acad229c1357c720e4adf45391f06c60ea615..921d856a990d33e3e3d7fd0282b29760aa0c007f 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/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index fd2476ce9496e76741c94c109991d3215a2d3eec..f786bafc9b6c926437353d2d3faaf041cb94d70f 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -15,14 +15,13 @@ #include "ETSCompiler.h" -#include "checker/types/ets/etsDynamicFunctionType.h" #include "compiler/base/catchTable.h" -#include "checker/types/ts/enumLiteralType.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/ETSGen.h" #include "compiler/core/switchBuilder.h" #include "compiler/function/functionBuilder.h" +#include "checker/types/ets/etsDynamicFunctionType.h" namespace panda::es2panda::compiler { @@ -216,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(); @@ -236,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); @@ -328,15 +327,13 @@ 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 { ETSGen *etsg = GetETSGen(); - etsg->InitObject(expr, expr->signature_, expr->dimensions_); + etsg->InitObject(expr, expr->Signature(), expr->Dimensions()); etsg->SetAccumulatorType(expr->TsType()); } @@ -659,11 +656,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 +676,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 +809,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 +828,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 +881,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 +895,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 5421dde41f556632d1816b3a6b7d8629a288390a..4e0e04dbd3533afc6f9d663515873a6b8508c7cf 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 9274234954f7ee0ee3b3571792d2b28c79c2358b..c771dc9d13e46b5d1fce13cdbe05c5165b57cec1 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 b1c5907351785069c931ff85b42de93fc4fc8891..cf832702961cac2447937165cab7f6a52f56cd14 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); @@ -559,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); @@ -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); @@ -984,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) { @@ -1035,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); @@ -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/core/ETSfunction.cpp b/ets2panda/compiler/core/ETSfunction.cpp index 75739a159d7c1b59ae125e4bac3c15f531058c34..8ad11cb7e09ec304e3138e7dbdcdc0f796613afc 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 a5bc7da17f8c88a8590f7f614c19c2cde78c9772..dfc46cabf36654d55d80455cc9d1a91f999718ef 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 d8936fe26a9f60761cdbd080b6cac0bcf7a2114d..d8640ce6730c9a76ae32072e6de0d3ce14442a95 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), 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 406d7f28327f0bbcf55d844ae9cf4da4c3d496ae..6b47d2eb6f938f64b8d3cd6cf4b1f05fea076685 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/ets/interfacePropertyDeclarations.cpp b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp index 97b56809eb6984326651ea51d1dbcee4b8cfb6e9..35a6278c38eaa18ee5e49ff427a86af58543df26 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 9b4bfa606ba31d881cd882c665d28ff3401a5bc1..8253e18c6adf1e7876d37c14c22793d5a69f84e3 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 5d81de89d92defb083849f27f1ce2981cb5b398c..67132fed0935af2176618ed5b64411a6a99e739e 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 ef64447b6944d8ca51ff118cfb8fa9bacefa6218..f6b9c5f3949eb20ed6418a202af6b4c659691528 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 736ba8c6cdf4bc7beef7a3a4389db2618998c8e9..3c4e61f9717db87ee81e80fdafda7d6df918f19d 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/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index cab0d07614b40166d81e52ebd0a9519aad041dd2..a558ce5136ab6181c840aebcf4a3434bff7a8023 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/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index c0797950622c2fd8f0b8e17cf44e2c24bc607b68..a4b5949abc6d39373b2df201692c49ca2ce039dd 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/astNode.h b/ets2panda/ir/astNode.h index 4b20f93db346cc953bcf72a36e663d1400b190c3..3075935b3a9af3f5d7a45d91fc64f3b552e27d28 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 cfb7ac8dc8e3fad80cfdd96a3f50e5f338dd6d33..94b77be1b6577a18913e0aecb3d66c34b26a1d07 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 49d1237bf1e0fe3badf2223a99e4d65cd0b3a110..7161da90078b82d2d9b26951094e4ea54a6e31a1 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 62b0ebb1003ff02519fe98bdc74c1bd7df759be1..8e41ec34c7b174c3b10275162c65778f9417bb16 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 9d97cafadaaca1b8a9b4419360f297fc280b21e9..12c6583b73f02fc4efe12432354d63408947ae52 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 25ac075f90cbaa9e1067f59b33793e39b4782f2b..0f2c7d5ba3e7209501f2321143cb631403433c6b 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 eed3b5f6db795245ea5de04beba6a767083be7d1..4ae382fa2522f2d26eb74ffc4cbcd88a0aa40244 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 dfbcc9027c1a169d64f2a3ca4333b90588b76964..779e08c90c021fce01569291af01d97c444ff6bb 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 a5208db90f2428856a38f8611feab9b44c39c97d..bf4cb3a214e08eca54977902b3f6ad861ee613e0 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 c5eb1bb8448c390cfcb2393bddb5107357585de5..369b6ba66bab9b54992b9b087cd70aa31899cafe 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 9ab31f5844ea2a82ebc8dc12763a240f4dac9829..3f6be2a26aa24d15fc45f03304c27c7b85c6ddbc 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 d3a314df0bfbbeccde183a29cf17a35367026937..bf0f208af96c46172eb182b83fdf0641e3e97c42 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 c6811cba023796fca9a5ae456c424d75ddf66dcc..d70ba1108c4dd066706e7287d9a42585739a189e 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 d643644cfb1c6931e1955b05b4aeade0024680e3..ccfdde132f384de1ccd30baa191da01f4d877a79 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 b033e6749cc8fe68808da58153043f796ae91f6e..8c99eda9f0b1f4347f1d6dde08ffa71058e0cbd5 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 36e35e5461e0e9b8b7cf6c4d8f4a4b28e538a428..3104009fe127181fd9030f18215c35510bdef928 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 f66d00367927fc317b84b8286791c4d5ac87997f..c9d519118ee99bf463612d87d32de69e77149e69 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 939f60c97555d0ea9f290adb29a3f10ebf7ee7cf..40c8b0dbe6cb8d1a1933c7cf388ab9ad8504798b 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 8816ba413cc58502d302ef49f5cb7e747013707e..09a61236abb4273092028aaf38ca63b0df794dc4 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 85154cdd14255dc18b8e3572d3d5ba44e9bac7aa..45f96e6202073b2f8e28b472abed0b7c5333bd0b 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 c85adb93c74056577ed34accc8c954f0cd8097b4..a878eeb13a400fcb470413c7fdfa467b696f7e12 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 cff8d5fd215fb78e5d876c5e5f03a42397813caf..9b1b1c1d29b4f5af3c0c05dfa4703f775442be45 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 4dd052b5d6dedbe87310d771da7c4df6aa0c02a2..49c0ac995c3382d5f0c7f5bb1a14933143734235 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 c3a0f73429f7d6bb7dfa5d5fc4eee149dcee43e3..8171be38e4d6550beaaaceb22c50c3d0bd6e7266 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 ad0eabe30565db726b6ce609ef4152c5157c70ad..787e96b37780c004b53ede450dd43332c772ee64 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 592f3536fdab61e8af1a6f23c36c7db931883e49..d52bf955f66ec2cf059fc0eef2bb0f707fa553d8 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 0eec9494ff1873f520f4a08759076ad54634a057..7ff4c9b59d3c5df28aa383a330363bf6de21c7bd 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 42f7323db5f68c696d1a719df092521ba6937f1c..6dbe8554843321a68b413cf5a511567486fc5c3a 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; @@ -109,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 a492c7c3f23c6b867d27358dcac6bb5403e62d73..0ac08f618599788288766afba71ad35ff2b5ee44 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 5f41d342c81945a35e8e70c640bd38d2c7cb8000..eee51886e92688ef25ccd9806ffbc6c771844bd3 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 71277d93848ce75adca9d42bbcadc2042662cfce..4f3f013c77822086775335db46016930f41dce40 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -72,24 +72,28 @@ 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 (auto *const clone = allocator->New(typeRef, dimension); clone != nullptr) { if (typeRef != nullptr) { typeRef->SetParent(clone); } + if (dimension != nullptr) { dimension->SetParent(clone); } + if (parent != nullptr) { 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 e1f121eaee960d5a1ac0edbecfac12e2509e5c72..bf744f17b4aff4041a7be66d03503863ed32abd9 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -37,45 +37,57 @@ 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) { + dimension_->SetParent(this); + } + } + + void SetSignature(checker::Signature *signature) noexcept + { + defaultConstructorSignature_ = signature; } - // 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; @@ -95,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/etsNewClassInstanceExpression.cpp b/ets2panda/ir/ets/etsNewClassInstanceExpression.cpp index c85d7639ca48255dc4d9caa5bcc9e3cd9d1b88fd..0a6c95d2147eb240d1f4c446d425b6dcbf0ff55a 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 6cbef0d1232afe31ba19868368b88596ad34beda..4df829352a1597312b223aa52e0a7f1dcd1749e6 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 4b2bc1500d9ce02d0b8257bc60374f03ae65a900..e9de7f927bbeac14e04eb432f63ecd2d1d0d89a4 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 825aae727d29910e573c58d102a043e7587c9a61..2f284625dcd7be77a5786ef60d95da9afb9e3215 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,9 +78,12 @@ public: return signature_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] ETSNewMultiDimArrayInstanceExpression *Clone(ArenaAllocator *allocator, - AstNode *parent = nullptr) override; + void SetSignature(checker::Signature *signature) noexcept + { + signature_ = signature; + } + + [[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 27a44e419c25a17abcac4bbef2d311b10f7f4661..1af22f1a87ff3067bed7179f8d19cc0361b942d5 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 88d51f0c08ef9f2c1672532ca4b3abb1334fda04..98463a9102685ec3e2b08b86bd4b463fad11f98f 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 7b808c79c3d5db489990c301f5855ed7d6747d6a..ec2682f77615ce514b8a606bf5f07822c635d310 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 aedc3e7166a1c3079d162b5d2c8793cfc041ced6..ec6fde41a59b2dd9392ffa6f145442ba9419fbad 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 bfc3562cfad72ea422ce2db83a378064d1a62ae3..be255ddd3abdd8d7de76490791dcce937da28ef5 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 b2ad1451dfa0abbb2cc0729962d0a5fa69004057..2fb0d551728ddcd9b49d157b8c885ce960b89b19 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 37026f4a624b1ec9c717e63a4a15b39a11ebd36d..873c13499fcb7fef5ff579cf848b6d0c4c55926f 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 b7d6176e72ec0af562f262aed793e09b8c883c5b..f16200a8dd5ebc55b09299d331c855666bbbd9c5 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 b65b9a68d67e56a5f28b6f68eefde831004ba563..0ef5afa775895e3363d376a0c771df4613a57893 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 d67d7f49ac4b51c2789cc6f603fe0248791bcace..dfcecf74bbe2f6483a52a11907108d84f483a634 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 792e942e8ce8737c4f2060ac5b61480a38a2ef19..21cb3dbbf724b938c32d446aa4aae8d8fa7ab4db 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 ab785f6f9cb59cb1e429c112b870040cc4eed2cb..4493d5630783c65c83b9beeabd25ed87f029fc4a 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 294f8f23ae7d769442d8c22f8aee5a36b4f8f615..653b922f980f3791b8163ece2f192c0e5caed914 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 34e834a7765ecab2b31dc9122a7088c3c31175fd..90dfd3e7aa86f1f043c075a51b04a5e7b8df96e0 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 3e4f53a46ed8095ae3767a5f02a07fc3ba4cf673..63676ae3870886639563672e09568213469f246b 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 c1358a17226898a2ebb656b6b9d5b97251dc6fd5..79bc5b379f7f3fd5a3944986f3120bec6fb17408 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 b4a288a8231c59ed255f5dee3f7c99dddd932a17..bebb7e2b2e3d161c9748e4e67da4da1fea8d2798 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 ae8eea339769b2ea8d20abf12824dda0f4acba5f..4077716d10ce6512b5da4aeacfcdf22b7081c2b6 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 5048bd86c4c62fe1875b9616575222fb9a2b907f..bd59fee26901fa9f56dd73e0bbeedb54356cd44a 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 ab1160ad375e45e0d074c89472bd8a47f42346fd..5754b7b9765130257aebd09c9ccf0dcaf1fa5a90 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 69de43333363cff079a95bbcc10db776dccb20c6..dbbfc271d005740d48664b5e88f71fbc0efe2c40 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 c4222f4db9ade7a1937bbe987dde6559c33f6caf..82b484185e9d58618d9ce4fb5b4aef2b20131e75 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 63b795532e49e71648cbe153cfa5cd339bb9dbb7..eaf53644da99ba43f555db33ff619b3159fb3e65 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 6c6329ccd290328d853051c071a39ee337e183b7..1fd672f964f40a824f7e2e00336e0b4391d47240 100644 --- a/ets2panda/ir/expressions/blockExpression.h +++ b/ets2panda/ir/expressions/blockExpression.h @@ -41,8 +41,27 @@ public: return statements_; } - // NOLINTNEXTLINE(google-default-arguments) - [[nodiscard]] BlockExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + 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; void Iterate(const NodeTraverser &cb) const override; diff --git a/ets2panda/ir/expressions/callExpression.cpp b/ets2panda/ir/expressions/callExpression.cpp index 577a4393b39525a3c6d9355de9ac034bf7bcfa73..630e59b9510f346cd2f700092616e03ed44f8762 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 cd2e29cb97e968884b92241c1539e0b85ea7ca58..92c87a41e8894a597d9cc92489c49cd3c326ec3b 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 7513d034fe0a30e3114d33369b798cd9caa48ef4..83f518121259a170040ff308aea9b6dd42df291f 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 9c124c9c91ce4a2a818f8823c74efb209a624c42..0ee4506fc97f8aeeca00cdc998a09a0583783b14 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 6caf00999f2954395085a8dabebfe401ab4859b4..7d8e14ddff37d0e6acd3ea057ba32aea108a1330 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 3277ec23ae89f68e4ca2ee43640cc600fc100ab3..2073d0690d5b9dc859f2c69d0b958c4423b58c70 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 c75255d97188df4c7fbe4530b8f751ac084ef92d..839f243ca187870718d816cc0345840383943955 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 f7e3bb822a3bf31d1ef8985ee8921e0fe79b148c..466228c48145db99b5c150fe9cb2b3af3fa3a04a 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 243a94df429a4bdb343ce2627d78015975ed0efc..d677d21281122a8ebc34a58fd498a274065065d0 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 ae284499ced5dd641e6d70974b0d5e6f3d6b2e09..ce81316c51dfbc190eaecc9ec860bef8fe2ab8a7 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 03d77fb78166ad73d985284bf04b022e10861904..7376be7a24970e69acaf4d9c1a0ead4c3e2c754d 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 b91b01311f60a87343d224ad40c97d0e67ae2560..48196b964b056cc3da37e992cd51cfcc14a9c40c 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 21a048c903dcaf08dab58a2b38a3546ee291101f..37a2df2530b2bb7a183045341cb46a8ca2530738 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 4ac17ab18829b21685e1b5da20902fe239257cde..bb3a5fab15804ab1701224e7ec8e1851345483e5 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 9b72a6a358ad482b3a68aafd4fc71e28f4862a51..2dd72386fb3890041901a4c4d24ddd5cd5360dbc 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 6ac3d773856d79e9b3c2506673822667a22206ef..217e99057d3d88ff02f0cd45548ad19fe3645289 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 40bfa7bc655ee69bfa3c3dfc49ae8096f6ca392d..d6c73467be6377dd445bf9288ecf6296891d95a9 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 88f62c6bf7280a0a8810fb478c66b0eaf201f8c5..f3ede215ba13fda9f54b48bf3ab4c0fa6e15b6ec 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 ce4be05ffc2477b40d3f8b1285826beb78cb5d3c..6ae2efc53f575c00ae98bd1c470a64f4386820fc 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 629e1a0d036151a3cbda6cc6a2bb4a19a3733274..003e922b4a9baf73c6b17cb59f788063c57f0d16 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 74c0e578162e27db70a51af734be3e39f602404a..6c45263aba6f17e08e4e3c66675ef4be53fadb15 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 4fb46bb414389a8f35e34285f693b6f90e81dd47..40a5f7b299ff8f582af5cf1221c89ef0aa04fdac 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 dc7e40501b5050e86919f7ca6ca722669a150878..3a832b8da05f2fff804af58e58c6d89b113001dd 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 0abcbbce6ddbe60216a9803378b4413654f47078..7a4412d2f39fa6844770ff8e2785f87cbe80a1e1 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 e14f0fad2da61127d333ca7580bc1f299dae8bc2..c05a8ede16ab4120d9d44f93fb657bc4012fe19e 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 9666670fe75038b2d2f231e7ba3add4555716a7f..9e21afa71f3448a5347108e721de953b45f344d8 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 11bc091825b5792eea11813beff594fc8b514802..8fb5ab112eabebf7186126b0db9ed64905153f76 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 081eed374fde1f4fce86bef53f75795b3a9095b7..3183fd6cd3d76fed67ff93a7dc9a7570f9f8b0d1 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 5ba4fd860aa2e4a92cb9ba2447fd0993fdb0181f..3195df4ce886fe8e93cd4a6098ec2ca0c384915f 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 ae0ec9e0bf9cc132690194d38d98aaae415f7454..ec8b9340a2c035adbccf46fc476ad52ddb3eb6aa 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 b59a73b4097f5ae6b818081e7af80ca1c5098045..581b342eb2b7542ac30c2ccded7543e5f0edae7f 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 f56cdeb805147dc9c04dea64b87a01bb9811a501..8fb67ccc9fb8b484177c50868f8f12657e4aaa67 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 a1d974cd3fee0d1a0cf847f28f432304e68b5677..883e310a292a25c1e01439089b852581484b2520 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 6ebf574910a112e74a06bc44f39cc501ccf5d8c0..4ba78c48b3c5ea0b3f2afae22badf44943d95371 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 0beef0b780c051665b6f3c5622a7d42f1207772e..758a46c1613b7c809d39ac83798dad6f0a3efd00 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 0ab3d1f33203eefd29e3f44e8ed5442c0d3860c3..abbfdd6774d751c50053adf9386671e3a7c31a7b 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 4f1f340b78dfb90e6b0069d7a7b7ece85daf6c68..b29553d7c48099536533db51ccf9aa58696f7414 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 3830204255e2be254704e1b1fe96b17c82716c14..d4f37ffaef3de9a5bd586c75dcfea6d72c8be935 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 98c53be093291a81d397b3d45e3b209a0c983248..4c46022aad2d2a65e6ebf0d5da972434c1c1e54e 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 02e8244316ccb7c986413dbf8c83ae0aaa67a39e..8707b2b35ef2d32a2f3fc1a2ddaa2edc2cefdf83 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 29d12a994de0bed32b421f17ac355291e97b3b7e..a3d33a1f187cec7bf7fafa05845850390c612b94 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 238deecd3736e289f7ab88d65ef9623d3d23ec5c..bd0bce7063074c909906e8c496b07c7733fc3b3b 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 d8853db8a91e549b4363ff92411fef3cb8398b36..2f70a9451a0a351e1916012e1f636f10c792d9ef 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 732c96706b0a4377f457ba7407123afc62fb755e..30e37189f82c37e0b08ff1c5cd815d7133d81483 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 046ea69c4f13e5e228751330bf8f09d6872b2433..0b7b58711633734476225f6c6c16da164469c7af 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 9598cea01a9637091955cd6b91a2cb479a84da51..7ab66d905ce236004c1411cd436afb457bd92365 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 51ab0411293e170091a9ea594be62454044870ef..c1db0af614090524188647b8708224117ca62e87 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 835456d9c4d10eba065554631f9af6119032b3a4..575990650740d907331df70ce4f9bb11883dc1f2 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 bbb261d3a0582bdadd7493c5b0a8c0191c970893..af060bca824a5f0fe3443e10eeb8e9212d99f39a 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 5453e7543cf9303ea6550a828cedc953f6978fcd..3e498d2bff7e18fef98be4cb21a1afb447287e22 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 312a73df3306da2da2f1e1a7ae21f1c753dac93c..51539cccf5f8fbb3df53464a7c5e4695c5cafaa0 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 36ce163da7007580178c8b8e8f8caf8c804930a2..3c8400649d31a0dc6430f52ed4f900d150330cee 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 793843063c900c0ac63c43014cbbd40c37258dbd..c7e2f278f9e50fb0ef497f633b164edb2451a8b8 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 e6973d5d36bf6576b3a0b35348203d1e52a4b7a8..59a5277dddbbf3a11f13f0a985508691c4859f4a 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 b4c9d27caea08b929459d42482688d807dcc4c90..328476307bef27d9f4a754e5288eff7c993e8518 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 12752a30046a61ffc28895d56c02ab5bcfa5b9db..131d10a5d0339925179a21bbef0eb1eb68462377 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 051d18b7a501ad7c7ffb506028571cc785f713ef..c28ff0e5cc35808f2ced439a3efbf539dd9e5058 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 ba4903adaba877e18f6e07985238cfdfcfec036e..7639332ad451d8d9d173f54fccfe46a660c67c2e 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,19 +42,27 @@ 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_; } + [[nodiscard]] TSAsExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; + + void SetUncheckedCast(bool isUncheckedCast) noexcept + { + 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/ir/ts/tsInterfaceBody.cpp b/ets2panda/ir/ts/tsInterfaceBody.cpp index ecdb20767258843ee742c126607d2a0c44bd21a3..34392b288281970da3a67f6fb16b19bb0cd3d05a 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 d3c4751114aecc79edb26fa7ece0fa23cf5d1dbd..65fe1b15bb654daecdfb2e23028e19f3f0d3b2b5 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 a59bf6aa3a2fd7988ad27fd2e8de52b53817ea14..ff2e145f8f224f4ca97f5382a3a7f94add1433c4 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 ef538c9bcf72eee3a1a702979bec167a0f0163f1..84496dcd92e2889b2426dc65cc4fa70d628bc348 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 be57a1c502e38aa4e83c37d498263212135bfbe5..e6c02c9e585dee7d228d5f808e6f26bb259d807d 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 be22e10ee704a4131e7b904c37bcbe46245b34a3..c90e0234ae5e3f4a3bc3403da01b03c431176bc4 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 7933f9b5e407daaa0898bc2b39b20c5107b542c4..72f4ceb54011618bdab613b38036c72fe9749a47 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 b91b25f8162a6920f18bda39f0b4fbc7946231e4..92e289060ec3ffe2ff9812a298f1a5d87dcb9d86 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(); @@ -4220,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; } @@ -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 4b4afef511257ad239e6150fd9db23e9cc66d76e..01e8b642042571d1417300cb37d2b7f4410bbbde 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 a3018356f2b0dc8c995306197b600d68d79f8d2f..9851f05a727fe667ccf38ed487b31a68d0b1eb78 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 926fc510f0f3a3a425aa047e84bd55866d54c64e..5a3c4ce5118a483d24d84b9d7cf5e2bd299b51f5 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 5eaa24e774c206db6312bfb73a1e4122b46ab6c1..ab8912e19f5961142947f5e516414528409ab06f 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 5f4d6b623c1ca9ad05b63236f238f0573b00a73c..675bdf760b447c0d967cfb515457efb033dafe69 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 4386ff754fa662041883a3db460aa90a65220c0f..a5ab58c8a14b9856e47cb0a8c4c2f321c3d1d7c3 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) @@ -2023,8 +2022,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/compiler/ets/FunctionType1-expected.txt b/ets2panda/test/compiler/ets/FunctionType1-expected.txt index eb64020f40e49445ed82f79f28fa02782d538428..a62c8dd85d60ae17e7e06f6baa860ffc9336f53d 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 bbb4c6e27b15eea2054e80a1da9798db1abe9305..0d0d88e229b078e339a18c8a16becd16b3ed2448 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 a92c60328361986dbfda8e79c83c01c8505f41a3..37dcab16aececbdb7b0660c38bc52df306ee85f5 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 c96da27d618f81a70d048be77af960f521cdfca5..dbdd0fed4e0b5ac0e13c4f998d7ee93908e232b9 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 0000000000000000000000000000000000000000..ca68775f5e7c4bc5c7f56237ce0df6d0a6b5102e --- /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 0000000000000000000000000000000000000000..0b2ffc867e56034fb79f90e76dc9f53a784492f0 --- /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 0000000000000000000000000000000000000000..b49902e0360b9b56bf1c02ddee4587169b8038a5 --- /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 0000000000000000000000000000000000000000..64860a92b84090397682ef3b294ceaf8f3238e5e --- /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 0000000000000000000000000000000000000000..55e50a03bc5ecb3b7575a869ff4157abd02441b0 --- /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 0000000000000000000000000000000000000000..4e57a855ae937b56c005189c6c52c898c43b5c5b --- /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 0000000000000000000000000000000000000000..abef87ab4c4cf75d73e08363d4d783627af2c92e --- /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 0000000000000000000000000000000000000000..dee382251f27b4b4bf54bd1301d60bd5101e1333 --- /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 0000000000000000000000000000000000000000..227f565f389428b1045e0e534beb36cd377f33cd --- /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 0000000000000000000000000000000000000000..a3bc04b21106d940201239715b1df566b8c54390 --- /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 0000000000000000000000000000000000000000..3bb1aa6f553a968fa3737fc7131a53455a5471f3 --- /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 0000000000000000000000000000000000000000..2b61cf93020ab46e12e7ff3529e19a89aeced8a0 --- /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 0000000000000000000000000000000000000000..a3be0edfd53c7b33af22adc6758d875021534c77 --- /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 0000000000000000000000000000000000000000..bc985183024577a560e50aa367a96c900c579be2 --- /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 0000000000000000000000000000000000000000..07709a6558f4d84f09ff4d90575315dab782d991 --- /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 0000000000000000000000000000000000000000..9e351ad8f9ad8cd90c7a8bb0514f9d2122b4917c --- /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 c0fb2875eaa35752d68d03bccc91b4ba8fc0d2a9..100cdc5d9da37ed85518a0c2b428f0fb57b24619 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 a17df28bb337b0d74b04879a1bb4e4a8890a0fd9..d7fafa4654f0fea7e5ee572646ba22800f3d2d44 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 22b2a3c2f299f5bea005e116a3f713eede8dbe30..1e358988d23eb51fd4051bddf93911fcf3861fb8 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 5737ced2b4eaa0c3cb5614fd7a5e7a02b82a8e43..b82ab2b93218d0c24802219361d0308fec15622e 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 545b1715cf2905525d1f37c516f466f808038e42..21e87c7c1a01ed9ce6bec01f0688ec0e8f443579 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 cb90f223b65492d77d5f230dba1fa2e5a2097eaf..2d5c270007400772d8aa797f644c91391f04ca04 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 186fa4c37141f593fb820c8dc978c6d5a0388b67..36610c08a0f6982d1fad63bdf19f31ef144a989f 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 218cfffdcb33c7c392be1d8fa7840ee67f888e43..50c023906d4668b5aceccf46af2ffaef33053903 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 8dab208be01f4e78883dae08af77e7f8022f906a..bbe9f2aa80e7c880b27ccd0ca7dcc9b9745f1368 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 0000000000000000000000000000000000000000..8b5703c1493afd528dc17347c6a422110916f61e --- /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 0000000000000000000000000000000000000000..b0c007e32a8c5ff832dc535cd86bee703c13e6b3 --- /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 b1fa4f9c7e759e54e7a618c444c7222a23ae0ede..cf234349f288e38c4ac38e767197a72ad85eaf39 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/array_new_failed-expected.txt b/ets2panda/test/parser/ets/array_new_failed-expected.txt index 7a1d50898a8ca2833466062a25840c411cdc8a80..9d3ca1198d87e3e42e158728975c84e0e40cedb1 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/parser/ets/function_implicit_return_type2-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type2-expected.txt index b9803f021ffc4714d36a4bbeaddbe716a29f4bc7..b6a70f9b2ed7e2cdf74a7afe6b606d23ab8f9970 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 86af963d88c0da2bfb2a9312765e549b3382fb33..ef11ad3a7588f5e3f482653456dfb26ed32c6505 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 a84f38f68d4849754da0362d7b5a9cd6bd526622..13e389abc2acaec44366f508159f099715f13716 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 e43e384d53b1f2491e8c060ef52b7fe76e876e35..80534bb52cecbe31aa07ffe20355ce2d8675a65c 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 b814441ff1eb97ccfdb53687762b638838cc1e19..4ac2df4d2f11ea619c64a304f402819012fa2efe 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 5c3f1759fa7bb05c48bd7259abfb0a31864cbf07..898613c8c74f3a5b76c2dd433a9588aa22013ac9 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 76f9ea8e29cc817dac783009e3bda81123d9b699..2b8d23bc6885254a8d991ef612f7438ed9668492 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/multi-array-new-catched-1.ets b/ets2panda/test/runtime/ets/multi-array-new-catched-1.ets new file mode 100644 index 0000000000000000000000000000000000000000..5a129195b9b2ca0af8ac45ccc00613d2d85ecf7d --- /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 0000000000000000000000000000000000000000..eefeb31395e1ff1ffbb1d8ca173bf534041033cb --- /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 0000000000000000000000000000000000000000..fe46e6e25da602585af97b405ebc53b36095104e --- /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/runtime/ets/unboxingBooleanConversion.ets b/ets2panda/test/runtime/ets/unboxingBooleanConversion.ets index 7fb437eeda604faf3dfea8614bab86f2a935cf2c..8a865706f58f9213c2b361f4d287947563dee922 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 e8521c7c0b4ab6db263b0c1cd4a4363e32f60403..c12cc9299c3a9aabffb9ddaff8c9db202086395b 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 de27323be467022892a7ff1d56c6205e070690fa..803f9a2c5e09b17577ef15e31ae739395148efe6 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 a0cac35d0e8d349ebf833c8793d6cfe4aae7a44a..f6b8c9975e50857c132894302bfc84ac700052b9 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/test/unit/node_creator.h b/ets2panda/test/unit/node_creator.h index f345b56f2873b08a099d0d26400339232fab104b..4a054bcb10917116f0c357fdf07288e220b9962c 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/declgenEts2Ts.cpp b/ets2panda/util/declgenEts2Ts.cpp index 89cb7e1e34359a11593b62fd4faaffeec4f988e0..8e4d7c9c12af43a5d643ac99543aa8ba73554f91 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/util/options.cpp b/ets2panda/util/options.cpp index 7961ee7c144c5dae77f599155b7ad563d25b8c36..4f5e5c1db2e0b62c446d27b21a7067b22227f3f4 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 06d08f355360f8048f07c6523e8c017e54484f05..cb13eb13ff3d65926abef450ce4e13f9ae9e0070 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; } @@ -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 edd27f9a43a6b9cd3905d994d94ac3fbaf527937..0f7057727922ed23bafc385918c95c2e7a5d43a2 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) {