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
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** args, const std::vector<const std::string*>* keyword_names) {
/*
......@@ -1843,41 +1878,31 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
for (int i = 0; i < argspec.num_keywords; i++) {
assert(!rewrite_args && "would need to be handled here");
assert(arg_names);
int arg_idx = i + argspec.num_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);
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;
params_filled[j] = true;
Box* kwargs
= 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;
break;
}
}
BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs);
for (auto& p : d_kwargs->d) {
if (p.first->cls != str_cls)
raiseExcHelper(TypeError, "<function>() keywords must be strings");
if (!found) {
if (okwargs) {
okwargs->d[boxString(*(*keyword_names)[i])] = kw_val;
} else {
raiseExcHelper(TypeError, "<function>() got an unexpected keyword argument '%s'",
(*keyword_names)[i]->c_str());
}
BoxedString* s = static_cast<BoxedString*>(p.first);
placeKeyword(*arg_names, params_filled, s->s, p.second, oarg1, oarg2, oarg3, oargs, okwargs);
}
}
RELEASE_ASSERT(!argspec.has_kwargs, "need to copy the above");
......
......@@ -26,3 +26,4 @@ def f(a=1, b=2, **kw):
f(b=3, c=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