mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 14:38:32 +00:00
vim-patch:7.4.1102
Problem: Debugger has no stack backtrace support.
Solution: Add "backtrace", "frame", "up" and "down" commands. (Alberto
Fanjul, closes vim/vim#433)
f1f60f859c
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
*repeat.txt* For Vim version 7.4. Last change: 2015 Apr 13
|
*repeat.txt* For Vim version 7.4. Last change: 2016 Jan 16
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -467,16 +467,44 @@ Additionally, these commands can be used:
|
|||||||
finish Finish the current script or user function and come
|
finish Finish the current script or user function and come
|
||||||
back to debug mode for the command after the one that
|
back to debug mode for the command after the one that
|
||||||
sourced or called it.
|
sourced or called it.
|
||||||
|
*>bt*
|
||||||
|
*>backtrace*
|
||||||
|
*>where*
|
||||||
|
backtrace Show the call stacktrace for current debugging session.
|
||||||
|
bt
|
||||||
|
where
|
||||||
|
*>frame*
|
||||||
|
frame N Goes to N backtrace level. + and - signs make movement
|
||||||
|
relative. E.g., ":frame +3" goes three frames up.
|
||||||
|
*>up*
|
||||||
|
up Goes one level up from call stacktrace.
|
||||||
|
*>down*
|
||||||
|
down Goes one level down from call stacktrace.
|
||||||
|
|
||||||
About the additional commands in debug mode:
|
About the additional commands in debug mode:
|
||||||
- There is no command-line completion for them, you get the completion for the
|
- There is no command-line completion for them, you get the completion for the
|
||||||
normal Ex commands only.
|
normal Ex commands only.
|
||||||
- You can shorten them, up to a single character: "c", "n", "s" and "f".
|
- You can shorten them, up to a single character, unless more then one command
|
||||||
|
starts with the same letter. "f" stands for "finish", use "fr" for "frame".
|
||||||
- Hitting <CR> will repeat the previous one. When doing another command, this
|
- Hitting <CR> will repeat the previous one. When doing another command, this
|
||||||
is reset (because it's not clear what you want to repeat).
|
is reset (because it's not clear what you want to repeat).
|
||||||
- When you want to use the Ex command with the same name, prepend a colon:
|
- When you want to use the Ex command with the same name, prepend a colon:
|
||||||
":cont", ":next", ":finish" (or shorter).
|
":cont", ":next", ":finish" (or shorter).
|
||||||
|
|
||||||
|
The backtrace shows the hierarchy of function calls, e.g.:
|
||||||
|
>bt ~
|
||||||
|
3 function One[3] ~
|
||||||
|
2 Two[3] ~
|
||||||
|
->1 Three[3] ~
|
||||||
|
0 Four ~
|
||||||
|
line 1: let four = 4 ~
|
||||||
|
|
||||||
|
The "->" points to the current frame. Use "up", "down" and "frame N" to
|
||||||
|
select another frame.
|
||||||
|
|
||||||
|
In the current frame you can evaluate the local function variables. There is
|
||||||
|
no way to see the command at the current line yet.
|
||||||
|
|
||||||
|
|
||||||
DEFINING BREAKPOINTS
|
DEFINING BREAKPOINTS
|
||||||
*:breaka* *:breakadd*
|
*:breaka* *:breakadd*
|
||||||
|
@@ -18123,6 +18123,25 @@ static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, in
|
|||||||
return HI2DI(hi);
|
return HI2DI(hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get function call environment based on backtrace debug level
|
||||||
|
static funccall_T *get_funccal(void)
|
||||||
|
{
|
||||||
|
funccall_T *funccal = current_funccal;
|
||||||
|
if (debug_backtrace_level > 0) {
|
||||||
|
for (int i = 0; i < debug_backtrace_level; i++) {
|
||||||
|
funccall_T *temp_funccal = funccal->caller;
|
||||||
|
if (temp_funccal) {
|
||||||
|
funccal = temp_funccal;
|
||||||
|
} else {
|
||||||
|
// backtrace level overflow. reset to max
|
||||||
|
debug_backtrace_level = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return funccal;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the dict and hashtable used for a variable name. Set "varname" to the
|
// Find the dict and hashtable used for a variable name. Set "varname" to the
|
||||||
// start of name without ':'.
|
// start of name without ':'.
|
||||||
static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
|
static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
|
||||||
@@ -18147,7 +18166,11 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
|
|||||||
return &compat_hashtab;
|
return &compat_hashtab;
|
||||||
}
|
}
|
||||||
|
|
||||||
*d = current_funccal ? ¤t_funccal->l_vars : &globvardict;
|
if (current_funccal == NULL) {
|
||||||
|
*d = &globvardict;
|
||||||
|
} else {
|
||||||
|
*d = &get_funccal()->l_vars; // l: variable
|
||||||
|
}
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18169,9 +18192,9 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
|
|||||||
} else if (*name == 'v') { // v: variable
|
} else if (*name == 'v') { // v: variable
|
||||||
*d = &vimvardict;
|
*d = &vimvardict;
|
||||||
} else if (*name == 'a' && current_funccal != NULL) { // function argument
|
} else if (*name == 'a' && current_funccal != NULL) { // function argument
|
||||||
*d = ¤t_funccal->l_avars;
|
*d = &get_funccal()->l_avars;
|
||||||
} else if (*name == 'l' && current_funccal != NULL) { // local variable
|
} else if (*name == 'l' && current_funccal != NULL) { // local variable
|
||||||
*d = ¤t_funccal->l_vars;
|
*d = &get_funccal()->l_vars;
|
||||||
} else if (*name == 's' // script variable
|
} else if (*name == 's' // script variable
|
||||||
&& current_SID > 0 && current_SID <= ga_scripts.ga_len) {
|
&& current_SID > 0 && current_SID <= ga_scripts.ga_len) {
|
||||||
*d = &SCRIPT_SV(current_SID)->sv_dict;
|
*d = &SCRIPT_SV(current_SID)->sv_dict;
|
||||||
|
@@ -116,6 +116,11 @@ struct source_cookie {
|
|||||||
static int debug_greedy = FALSE; /* batch mode debugging: don't save
|
static int debug_greedy = FALSE; /* batch mode debugging: don't save
|
||||||
and restore typeahead. */
|
and restore typeahead. */
|
||||||
|
|
||||||
|
static int get_maxbacktrace_level(void);
|
||||||
|
static void do_setdebugtracelevel(char_u *arg);
|
||||||
|
static void do_checkbacktracelevel(void);
|
||||||
|
static void do_showbacktrace(char_u *cmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do_debug(): Debug mode.
|
* do_debug(): Debug mode.
|
||||||
* Repeatedly get Ex commands, until told to continue normal execution.
|
* Repeatedly get Ex commands, until told to continue normal execution.
|
||||||
@@ -144,6 +149,10 @@ void do_debug(char_u *cmd)
|
|||||||
#define CMD_FINISH 4
|
#define CMD_FINISH 4
|
||||||
#define CMD_QUIT 5
|
#define CMD_QUIT 5
|
||||||
#define CMD_INTERRUPT 6
|
#define CMD_INTERRUPT 6
|
||||||
|
#define CMD_BACKTRACE 7
|
||||||
|
#define CMD_FRAME 8
|
||||||
|
#define CMD_UP 9
|
||||||
|
#define CMD_DOWN 10
|
||||||
|
|
||||||
|
|
||||||
++RedrawingDisabled; /* don't redisplay the window */
|
++RedrawingDisabled; /* don't redisplay the window */
|
||||||
@@ -194,6 +203,7 @@ void do_debug(char_u *cmd)
|
|||||||
ex_normal_busy = save_ex_normal_busy;
|
ex_normal_busy = save_ex_normal_busy;
|
||||||
|
|
||||||
cmdline_row = msg_row;
|
cmdline_row = msg_row;
|
||||||
|
msg_starthere();
|
||||||
if (cmdline != NULL) {
|
if (cmdline != NULL) {
|
||||||
/* If this is a debug command, set "last_cmd".
|
/* If this is a debug command, set "last_cmd".
|
||||||
* If not, reset "last_cmd".
|
* If not, reset "last_cmd".
|
||||||
@@ -210,8 +220,15 @@ void do_debug(char_u *cmd)
|
|||||||
case 's': last_cmd = CMD_STEP;
|
case 's': last_cmd = CMD_STEP;
|
||||||
tail = "tep";
|
tail = "tep";
|
||||||
break;
|
break;
|
||||||
case 'f': last_cmd = CMD_FINISH;
|
case 'f':
|
||||||
tail = "inish";
|
last_cmd = 0;
|
||||||
|
if (p[1] == 'r') {
|
||||||
|
last_cmd = CMD_FRAME;
|
||||||
|
tail = "rame";
|
||||||
|
} else {
|
||||||
|
last_cmd = CMD_FINISH;
|
||||||
|
tail = "inish";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'q': last_cmd = CMD_QUIT;
|
case 'q': last_cmd = CMD_QUIT;
|
||||||
tail = "uit";
|
tail = "uit";
|
||||||
@@ -219,6 +236,26 @@ void do_debug(char_u *cmd)
|
|||||||
case 'i': last_cmd = CMD_INTERRUPT;
|
case 'i': last_cmd = CMD_INTERRUPT;
|
||||||
tail = "nterrupt";
|
tail = "nterrupt";
|
||||||
break;
|
break;
|
||||||
|
case 'b':
|
||||||
|
last_cmd = CMD_BACKTRACE;
|
||||||
|
if (p[1] == 't') {
|
||||||
|
tail = "t";
|
||||||
|
} else {
|
||||||
|
tail = "acktrace";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
last_cmd = CMD_BACKTRACE;
|
||||||
|
tail = "here";
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
last_cmd = CMD_UP;
|
||||||
|
tail = "p";
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
last_cmd = CMD_DOWN;
|
||||||
|
tail = "own";
|
||||||
|
break;
|
||||||
default: last_cmd = 0;
|
default: last_cmd = 0;
|
||||||
}
|
}
|
||||||
if (last_cmd != 0) {
|
if (last_cmd != 0) {
|
||||||
@@ -228,8 +265,9 @@ void do_debug(char_u *cmd)
|
|||||||
++p;
|
++p;
|
||||||
++tail;
|
++tail;
|
||||||
}
|
}
|
||||||
if (ASCII_ISALPHA(*p))
|
if (ASCII_ISALPHA(*p) && last_cmd != CMD_FRAME) {
|
||||||
last_cmd = 0;
|
last_cmd = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +297,28 @@ void do_debug(char_u *cmd)
|
|||||||
/* Do not repeat ">interrupt" cmd, continue stepping. */
|
/* Do not repeat ">interrupt" cmd, continue stepping. */
|
||||||
last_cmd = CMD_STEP;
|
last_cmd = CMD_STEP;
|
||||||
break;
|
break;
|
||||||
|
case CMD_BACKTRACE:
|
||||||
|
do_showbacktrace(cmd);
|
||||||
|
continue;
|
||||||
|
case CMD_FRAME:
|
||||||
|
if (*p == NUL) {
|
||||||
|
do_showbacktrace(cmd);
|
||||||
|
} else {
|
||||||
|
p = skipwhite(p);
|
||||||
|
do_setdebugtracelevel(p);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case CMD_UP:
|
||||||
|
debug_backtrace_level++;
|
||||||
|
do_checkbacktracelevel();
|
||||||
|
continue;
|
||||||
|
case CMD_DOWN:
|
||||||
|
debug_backtrace_level--;
|
||||||
|
do_checkbacktracelevel();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
// Going out reset backtrace_level
|
||||||
|
debug_backtrace_level = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,6 +353,78 @@ void do_debug(char_u *cmd)
|
|||||||
debug_did_msg = TRUE;
|
debug_did_msg = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_maxbacktrace_level(void)
|
||||||
|
{
|
||||||
|
int maxbacktrace = 0;
|
||||||
|
|
||||||
|
if (sourcing_name != NULL) {
|
||||||
|
char *p = (char *)sourcing_name;
|
||||||
|
char *q;
|
||||||
|
while ((q = strstr(p, "..")) != NULL) {
|
||||||
|
p = q + 2;
|
||||||
|
maxbacktrace++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxbacktrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_setdebugtracelevel(char_u *arg)
|
||||||
|
{
|
||||||
|
int level = atoi((char *)arg);
|
||||||
|
if (*arg == '+' || level < 0) {
|
||||||
|
debug_backtrace_level += level;
|
||||||
|
} else {
|
||||||
|
debug_backtrace_level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_checkbacktracelevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_checkbacktracelevel(void)
|
||||||
|
{
|
||||||
|
if (debug_backtrace_level < 0) {
|
||||||
|
debug_backtrace_level = 0;
|
||||||
|
MSG(_("frame is zero"));
|
||||||
|
} else {
|
||||||
|
int max = get_maxbacktrace_level();
|
||||||
|
if (debug_backtrace_level > max) {
|
||||||
|
debug_backtrace_level = max;
|
||||||
|
smsg(_("frame at highest level: %d"), max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_showbacktrace(char_u *cmd)
|
||||||
|
{
|
||||||
|
if (sourcing_name != NULL) {
|
||||||
|
int i = 0;
|
||||||
|
int max = get_maxbacktrace_level();
|
||||||
|
char *cur = (char *)sourcing_name;
|
||||||
|
while (!got_int) {
|
||||||
|
char *next = strstr(cur, "..");
|
||||||
|
if (next != NULL) {
|
||||||
|
*next = NUL;
|
||||||
|
}
|
||||||
|
if (i == max - debug_backtrace_level) {
|
||||||
|
smsg("->%d %s", max - i, cur);
|
||||||
|
} else {
|
||||||
|
smsg(" %d %s", max - i, cur);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
if (next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*next = '.';
|
||||||
|
cur = next + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourcing_lnum != 0) {
|
||||||
|
smsg(_("line %" PRId64 ": %s"), (int64_t)sourcing_lnum, cmd);
|
||||||
|
} else {
|
||||||
|
smsg(_("cmd: %s"), cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":debug".
|
* ":debug".
|
||||||
*/
|
*/
|
||||||
|
@@ -293,10 +293,11 @@ EXTERN int msg_no_more INIT(= FALSE); /* don't use more prompt, truncate
|
|||||||
EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */
|
EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */
|
||||||
EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */
|
EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */
|
||||||
|
|
||||||
EXTERN int ex_nesting_level INIT(= 0); /* nesting level */
|
EXTERN int ex_nesting_level INIT(= 0); // nesting level
|
||||||
EXTERN int debug_break_level INIT(= -1); /* break below this level */
|
EXTERN int debug_break_level INIT(= -1); // break below this level
|
||||||
EXTERN int debug_did_msg INIT(= FALSE); /* did "debug mode" message */
|
EXTERN int debug_did_msg INIT(= false); // did "debug mode" message
|
||||||
EXTERN int debug_tick INIT(= 0); /* breakpoint change count */
|
EXTERN int debug_tick INIT(= 0); // breakpoint change count
|
||||||
|
EXTERN int debug_backtrace_level INIT(= 0); // breakpoint backtrace level
|
||||||
|
|
||||||
/* Values for "do_profiling". */
|
/* Values for "do_profiling". */
|
||||||
#define PROF_NONE 0 /* profiling not started */
|
#define PROF_NONE 0 /* profiling not started */
|
||||||
|
@@ -580,7 +580,7 @@ static int included_patches[] = {
|
|||||||
1105,
|
1105,
|
||||||
// 1104 NA
|
// 1104 NA
|
||||||
// 1103 NA
|
// 1103 NA
|
||||||
// 1102,
|
1102,
|
||||||
1101,
|
1101,
|
||||||
// 1100 NA
|
// 1100 NA
|
||||||
// 1099 NA
|
// 1099 NA
|
||||||
|
176
test/functional/legacy/108_backtrace_debug_commands_spec.lua
Normal file
176
test/functional/legacy/108_backtrace_debug_commands_spec.lua
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
-- Tests for backtrace debug commands.
|
||||||
|
|
||||||
|
local helpers = require('test.functional.helpers')
|
||||||
|
local feed, insert, source = helpers.feed, helpers.insert, helpers.source
|
||||||
|
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
|
||||||
|
|
||||||
|
describe('108', function()
|
||||||
|
before_each(clear)
|
||||||
|
|
||||||
|
it('is working', function()
|
||||||
|
execute('function! Foo()')
|
||||||
|
execute(' let var1 = 1')
|
||||||
|
execute(' let var2 = Bar(var1) + 9')
|
||||||
|
execute(' return var2')
|
||||||
|
execute('endfunction')
|
||||||
|
execute('function! Bar(var)')
|
||||||
|
execute(' let var1 = 2 + a:var')
|
||||||
|
execute(' let var2 = Bazz(var1) + 4')
|
||||||
|
execute(' return var2')
|
||||||
|
execute('endfunction')
|
||||||
|
execute('function! Bazz(var)')
|
||||||
|
execute(' let var1 = 3 + a:var')
|
||||||
|
execute(' let var3 = "another var"')
|
||||||
|
execute(' return var1')
|
||||||
|
execute('endfunction')
|
||||||
|
execute('new')
|
||||||
|
execute('debuggreedy')
|
||||||
|
execute('redir => out')
|
||||||
|
execute('debug echo Foo()')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed([[echo "- show backtrace:\n"<cr>]])
|
||||||
|
feed('backtrace<cr>')
|
||||||
|
feed([[echo "\nshow variables on different levels:\n"<cr>]])
|
||||||
|
feed('echo var1<cr>')
|
||||||
|
feed('up<cr>')
|
||||||
|
feed('back<cr>')
|
||||||
|
feed('echo var1<cr>')
|
||||||
|
feed('u<cr>')
|
||||||
|
feed('bt<cr>')
|
||||||
|
feed('echo var1<cr>')
|
||||||
|
feed([[echo "\n- undefined vars:\n"<cr>]])
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('frame 2<cr>')
|
||||||
|
feed('echo "undefined var3 on former level:"<cr>')
|
||||||
|
feed('echo var3<cr>')
|
||||||
|
feed('fr 0<cr>')
|
||||||
|
feed([[echo "here var3 is defined with \"another var\":"<cr>]])
|
||||||
|
feed('echo var3<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('step<cr>')
|
||||||
|
feed('up<cr>')
|
||||||
|
feed([[echo "\nundefined var2 on former level"<cr>]])
|
||||||
|
feed('echo var2<cr>')
|
||||||
|
feed('down<cr>')
|
||||||
|
feed('echo "here var2 is defined with 10:"<cr>')
|
||||||
|
feed('echo var2<cr>')
|
||||||
|
feed([[echo "\n- backtrace movements:\n"<cr>]])
|
||||||
|
feed('b<cr>')
|
||||||
|
feed([[echo "\nnext command cannot go down, we are on bottom\n"<cr>]])
|
||||||
|
feed('down<cr>')
|
||||||
|
feed('up<cr>')
|
||||||
|
feed([[echo "\nnext command cannot go up, we are on top\n"<cr>]])
|
||||||
|
feed('up<cr>')
|
||||||
|
feed('b<cr>')
|
||||||
|
feed('echo "fil is not frame or finish, it is file"<cr>')
|
||||||
|
feed('fil<cr>')
|
||||||
|
feed([[echo "\n- relative backtrace movement\n"<cr>]])
|
||||||
|
feed('fr -1<cr>')
|
||||||
|
feed('frame<cr>')
|
||||||
|
feed('fra +1<cr>')
|
||||||
|
feed('fram<cr>')
|
||||||
|
feed([[echo "\n- go beyond limits does not crash\n"<cr>]])
|
||||||
|
feed('fr 100<cr>')
|
||||||
|
feed('fra<cr>')
|
||||||
|
feed('frame -40<cr>')
|
||||||
|
feed('fram<cr>')
|
||||||
|
feed([[echo "\n- final result 19:"<cr>]])
|
||||||
|
feed('cont<cr>')
|
||||||
|
execute('0debuggreedy')
|
||||||
|
execute('redir END')
|
||||||
|
execute('$put =out')
|
||||||
|
|
||||||
|
-- Assert buffer contents.
|
||||||
|
expect([=[
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- show backtrace:
|
||||||
|
|
||||||
|
2 function Foo[2]
|
||||||
|
1 Bar[2]
|
||||||
|
->0 Bazz
|
||||||
|
line 2: let var3 = "another var"
|
||||||
|
|
||||||
|
show variables on different levels:
|
||||||
|
|
||||||
|
6
|
||||||
|
2 function Foo[2]
|
||||||
|
->1 Bar[2]
|
||||||
|
0 Bazz
|
||||||
|
line 2: let var3 = "another var"
|
||||||
|
3
|
||||||
|
->2 function Foo[2]
|
||||||
|
1 Bar[2]
|
||||||
|
0 Bazz
|
||||||
|
line 2: let var3 = "another var"
|
||||||
|
1
|
||||||
|
|
||||||
|
- undefined vars:
|
||||||
|
|
||||||
|
undefined var3 on former level:
|
||||||
|
Error detected while processing function Foo[2]..Bar[2]..Bazz:
|
||||||
|
line 3:
|
||||||
|
E121: Undefined variable: var3
|
||||||
|
E15: Invalid expression: var3
|
||||||
|
here var3 is defined with "another var":
|
||||||
|
another var
|
||||||
|
|
||||||
|
undefined var2 on former level
|
||||||
|
Error detected while processing function Foo[2]..Bar:
|
||||||
|
line 3:
|
||||||
|
E121: Undefined variable: var2
|
||||||
|
E15: Invalid expression: var2
|
||||||
|
here var2 is defined with 10:
|
||||||
|
10
|
||||||
|
|
||||||
|
- backtrace movements:
|
||||||
|
|
||||||
|
1 function Foo[2]
|
||||||
|
->0 Bar
|
||||||
|
line 3: End of function
|
||||||
|
|
||||||
|
next command cannot go down, we are on bottom
|
||||||
|
|
||||||
|
frame is zero
|
||||||
|
|
||||||
|
next command cannot go up, we are on top
|
||||||
|
|
||||||
|
frame at highest level: 1
|
||||||
|
->1 function Foo[2]
|
||||||
|
0 Bar
|
||||||
|
line 3: End of function
|
||||||
|
fil is not frame or finish, it is file
|
||||||
|
"[No Name]" --No lines in buffer--
|
||||||
|
|
||||||
|
- relative backtrace movement
|
||||||
|
|
||||||
|
1 function Foo[2]
|
||||||
|
->0 Bar
|
||||||
|
line 3: End of function
|
||||||
|
->1 function Foo[2]
|
||||||
|
0 Bar
|
||||||
|
line 3: End of function
|
||||||
|
|
||||||
|
- go beyond limits does not crash
|
||||||
|
|
||||||
|
frame at highest level: 1
|
||||||
|
->1 function Foo[2]
|
||||||
|
0 Bar
|
||||||
|
line 3: End of function
|
||||||
|
frame is zero
|
||||||
|
1 function Foo[2]
|
||||||
|
->0 Bar
|
||||||
|
line 3: End of function
|
||||||
|
|
||||||
|
- final result 19:
|
||||||
|
19
|
||||||
|
]=])
|
||||||
|
end)
|
||||||
|
end)
|
Reference in New Issue
Block a user