88#include "mpconfig.h"
99#include "qstr.h"
1010#include "obj.h"
11+ #include "objtuple.h"
1112#include "map.h"
1213#include "runtime.h"
1314#include "bc.h"
@@ -136,21 +137,32 @@ mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var
136137typedef struct _mp_obj_fun_bc_t {
137138 mp_obj_base_t base ;
138139 mp_map_t * globals ; // the context within which this function was defined
139- int n_args ; // number of arguments this function takes
140+ short n_args ; // number of arguments this function takes
141+ short n_def_args ; // number of default arguments
140142 uint n_state ; // total state size for the executing function (incl args, locals, stack)
141143 const byte * bytecode ; // bytecode for the function
144+ mp_obj_t def_args []; // values of default args, if any
142145} mp_obj_fun_bc_t ;
143146
144147mp_obj_t fun_bc_call (mp_obj_t self_in , uint n_args , uint n_kw , const mp_obj_t * args ) {
145148 mp_obj_fun_bc_t * self = self_in ;
146149
147- if (n_args != self -> n_args ) {
150+ if (n_args < self -> n_args - self -> n_def_args || n_args > self -> n_args ) {
148151 nlr_jump (mp_obj_new_exception_msg_2_args (MP_QSTR_TypeError , "function takes %d positional arguments but %d were given" , (const char * )(machine_int_t )self -> n_args , (const char * )(machine_int_t )n_args ));
149152 }
150153 if (n_kw != 0 ) {
151154 nlr_jump (mp_obj_new_exception_msg (MP_QSTR_TypeError , "function does not take keyword arguments" ));
152155 }
153156
157+ mp_obj_t full_args [n_args ];
158+ if (n_args < self -> n_args ) {
159+ memcpy (full_args , args , n_args * sizeof (* args ));
160+ int use_def_args = self -> n_args - n_args ;
161+ memcpy (full_args + n_args , self -> def_args + self -> n_def_args - use_def_args , use_def_args * sizeof (* args ));
162+ args = full_args ;
163+ n_args = self -> n_args ;
164+ }
165+
154166 // optimisation: allow the compiler to optimise this tail call for
155167 // the common case when the globals don't need to be changed
156168 mp_map_t * old_globals = rt_globals_get ();
@@ -170,13 +182,22 @@ const mp_obj_type_t fun_bc_type = {
170182 .call = fun_bc_call ,
171183};
172184
173- mp_obj_t mp_obj_new_fun_bc (int n_args , uint n_state , const byte * code ) {
174- mp_obj_fun_bc_t * o = m_new_obj (mp_obj_fun_bc_t );
185+ mp_obj_t mp_obj_new_fun_bc (int n_args , mp_obj_t def_args_in , uint n_state , const byte * code ) {
186+ int n_def_args = 0 ;
187+ mp_obj_tuple_t * def_args = def_args_in ;
188+ if (def_args != MP_OBJ_NULL ) {
189+ n_def_args = def_args -> len ;
190+ }
191+ mp_obj_fun_bc_t * o = m_new_obj_var (mp_obj_fun_bc_t , mp_obj_t , n_def_args );
175192 o -> base .type = & fun_bc_type ;
176193 o -> globals = rt_globals_get ();
177194 o -> n_args = n_args ;
195+ o -> n_def_args = n_def_args ;
178196 o -> n_state = n_state ;
179197 o -> bytecode = code ;
198+ if (def_args != MP_OBJ_NULL ) {
199+ memcpy (o -> def_args , def_args -> items , n_def_args * sizeof (* o -> def_args ));
200+ }
180201 return o ;
181202}
182203
0 commit comments