summaryrefslogtreecommitdiff
path: root/src/vim9execute.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-06-13 14:01:26 +0200
committerBram Moolenaar <Bram@vim.org>2021-06-13 14:01:26 +0200
commite99d422bbd3e47620915bf89671673f0711671b4 (patch)
treeda9d46ec8f793ae3f70ddcd229bc4a34122a3170 /src/vim9execute.c
parente6174fd58d459722847c76f8c5aa1b08a49c3e0d (diff)
downloadvim-git-e99d422bbd3e47620915bf89671673f0711671b4.tar.gz
patch 8.2.2985: Vim9: a compiled function cannot be debuggedv8.2.2985
Problem: Vim9: a compiled function cannot be debugged. Solution: Add initial debugging support.
Diffstat (limited to 'src/vim9execute.c')
-rw-r--r--src/vim9execute.c84
1 files changed, 67 insertions, 17 deletions
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 767dcea3c..c1e40a68f 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -204,8 +204,8 @@ call_dfunc(
// Profiling might be enabled/disabled along the way. This should not
// fail, since the function was compiled before and toggling profiling
// doesn't change any errors.
- if (func_needs_compiling(ufunc, PROFILING(ufunc))
- && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
+ if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
+ && compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
== FAIL)
return FAIL;
}
@@ -264,6 +264,7 @@ call_dfunc(
// If depth of calling is getting too high, don't execute the function.
if (funcdepth_increment() == FAIL)
return FAIL;
+ ++ex_nesting_level;
// Only make a copy of funclocal if it contains something to restore.
if (ectx->ec_funclocal.floc_restore_cmdmod)
@@ -647,6 +648,7 @@ func_return(ectx_T *ectx)
ectx->ec_stack.ga_len = top;
funcdepth_decrement();
+ --ex_nesting_level;
return OK;
}
@@ -737,13 +739,15 @@ call_ufunc(
int idx;
int did_emsg_before = did_emsg;
#ifdef FEAT_PROFILE
- int profiling = do_profiling == PROF_YES && ufunc->uf_profiling;
+ compiletype_T compile_type = do_profiling == PROF_YES
+ && ufunc->uf_profiling ? CT_PROFILE : CT_NONE;
#else
-# define profiling FALSE
+# define compile_type CT_NONE
#endif
- if (func_needs_compiling(ufunc, profiling)
- && compile_def_function(ufunc, FALSE, profiling, NULL) == FAIL)
+ if (func_needs_compiling(ufunc, compile_type)
+ && compile_def_function(ufunc, FALSE, compile_type, NULL)
+ == FAIL)
return FAIL;
if (ufunc->uf_def_status == UF_COMPILED)
{
@@ -4099,6 +4103,22 @@ exec_instructions(ectx_T *ectx)
}
break;
+ case ISN_DEBUG:
+ if (ex_nesting_level <= debug_break_level)
+ {
+ char_u *line;
+ ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
+ + ectx->ec_dfunc_idx)->df_ufunc;
+
+ SOURCING_LNUM = iptr->isn_lnum;
+ line = ((char_u **)ufunc->uf_lines.ga_data)[
+ iptr->isn_lnum - 1];
+ if (line == NULL)
+ line = (char_u *)"[empty]";
+ do_debug(line);
+ }
+ break;
+
case ISN_SHUFFLE:
{
typval_T tmp_tv;
@@ -4258,6 +4278,7 @@ call_def_function(
int save_emsg_silent_def = emsg_silent_def;
int save_did_emsg_def = did_emsg_def;
int orig_funcdepth;
+ int orig_nesting_level = ex_nesting_level;
// Get pointer to item in the stack.
#undef STACK_TV
@@ -4273,8 +4294,8 @@ call_def_function(
if (ufunc->uf_def_status == UF_NOT_COMPILED
|| ufunc->uf_def_status == UF_COMPILE_ERROR
- || (func_needs_compiling(ufunc, PROFILING(ufunc))
- && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
+ || (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
+ && compile_def_function(ufunc, FALSE, COMPILE_TYPE(ufunc), NULL)
== FAIL))
{
if (did_emsg_cumul + did_emsg == did_emsg_before)
@@ -4310,6 +4331,7 @@ call_def_function(
ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10);
ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10);
ectx.ec_did_emsg_before = did_emsg_before;
+ ++ex_nesting_level;
idx = argc - ufunc->uf_args.ga_len;
if (idx > 0 && ufunc->uf_va_name == NULL)
@@ -4553,6 +4575,7 @@ failed_early:
// Free all local variables, but not arguments.
for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
clear_tv(STACK_TV(idx));
+ ex_nesting_level = orig_nesting_level;
vim_free(ectx.ec_stack.ga_data);
vim_free(ectx.ec_trystack.ga_data);
@@ -5315,13 +5338,18 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_CMDMOD_REV: smsg("%s%4d CMDMOD_REV", pfx, current); break;
case ISN_PROF_START:
- smsg("%s%4d PROFILE START line %d", pfx, current, iptr->isn_lnum);
+ smsg("%s%4d PROFILE START line %d", pfx, current,
+ iptr->isn_lnum);
break;
case ISN_PROF_END:
smsg("%s%4d PROFILE END", pfx, current);
break;
+ case ISN_DEBUG:
+ smsg("%s%4d DEBUG line %d", pfx, current, iptr->isn_lnum);
+ break;
+
case ISN_UNPACK: smsg("%s%4d UNPACK %d%s", pfx, current,
iptr->isn_arg.unpack.unp_count,
iptr->isn_arg.unpack.unp_semicolon ? " semicolon" : "");
@@ -5358,6 +5386,18 @@ ex_disassemble(exarg_T *eap)
isn_T *instr;
int instr_count;
int is_global = FALSE;
+ compiletype_T compile_type = CT_NONE;
+
+ if (STRNCMP(arg, "profile", 7) == 0)
+ {
+ compile_type = CT_PROFILE;
+ arg = skipwhite(arg + 7);
+ }
+ else if (STRNCMP(arg, "debug", 5) == 0)
+ {
+ compile_type = CT_DEBUG;
+ arg = skipwhite(arg + 5);
+ }
if (STRNCMP(arg, "<lambda>", 8) == 0)
{
@@ -5389,8 +5429,8 @@ ex_disassemble(exarg_T *eap)
semsg(_(e_cannot_find_function_str), eap->arg);
return;
}
- if (func_needs_compiling(ufunc, eap->forceit)
- && compile_def_function(ufunc, FALSE, eap->forceit, NULL) == FAIL)
+ if (func_needs_compiling(ufunc, compile_type)
+ && compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
return;
if (ufunc->uf_def_status != UF_COMPILED)
{
@@ -5403,14 +5443,24 @@ ex_disassemble(exarg_T *eap)
msg((char *)ufunc->uf_name);
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
+ switch (compile_type)
+ {
+ case CT_PROFILE:
#ifdef FEAT_PROFILE
- instr = eap->forceit ? dfunc->df_instr_prof : dfunc->df_instr;
- instr_count = eap->forceit ? dfunc->df_instr_prof_count
- : dfunc->df_instr_count;
-#else
- instr = dfunc->df_instr;
- instr_count = dfunc->df_instr_count;
+ instr = dfunc->df_instr_prof;
+ instr_count = dfunc->df_instr_prof_count;
+ break;
#endif
+ // FALLTHROUGH
+ case CT_NONE:
+ instr = dfunc->df_instr;
+ instr_count = dfunc->df_instr_count;
+ break;
+ case CT_DEBUG:
+ instr = dfunc->df_instr_debug;
+ instr_count = dfunc->df_instr_debug_count;
+ break;
+ }
list_instructions("", instr, instr_count, ufunc);
}