diff options
author | Griffin Smith <root@gws.fyi> | 2020-08-27 12:28:12 -0400 |
---|---|---|
committer | Griffin Smith <root@gws.fyi> | 2020-08-27 12:38:25 -0400 |
commit | 626200713bb3cc844a9feb6af583c9b6b42c6dbc (patch) | |
tree | 14f1b5193add9e0502cd2bbad06f122eef34b2d5 /src/libexpr/eval.cc | |
parent | eb75282b8dc855983368c79cc4c2943c298518f7 (diff) |
Pass all args when auto-calling a function with an ellipsis
The command line options --arg and --argstr that are used by a bunch of
CLI commands to pass arguments to top-level functions in files go
through the same code-path as auto-calling top-level functions with
their default arguments - this, however, was only passing the arguments
that were *explicitly* mentioned in the formals of the function - in the
case of an as-pattern with an ellipsis (eg args @ { ... }) extra passed
arguments would get omitted. This fixes that to instead pass *all*
specified auto args in the case that our function has an ellipsis.
Fixes #598
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0123070d1..00191bce0 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1299,12 +1299,23 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res) Value * actualArgs = allocValue(); mkAttrs(*actualArgs, fun.lambda.fun->formals->formals.size()); - for (auto & i : fun.lambda.fun->formals->formals) { - Bindings::iterator j = args.find(i.name); - if (j != args.end()) - actualArgs->attrs->push_back(*j); - else if (!i.def) - throwTypeError("cannot auto-call a function that has an argument without a default value ('%1%')", i.name); + if (fun.lambda.fun->formals->ellipsis) { + // If the formals have an ellipsis (eg the function accepts extra args) pass + // all available automatic arguments (which includes arguments specified on + // the command line via --arg/--argstr) + for (auto& v : args) { + actualArgs->attrs->push_back(v); + } + } else { + // Otherwise, only pass the arguments that the function accepts + for (auto & i : fun.lambda.fun->formals->formals) { + Bindings::iterator j = args.find(i.name); + if (j != args.end()) { + actualArgs->attrs->push_back(*j); + } else if (!i.def) { + throwTypeError("cannot auto-call a function that has an argument without a default value ('%1%')", i.name); + } + } } actualArgs->attrs->sort(); |