@@ -94,11 +94,26 @@ static inline void fillArgsFromStarArg(Box** args_out, Box* given_varargs, ArgPa
9494 }
9595 }
9696
97- if (i < numParams || (i > numParams && !takesStarParam)) {
98- if (takesStarParam) {
99- raiseExcHelper (TypeError, takesStarParam ? " %s() takes at least %d argument%s (%d given)"
100- : " %s() takes exactly %d argument%s (%d given)" ,
101- fname, paramspec.num_args , paramspec.num_args == 1 ? " " : " s" , argspec.num_args + i);
97+ assert (!paramspec.num_defaults );
98+ // Because there are no defaults, we don't need to do the 'at most' error message.
99+ // Right now i is the number of args (not eaten by the star param, if applicable)
100+ if (takesStarParam) {
101+ // It takes star params, so it takes at least this many arguments.
102+ // If we found less than that, then error.
103+ if (i < numParams) {
104+ raiseExcHelper (TypeError, " %s() takes at least %d argument%s (%d given)" , fname, paramspec.num_args ,
105+ paramspec.num_args == 1 ? " " : " s" , argspec.num_args + i);
106+ }
107+ } else {
108+ // It doesn't take star params, so we needed to have found exactly numParams
109+ // arguments. If we found any other number, then error.
110+ if (i != numParams) {
111+ if (paramspec.num_args == 0 ) {
112+ raiseExcHelper (TypeError, " %s() takes no arguments (%d given)" , fname, argspec.num_args + i);
113+ } else {
114+ raiseExcHelper (TypeError, " %s() takes exactly %d argument%s (%d given)" , fname, paramspec.num_args ,
115+ paramspec.num_args == 1 ? " " : " s" , argspec.num_args + i);
116+ }
102117 }
103118 }
104119
@@ -128,7 +143,8 @@ extern "C" BoxedTuple* makeVarArgsFromArgsAndStarArgs(Box* arg1, Box* arg2, Box*
128143 assert (argspec.has_starargs );
129144 assert (paramspec.takes_varargs );
130145
131- llvm::SmallVector<Box*, 8 > starParamElts;
146+ // TODO use PyTuple_Resize
147+ std::vector<Box*, StlCompatAllocator<Box*>> starParamElts;
132148
133149 for (int i = paramspec.num_args ; i < argspec.num_args ; i++) {
134150 starParamElts.push_back (getArg (i, arg1, arg2, arg3, args));
@@ -258,8 +274,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
258274 Box* ovarargs = BoxedTuple::create (unused_positional.size (), &unused_positional[0 ]);
259275 getArg (varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs;
260276 } else if (unused_positional.size ()) {
261- raiseExcHelper (TypeError, " %s() takes at most %d argument%s (%d given)" , func_name, paramspec.num_args ,
262- (paramspec.num_args == 1 ? " " : " s" ), argspec.num_args + argspec.num_keywords + varargs.size ());
277+ if (paramspec.num_args == 0 ) {
278+ raiseExcHelper (TypeError, " %s() takes no argument%s (%d given)" , func_name,
279+ (paramspec.num_args == 1 ? " " : " s" ),
280+ argspec.num_args + argspec.num_keywords + varargs.size ());
281+ } else {
282+ raiseExcHelper (TypeError, " %s() takes at most %d argument%s (%d given)" , func_name, paramspec.num_args ,
283+ (paramspec.num_args == 1 ? " " : " s" ),
284+ argspec.num_args + argspec.num_keywords + varargs.size ());
285+ }
263286 }
264287
265288 // //
@@ -331,10 +354,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
331354 // Fill with defaults:
332355
333356 for (int i = 0 ; i < paramspec.num_args - paramspec.num_defaults ; i++) {
334- if (params_filled[i])
335- continue ;
336- // TODO not right error message
337- raiseExcHelper (TypeError, " %s() did not get a value for positional argument %d" , func_name, i);
357+ if (!params_filled[i]) {
358+ // TODO not right error message
359+ if (paramspec.num_defaults || paramspec.takes_varargs )
360+ raiseExcHelper (TypeError, " %s() takes at least %d arguments (%d given)" , func_name,
361+ paramspec.num_args - paramspec.num_defaults , argspec.num_args + varargs.size ());
362+ else
363+ raiseExcHelper (TypeError, " %s() takes exactly %d arguments (%d given)" , func_name,
364+ paramspec.num_args - paramspec.num_defaults , argspec.num_args + varargs.size ());
365+ }
338366 }
339367
340368 for (int arg_idx = paramspec.num_args - paramspec.num_defaults ; arg_idx < paramspec.num_args ; arg_idx++) {
@@ -367,6 +395,8 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
367395 if (argspec.has_starargs && !paramspec.num_defaults ) {
368396 assert (!argspec.has_kwargs );
369397 assert (!argspec.num_keywords );
398+ assert (!paramspec.num_defaults );
399+
370400 // We just dispatch to a helper function to copy the args and call pyElements
371401 // TODO In some cases we can be smarter depending on the arrangement of args and type
372402 // of the star args object. For example if star args is an (immutable) tuple,
@@ -375,10 +405,11 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
375405 assert (paramspec.takes_varargs );
376406
377407 RewriterVar::SmallVector callargs;
378- callargs.push_back (rewrite_args->arg1 ? rewrite_args->arg1 : rewrite_args->rewriter ->loadConst (0 ));
379- callargs.push_back (rewrite_args->arg2 ? rewrite_args->arg2 : rewrite_args->rewriter ->loadConst (0 ));
380- callargs.push_back (rewrite_args->arg3 ? rewrite_args->arg3 : rewrite_args->rewriter ->loadConst (0 ));
381- callargs.push_back (rewrite_args->args ? rewrite_args->args : rewrite_args->rewriter ->loadConst (0 ));
408+ // TODO no need to actually load the constant 0 since makeVarArgsAndStarArgs won't look at them
409+ callargs.push_back (num_passed_args >= 1 ? rewrite_args->arg1 : rewrite_args->rewriter ->loadConst (0 ));
410+ callargs.push_back (num_passed_args >= 2 ? rewrite_args->arg2 : rewrite_args->rewriter ->loadConst (0 ));
411+ callargs.push_back (num_passed_args >= 3 ? rewrite_args->arg3 : rewrite_args->rewriter ->loadConst (0 ));
412+ callargs.push_back (num_passed_args >= 4 ? rewrite_args->args : rewrite_args->rewriter ->loadConst (0 ));
382413 callargs.push_back (rewrite_args->rewriter ->loadConst (argspec.asInt ()));
383414 callargs.push_back (rewrite_args->rewriter ->loadConst (paramspec.asInt ()));
384415 RewriterVar* r_varargs = rewrite_args->rewriter ->call (true /* has side effects */ ,
0 commit comments