mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.3981: Vim9: debugging a for loop doesn't stop before it starts
Problem: Vim9: debugging a for loop doesn't stop before it starts. Solution: Keep the DEBUG instruction before the expression is evaluated. (closes #9456)
This commit is contained in:
@@ -2434,6 +2434,43 @@ def Test_debug_elseif()
|
|||||||
res)
|
res)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def s:DebugFor()
|
||||||
|
echo "hello"
|
||||||
|
for a in [0]
|
||||||
|
echo a
|
||||||
|
endfor
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_debug_for()
|
||||||
|
var res = execute('disass debug s:DebugFor')
|
||||||
|
assert_match('<SNR>\d*_DebugFor\_s*' ..
|
||||||
|
'echo "hello"\_s*' ..
|
||||||
|
'0 DEBUG line 1-1 varcount 0\_s*' ..
|
||||||
|
'1 PUSHS "hello"\_s*' ..
|
||||||
|
'2 ECHO 1\_s*' ..
|
||||||
|
|
||||||
|
'for a in \[0\]\_s*' ..
|
||||||
|
'3 DEBUG line 2-2 varcount 0\_s*' ..
|
||||||
|
'4 STORE -1 in $0\_s*' ..
|
||||||
|
'5 PUSHNR 0\_s*' ..
|
||||||
|
'6 NEWLIST size 1\_s*' ..
|
||||||
|
'7 DEBUG line 2-2 varcount 2\_s*' ..
|
||||||
|
'8 FOR $0 -> 15\_s*' ..
|
||||||
|
'9 STORE $1\_s*' ..
|
||||||
|
|
||||||
|
'echo a\_s*' ..
|
||||||
|
'10 DEBUG line 3-3 varcount 2\_s*' ..
|
||||||
|
'11 LOAD $1\_s*' ..
|
||||||
|
'12 ECHO 1\_s*' ..
|
||||||
|
|
||||||
|
'endfor\_s*' ..
|
||||||
|
'13 DEBUG line 4-4 varcount 2\_s*' ..
|
||||||
|
'14 JUMP -> 7\_s*' ..
|
||||||
|
'15 DROP\_s*' ..
|
||||||
|
'16 RETURN void*',
|
||||||
|
res)
|
||||||
|
enddef
|
||||||
|
|
||||||
func Legacy() dict
|
func Legacy() dict
|
||||||
echo 'legacy'
|
echo 'legacy'
|
||||||
endfunc
|
endfunc
|
||||||
|
@@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
3981,
|
||||||
/**/
|
/**/
|
||||||
3980,
|
3980,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -803,14 +803,13 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
|||||||
if (may_get_next_line_error(wp, &p, cctx) == FAIL)
|
if (may_get_next_line_error(wp, &p, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Remove the already generated ISN_DEBUG, it is written below the ISN_FOR
|
// Find the already generated ISN_DEBUG to get the line number for the
|
||||||
// instruction.
|
// instruction written below the ISN_FOR instruction.
|
||||||
if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
|
if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
|
||||||
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||||
.isn_type == ISN_DEBUG)
|
.isn_type == ISN_DEBUG)
|
||||||
{
|
{
|
||||||
--instr->ga_len;
|
prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||||
prev_lnum = ((isn_T *)instr->ga_data)[instr->ga_len]
|
|
||||||
.isn_arg.debug.dbg_break_lnum;
|
.isn_arg.debug.dbg_break_lnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,6 +874,22 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
|||||||
// "for_end" is set when ":endfor" is found
|
// "for_end" is set when ":endfor" is found
|
||||||
scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
|
scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
|
||||||
|
|
||||||
|
if (cctx->ctx_compile_type == CT_DEBUG)
|
||||||
|
{
|
||||||
|
int save_prev_lnum = cctx->ctx_prev_lnum;
|
||||||
|
isn_T *isn;
|
||||||
|
|
||||||
|
// Add ISN_DEBUG here, before deciding to end the loop. There will
|
||||||
|
// be another ISN_DEBUG before the next instruction.
|
||||||
|
// Use the prev_lnum from the ISN_DEBUG instruction removed above.
|
||||||
|
// Increment the variable count so that the loop variable can be
|
||||||
|
// inspected.
|
||||||
|
cctx->ctx_prev_lnum = prev_lnum;
|
||||||
|
isn = generate_instr_debug(cctx);
|
||||||
|
++isn->isn_arg.debug.dbg_var_names_len;
|
||||||
|
cctx->ctx_prev_lnum = save_prev_lnum;
|
||||||
|
}
|
||||||
|
|
||||||
generate_FOR(cctx, loop_lvar->lv_idx);
|
generate_FOR(cctx, loop_lvar->lv_idx);
|
||||||
|
|
||||||
arg = arg_start;
|
arg = arg_start;
|
||||||
@@ -979,17 +994,6 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
|||||||
arg = skipwhite(p);
|
arg = skipwhite(p);
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cctx->ctx_compile_type == CT_DEBUG)
|
|
||||||
{
|
|
||||||
int save_prev_lnum = cctx->ctx_prev_lnum;
|
|
||||||
|
|
||||||
// Add ISN_DEBUG here, so that the loop variables can be inspected.
|
|
||||||
// Use the prev_lnum from the ISN_DEBUG instruction removed above.
|
|
||||||
cctx->ctx_prev_lnum = prev_lnum;
|
|
||||||
generate_instr_debug(cctx);
|
|
||||||
cctx->ctx_prev_lnum = save_prev_lnum;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return arg_end;
|
return arg_end;
|
||||||
@@ -1029,7 +1033,9 @@ compile_endfor(char_u *arg, cctx_T *cctx)
|
|||||||
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
||||||
|
|
||||||
// Fill in the "end" label in the FOR statement so it can jump here.
|
// Fill in the "end" label in the FOR statement so it can jump here.
|
||||||
isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
|
// In debug mode an ISN_DEBUG was inserted.
|
||||||
|
isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label
|
||||||
|
+ (cctx->ctx_compile_type == CT_DEBUG ? 1 : 0);
|
||||||
isn->isn_arg.forloop.for_end = instr->ga_len;
|
isn->isn_arg.forloop.for_end = instr->ga_len;
|
||||||
|
|
||||||
// Fill in the "end" label any BREAK statements
|
// Fill in the "end" label any BREAK statements
|
||||||
|
Reference in New Issue
Block a user