Skip to content

Commit 2447a5b

Browse files
committed
py: Support closures with default args.
1 parent c12b221 commit 2447a5b

8 files changed

Lines changed: 35 additions & 8 deletions

File tree

py/bc0.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#define MP_BC_CALL_METHOD_KW (0x98) // uint
9696
#define MP_BC_CALL_METHOD_VAR_KW (0x99) // uint
9797
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x9a) // uint
98+
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x9b) // uint
9899

99100
#define MP_BC_IMPORT_NAME (0xe0) // qstr
100101
#define MP_BC_IMPORT_FROM (0xe1) // qstr

py/compile.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,9 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
766766

767767
// stuff for lambda and comprehensions and generators
768768
void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
769+
if (n_default_params) {
770+
EMIT_ARG(build_tuple, n_default_params);
771+
}
769772
// make closed over variables, if any
770773
// ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
771774
int nfree = 0;

py/emitbc.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -722,16 +722,20 @@ STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_param
722722
emit_pre(emit, 1);
723723
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
724724
} else {
725-
emit_bc_build_tuple(emit, n_default_params);
726725
emit_pre(emit, 0);
727726
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id);
728727
}
729728
}
730729

731730
STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
732-
assert(n_default_params == 0 && n_dict_params == 0);
733-
emit_pre(emit, 0);
734-
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
731+
assert(n_dict_params == 0);
732+
if (n_default_params == 0) {
733+
emit_pre(emit, 0);
734+
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
735+
} else {
736+
emit_pre(emit, -1);
737+
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id);
738+
}
735739
}
736740

737741
STATIC void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {

py/runtime.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,10 +683,10 @@ mp_obj_t rt_make_function_from_id(int unique_code_id, mp_obj_t def_args) {
683683
return fun;
684684
}
685685

686-
mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple) {
686+
mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args) {
687687
DEBUG_OP_printf("make_closure_from_id %d\n", unique_code_id);
688688
// make function object
689-
mp_obj_t ffun = rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
689+
mp_obj_t ffun = rt_make_function_from_id(unique_code_id, def_args);
690690
// wrap function in closure object
691691
return mp_obj_new_closure(ffun, closure_tuple);
692692
}

py/runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mp_obj_t rt_make_function_from_id(int unique_code_id, mp_obj_t def_args);
1919
mp_obj_t rt_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments
2020
mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun);
2121
mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive
22-
mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple);
22+
mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args);
2323
mp_obj_t rt_call_function_0(mp_obj_t fun);
2424
mp_obj_t rt_call_function_1(mp_obj_t fun, mp_obj_t arg);
2525
mp_obj_t rt_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);

py/showbc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,11 @@ void mp_byte_code_print(const byte *ip, int len) {
371371
printf("MAKE_CLOSURE " UINT_FMT, unum);
372372
break;
373373

374+
case MP_BC_MAKE_CLOSURE_DEFARGS:
375+
DECODE_UINT;
376+
printf("MAKE_CLOSURE_DEFARGS " UINT_FMT, unum);
377+
break;
378+
374379
case MP_BC_CALL_FUNCTION:
375380
DECODE_UINT;
376381
printf("CALL_FUNCTION n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);

py/vm.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,13 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
561561

562562
case MP_BC_MAKE_CLOSURE:
563563
DECODE_UINT;
564-
SET_TOP(rt_make_closure_from_id(unum, TOP()));
564+
SET_TOP(rt_make_closure_from_id(unum, TOP(), MP_OBJ_NULL));
565+
break;
566+
567+
case MP_BC_MAKE_CLOSURE_DEFARGS:
568+
DECODE_UINT;
569+
obj1 = POP();
570+
SET_TOP(rt_make_closure_from_id(unum, obj1, TOP()));
565571
break;
566572

567573
case MP_BC_CALL_FUNCTION:

tests/basics/closure-defargs.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def f():
2+
a = 1
3+
def bar(b = 10, c = 20):
4+
print(a + b + c)
5+
bar()
6+
7+
print(f())
8+

0 commit comments

Comments
 (0)