Skip to content

Commit 9a42eb5

Browse files
committed
py: Fix naming of function arguments when function is a closure.
Addresses issue adafruit#1226.
1 parent cd87d20 commit 9a42eb5

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

py/emitbc.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,26 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
305305
// we store them as full word-sized objects for efficient access in mp_setup_code_state
306306
// this is the start of the prelude and is guaranteed to be aligned on a word boundary
307307
{
308+
// For a given argument position (indexed by i) we need to find the
309+
// corresponding id_info which is a parameter, as it has the correct
310+
// qstr name to use as the argument name. Note that it's not a simple
311+
// 1-1 mapping (ie i!=j in general) because of possible closed-over
312+
// variables. In the case that the argument i has no corresponding
313+
// parameter we use "*" as its name (since no argument can ever be named
314+
// "*"). We could use a blank qstr but "*" is better for debugging.
315+
// Note: there is some wasted RAM here for the case of storing a qstr
316+
// for each closed-over variable, and maybe there is a better way to do
317+
// it, but that would require changes to mp_setup_code_state.
308318
for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
309-
emit_write_bytecode_prealigned_ptr(emit, MP_OBJ_NEW_QSTR(scope->id_info[i].qst));
319+
qstr qst = MP_QSTR__star_;
320+
for (int j = 0; j < scope->id_info_len; ++j) {
321+
id_info_t *id = &scope->id_info[j];
322+
if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
323+
qst = id->qst;
324+
break;
325+
}
326+
}
327+
emit_write_bytecode_prealigned_ptr(emit, MP_OBJ_NEW_QSTR(qst));
310328
}
311329
}
312330

py/emitnative.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,17 @@ STATIC void emit_native_end_pass(emit_t *emit) {
796796
ASM_DATA(emit->as, 1, emit->code_info_size);
797797
ASM_ALIGN(emit->as, ASM_WORD_SIZE);
798798
emit->code_info_size = ASM_GET_CODE_POS(emit->as) - emit->code_info_offset;
799+
// see comment in corresponding part of emitbc.c about the logic here
799800
for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) {
800-
ASM_DATA(emit->as, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(emit->scope->id_info[i].qst));
801+
qstr qst = MP_QSTR__star_;
802+
for (int j = 0; j < emit->scope->id_info_len; ++j) {
803+
id_info_t *id = &emit->scope->id_info[j];
804+
if ((id->flags & ID_FLAG_IS_PARAM) && id->local_num == i) {
805+
qst = id->qst;
806+
break;
807+
}
808+
}
809+
ASM_DATA(emit->as, ASM_WORD_SIZE, (mp_uint_t)MP_OBJ_NEW_QSTR(qst));
801810
}
802811

803812
// bytecode prelude: initialise closed over variables

tests/basics/closure_namedarg.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# test passing named arg to closed-over function
2+
3+
def f():
4+
x = 1
5+
def g(z):
6+
print(x, z)
7+
return g
8+
9+
f()(z=42)

tests/cmdline/cmd_showbc.py.exp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @
354354
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
355355
########
356356
\.\+5b
357-
arg names: c e
357+
arg names: * * *
358358
(N_STATE 6)
359359
(N_EXC_STACK 0)
360360
bc=-\\d\+ line=1
@@ -373,7 +373,7 @@ File cmdline/cmd_showbc.py, code block '<listcomp>' (descriptor: \.\+, bytecode
373373
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
374374
########
375375
\.\+5b
376-
arg names: c e
376+
arg names: * * *
377377
(N_STATE 7)
378378
(N_EXC_STACK 0)
379379
bc=-\\d\+ line=1
@@ -391,7 +391,7 @@ File cmdline/cmd_showbc.py, code block '<dictcomp>' (descriptor: \.\+, bytecode
391391
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
392392
########
393393
\.\+5b
394-
arg names: c e
394+
arg names: * * *
395395
(N_STATE 8)
396396
(N_EXC_STACK 0)
397397
bc=-\\d\+ line=1
@@ -411,7 +411,7 @@ File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.
411411
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
412412
########
413413
\.\+5b
414-
arg names: x
414+
arg names: *
415415
(N_STATE 4)
416416
(N_EXC_STACK 0)
417417
bc=-\\d\+ line=1
@@ -430,7 +430,7 @@ File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ byt
430430
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
431431
########
432432
\.\+5b
433-
arg names: b a
433+
arg names: * b
434434
(N_STATE 4)
435435
(N_EXC_STACK 0)
436436
bc=-\\d\+ line=1

0 commit comments

Comments
 (0)