py: Fix compiler to handle lambdas used as default arguments.
Addresses issue #1709.
This commit is contained in:
parent
bb7f5b5501
commit
29e9db0c58
12
py/compile.c
12
py/compile.c
@ -662,6 +662,13 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {
|
STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {
|
||||||
|
// When we call compile_funcdef_lambdef_param below it can compile an arbitrary
|
||||||
|
// expression for default arguments, which may contain a lambda. The lambda will
|
||||||
|
// call here in a nested way, so we must save and restore the relevant state.
|
||||||
|
bool orig_have_star = comp->have_star;
|
||||||
|
uint16_t orig_num_dict_params = comp->num_dict_params;
|
||||||
|
uint16_t orig_num_default_params = comp->num_default_params;
|
||||||
|
|
||||||
// compile default parameters
|
// compile default parameters
|
||||||
comp->have_star = false;
|
comp->have_star = false;
|
||||||
comp->num_dict_params = 0;
|
comp->num_dict_params = 0;
|
||||||
@ -681,6 +688,11 @@ STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_n
|
|||||||
|
|
||||||
// make the function
|
// make the function
|
||||||
close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
|
close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
|
||||||
|
|
||||||
|
// restore state
|
||||||
|
comp->have_star = orig_have_star;
|
||||||
|
comp->num_dict_params = orig_num_dict_params;
|
||||||
|
comp->num_default_params = orig_num_default_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
// leaves function object on stack
|
// leaves function object on stack
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# testing default args to a function
|
||||||
|
|
||||||
def fun1(val=5):
|
def fun1(val=5):
|
||||||
print(val)
|
print(val)
|
||||||
|
|
||||||
@ -18,3 +20,10 @@ try:
|
|||||||
fun2(1, 2, 3, 4)
|
fun2(1, 2, 3, 4)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
print("TypeError")
|
print("TypeError")
|
||||||
|
|
||||||
|
# lambda as default arg (exposes nested behaviour in compiler)
|
||||||
|
def f(x=lambda:1):
|
||||||
|
return x()
|
||||||
|
print(f())
|
||||||
|
print(f(f))
|
||||||
|
print(f(lambda:2))
|
||||||
|
@ -57,3 +57,10 @@ def f(a, *b, c):
|
|||||||
f(1, c=2)
|
f(1, c=2)
|
||||||
f(1, 2, c=3)
|
f(1, 2, c=3)
|
||||||
f(a=1, c=3)
|
f(a=1, c=3)
|
||||||
|
|
||||||
|
# lambda as kw-only arg (exposes nested behaviour in compiler)
|
||||||
|
def f(*, x=lambda:1):
|
||||||
|
return x()
|
||||||
|
print(f())
|
||||||
|
print(f(x=f))
|
||||||
|
print(f(x=lambda:2))
|
||||||
|
Loading…
Reference in New Issue
Block a user