@@ -94,11 +94,26 @@ static inline void fillArgsFromStarArg(Box** args_out, Box* given_varargs, ArgPa
94
94
}
95
95
}
96
96
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
+ }
102
117
}
103
118
}
104
119
@@ -128,7 +143,8 @@ extern "C" BoxedTuple* makeVarArgsFromArgsAndStarArgs(Box* arg1, Box* arg2, Box*
128
143
assert (argspec.has_starargs );
129
144
assert (paramspec.takes_varargs );
130
145
131
- llvm::SmallVector<Box*, 8 > starParamElts;
146
+ // TODO use PyTuple_Resize
147
+ std::vector<Box*, StlCompatAllocator<Box*>> starParamElts;
132
148
133
149
for (int i = paramspec.num_args ; i < argspec.num_args ; i++) {
134
150
starParamElts.push_back (getArg (i, arg1, arg2, arg3, args));
@@ -258,8 +274,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
258
274
Box* ovarargs = BoxedTuple::create (unused_positional.size (), &unused_positional[0 ]);
259
275
getArg (varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs;
260
276
} 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
+ }
263
286
}
264
287
265
288
// //
@@ -331,10 +354,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
331
354
// Fill with defaults:
332
355
333
356
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
+ }
338
366
}
339
367
340
368
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
367
395
if (argspec.has_starargs && !paramspec.num_defaults ) {
368
396
assert (!argspec.has_kwargs );
369
397
assert (!argspec.num_keywords );
398
+ assert (!paramspec.num_defaults );
399
+
370
400
// We just dispatch to a helper function to copy the args and call pyElements
371
401
// TODO In some cases we can be smarter depending on the arrangement of args and type
372
402
// 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
375
405
assert (paramspec.takes_varargs );
376
406
377
407
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 ));
382
413
callargs.push_back (rewrite_args->rewriter ->loadConst (argspec.asInt ()));
383
414
callargs.push_back (rewrite_args->rewriter ->loadConst (paramspec.asInt ()));
384
415
RewriterVar* r_varargs = rewrite_args->rewriter ->call (true /* has side effects */ ,
0 commit comments