mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.0185: Vim9 script: cannot use "if has()" to skip lines
Problem: Vim9 script: cannot use "if has()" to skip lines. Solution: Evaluate constant expression at runtime.
This commit is contained in:
@@ -100,7 +100,6 @@ static void f_getpos(typval_T *argvars, typval_T *rettv);
|
|||||||
static void f_getreg(typval_T *argvars, typval_T *rettv);
|
static void f_getreg(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_getregtype(typval_T *argvars, typval_T *rettv);
|
static void f_getregtype(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_gettagstack(typval_T *argvars, typval_T *rettv);
|
static void f_gettagstack(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_has(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_haslocaldir(typval_T *argvars, typval_T *rettv);
|
static void f_haslocaldir(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_hasmapto(typval_T *argvars, typval_T *rettv);
|
static void f_hasmapto(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_hlID(typval_T *argvars, typval_T *rettv);
|
static void f_hlID(typval_T *argvars, typval_T *rettv);
|
||||||
@@ -3261,7 +3260,7 @@ f_gettagstack(typval_T *argvars, typval_T *rettv)
|
|||||||
/*
|
/*
|
||||||
* "has()" function
|
* "has()" function
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
f_has(typval_T *argvars, typval_T *rettv)
|
f_has(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@@ -17,6 +17,7 @@ buf_T *get_buf_arg(typval_T *arg);
|
|||||||
win_T *get_optional_window(typval_T *argvars, int idx);
|
win_T *get_optional_window(typval_T *argvars, int idx);
|
||||||
void execute_redir_str(char_u *value, int value_len);
|
void execute_redir_str(char_u *value, int value_len);
|
||||||
void execute_common(typval_T *argvars, typval_T *rettv, int arg_off);
|
void execute_common(typval_T *argvars, typval_T *rettv, int arg_off);
|
||||||
|
void f_has(typval_T *argvars, typval_T *rettv);
|
||||||
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
|
void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
|
||||||
void range_list_materialize(list_T *list);
|
void range_list_materialize(list_T *list);
|
||||||
float_T vim_round(float_T f);
|
float_T vim_round(float_T f);
|
||||||
|
@@ -368,5 +368,35 @@ def do_something():
|
|||||||
EOF
|
EOF
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
def HasEval()
|
||||||
|
if has('eval')
|
||||||
|
echo 'yes'
|
||||||
|
else
|
||||||
|
echo 'no'
|
||||||
|
endif
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def HasNothing()
|
||||||
|
if has('nothing')
|
||||||
|
echo 'yes'
|
||||||
|
else
|
||||||
|
echo 'no'
|
||||||
|
endif
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_compile_const_expr()
|
||||||
|
assert_equal("\nyes", execute('call HasEval()'))
|
||||||
|
let instr = execute('disassemble HasEval')
|
||||||
|
call assert_match('PUSHS "yes"', instr)
|
||||||
|
call assert_notmatch('PUSHS "no"', instr)
|
||||||
|
call assert_notmatch('JUMP', instr)
|
||||||
|
|
||||||
|
assert_equal("\nno", execute('call HasNothing()'))
|
||||||
|
instr = execute('disassemble HasNothing')
|
||||||
|
call assert_notmatch('PUSHS "yes"', instr)
|
||||||
|
call assert_match('PUSHS "no"', instr)
|
||||||
|
call assert_notmatch('JUMP', instr)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@@ -2691,9 +2691,10 @@ ex_function(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for ":append", ":change", ":insert".
|
// Check for ":append", ":change", ":insert". Not for :def.
|
||||||
p = skip_range(p, NULL);
|
p = skip_range(p, NULL);
|
||||||
if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
|
if (eap->cmdidx != CMD_def
|
||||||
|
&& ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
|
||||||
|| (p[0] == 'c'
|
|| (p[0] == 'c'
|
||||||
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'h'
|
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'h'
|
||||||
&& (!ASCII_ISALPHA(p[2]) || (p[2] == 'a'
|
&& (!ASCII_ISALPHA(p[2]) || (p[2] == 'a'
|
||||||
@@ -2701,7 +2702,10 @@ ex_function(exarg_T *eap)
|
|||||||
|| !ASCII_ISALPHA(p[6])))))))
|
|| !ASCII_ISALPHA(p[6])))))))
|
||||||
|| (p[0] == 'i'
|
|| (p[0] == 'i'
|
||||||
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
|
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
|
||||||
&& (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
|
&& (!ASCII_ISALPHA(p[2])
|
||||||
|
|| (p[2] == 's'
|
||||||
|
&& (!ASCII_ISALPHA(p[3])
|
||||||
|
|| p[3] == 'e'))))))))
|
||||||
skip_until = vim_strsave((char_u *)".");
|
skip_until = vim_strsave((char_u *)".");
|
||||||
|
|
||||||
// Check for ":python <<EOF", ":tcl <<EOF", etc.
|
// Check for ":python <<EOF", ":tcl <<EOF", etc.
|
||||||
|
@@ -742,6 +742,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
185,
|
||||||
/**/
|
/**/
|
||||||
184,
|
184,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -115,6 +115,8 @@ struct cctx_S {
|
|||||||
|
|
||||||
garray_T ctx_imports; // imported items
|
garray_T ctx_imports; // imported items
|
||||||
|
|
||||||
|
int ctx_skip; // when TRUE skip commands, when FALSE skip
|
||||||
|
// commands after "else"
|
||||||
scope_T *ctx_scope; // current scope, NULL at toplevel
|
scope_T *ctx_scope; // current scope, NULL at toplevel
|
||||||
|
|
||||||
garray_T ctx_type_stack; // type of each item on the stack
|
garray_T ctx_type_stack; // type of each item on the stack
|
||||||
@@ -3458,6 +3460,185 @@ new_scope(cctx_T *cctx, scopetype_T type)
|
|||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluate an expression that is a constant: has(arg)
|
||||||
|
* Return FAIL if the expression is not a constant.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
evaluate_const_expr4(char_u **arg, cctx_T *cctx UNUSED, typval_T *tv)
|
||||||
|
{
|
||||||
|
typval_T argvars[2];
|
||||||
|
|
||||||
|
if (STRNCMP("has(", *arg, 4) != 0)
|
||||||
|
return FAIL;
|
||||||
|
*arg = skipwhite(*arg + 4);
|
||||||
|
|
||||||
|
if (**arg == '"')
|
||||||
|
{
|
||||||
|
if (get_string_tv(arg, tv, TRUE) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
else if (**arg == '\'')
|
||||||
|
{
|
||||||
|
if (get_lit_string_tv(arg, tv, TRUE) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
*arg = skipwhite(*arg);
|
||||||
|
if (**arg != ')')
|
||||||
|
return FAIL;
|
||||||
|
*arg = skipwhite(*arg + 1);
|
||||||
|
|
||||||
|
argvars[0] = *tv;
|
||||||
|
argvars[1].v_type = VAR_UNKNOWN;
|
||||||
|
tv->v_type = VAR_NUMBER;
|
||||||
|
tv->vval.v_number = 0;
|
||||||
|
f_has(argvars, tv);
|
||||||
|
clear_tv(&argvars[0]);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compile constant || or &&.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
evaluate_const_and_or(char_u **arg, cctx_T *cctx, char *op, typval_T *tv)
|
||||||
|
{
|
||||||
|
char_u *p = skipwhite(*arg);
|
||||||
|
int opchar = *op;
|
||||||
|
|
||||||
|
if (p[0] == opchar && p[1] == opchar)
|
||||||
|
{
|
||||||
|
int val = tv2bool(tv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Repeat until there is no following "||" or "&&"
|
||||||
|
*/
|
||||||
|
while (p[0] == opchar && p[1] == opchar)
|
||||||
|
{
|
||||||
|
typval_T tv2;
|
||||||
|
|
||||||
|
if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2]))
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// eval the next expression
|
||||||
|
*arg = skipwhite(p + 2);
|
||||||
|
tv2.v_type = VAR_UNKNOWN;
|
||||||
|
if ((opchar == '|' ? evaluate_const_expr3(arg, cctx, &tv2)
|
||||||
|
: evaluate_const_expr4(arg, cctx, &tv2)) == FAIL)
|
||||||
|
{
|
||||||
|
clear_tv(&tv2);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if ((opchar == '&') == val)
|
||||||
|
{
|
||||||
|
// false || tv2 or true && tv2: use tv2
|
||||||
|
clear_tv(tv);
|
||||||
|
*tv = tv2;
|
||||||
|
val = tv2bool(tv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
clear_tv(&tv2);
|
||||||
|
p = skipwhite(*arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluate an expression that is a constant: expr4 && expr4 && expr4
|
||||||
|
* Return FAIL if the expression is not a constant.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
evaluate_const_expr3(char_u **arg, cctx_T *cctx, typval_T *tv)
|
||||||
|
{
|
||||||
|
// evaluate the first expression
|
||||||
|
if (evaluate_const_expr4(arg, cctx, tv) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// || and && work almost the same
|
||||||
|
return evaluate_const_and_or(arg, cctx, "&&", tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluate an expression that is a constant: expr3 || expr3 || expr3
|
||||||
|
* Return FAIL if the expression is not a constant.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
evaluate_const_expr2(char_u **arg, cctx_T *cctx, typval_T *tv)
|
||||||
|
{
|
||||||
|
// evaluate the first expression
|
||||||
|
if (evaluate_const_expr3(arg, cctx, tv) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// || and && work almost the same
|
||||||
|
return evaluate_const_and_or(arg, cctx, "||", tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Evaluate an expression that is a constant: expr2 ? expr1 : expr1
|
||||||
|
* E.g. for "has('feature')".
|
||||||
|
* This does not produce error messages. "tv" should be cleared afterwards.
|
||||||
|
* Return FAIL if the expression is not a constant.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
evaluate_const_expr1(char_u **arg, cctx_T *cctx, typval_T *tv)
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
// evaluate the first expression
|
||||||
|
if (evaluate_const_expr2(arg, cctx, tv) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
p = skipwhite(*arg);
|
||||||
|
if (*p == '?')
|
||||||
|
{
|
||||||
|
int val = tv2bool(tv);
|
||||||
|
typval_T tv2;
|
||||||
|
|
||||||
|
if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// evaluate the second expression; any type is accepted
|
||||||
|
clear_tv(tv);
|
||||||
|
*arg = skipwhite(p + 1);
|
||||||
|
if (evaluate_const_expr1(arg, cctx, tv) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// Check for the ":".
|
||||||
|
p = skipwhite(*arg);
|
||||||
|
if (*p != ':' || !VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1]))
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
// evaluate the third expression
|
||||||
|
*arg = skipwhite(p + 1);
|
||||||
|
tv2.v_type = VAR_UNKNOWN;
|
||||||
|
if (evaluate_const_expr1(arg, cctx, &tv2) == FAIL)
|
||||||
|
{
|
||||||
|
clear_tv(&tv2);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
// use the expr after "?"
|
||||||
|
clear_tv(&tv2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// use the expr after ":"
|
||||||
|
clear_tv(tv);
|
||||||
|
*tv = tv2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* compile "if expr"
|
* compile "if expr"
|
||||||
*
|
*
|
||||||
@@ -3496,18 +3677,34 @@ compile_if(char_u *arg, cctx_T *cctx)
|
|||||||
char_u *p = arg;
|
char_u *p = arg;
|
||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
scope_T *scope;
|
scope_T *scope;
|
||||||
|
typval_T tv;
|
||||||
|
|
||||||
// compile "expr"
|
// compile "expr"; if we know it evaluates to FALSE skip the block
|
||||||
|
tv.v_type = VAR_UNKNOWN;
|
||||||
|
if (evaluate_const_expr1(&p, cctx, &tv) == OK)
|
||||||
|
cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
|
||||||
|
else
|
||||||
|
cctx->ctx_skip = MAYBE;
|
||||||
|
clear_tv(&tv);
|
||||||
|
if (cctx->ctx_skip == MAYBE)
|
||||||
|
{
|
||||||
|
p = arg;
|
||||||
if (compile_expr1(&p, cctx) == FAIL)
|
if (compile_expr1(&p, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
scope = new_scope(cctx, IF_SCOPE);
|
scope = new_scope(cctx, IF_SCOPE);
|
||||||
if (scope == NULL)
|
if (scope == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (cctx->ctx_skip == MAYBE)
|
||||||
|
{
|
||||||
// "where" is set when ":elseif", "else" or ":endif" is found
|
// "where" is set when ":elseif", "else" or ":endif" is found
|
||||||
scope->se_u.se_if.is_if_label = instr->ga_len;
|
scope->se_u.se_if.is_if_label = instr->ga_len;
|
||||||
generate_JUMP(cctx, JUMP_IF_FALSE, 0);
|
generate_JUMP(cctx, JUMP_IF_FALSE, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scope->se_u.se_if.is_if_label = -1;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -3519,6 +3716,7 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
|||||||
garray_T *instr = &cctx->ctx_instr;
|
garray_T *instr = &cctx->ctx_instr;
|
||||||
isn_T *isn;
|
isn_T *isn;
|
||||||
scope_T *scope = cctx->ctx_scope;
|
scope_T *scope = cctx->ctx_scope;
|
||||||
|
typval_T tv;
|
||||||
|
|
||||||
if (scope == NULL || scope->se_type != IF_SCOPE)
|
if (scope == NULL || scope->se_type != IF_SCOPE)
|
||||||
{
|
{
|
||||||
@@ -3527,22 +3725,35 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
cctx->ctx_locals.ga_len = scope->se_local_count;
|
||||||
|
|
||||||
// jump from previous block to the end
|
if (cctx->ctx_skip != TRUE)
|
||||||
|
{
|
||||||
if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
|
if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
|
||||||
JUMP_ALWAYS, cctx) == FAIL)
|
JUMP_ALWAYS, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// previous "if" or "elseif" jumps here
|
// previous "if" or "elseif" jumps here
|
||||||
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
|
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
|
||||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||||
|
}
|
||||||
|
|
||||||
// compile "expr"
|
// compile "expr"; if we know it evaluates to FALSE skip the block
|
||||||
|
tv.v_type = VAR_UNKNOWN;
|
||||||
|
if (evaluate_const_expr1(&p, cctx, &tv) == OK)
|
||||||
|
cctx->ctx_skip = tv2bool(&tv) ? FALSE : TRUE;
|
||||||
|
else
|
||||||
|
cctx->ctx_skip = MAYBE;
|
||||||
|
clear_tv(&tv);
|
||||||
|
if (cctx->ctx_skip == MAYBE)
|
||||||
|
{
|
||||||
|
p = arg;
|
||||||
if (compile_expr1(&p, cctx) == FAIL)
|
if (compile_expr1(&p, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// "where" is set when ":elseif", "else" or ":endif" is found
|
// "where" is set when ":elseif", "else" or ":endif" is found
|
||||||
scope->se_u.se_if.is_if_label = instr->ga_len;
|
scope->se_u.se_if.is_if_label = instr->ga_len;
|
||||||
generate_JUMP(cctx, JUMP_IF_FALSE, 0);
|
generate_JUMP(cctx, JUMP_IF_FALSE, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scope->se_u.se_if.is_if_label = -1;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -3562,14 +3773,26 @@ compile_else(char_u *arg, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
cctx->ctx_locals.ga_len = scope->se_local_count;
|
||||||
|
|
||||||
// jump from previous block to the end
|
// jump from previous block to the end, unless the else block is empty
|
||||||
|
if (cctx->ctx_skip == MAYBE)
|
||||||
|
{
|
||||||
if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
|
if (compile_jump_to_end(&scope->se_u.se_if.is_end_label,
|
||||||
JUMP_ALWAYS, cctx) == FAIL)
|
JUMP_ALWAYS, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cctx->ctx_skip != TRUE)
|
||||||
|
{
|
||||||
|
if (scope->se_u.se_if.is_if_label >= 0)
|
||||||
|
{
|
||||||
// previous "if" or "elseif" jumps here
|
// previous "if" or "elseif" jumps here
|
||||||
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
|
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
|
||||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cctx->ctx_skip != MAYBE)
|
||||||
|
cctx->ctx_skip = !cctx->ctx_skip;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -3591,12 +3814,15 @@ compile_endif(char_u *arg, cctx_T *cctx)
|
|||||||
cctx->ctx_scope = scope->se_outer;
|
cctx->ctx_scope = scope->se_outer;
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
cctx->ctx_locals.ga_len = scope->se_local_count;
|
||||||
|
|
||||||
|
if (scope->se_u.se_if.is_if_label >= 0)
|
||||||
|
{
|
||||||
// previous "if" or "elseif" jumps here
|
// previous "if" or "elseif" jumps here
|
||||||
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
|
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_if.is_if_label;
|
||||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||||
|
}
|
||||||
// Fill in the "end" label in jumps at the end of the blocks.
|
// Fill in the "end" label in jumps at the end of the blocks.
|
||||||
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
|
compile_fill_jump_to_end(&ifscope->is_end_label, cctx);
|
||||||
|
cctx->ctx_skip = FALSE;
|
||||||
|
|
||||||
vim_free(scope);
|
vim_free(scope);
|
||||||
return arg;
|
return arg;
|
||||||
@@ -4326,6 +4552,12 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
|
|
||||||
if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
|
if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
|
||||||
{
|
{
|
||||||
|
if (cctx.ctx_skip == TRUE)
|
||||||
|
{
|
||||||
|
line += STRLEN(line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Expression or function call.
|
// Expression or function call.
|
||||||
if (ea.cmdidx == CMD_eval)
|
if (ea.cmdidx == CMD_eval)
|
||||||
{
|
{
|
||||||
@@ -4351,6 +4583,15 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
|
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
|
|
||||||
|
if (cctx.ctx_skip == TRUE
|
||||||
|
&& ea.cmdidx != CMD_elseif
|
||||||
|
&& ea.cmdidx != CMD_else
|
||||||
|
&& ea.cmdidx != CMD_endif)
|
||||||
|
{
|
||||||
|
line += STRLEN(line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ea.cmdidx)
|
switch (ea.cmdidx)
|
||||||
{
|
{
|
||||||
case CMD_def:
|
case CMD_def:
|
||||||
|
Reference in New Issue
Block a user