# HG changeset patch # User Bram Moolenaar # Date 1623864604 -7200 # Node ID 5c418c774f95677a92d227595b680bc7b18549a7 # Parent 9de14748d25eee74ff6cddbf1b57be64811db3a5 patch 8.2.3011: Vim9: cannot get argument values during debugging Commit: https://github.com/vim/vim/commit/6bc30b05e6081bcaece6d1a7fcfca238ea5a194f Author: Bram Moolenaar Date: Wed Jun 16 19:19:55 2021 +0200 patch 8.2.3011: Vim9: cannot get argument values during debugging Problem: Vim9: cannot get argument values during debugging. Solution: Lookup names in the list of arguments. Put debug instruction halfway for command. diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim --- a/src/testdir/test_debugger.vim +++ b/src/testdir/test_debugger.vim @@ -937,12 +937,20 @@ func Test_debug_def_function() let file =<< trim END vim9script def g:Func() - var n: number - def Closure(): number - return n + 3 - enddef - n += Closure() - echo 'result: ' .. n + var n: number + def Closure(): number + return n + 3 + enddef + n += Closure() + echo 'result: ' .. n + enddef + + def g:FuncWithArgs(text: string, nr: number, ...items: list) + echo text .. nr + for it in items + echo it + endfor + echo "done" enddef END call writefile(file, 'Xtest.vim') @@ -954,7 +962,30 @@ func Test_debug_def_function() \ ['cmd: call Func()']) call RunDbgCmd(buf, 'next', ['result: 3']) call term_sendkeys(buf, "\r") + call RunDbgCmd(buf, 'cont') + call RunDbgCmd(buf, + \ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)', + \ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)']) + call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr']) + call RunDbgCmd(buf, 'echo text', ['asdf']) + call RunDbgCmd(buf, 'echo nr', ['42']) + call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]']) + call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items']) + call RunDbgCmd(buf, 'echo it', ['1']) + call RunDbgCmd(buf, 'step', ['line 3: echo it']) + call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor']) + call RunDbgCmd(buf, 'step', ['line 2: for it in items']) + call RunDbgCmd(buf, 'echo it', ['2']) + call RunDbgCmd(buf, 'step', ['line 3: echo it']) + call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor']) + call RunDbgCmd(buf, 'step', ['line 2: for it in items']) + call RunDbgCmd(buf, 'echo it', ['3']) + call RunDbgCmd(buf, 'step', ['line 3: echo it']) + call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor']) + call RunDbgCmd(buf, 'step', ['line 5: echo "done"']) + + call RunDbgCmd(buf, 'cont') call StopVimInTerminal(buf) call delete('Xtest.vim') endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3011, +/**/ 3010, /**/ 3009, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -7711,6 +7711,7 @@ compile_for(char_u *arg_start, cctx_T *c int semicolon = FALSE; size_t varlen; garray_T *stack = &cctx->ctx_type_stack; + garray_T *instr = &cctx->ctx_instr; scope_T *scope; lvar_T *loop_lvar; // loop iteration variable lvar_T *var_lvar; // variable for "var" @@ -7737,6 +7738,13 @@ compile_for(char_u *arg_start, cctx_T *c if (may_get_next_line_error(wp, &p, cctx) == FAIL) return NULL; + // Remove the already generated ISN_DEBUG, it is written below the ISN_FOR + // instruction. + if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0 + && ((isn_T *)instr->ga_data)[instr->ga_len - 1] + .isn_type == ISN_DEBUG) + --instr->ga_len; + scope = new_scope(cctx, FOR_SCOPE); if (scope == NULL) return NULL; @@ -7788,11 +7796,12 @@ compile_for(char_u *arg_start, cctx_T *c item_type = vartype->tt_member->tt_member; } - // CMDMOD_REV must come before the FOR instruction + // CMDMOD_REV must come before the FOR instruction. generate_undo_cmdmods(cctx); // "for_end" is set when ":endfor" is found scope->se_u.se_for.fs_top_label = current_instr_idx(cctx); + generate_FOR(cctx, loop_lvar->lv_idx); arg = arg_start; @@ -7893,6 +7902,10 @@ compile_for(char_u *arg_start, cctx_T *c vim_free(name); } + if (cctx->ctx_compile_type == CT_DEBUG) + // Add ISN_DEBUG here, so that the loop variables can be inspected. + generate_instr_debug(cctx); + return arg_end; failed: @@ -7927,7 +7940,7 @@ compile_endfor(char_u *arg, cctx_T *cctx // At end of ":for" scope jump back to the FOR instruction. 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; isn->isn_arg.forloop.for_end = instr->ga_len; @@ -8234,6 +8247,7 @@ compile_catch(char_u *arg, cctx_T *cctx #ifdef FEAT_PROFILE // the profile-start should be after the jump if (cctx->ctx_compile_type == CT_PROFILE + && instr->ga_len > 0 && ((isn_T *)instr->ga_data)[instr->ga_len - 1] .isn_type == ISN_PROF_START) --instr->ga_len; diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1394,7 +1394,7 @@ typedef struct subs_expr_S { // Set when calling do_debug(). static ectx_T *debug_context = NULL; -static int debug_arg_count; +static int debug_var_count; /* * When debugging lookup "name" and return the typeval. @@ -1405,20 +1405,31 @@ lookup_debug_var(char_u *name) { int idx; dfunc_T *dfunc; + ufunc_T *ufunc; ectx_T *ectx = debug_context; + int varargs_off; if (ectx == NULL) return NULL; dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; // Go through the local variable names, from last to first. - for (idx = debug_arg_count - 1; idx >= 0; --idx) + for (idx = debug_var_count - 1; idx >= 0; --idx) { - char_u *s = ((char_u **)dfunc->df_var_names.ga_data)[idx]; - if (STRCMP(s, name) == 0) + if (STRCMP(((char_u **)dfunc->df_var_names.ga_data)[idx], name) == 0) return STACK_TV_VAR(idx); } + // Go through argument names. + ufunc = dfunc->df_ufunc; + varargs_off = ufunc->uf_va_name == NULL ? 0 : 1; + for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx) + if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0) + return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len + - varargs_off + idx); + if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0) + return STACK_TV(ectx->ec_frame_idx - 1); + return NULL; } @@ -4152,7 +4163,7 @@ exec_instructions(ectx_T *ectx) SOURCING_LNUM = iptr->isn_lnum; debug_context = ectx; - debug_arg_count = iptr->isn_arg.number; + debug_var_count = iptr->isn_arg.number; line = ((char_u **)ufunc->uf_lines.ga_data)[ iptr->isn_lnum - 1]; if (line == NULL)