Bind local name for decorated function early so it can be closed

This commit is contained in:
K. Lange 2023-12-12 18:57:05 +09:00
parent 0425becba9
commit f247bba985
5 changed files with 44 additions and 4 deletions

View File

@ -1847,6 +1847,10 @@ static KrkToken decorator(struct GlobalState * state, size_t level, FunctionType
if (identifiersEqual(&at_classmethod, &state->parser.current)) type = TYPE_CLASSMETHOD;
}
if (level == 0 && inType == TYPE_FUNCTION && state->current->scopeDepth != 0) {
emitByte(OP_NONE);
}
expression(state);
consume(TOKEN_EOL, "Expected end of line after decorator.");
@ -1863,6 +1867,10 @@ static KrkToken decorator(struct GlobalState * state, size_t level, FunctionType
if (type == TYPE_METHOD && funcName.length == 8 && !memcmp(funcName.start,"__init__",8)) {
type = TYPE_INIT;
}
if (type == TYPE_FUNCTION && state->current->scopeDepth > 0) {
declareVariable(state);
markInitialized(state);
}
function(state, type, blockWidth);
} else if (match(TOKEN_ASYNC)) {
if (!match(TOKEN_DEF)) {
@ -1871,6 +1879,10 @@ static KrkToken decorator(struct GlobalState * state, size_t level, FunctionType
}
consume(TOKEN_IDENTIFIER, "Expected coroutine name after 'def'.");
funcName = state->parser.previous;
if (type == TYPE_FUNCTION && state->current->scopeDepth > 0) {
declareVariable(state);
markInitialized(state);
}
function(state, type == TYPE_METHOD ? TYPE_COROUTINE_METHOD : TYPE_COROUTINE, blockWidth);
} else if (check(TOKEN_AT)) {
funcName = decorator(state, level+1, type);
@ -1889,10 +1901,12 @@ static KrkToken decorator(struct GlobalState * state, size_t level, FunctionType
if (level == 0) {
if (inType == TYPE_FUNCTION) {
state->parser.previous = funcName;
declareVariable(state);
size_t ind = (state->current->scopeDepth > 0) ? 0 : identifierConstant(state, &funcName);
defineVariable(state, ind);
if (state->current->scopeDepth == 0) {
size_t ind = identifierConstant(state, &funcName);
defineVariable(state, ind);
} else {
emitByte(OP_SWAP_POP);
}
} else {
size_t ind = identifierConstant(state, &funcName);
rememberClassProperty(state, ind);

View File

@ -121,3 +121,4 @@ SIMPLE(OP_TUPLE_FROM_LIST)
OPERAND(OP_UNPACK_EX,NOOP)
JUMP(OP_ENTER_EXCEPT,+)
SIMPLE(OP_SWAP_POP)

View File

@ -2258,6 +2258,7 @@ _finishReturn: (void)0;
case OP_FALSE: krk_push(BOOLEAN_VAL(0)); break;
case OP_UNSET: krk_push(KWARGS_VAL(0)); break;
case OP_NOT: krk_currentThread.stackTop[-1] = BOOLEAN_VAL(krk_isFalsey(krk_peek(0))); break;
case OP_SWAP_POP: krk_swap(1); /* fallthrough */
case OP_POP: krk_pop(); break;
case OP_INPLACE_ADD: INPLACE_BINARY_OP(add)

View File

@ -0,0 +1,18 @@
def decorate(func):
def _inner(a):
print('in')
a = func(a)
print('out')
return a
return _inner
def foo():
@decorate
def bar(a):
if a <= 0:
return 0
return bar(a-1)
bar(2)
foo()

View File

@ -0,0 +1,6 @@
in
in
in
out
out
out