diff src/vim9execute.c @ 24895:e61a2085c89b v8.2.2985

patch 8.2.2985: Vim9: a compiled function cannot be debugged Commit: https://github.com/vim/vim/commit/e99d422bbd3e47620915bf89671673f0711671b4 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 13 14:01:26 2021 +0200 patch 8.2.2985: Vim9: a compiled function cannot be debugged Problem: Vim9: a compiled function cannot be debugged. Solution: Add initial debugging support.
author Bram Moolenaar <Bram@vim.org>
date Sun, 13 Jun 2021 14:15:04 +0200
parents 193cc8bd8a2f
children 701e4a2576dd
line wrap: on
line diff
--- 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 *inst
 	    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);
 }