Commit 119ecf1a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Allow passing **kwargs (at callsites)

parent 87539176
...@@ -1660,6 +1660,41 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa ...@@ -1660,6 +1660,41 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
return chosen_cf; return chosen_cf;
} }
static void placeKeyword(const std::vector<AST_expr*>& arg_names, std::vector<bool>& params_filled,
const std::string& kw_name, Box* kw_val, Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** oargs,
BoxedDict* okwargs) {
assert(kw_val);
bool found = false;
for (int j = 0; j < arg_names.size(); j++) {
AST_expr* e = arg_names[j];
if (e->type != AST_TYPE::Name)
continue;
AST_Name* n = ast_cast<AST_Name>(e);
if (n->id == kw_name) {
if (params_filled[j]) {
raiseExcHelper(TypeError, "<function>() got multiple values for keyword argument '%s'",
kw_name.c_str());
}
getArg(j, oarg1, oarg2, oarg3, oargs) = kw_val;
params_filled[j] = true;
found = true;
break;
}
}
if (!found) {
if (okwargs) {
okwargs->d[boxString(kw_name)] = kw_val;
} else {
raiseExcHelper(TypeError, "<function>() got an unexpected keyword argument '%s'", kw_name.c_str());
}
}
}
Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<const std::string*>* keyword_names) { Box** args, const std::vector<const std::string*>* keyword_names) {
/* /*
...@@ -1843,41 +1878,31 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -1843,41 +1878,31 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
for (int i = 0; i < argspec.num_keywords; i++) { for (int i = 0; i < argspec.num_keywords; i++) {
assert(!rewrite_args && "would need to be handled here"); assert(!rewrite_args && "would need to be handled here");
assert(arg_names);
int arg_idx = i + argspec.num_args; int arg_idx = i + argspec.num_args;
Box* kw_val = getArg(arg_idx, arg1, arg2, arg3, args); Box* kw_val = getArg(arg_idx, arg1, arg2, arg3, args);
placeKeyword(*arg_names, params_filled, *(*keyword_names)[i], kw_val, oarg1, oarg2, oarg3, oargs, okwargs);
}
if (argspec.has_kwargs) {
assert(!rewrite_args && "would need to be handled here");
assert(arg_names); assert(arg_names);
bool found = false;
for (int j = 0; j < arg_names->size(); j++) {
AST_expr* e = (*arg_names)[j];
if (e->type != AST_TYPE::Name)
continue;
AST_Name* n = ast_cast<AST_Name>(e);
if (n->id == *(*keyword_names)[i]) {
if (params_filled[j]) {
raiseExcHelper(TypeError, "<function>() got multiple values for keyword argument '%s'",
n->id.c_str());
}
getArg(j, oarg1, oarg2, oarg3, oargs) = kw_val; Box* kwargs
params_filled[j] = true; = getArg(argspec.num_args + argspec.num_keywords + (argspec.has_starargs ? 1 : 0), arg1, arg2, arg3, args);
RELEASE_ASSERT(kwargs->cls == dict_cls, "haven't implemented this for non-dicts");
found = true; BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs);
break; for (auto& p : d_kwargs->d) {
} if (p.first->cls != str_cls)
} raiseExcHelper(TypeError, "<function>() keywords must be strings");
if (!found) { BoxedString* s = static_cast<BoxedString*>(p.first);
if (okwargs) { placeKeyword(*arg_names, params_filled, s->s, p.second, oarg1, oarg2, oarg3, oargs, okwargs);
okwargs->d[boxString(*(*keyword_names)[i])] = kw_val;
} else {
raiseExcHelper(TypeError, "<function>() got an unexpected keyword argument '%s'",
(*keyword_names)[i]->c_str());
}
} }
} }
RELEASE_ASSERT(!argspec.has_kwargs, "need to copy the above");
......
...@@ -26,3 +26,4 @@ def f(a=1, b=2, **kw): ...@@ -26,3 +26,4 @@ def f(a=1, b=2, **kw):
f(b=3, c=4) f(b=3, c=4)
f(b=3, a=4) f(b=3, a=4)
f(b=2, **{'c':3})
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment