mirror of
https://github.com/vim/vim.git
synced 2025-09-01 21:03:39 -04:00
patch 9.0.0724: closure in compiled function gets same variable in block
Problem: Closure in compiled function gets same variable in block. Solution: At the end of a block to not always reset the variable count. (issue #11094)
This commit is contained in:
parent
a9a364872e
commit
a275f2cdcc
@ -2314,6 +2314,36 @@ def Test_for_loop_with_closure()
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# also with an extra block level
|
||||
lines =<< trim END
|
||||
var flist: list<func>
|
||||
for i in range(5)
|
||||
{
|
||||
var inloop = i
|
||||
flist[i] = () => inloop
|
||||
}
|
||||
endfor
|
||||
for i in range(5)
|
||||
assert_equal(i, flist[i]())
|
||||
endfor
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# and declaration in higher block
|
||||
lines =<< trim END
|
||||
var flist: list<func>
|
||||
for i in range(5)
|
||||
var inloop = i
|
||||
{
|
||||
flist[i] = () => inloop
|
||||
}
|
||||
endfor
|
||||
for i in range(5)
|
||||
assert_equal(i, flist[i]())
|
||||
endfor
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
var flist: list<func>
|
||||
for i in range(5)
|
||||
|
@ -699,6 +699,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
724,
|
||||
/**/
|
||||
723,
|
||||
/**/
|
||||
|
@ -57,22 +57,20 @@ current_instr_idx(cctx_T *cctx)
|
||||
}
|
||||
/*
|
||||
* Remove local variables above "new_top".
|
||||
* Do this by clearing the name. If "keep" is TRUE do not reset the length, a
|
||||
* closure may still need location of the variable.
|
||||
*/
|
||||
static void
|
||||
unwind_locals(cctx_T *cctx, int new_top)
|
||||
unwind_locals(cctx_T *cctx, int new_top, int keep)
|
||||
{
|
||||
if (cctx->ctx_locals.ga_len > new_top)
|
||||
{
|
||||
int idx;
|
||||
lvar_T *lvar;
|
||||
|
||||
for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
|
||||
for (int idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
|
||||
{
|
||||
lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
|
||||
vim_free(lvar->lv_name);
|
||||
lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
|
||||
VIM_CLEAR(lvar->lv_name);
|
||||
}
|
||||
}
|
||||
cctx->ctx_locals.ga_len = new_top;
|
||||
if (!keep)
|
||||
cctx->ctx_locals.ga_len = new_top;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -81,7 +79,7 @@ unwind_locals(cctx_T *cctx, int new_top)
|
||||
void
|
||||
free_locals(cctx_T *cctx)
|
||||
{
|
||||
unwind_locals(cctx, 0);
|
||||
unwind_locals(cctx, 0, FALSE);
|
||||
ga_clear(&cctx->ctx_locals);
|
||||
}
|
||||
|
||||
@ -525,7 +523,7 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
||||
emsg(_(e_elseif_without_if));
|
||||
return NULL;
|
||||
}
|
||||
unwind_locals(cctx, scope->se_local_count);
|
||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
||||
if (!cctx->ctx_had_return)
|
||||
scope->se_u.se_if.is_had_return = FALSE;
|
||||
|
||||
@ -672,7 +670,7 @@ compile_else(char_u *arg, cctx_T *cctx)
|
||||
emsg(_(e_else_without_if));
|
||||
return NULL;
|
||||
}
|
||||
unwind_locals(cctx, scope->se_local_count);
|
||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
||||
if (!cctx->ctx_had_return)
|
||||
scope->se_u.se_if.is_had_return = FALSE;
|
||||
scope->se_u.se_if.is_seen_else = TRUE;
|
||||
@ -744,7 +742,7 @@ compile_endif(char_u *arg, cctx_T *cctx)
|
||||
return NULL;
|
||||
}
|
||||
ifscope = &scope->se_u.se_if;
|
||||
unwind_locals(cctx, scope->se_local_count);
|
||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
||||
if (!cctx->ctx_had_return)
|
||||
ifscope->is_had_return = FALSE;
|
||||
|
||||
@ -1122,7 +1120,7 @@ compile_endfor(char_u *arg, cctx_T *cctx)
|
||||
if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
|
||||
return NULL;
|
||||
|
||||
unwind_locals(cctx, scope->se_local_count);
|
||||
unwind_locals(cctx, scope->se_local_count, FALSE);
|
||||
|
||||
// At end of ":for" scope jump back to the FOR instruction.
|
||||
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
||||
@ -1249,7 +1247,7 @@ compile_endwhile(char_u *arg, cctx_T *cctx)
|
||||
if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
|
||||
return NULL;
|
||||
|
||||
unwind_locals(cctx, scope->se_local_count);
|
||||
unwind_locals(cctx, scope->se_local_count, FALSE);
|
||||
|
||||
#ifdef FEAT_PROFILE
|
||||
// count the endwhile before jumping
|
||||
@ -1471,7 +1469,7 @@ compile_endblock(cctx_T *cctx)
|
||||
scope_T *scope = cctx->ctx_scope;
|
||||
|
||||
cctx->ctx_scope = scope->se_outer;
|
||||
unwind_locals(cctx, scope->se_local_count);
|
||||
unwind_locals(cctx, scope->se_local_count, TRUE);
|
||||
vim_free(scope);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,8 @@ lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx)
|
||||
for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx)
|
||||
{
|
||||
lvp = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
|
||||
if (STRNCMP(name, lvp->lv_name, len) == 0
|
||||
if (lvp->lv_name != NULL
|
||||
&& STRNCMP(name, lvp->lv_name, len) == 0
|
||||
&& STRLEN(lvp->lv_name) == len)
|
||||
{
|
||||
if (lvar != NULL)
|
||||
|
Loading…
x
Reference in New Issue
Block a user