From 3fcfa1e829e7cbbc33539d349c3bc48008c876a9 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Fri, 1 Mar 2024 12:03:13 +0300 Subject: [PATCH] Fix fuction references with rest parameters (FunctionN) Signed-off-by: Georgy Bronnikov --- ets2panda/checker/ETSchecker.h | 7 + ets2panda/checker/ets/function.cpp | 222 ++++++++++++------ ets2panda/checker/types/signature.cpp | 2 - ets2panda/checker/types/signature.h | 1 + ets2panda/compiler/core/ETSCompiler.cpp | 11 +- ets2panda/compiler/lowering/phase.cpp | 14 +- ets2panda/compiler/lowering/phase.h | 6 - .../runtime/ets/funcRefWithRestArguments.ets | 36 +++ ets2panda/util/options.cpp | 6 +- 9 files changed, 217 insertions(+), 88 deletions(-) create mode 100644 ets2panda/test/runtime/ets/funcRefWithRestArguments.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 83a8ff559d..f5bcb5f098 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -409,6 +409,13 @@ public: bool ifaceOverride); void ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaObject, ir::ArrowFunctionExpression *lambda, ir::MethodDefinition *proxyMethod, bool isStatic, bool ifaceOverride); + ArenaVector ResolveCallParametersForLambdaFuncBody(ir::ClassDefinition *lambdaObject, + ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, bool isStatic, + bool ifaceOverride); + ArenaVector ResolveCallParametersForLambdaFuncBody(Signature *signatureRef, + ir::ScriptFunction *invokeFunc, + bool ifaceOverride); void CheckCapturedVariables(); void CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var); void CheckCapturedVariable(ir::AstNode *node, varbinder::Variable *var); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 438481b54f..154f412389 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -48,7 +48,6 @@ #include "ir/expressions/literals/undefinedLiteral.h" #include "ir/expressions/memberExpression.h" #include "ir/expressions/objectExpression.h" -#include "ir/expressions/sequenceExpression.h" #include "ir/expressions/thisExpression.h" #include "ir/statements/blockStatement.h" #include "ir/statements/doWhileStatement.h" @@ -59,8 +58,6 @@ #include "ir/statements/returnStatement.h" #include "ir/statements/switchStatement.h" #include "ir/statements/whileStatement.h" -#include "ir/ts/tsArrayType.h" -#include "ir/ts/tsInterfaceBody.h" #include "ir/ts/tsTypeAliasDeclaration.h" #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterInstantiation.h" @@ -1480,6 +1477,37 @@ void ETSChecker::ResolveLambdaObject(ir::ClassDefinition *lambdaObject, ETSObjec ResolveLambdaObjectInvoke(lambdaObject, lambda, proxyMethod, !saveThis, false); } +static void CreateParametersForInvokeSignature(ETSChecker *checker, ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, SignatureInfo *invokeSignatureInfo, + bool ifaceOverride) +{ + auto *allocator = checker->Allocator(); + 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)_; + if (!ifaceOverride) { + var->SetTsType(param->Variable()->TsType()); + } else if (param->IsRestParameter()) { + var->SetTsType(checker->CreateETSArrayType(checker->GlobalETSNullishObjectType())); + } else { + var->SetTsType(checker->GlobalETSNullishObjectType()); + } + param->Ident()->SetVariable(var); + param->Ident()->SetTsType(var->TsType()); + param->SetTsType(var->TsType()); + invokeFunc->Params().push_back(param); + if (param->IsRestParameter()) { + invokeSignatureInfo->restVar = var->AsLocalVariable(); + } else { + invokeSignatureInfo->minArgCount++; + invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + } + } +} + static Signature *CreateInvokeSignature(ETSChecker *checker, ir::ArrowFunctionExpression *lambda, ir::ScriptFunction *invokeFunc, ETSObjectType *lambdaObjectType, bool ifaceOverride) @@ -1494,18 +1522,7 @@ static Signature *CreateInvokeSignature(ETSChecker *checker, ir::ArrowFunctionEx 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()); - } + CreateParametersForInvokeSignature(checker, lambda, invokeFunc, invokeSignatureInfo, ifaceOverride); } else { auto paramCtx = varbinder::LexicalScope::Enter( checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); @@ -1596,18 +1613,42 @@ static ir::TSAsExpression *BuildNarrowingToType(ETSChecker *checker, ir::Express return paramAsExpr; } -static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSChecker *checker, - ir::ClassDefinition *lambdaObject, - ir::ArrowFunctionExpression *lambda, - ir::ScriptFunction *invokeFunc, - bool isStatic, bool ifaceOverride) +static void AddLambdaFunctionParameters(ETSChecker *checker, ir::ScriptFunction *invokeFunc, + ir::ArrowFunctionExpression *lambda, ArenaVector &callParams) { auto *allocator = checker->Allocator(); + 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()); + if (param->IsRestParameter()) { + auto *spread = + checker->AllocNode(ir::AstNodeType::SPREAD_ELEMENT, allocator, paramIdent); + spread->SetTsType(param->Variable()->TsType()); + callParams.push_back(spread); + } else { + auto *lambdaParam = lambda->Function()->Params()[i]->AsETSParameterExpression(); + auto *const paramCast = + BuildNarrowingToType(checker, paramIdent, lambdaParam->TypeAnnotation()->GetType(checker)); + paramCast->Check(checker); + callParams.push_back(paramCast); + } + } +} + +ArenaVector ETSChecker::ResolveCallParametersForLambdaFuncBody(ir::ClassDefinition *lambdaObject, + ir::ArrowFunctionExpression *lambda, + ir::ScriptFunction *invokeFunc, + bool isStatic, bool ifaceOverride) +{ + auto *allocator = Allocator(); ArenaVector callParams(allocator->Adapter()); - AddFieldRefsToCallParameters(checker, lambdaObject, isStatic, callParams); + AddFieldRefsToCallParameters(this, lambdaObject, isStatic, callParams); - auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto maxParamsNum = GlobalBuiltinFunctionTypeVariadicThreshold(); auto paramsNum = lambda->Function()->Params().size(); if (!ifaceOverride) { for (auto const *const it : invokeFunc->Params()) { @@ -1615,23 +1656,17 @@ static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSC auto *const paramIdent = allocator->New(param->Ident()->Name(), allocator); paramIdent->SetVariable(param->Variable()); paramIdent->SetTsType(param->Variable()->TsType()); - callParams.push_back(paramIdent); + if (param->IsRestParameter()) { + auto *spread = AllocNode(ir::AstNodeType::SPREAD_ELEMENT, allocator, paramIdent); + spread->SetTsType(param->Variable()->TsType()); + callParams.push_back(spread); + } else { + 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 = - BuildNarrowingToType(checker, paramIdent, lambdaParam->TypeAnnotation()->GetType(checker)); - paramCast->Check(checker); - callParams.push_back(paramCast); - } + AddLambdaFunctionParameters(this, invokeFunc, lambda, callParams); } else { ASSERT(invokeFunc->Params().size() == 1); auto const *const param = invokeFunc->Params()[0]->AsETSParameterExpression(); @@ -1645,8 +1680,8 @@ static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSC true, false); auto *lambdaParam = lambda->Function()->Params()[i]->AsETSParameterExpression(); - auto *const paramCast = BuildNarrowingToType(checker, arg, lambdaParam->TypeAnnotation()->GetType(checker)); - paramCast->Check(checker); + auto *const paramCast = BuildNarrowingToType(this, arg, lambdaParam->TypeAnnotation()->GetType(this)); + paramCast->Check(this); callParams.push_back(paramCast); } } @@ -1689,7 +1724,7 @@ void ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaOb // Resolve the proxy method call arguments, first we add the captured fields to the call auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); ArenaVector callParams = - ResolveCallParametersForLambdaFuncBody(this, lambdaObject, lambda, invokeFunc, isStatic, ifaceOverride); + ResolveCallParametersForLambdaFuncBody(lambdaObject, lambda, invokeFunc, isStatic, ifaceOverride); // Create the synthetic call expression to the proxy method auto *resolvedCall = AllocNode(callee, std::move(callParams), nullptr, false); @@ -1788,8 +1823,13 @@ void ETSChecker::ResolveProxyMethod(ir::ClassDefinition *const classDefinition, signatureInfo->restVar = nullptr; for (auto const *const it : proxyMethod->Function()->Params()) { - signatureInfo->params.push_back(it->AsETSParameterExpression()->Variable()->AsLocalVariable()); - ++signatureInfo->minArgCount; + auto *param = it->AsETSParameterExpression(); + if (param->IsRestParameter()) { + signatureInfo->restVar = param->Variable()->AsLocalVariable(); + } else { + signatureInfo->params.push_back(param->Variable()->AsLocalVariable()); + ++signatureInfo->minArgCount; + } } signature->SetReturnType(lambda->Function()->Signature()->ReturnType()); @@ -2522,6 +2562,48 @@ void ETSChecker::ResolveLambdaObjectCtor(ir::ClassDefinition *lambdaObject, bool fieldinit->Right()->SetTsType(ctorSignature->Params()[0]->TsType()); } +static void CreateParametersForInvokeSignature(ETSChecker *checker, Signature *signatureRef, + ir::ScriptFunction *invokeFunc, bool ifaceOverride) +{ + auto *allocator = checker->Allocator(); + + // Create the signature for the invoke function type + auto *invokeSignatureInfo = checker->CreateSignatureInfo(); + 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->GlobalETSNullishObjectType() : it->TsType()); + paramIdent->SetVariable(var); + invokeFunc->Params().push_back(param); + invokeSignatureInfo->minArgCount++; + invokeSignatureInfo->params.push_back(var->AsLocalVariable()); + } + if (signatureRef->RestVar() != nullptr) { + auto *oldRestVar = signatureRef->RestVar(); + auto paramCtx = varbinder::LexicalScope::Enter( + checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); + auto *restParamIdent = checker->AllocNode(oldRestVar->Name(), allocator); + auto *restParamSpread = + checker->AllocNode(ir::AstNodeType::REST_ELEMENT, allocator, restParamIdent); + auto *restParam = checker->AllocNode(restParamSpread, nullptr); + auto [_, restVar] = checker->VarBinder()->AddParamDecl(restParam); + (void)_; + if (ifaceOverride) { + restVar->SetTsType(allocator->New(checker->GlobalETSNullishObjectType())); + } else { + restVar->SetTsType(oldRestVar->TsType()); + } + restParamIdent->SetVariable(restVar); + invokeFunc->Params().push_back(restParam); + invokeSignatureInfo->restVar = restVar->AsLocalVariable(); + } +} + static Signature *CreateInvokeSignature(ETSChecker *checker, Signature *signatureRef, ir::ScriptFunction *invokeFunc, ETSObjectType *lambdaObjectType, bool ifaceOverride) { @@ -2535,20 +2617,7 @@ static Signature *CreateInvokeSignature(ETSChecker *checker, Signature *signatur 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()); - } + CreateParametersForInvokeSignature(checker, signatureRef, invokeFunc, ifaceOverride); } else { auto paramCtx = varbinder::LexicalScope::Enter( checker->VarBinder(), invokeFunc->Scope()->ParamScope(), false); @@ -2616,15 +2685,35 @@ static ir::Expression *BuildParamExpression(ETSChecker *checker, ir::Identifier return paramCast; } -static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSChecker *checker, - Signature *signatureRef, - ir::ScriptFunction *invokeFunc, - bool ifaceOverride) +static void AddLambdaFunctionParameters(ETSChecker *checker, Signature *signatureRef, ir::ScriptFunction *invokeFunc, + ArenaVector &callParams) { auto *allocator = checker->Allocator(); + 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()); + if (param->IsRestParameter()) { + auto *spreadArg = BuildParamExpression(checker, paramIdent, signatureRef->RestVar()->TsType()); + auto *spread = checker->AllocNode(ir::AstNodeType::SPREAD_ELEMENT, allocator, spreadArg); + spread->SetTsType(signatureRef->RestVar()->TsType()); + callParams.push_back(spread); + } else { + callParams.push_back(BuildParamExpression(checker, paramIdent, signatureRef->Params()[i]->TsType())); + } + } +} + +ArenaVector ETSChecker::ResolveCallParametersForLambdaFuncBody(Signature *signatureRef, + ir::ScriptFunction *invokeFunc, + bool ifaceOverride) +{ + auto *allocator = Allocator(); ArenaVector callParams(allocator->Adapter()); - auto maxParamsNum = checker->GlobalBuiltinFunctionTypeVariadicThreshold(); + auto maxParamsNum = GlobalBuiltinFunctionTypeVariadicThreshold(); auto paramsNum = signatureRef->Params().size(); if (!ifaceOverride) { for (size_t idx = 0; idx != paramsNum; idx++) { @@ -2635,14 +2724,7 @@ static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSC } } 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())); - } + AddLambdaFunctionParameters(this, signatureRef, invokeFunc, callParams); } else { ASSERT(invokeFunc->Params().size() == 1); auto const *const param = invokeFunc->Params()[0]->AsETSParameterExpression(); @@ -2657,7 +2739,7 @@ static ArenaVector ResolveCallParametersForLambdaFuncBody(ETSC auto *type = signatureRef->Params()[i]->TsType(); if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - arg->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(type)); + arg->AddBoxingUnboxingFlags(GetUnboxingFlag(type)); callParams.push_back(arg); } else { auto *const paramCast = allocator->New(arg, nullptr, false); @@ -2707,7 +2789,7 @@ void ETSChecker::ResolveLambdaObjectInvokeFuncBody(ir::ClassDefinition *lambdaOb // Create the parameters for the referenced function call auto *invokeFunc = lambdaBody[lambdaBody.size() - (ifaceOverride ? 2 : 1)]->AsMethodDefinition()->Function(); ArenaVector callParams = - ResolveCallParametersForLambdaFuncBody(this, signatureRef, invokeFunc, ifaceOverride); + ResolveCallParametersForLambdaFuncBody(signatureRef, invokeFunc, ifaceOverride); // Create the synthetic call expression to the referenced function auto *resolvedCall = AllocNode(callee, std::move(callParams), nullptr, false); diff --git a/ets2panda/checker/types/signature.cpp b/ets2panda/checker/types/signature.cpp index 02447428bf..930cb7729e 100644 --- a/ets2panda/checker/types/signature.cpp +++ b/ets2panda/checker/types/signature.cpp @@ -160,8 +160,6 @@ void Signature::ToString(std::stringstream &ss, const varbinder::Variable *varia ss << signatureInfo_->restVar->Name(); ss << ": "; signatureInfo_->restVar->TsType()->ToString(ss, precise); - - ss << "[]"; } ss << ")"; diff --git a/ets2panda/checker/types/signature.h b/ets2panda/checker/types/signature.h index 63127d3e98..e0ea0292e5 100644 --- a/ets2panda/checker/types/signature.h +++ b/ets2panda/checker/types/signature.h @@ -46,6 +46,7 @@ public: if (other->restVar != nullptr) { restVar = other->restVar->Copy(allocator, other->restVar->Declaration()); + restVar->SetTsType(other->restVar->TsType()); } } diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 47f6805334..97c77fddba 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -743,8 +743,15 @@ void ConvertArgumentsForFunctionalCall(checker::ETSChecker *const checker, const 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()); + checker::Type *paramType; + if (i < signature->Params().size()) { + paramType = checker->MaybeBoxedType(signature->Params()[i], checker->Allocator()); + } else { + ASSERT(signature->RestVar() != nullptr); + auto *restType = signature->RestVar()->TsType(); + ASSERT(restType->IsETSArrayType()); + paramType = restType->AsETSArrayType()->ElementType(); + } auto *arg = arguments[i]; auto *cast = checker->Allocator()->New(arg, nullptr, false); diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 9303cb3a49..16cfea00b2 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -40,7 +40,6 @@ #include "ets/defaultParameterLowering.h" #include "lexer/token/sourceLocation.h" #include "public/es2panda_lib.h" -#include "utils/json_builder.h" namespace ark::es2panda::compiler { @@ -82,6 +81,11 @@ static InitScopesPhaseTs g_initScopesPhaseTs; static InitScopesPhaseJs g_initScopesPhaseJs; // NOLINTEND(fuchsia-statically-constructed-objects) +static void CheckOptionsBeforePhase(const CompilerOptions *options, const parser::Program *program, + const std::string &name); +static void CheckOptionsAfterPhase(const CompilerOptions *options, const parser::Program *program, + const std::string &name); + std::vector GetETSPhaseList() { return { @@ -184,8 +188,8 @@ bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) return true; } -void Phase::CheckOptionsBeforePhase(const CompilerOptions *options, const parser::Program *program, - const std::string &name) const +static void CheckOptionsBeforePhase(const CompilerOptions *options, const parser::Program *program, + const std::string &name) { if (options->dumpBeforePhases.count(name) > 0) { std::cout << "Before phase " << name << ":" << std::endl; @@ -199,8 +203,8 @@ void Phase::CheckOptionsBeforePhase(const CompilerOptions *options, const parser } } -void Phase::CheckOptionsAfterPhase(const CompilerOptions *options, const parser::Program *program, - const std::string &name) const +static void CheckOptionsAfterPhase(const CompilerOptions *options, const parser::Program *program, + const std::string &name) { if (options->dumpAfterPhases.count(name) > 0) { std::cout << "After phase " << name << ":" << std::endl; diff --git a/ets2panda/compiler/lowering/phase.h b/ets2panda/compiler/lowering/phase.h index af1cb1874d..b726d284ab 100644 --- a/ets2panda/compiler/lowering/phase.h +++ b/ets2panda/compiler/lowering/phase.h @@ -39,12 +39,6 @@ public: { return true; } - -private: - void CheckOptionsBeforePhase(const CompilerOptions *options, const parser::Program *program, - const std::string &name) const; - void CheckOptionsAfterPhase(const CompilerOptions *options, const parser::Program *program, - const std::string &name) const; }; std::vector GetPhaseList(ScriptExtension ext); diff --git a/ets2panda/test/runtime/ets/funcRefWithRestArguments.ets b/ets2panda/test/runtime/ets/funcRefWithRestArguments.ets new file mode 100644 index 0000000000..6926c3e6ee --- /dev/null +++ b/ets2panda/test/runtime/ets/funcRefWithRestArguments.ets @@ -0,0 +1,36 @@ +/* + * 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 + * + * 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 fn(...ns: (Object|null|undefined)[]): int { + let sum: int = 0 + for (const n of ns) { + sum += n as Int + } + return sum +} + +function main(): int { + const fp: FunctionN = fn + assert(fp(2, 3, 5) == 10) + const fp2: FunctionN = (...vs: (Object|null|undefined)[]): int => { + let sum: int = 0 + for (const v of vs) { + sum += v as Int + } + return sum + } + assert (fp2(7, 11, 13) == 31) + return 0 +} diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index 4c19590eca..d8393a0202 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -253,7 +253,7 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&dumpBeforePhases); argparser_->Add(&dumpEtsSrcBeforePhases); argparser_->Add(&dumpAfterPhases); - argparser_->Add(&dumpEtsSrcBeforePhases); + argparser_->Add(&dumpEtsSrcAfterPhases); argparser_->Add(&arktsConfig); argparser_->Add(&opTsDeclOut); @@ -346,7 +346,7 @@ bool Options::Parse(int argc, const char **argv) return false; } - if ((dumpEtsSrcAfterPhases.GetValue().size() + dumpEtsSrcAfterPhases.GetValue().size() > 0) && + if ((dumpEtsSrcBeforePhases.GetValue().size() + dumpEtsSrcAfterPhases.GetValue().size() > 0) && extension_ != es2panda::ScriptExtension::ETS) { errorMsg_ = "--dump-ets-src-* option is valid only with ETS extension"; return false; @@ -371,7 +371,7 @@ bool Options::Parse(int argc, const char **argv) compilerOptions_.verifierErrors = SplitToStringSet(verifierErrors.GetValue()); compilerOptions_.dumpBeforePhases = SplitToStringSet(dumpBeforePhases.GetValue()); compilerOptions_.dumpEtsSrcBeforePhases = SplitToStringSet(dumpEtsSrcBeforePhases.GetValue()); - compilerOptions_.dumpAfterPhases = SplitToStringSet(dumpBeforePhases.GetValue()); + compilerOptions_.dumpAfterPhases = SplitToStringSet(dumpAfterPhases.GetValue()); compilerOptions_.dumpEtsSrcAfterPhases = SplitToStringSet(dumpEtsSrcAfterPhases.GetValue()); return true; -- Gitee