mirror of
https://github.com/vim/vim.git
synced 2025-08-24 19:45:50 -04:00
patch 9.1.1614: Vim9: possible variable type change
Problem: Vim9: possible variable type change when using closure in a for loop (Maxim Kim) Solution: Use unwind_locals(..., TRUE) (Yegappan Lakshmanan) fixes: #17844 closes: #17951 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
a2bb21a895
commit
f56f490ca2
@ -4002,4 +4002,71 @@ def Test_disassemble_has_shortcircuit()
|
|||||||
'1 RETURN', g:instr)
|
'1 RETURN', g:instr)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
" Disassemble the code generated for a loop with closure following another loop
|
||||||
|
def Test_disassemble_loop_with_closure_after_loop()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Fn()
|
||||||
|
for i in "a"
|
||||||
|
var v1 = 0
|
||||||
|
endfor
|
||||||
|
var idx = 1
|
||||||
|
while idx > 0
|
||||||
|
idx -= 1
|
||||||
|
endwhile
|
||||||
|
var s = "abc"
|
||||||
|
for j in range(2)
|
||||||
|
var k = 0
|
||||||
|
g:Ref = () => j
|
||||||
|
endfor
|
||||||
|
enddef
|
||||||
|
g:instr = execute('disassemble Fn')
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
assert_match('<SNR>\d\+_Fn\_s*' ..
|
||||||
|
'for i in "a"\_s*' ..
|
||||||
|
'0 STORE -1 in $0\_s*' ..
|
||||||
|
'1 PUSHS "a"\_s*' ..
|
||||||
|
'2 FOR $0 -> 6\_s*' ..
|
||||||
|
'3 STORE $2\_s*' ..
|
||||||
|
'var v1 = 0\_s*' ..
|
||||||
|
'4 STORE 0 in $3\_s*' ..
|
||||||
|
'endfor\_s*' ..
|
||||||
|
'5 JUMP -> 2\_s*' ..
|
||||||
|
'6 DROP\_s*' ..
|
||||||
|
'var idx = 1\_s*' ..
|
||||||
|
'7 STORE 1 in $4\_s*' ..
|
||||||
|
'while idx > 0\_s*' ..
|
||||||
|
'8 LOAD $4\_s*' ..
|
||||||
|
'9 PUSHNR 0\_s*' ..
|
||||||
|
'10 COMPARENR >\_s*' ..
|
||||||
|
'11 WHILE $5 -> 17\_s*' ..
|
||||||
|
'idx -= 1\_s*' ..
|
||||||
|
'12 LOAD $4\_s*' ..
|
||||||
|
'13 PUSHNR 1\_s*' ..
|
||||||
|
'14 OPNR -\_s*' ..
|
||||||
|
'15 STORE $4\_s*' ..
|
||||||
|
'endwhile\_s*' ..
|
||||||
|
'16 JUMP -> 8\_s*' ..
|
||||||
|
'var s = "abc"\_s*' ..
|
||||||
|
'17 PUSHS "abc"\_s*' ..
|
||||||
|
'18 STORE $6\_s*' ..
|
||||||
|
'for j in range(2)\_s*' ..
|
||||||
|
'19 STORE -1 in $7\_s*' ..
|
||||||
|
'20 PUSHNR 2\_s*' ..
|
||||||
|
'21 BCALL range(argc 1)\_s*' ..
|
||||||
|
'22 FOR $7 -> 29\_s*' ..
|
||||||
|
'23 STORE $9\_s*' ..
|
||||||
|
'var k = 0\_s*' ..
|
||||||
|
'24 STORE 0 in $10\_s*' ..
|
||||||
|
'g:Ref = () => j\_s*' ..
|
||||||
|
'25 FUNCREF <lambda>\d\+ vars $10-$10\_s*' ..
|
||||||
|
'26 STOREG g:Ref\_s*' ..
|
||||||
|
'endfor\_s*' ..
|
||||||
|
'27 ENDLOOP ref $8 save $10-$10 depth 0\_s*' ..
|
||||||
|
'28 JUMP -> 22\_s*' ..
|
||||||
|
'29 DROP\_s*' ..
|
||||||
|
'30 RETURN void', g:instr)
|
||||||
|
enddef
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@ -2832,6 +2832,35 @@ def Test_define_global_closure_in_loops()
|
|||||||
delfunc g:Global_2c
|
delfunc g:Global_2c
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
" Test for using a closure in a for loop after another for/while loop
|
||||||
|
def Test_for_loop_with_closure_after_another_loop()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Fn()
|
||||||
|
# first loop with a local variable
|
||||||
|
for i in 'a'
|
||||||
|
var v1 = 0
|
||||||
|
endfor
|
||||||
|
var idx = 1
|
||||||
|
while idx > 0
|
||||||
|
idx -= 1
|
||||||
|
endwhile
|
||||||
|
var results = []
|
||||||
|
var s = 'abc'
|
||||||
|
# second loop with a local variable and a funcref
|
||||||
|
for j in range(2)
|
||||||
|
var k = 0
|
||||||
|
results->add(s)
|
||||||
|
g:FuncRefs = () => j
|
||||||
|
endfor
|
||||||
|
assert_equal(['abc', 'abc'], results)
|
||||||
|
enddef
|
||||||
|
Fn()
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
unlet g:FuncRefs
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_for_loop_fails()
|
def Test_for_loop_fails()
|
||||||
v9.CheckDefAndScriptFailure(['for '], ['E1097:', 'E690:'])
|
v9.CheckDefAndScriptFailure(['for '], ['E1097:', 'E690:'])
|
||||||
v9.CheckDefAndScriptFailure(['for x'], ['E1097:', 'E690:'])
|
v9.CheckDefAndScriptFailure(['for x'], ['E1097:', 'E690:'])
|
||||||
|
@ -719,6 +719,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1614,
|
||||||
/**/
|
/**/
|
||||||
1613,
|
1613,
|
||||||
/**/
|
/**/
|
||||||
|
@ -1252,7 +1252,7 @@ compile_endfor(char_u *arg, cctx_T *cctx)
|
|||||||
if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
|
if (compile_loop_end(&forscope->fs_loop_info, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
unwind_locals(cctx, scope->se_local_count, FALSE);
|
unwind_locals(cctx, scope->se_local_count, TRUE);
|
||||||
|
|
||||||
// At end of ":for" scope jump back to the FOR instruction.
|
// At end of ":for" scope jump back to the FOR instruction.
|
||||||
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
||||||
@ -1379,7 +1379,7 @@ compile_endwhile(char_u *arg, cctx_T *cctx)
|
|||||||
if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
|
if (compile_loop_end(&whilescope->ws_loop_info, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
unwind_locals(cctx, scope->se_local_count, FALSE);
|
unwind_locals(cctx, scope->se_local_count, TRUE);
|
||||||
|
|
||||||
#ifdef FEAT_PROFILE
|
#ifdef FEAT_PROFILE
|
||||||
// count the endwhile before jumping
|
// count the endwhile before jumping
|
||||||
|
@ -4510,7 +4510,7 @@ exec_instructions(ectx_T *ectx)
|
|||||||
tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
|
tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Store a value in a list, dict, blob or object variable.
|
// Store a value in a list, tuple, dict, blob or object variable.
|
||||||
case ISN_STOREINDEX:
|
case ISN_STOREINDEX:
|
||||||
{
|
{
|
||||||
int res = execute_storeindex(iptr, ectx);
|
int res = execute_storeindex(iptr, ectx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user