To: vim_dev@googlegroups.com Subject: Patch 8.2.3011 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3011 Problem: Vim9: cannot get argument values during debugging. Solution: Lookup names in the list of arguments. Put debug instruction halfway for command. Files: src/vim9compile.c, src/vim9execute.c, src/testdir/test_debugger.vim *** ../vim-8.2.3010/src/vim9compile.c 2021-06-15 22:13:23.829621578 +0200 --- src/vim9compile.c 2021-06-16 19:17:42.875046459 +0200 *************** *** 7711,7716 **** --- 7711,7717 ---- 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,7742 **** --- 7738,7750 ---- 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,7798 **** item_type = vartype->tt_member->tt_member; } ! // 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; --- 7796,7807 ---- item_type = vartype->tt_member->tt_member; } ! // 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,7898 **** --- 7902,7911 ---- 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,7933 **** // 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 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label; isn->isn_arg.forloop.for_end = instr->ga_len; --- 7940,7946 ---- // 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. isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label; isn->isn_arg.forloop.for_end = instr->ga_len; *************** *** 8234,8239 **** --- 8247,8253 ---- #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; *** ../vim-8.2.3010/src/vim9execute.c 2021-06-15 22:13:23.829621578 +0200 --- src/vim9execute.c 2021-06-16 17:25:48.614112545 +0200 *************** *** 1394,1400 **** // Set when calling do_debug(). static ectx_T *debug_context = NULL; ! static int debug_arg_count; /* * When debugging lookup "name" and return the typeval. --- 1394,1400 ---- // Set when calling do_debug(). static ectx_T *debug_context = NULL; ! static int debug_var_count; /* * When debugging lookup "name" and return the typeval. *************** *** 1405,1424 **** { int idx; dfunc_T *dfunc; ectx_T *ectx = debug_context; 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) { ! char_u *s = ((char_u **)dfunc->df_var_names.ga_data)[idx]; ! if (STRCMP(s, name) == 0) return STACK_TV_VAR(idx); } return NULL; } --- 1405,1435 ---- { 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_var_count - 1; idx >= 0; --idx) { ! 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,4158 **** SOURCING_LNUM = iptr->isn_lnum; debug_context = ectx; ! debug_arg_count = iptr->isn_arg.number; line = ((char_u **)ufunc->uf_lines.ga_data)[ iptr->isn_lnum - 1]; if (line == NULL) --- 4163,4169 ---- SOURCING_LNUM = iptr->isn_lnum; debug_context = ectx; ! debug_var_count = iptr->isn_arg.number; line = ((char_u **)ufunc->uf_lines.ga_data)[ iptr->isn_lnum - 1]; if (line == NULL) *** ../vim-8.2.3010/src/testdir/test_debugger.vim 2021-06-15 19:32:35.638516519 +0200 --- src/testdir/test_debugger.vim 2021-06-16 19:15:05.087417584 +0200 *************** *** 937,948 **** let file =<< trim END vim9script def g:Func() ! var n: number ! def Closure(): number ! return n + 3 ! enddef ! n += Closure() ! echo 'result: ' .. n enddef END call writefile(file, 'Xtest.vim') --- 937,956 ---- let file =<< trim END vim9script def g:Func() ! 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,960 **** --- 962,991 ---- \ ['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 *** ../vim-8.2.3010/src/version.c 2021-06-16 15:53:13.072696639 +0200 --- src/version.c 2021-06-16 16:46:53.039862308 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 3011, /**/ -- A consultant is a person who takes your money and annoys your employees while tirelessly searching for the best way to extend the consulting contract. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///