forked from aniani/vim
patch 8.2.1047: Vim9: script cannot use line continuation like :def function
Problem: Vim9: script cannot use line continuation like in a :def function.
Solution: Pass the getline function pointer to the eval() functions. Use it
for addition and multiplication operators.
This commit is contained in:
11
src/dict.c
11
src/dict.c
@@ -788,12 +788,14 @@ get_literal_key(char_u **arg, typval_T *tv)
|
|||||||
/*
|
/*
|
||||||
* Allocate a variable for a Dictionary and fill it from "*arg".
|
* Allocate a variable for a Dictionary and fill it from "*arg".
|
||||||
* "literal" is TRUE for #{key: val}
|
* "literal" is TRUE for #{key: val}
|
||||||
|
* "flags" can have EVAL_EVALUATE and other EVAL_ flags.
|
||||||
* Return OK or FAIL. Returns NOTDONE for {expr}.
|
* Return OK or FAIL. Returns NOTDONE for {expr}.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
|
eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
|
||||||
{
|
{
|
||||||
int evaluate = flags & EVAL_EVALUATE;
|
int evaluate = flags & EVAL_EVALUATE;
|
||||||
|
evalarg_T evalarg;
|
||||||
dict_T *d = NULL;
|
dict_T *d = NULL;
|
||||||
typval_T tvkey;
|
typval_T tvkey;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
@@ -803,6 +805,9 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
|
|||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9;
|
int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9;
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First check if it's not a curly-braces thing: {expr}.
|
* First check if it's not a curly-braces thing: {expr}.
|
||||||
* Must do this without evaluating, otherwise a function may be called
|
* Must do this without evaluating, otherwise a function may be called
|
||||||
@@ -812,7 +817,7 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
|
|||||||
*/
|
*/
|
||||||
if (!vim9script && *start != '}')
|
if (!vim9script && *start != '}')
|
||||||
{
|
{
|
||||||
if (eval1(&start, &tv, 0) == FAIL) // recursive!
|
if (eval1(&start, &tv, NULL) == FAIL) // recursive!
|
||||||
return FAIL;
|
return FAIL;
|
||||||
if (*start == '}')
|
if (*start == '}')
|
||||||
return NOTDONE;
|
return NOTDONE;
|
||||||
@@ -832,7 +837,7 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
|
|||||||
{
|
{
|
||||||
if ((literal
|
if ((literal
|
||||||
? get_literal_key(arg, &tvkey)
|
? get_literal_key(arg, &tvkey)
|
||||||
: eval1(arg, &tvkey, flags)) == FAIL) // recursive!
|
: eval1(arg, &tvkey, &evalarg)) == FAIL) // recursive!
|
||||||
goto failret;
|
goto failret;
|
||||||
|
|
||||||
if (**arg != ':')
|
if (**arg != ':')
|
||||||
@@ -854,7 +859,7 @@ eval_dict(char_u **arg, typval_T *rettv, int flags, int literal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (eval1(arg, &tv, flags) == FAIL) // recursive!
|
if (eval1(arg, &tv, &evalarg) == FAIL) // recursive!
|
||||||
{
|
{
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
clear_tv(&tvkey);
|
clear_tv(&tvkey);
|
||||||
|
|||||||
274
src/eval.c
274
src/eval.c
@@ -45,12 +45,12 @@ typedef struct
|
|||||||
} forinfo_T;
|
} forinfo_T;
|
||||||
|
|
||||||
static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
|
static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
|
||||||
static int eval2(char_u **arg, typval_T *rettv, int flags);
|
static int eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval3(char_u **arg, typval_T *rettv, int flags);
|
static int eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval4(char_u **arg, typval_T *rettv, int flags);
|
static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval5(char_u **arg, typval_T *rettv, int flags);
|
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval6(char_u **arg, typval_T *rettv, int flags, int want_string);
|
static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||||
static int eval7(char_u **arg, typval_T *rettv, int flags, int want_string);
|
static int eval7(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int want_string);
|
||||||
static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
|
static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
|
||||||
|
|
||||||
static int free_unref_items(int copyID);
|
static int free_unref_items(int copyID);
|
||||||
@@ -169,7 +169,7 @@ eval_to_bool(
|
|||||||
|
|
||||||
if (skip)
|
if (skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL)
|
if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE) == FAIL)
|
||||||
*error = TRUE;
|
*error = TRUE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -197,7 +197,7 @@ eval1_emsg(char_u **arg, typval_T *rettv, int evaluate)
|
|||||||
int did_emsg_before = did_emsg;
|
int did_emsg_before = did_emsg;
|
||||||
int called_emsg_before = called_emsg;
|
int called_emsg_before = called_emsg;
|
||||||
|
|
||||||
ret = eval1(arg, rettv, evaluate ? EVAL_EVALUATE : 0);
|
ret = eval1(arg, rettv, evaluate ? &EVALARG_EVALUATE : NULL);
|
||||||
if (ret == FAIL)
|
if (ret == FAIL)
|
||||||
{
|
{
|
||||||
// Report the invalid expression unless the expression evaluation has
|
// Report the invalid expression unless the expression evaluation has
|
||||||
@@ -325,7 +325,8 @@ eval_to_string_skip(
|
|||||||
|
|
||||||
if (skip)
|
if (skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL || skip)
|
if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE)
|
||||||
|
== FAIL || skip)
|
||||||
retval = NULL;
|
retval = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -348,7 +349,7 @@ skip_expr(char_u **pp)
|
|||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
|
|
||||||
*pp = skipwhite(*pp);
|
*pp = skipwhite(*pp);
|
||||||
return eval1(pp, &rettv, 0);
|
return eval1(pp, &rettv, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -370,7 +371,7 @@ eval_to_string(
|
|||||||
char_u numbuf[NUMBUFLEN];
|
char_u numbuf[NUMBUFLEN];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (eval0(arg, &tv, nextcmd, EVAL_EVALUATE) == FAIL)
|
if (eval0(arg, &tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
|
||||||
retval = NULL;
|
retval = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -440,7 +441,7 @@ eval_to_number(char_u *expr)
|
|||||||
|
|
||||||
++emsg_off;
|
++emsg_off;
|
||||||
|
|
||||||
if (eval1(&p, &rettv, EVAL_EVALUATE) == FAIL)
|
if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL)
|
||||||
retval = -1;
|
retval = -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -463,7 +464,7 @@ eval_expr(char_u *arg, char_u **nextcmd)
|
|||||||
typval_T *tv;
|
typval_T *tv;
|
||||||
|
|
||||||
tv = ALLOC_ONE(typval_T);
|
tv = ALLOC_ONE(typval_T);
|
||||||
if (tv != NULL && eval0(arg, tv, nextcmd, EVAL_EVALUATE) == FAIL)
|
if (tv != NULL && eval0(arg, tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
|
||||||
VIM_CLEAR(tv);
|
VIM_CLEAR(tv);
|
||||||
|
|
||||||
return tv;
|
return tv;
|
||||||
@@ -588,7 +589,7 @@ eval_foldexpr(char_u *arg, int *cp)
|
|||||||
++sandbox;
|
++sandbox;
|
||||||
++textwinlock;
|
++textwinlock;
|
||||||
*cp = NUL;
|
*cp = NUL;
|
||||||
if (eval0(arg, &tv, NULL, EVAL_EVALUATE) == FAIL)
|
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -776,7 +777,7 @@ get_lval(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
empty1 = FALSE;
|
empty1 = FALSE;
|
||||||
if (eval1(&p, &var1, EVAL_EVALUATE) == FAIL) // recursive!
|
if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL) // recursive!
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tv_get_string_chk(&var1) == NULL)
|
if (tv_get_string_chk(&var1) == NULL)
|
||||||
{
|
{
|
||||||
@@ -814,7 +815,7 @@ get_lval(
|
|||||||
{
|
{
|
||||||
lp->ll_empty2 = FALSE;
|
lp->ll_empty2 = FALSE;
|
||||||
// recursive!
|
// recursive!
|
||||||
if (eval1(&p, &var2, EVAL_EVALUATE) == FAIL)
|
if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(&var1);
|
clear_tv(&var1);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1424,7 +1425,10 @@ eval_for_line(
|
|||||||
char_u *expr;
|
char_u *expr;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
list_T *l;
|
list_T *l;
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = skip ? 0 : EVAL_EVALUATE;
|
||||||
*errp = TRUE; // default: there is an error
|
*errp = TRUE; // default: there is an error
|
||||||
|
|
||||||
fi = ALLOC_CLEAR_ONE(forinfo_T);
|
fi = ALLOC_CLEAR_ONE(forinfo_T);
|
||||||
@@ -1444,8 +1448,7 @@ eval_for_line(
|
|||||||
|
|
||||||
if (skip)
|
if (skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
if (eval0(skipwhite(expr + 2), &tv, nextcmdp, skip ? 0 : EVAL_EVALUATE)
|
if (eval0(skipwhite(expr + 2), &tv, nextcmdp, &evalarg) == OK)
|
||||||
== OK)
|
|
||||||
{
|
{
|
||||||
*errp = FALSE;
|
*errp = FALSE;
|
||||||
if (!skip)
|
if (!skip)
|
||||||
@@ -1763,6 +1766,35 @@ eval_func(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If inside Vim9 script, "arg" points to the end of a line (ignoring comments)
|
||||||
|
* and there is a next line, return the next line (skipping blanks) and set
|
||||||
|
* "getnext".
|
||||||
|
* Otherwise just return "arg" unmodified and set "getnext" to FALSE.
|
||||||
|
* "arg" must point somewhere inside a line, not at the start.
|
||||||
|
*/
|
||||||
|
static char_u *
|
||||||
|
eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
|
||||||
|
{
|
||||||
|
*getnext = FALSE;
|
||||||
|
if (current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
||||||
|
&& evalarg != NULL
|
||||||
|
&& evalarg->eval_cookie != NULL
|
||||||
|
&& (*arg == NUL || (VIM_ISWHITE(arg[-1])
|
||||||
|
&& (*arg == '"' || *arg == '#')))
|
||||||
|
&& source_nextline(evalarg->eval_cookie) != NULL)
|
||||||
|
{
|
||||||
|
char_u *p = source_nextline(evalarg->eval_cookie);
|
||||||
|
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
*getnext = TRUE;
|
||||||
|
return skipwhite(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "evaluate" argument: When FALSE, the argument is only parsed but not
|
* The "evaluate" argument: When FALSE, the argument is only parsed but not
|
||||||
* executed. The function may return OK, but the rettv will be of type
|
* executed. The function may return OK, but the rettv will be of type
|
||||||
@@ -1774,7 +1806,7 @@ eval_func(
|
|||||||
* This calls eval1() and handles error message and nextcmd.
|
* This calls eval1() and handles error message and nextcmd.
|
||||||
* Put the result in "rettv" when returning OK and "evaluate" is TRUE.
|
* Put the result in "rettv" when returning OK and "evaluate" is TRUE.
|
||||||
* Note: "rettv.v_lock" is not set.
|
* Note: "rettv.v_lock" is not set.
|
||||||
* "flags" has EVAL_EVALUATE and similar flags.
|
* "evalarg" can be NULL, EVALARG_EVALUATE or a pointer.
|
||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@@ -1782,15 +1814,16 @@ eval0(
|
|||||||
char_u *arg,
|
char_u *arg,
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
char_u **nextcmd,
|
char_u **nextcmd,
|
||||||
int flags)
|
evalarg_T *evalarg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int did_emsg_before = did_emsg;
|
int did_emsg_before = did_emsg;
|
||||||
int called_emsg_before = called_emsg;
|
int called_emsg_before = called_emsg;
|
||||||
|
int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
|
||||||
|
|
||||||
p = skipwhite(arg);
|
p = skipwhite(arg);
|
||||||
ret = eval1(&p, rettv, flags);
|
ret = eval1(&p, rettv, evalarg);
|
||||||
if (ret == FAIL || !ends_excmd2(arg, p))
|
if (ret == FAIL || !ends_excmd2(arg, p))
|
||||||
{
|
{
|
||||||
if (ret != FAIL)
|
if (ret != FAIL)
|
||||||
@@ -1826,23 +1859,36 @@ eval0(
|
|||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
eval1(char_u **arg, typval_T *rettv, int flags)
|
eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||||
{
|
{
|
||||||
int result;
|
|
||||||
typval_T var2;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
*/
|
*/
|
||||||
if (eval2(arg, rettv, flags) == FAIL)
|
if (eval2(arg, rettv, evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if ((*arg)[0] == '?')
|
if ((*arg)[0] == '?')
|
||||||
{
|
{
|
||||||
int evaluate = flags & EVAL_EVALUATE;
|
int result;
|
||||||
|
typval_T var2;
|
||||||
|
evalarg_T nested_evalarg;
|
||||||
|
int orig_flags;
|
||||||
|
|
||||||
|
if (evalarg == NULL)
|
||||||
|
{
|
||||||
|
CLEAR_FIELD(nested_evalarg);
|
||||||
|
orig_flags = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nested_evalarg = *evalarg;
|
||||||
|
orig_flags = evalarg->eval_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
int evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
|
||||||
|
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
if (flags & EVAL_EVALUATE)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
int error = FALSE;
|
int error = FALSE;
|
||||||
|
|
||||||
@@ -1857,7 +1903,9 @@ eval1(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Get the second variable. Recursive!
|
* Get the second variable. Recursive!
|
||||||
*/
|
*/
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (eval1(arg, rettv, result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
|
nested_evalarg.eval_flags = result ? orig_flags
|
||||||
|
: orig_flags & ~EVAL_EVALUATE;
|
||||||
|
if (eval1(arg, rettv, &nested_evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1875,7 +1923,9 @@ eval1(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Get the third variable. Recursive!
|
* Get the third variable. Recursive!
|
||||||
*/
|
*/
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (eval1(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
|
nested_evalarg.eval_flags = !result ? orig_flags
|
||||||
|
: orig_flags & ~EVAL_EVALUATE;
|
||||||
|
if (eval1(arg, &var2, &nested_evalarg) == FAIL)
|
||||||
{
|
{
|
||||||
if (evaluate && result)
|
if (evaluate && result)
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
@@ -1898,7 +1948,7 @@ eval1(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
eval2(char_u **arg, typval_T *rettv, int flags)
|
eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
long result;
|
long result;
|
||||||
@@ -1908,7 +1958,7 @@ eval2(char_u **arg, typval_T *rettv, int flags)
|
|||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
*/
|
*/
|
||||||
if (eval3(arg, rettv, flags) == FAIL)
|
if (eval3(arg, rettv, evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1918,7 +1968,22 @@ eval2(char_u **arg, typval_T *rettv, int flags)
|
|||||||
result = FALSE;
|
result = FALSE;
|
||||||
while ((*arg)[0] == '|' && (*arg)[1] == '|')
|
while ((*arg)[0] == '|' && (*arg)[1] == '|')
|
||||||
{
|
{
|
||||||
int evaluate = flags & EVAL_EVALUATE;
|
evalarg_T nested_evalarg;
|
||||||
|
int evaluate;
|
||||||
|
int orig_flags;
|
||||||
|
|
||||||
|
if (evalarg == NULL)
|
||||||
|
{
|
||||||
|
CLEAR_FIELD(nested_evalarg);
|
||||||
|
orig_flags = 0;
|
||||||
|
evaluate = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nested_evalarg = *evalarg;
|
||||||
|
orig_flags = evalarg->eval_flags;
|
||||||
|
evaluate = orig_flags & EVAL_EVALUATE;
|
||||||
|
}
|
||||||
|
|
||||||
if (evaluate && first)
|
if (evaluate && first)
|
||||||
{
|
{
|
||||||
@@ -1934,8 +1999,9 @@ eval2(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Get the second variable.
|
* Get the second variable.
|
||||||
*/
|
*/
|
||||||
*arg = skipwhite(*arg + 2);
|
*arg = skipwhite(*arg + 2);
|
||||||
if (eval3(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE)
|
nested_evalarg.eval_flags = !result ? orig_flags
|
||||||
== FAIL)
|
: orig_flags & ~EVAL_EVALUATE;
|
||||||
|
if (eval3(arg, &var2, &nested_evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1969,7 +2035,7 @@ eval2(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
eval3(char_u **arg, typval_T *rettv, int flags)
|
eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
long result;
|
long result;
|
||||||
@@ -1979,7 +2045,7 @@ eval3(char_u **arg, typval_T *rettv, int flags)
|
|||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
*/
|
*/
|
||||||
if (eval4(arg, rettv, flags) == FAIL)
|
if (eval4(arg, rettv, evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1989,8 +2055,22 @@ eval3(char_u **arg, typval_T *rettv, int flags)
|
|||||||
result = TRUE;
|
result = TRUE;
|
||||||
while ((*arg)[0] == '&' && (*arg)[1] == '&')
|
while ((*arg)[0] == '&' && (*arg)[1] == '&')
|
||||||
{
|
{
|
||||||
int evaluate = flags & EVAL_EVALUATE;
|
evalarg_T nested_evalarg;
|
||||||
|
int orig_flags;
|
||||||
|
int evaluate;
|
||||||
|
|
||||||
|
if (evalarg == NULL)
|
||||||
|
{
|
||||||
|
CLEAR_FIELD(nested_evalarg);
|
||||||
|
orig_flags = 0;
|
||||||
|
evaluate = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nested_evalarg = *evalarg;
|
||||||
|
orig_flags = evalarg->eval_flags;
|
||||||
|
evaluate = orig_flags & EVAL_EVALUATE;
|
||||||
|
}
|
||||||
if (evaluate && first)
|
if (evaluate && first)
|
||||||
{
|
{
|
||||||
if (tv_get_number_chk(rettv, &error) == 0)
|
if (tv_get_number_chk(rettv, &error) == 0)
|
||||||
@@ -2005,7 +2085,9 @@ eval3(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Get the second variable.
|
* Get the second variable.
|
||||||
*/
|
*/
|
||||||
*arg = skipwhite(*arg + 2);
|
*arg = skipwhite(*arg + 2);
|
||||||
if (eval4(arg, &var2, result ? flags : flags & ~EVAL_EVALUATE) == FAIL)
|
nested_evalarg.eval_flags = result ? orig_flags
|
||||||
|
: orig_flags & ~EVAL_EVALUATE;
|
||||||
|
if (eval4(arg, &var2, &nested_evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2048,7 +2130,7 @@ eval3(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
eval4(char_u **arg, typval_T *rettv, int flags)
|
eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@@ -2060,7 +2142,7 @@ eval4(char_u **arg, typval_T *rettv, int flags)
|
|||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
*/
|
*/
|
||||||
if (eval5(arg, rettv, flags) == FAIL)
|
if (eval5(arg, rettv, evalarg) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
p = *arg;
|
p = *arg;
|
||||||
@@ -2128,12 +2210,12 @@ eval4(char_u **arg, typval_T *rettv, int flags)
|
|||||||
* Get the second variable.
|
* Get the second variable.
|
||||||
*/
|
*/
|
||||||
*arg = skipwhite(p + len);
|
*arg = skipwhite(p + len);
|
||||||
if (eval5(arg, &var2, flags) == FAIL)
|
if (eval5(arg, &var2, evalarg) == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (flags & EVAL_EVALUATE)
|
if (evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE))
|
||||||
{
|
{
|
||||||
int ret = typval_compare(rettv, &var2, type, ic);
|
int ret = typval_compare(rettv, &var2, type, ic);
|
||||||
|
|
||||||
@@ -2195,23 +2277,14 @@ eval_addlist(typval_T *tv1, typval_T *tv2)
|
|||||||
* Return OK or FAIL.
|
* Return OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
eval5(char_u **arg, typval_T *rettv, int flags)
|
eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||||
{
|
{
|
||||||
typval_T var2;
|
int evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
|
||||||
int op;
|
|
||||||
varnumber_T n1, n2;
|
|
||||||
#ifdef FEAT_FLOAT
|
|
||||||
float_T f1 = 0, f2 = 0;
|
|
||||||
#endif
|
|
||||||
char_u *s1, *s2;
|
|
||||||
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
|
|
||||||
char_u *p;
|
|
||||||
int concat;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
*/
|
*/
|
||||||
if (eval6(arg, rettv, flags, FALSE) == FAIL)
|
if (eval6(arg, rettv, evalarg, FALSE) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2219,12 +2292,20 @@ eval5(char_u **arg, typval_T *rettv, int flags)
|
|||||||
*/
|
*/
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
int getnext;
|
||||||
|
char_u *p;
|
||||||
|
int op;
|
||||||
|
int concat;
|
||||||
|
typval_T var2;
|
||||||
|
|
||||||
// "." is only string concatenation when scriptversion is 1
|
// "." is only string concatenation when scriptversion is 1
|
||||||
op = **arg;
|
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
concat = op == '.'
|
op = *p;
|
||||||
&& (*(*arg + 1) == '.' || current_sctx.sc_version < 2);
|
concat = op == '.' && (*(p + 1) == '.' || current_sctx.sc_version < 2);
|
||||||
if (op != '+' && op != '-' && !concat)
|
if (op != '+' && op != '-' && !concat)
|
||||||
break;
|
break;
|
||||||
|
if (getnext)
|
||||||
|
*arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
|
||||||
|
|
||||||
if ((op != '+' || (rettv->v_type != VAR_LIST
|
if ((op != '+' || (rettv->v_type != VAR_LIST
|
||||||
&& rettv->v_type != VAR_BLOB))
|
&& rettv->v_type != VAR_BLOB))
|
||||||
@@ -2240,7 +2321,7 @@ eval5(char_u **arg, typval_T *rettv, int flags)
|
|||||||
// we know that the first operand needs to be a string or number
|
// we know that the first operand needs to be a string or number
|
||||||
// without evaluating the 2nd operand. So check before to avoid
|
// without evaluating the 2nd operand. So check before to avoid
|
||||||
// side effects after an error.
|
// side effects after an error.
|
||||||
if ((flags & EVAL_EVALUATE) && tv_get_string_chk(rettv) == NULL)
|
if (evaluate && tv_get_string_chk(rettv) == NULL)
|
||||||
{
|
{
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -2253,21 +2334,23 @@ eval5(char_u **arg, typval_T *rettv, int flags)
|
|||||||
if (op == '.' && *(*arg + 1) == '.') // .. string concatenation
|
if (op == '.' && *(*arg + 1) == '.') // .. string concatenation
|
||||||
++*arg;
|
++*arg;
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (eval6(arg, &var2, flags, op == '.') == FAIL)
|
if (eval6(arg, &var2, evalarg, op == '.') == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & EVAL_EVALUATE)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Compute the result.
|
* Compute the result.
|
||||||
*/
|
*/
|
||||||
if (op == '.')
|
if (op == '.')
|
||||||
{
|
{
|
||||||
s1 = tv_get_string_buf(rettv, buf1); // already checked
|
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
|
||||||
s2 = tv_get_string_buf_chk(&var2, buf2);
|
char_u *s1 = tv_get_string_buf(rettv, buf1);
|
||||||
|
char_u *s2 = tv_get_string_buf_chk(&var2, buf2);
|
||||||
|
|
||||||
if (s2 == NULL) // type error ?
|
if (s2 == NULL) // type error ?
|
||||||
{
|
{
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
@@ -2290,9 +2373,11 @@ eval5(char_u **arg, typval_T *rettv, int flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int error = FALSE;
|
int error = FALSE;
|
||||||
|
varnumber_T n1, n2;
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
|
float_T f1 = 0, f2 = 0;
|
||||||
|
|
||||||
if (rettv->v_type == VAR_FLOAT)
|
if (rettv->v_type == VAR_FLOAT)
|
||||||
{
|
{
|
||||||
f1 = rettv->vval.v_float;
|
f1 = rettv->vval.v_float;
|
||||||
@@ -2381,7 +2466,7 @@ eval5(char_u **arg, typval_T *rettv, int flags)
|
|||||||
eval6(
|
eval6(
|
||||||
char_u **arg,
|
char_u **arg,
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
int flags,
|
evalarg_T *evalarg,
|
||||||
int want_string) // after "." operator
|
int want_string) // after "." operator
|
||||||
{
|
{
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
@@ -2396,7 +2481,7 @@ eval6(
|
|||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
*/
|
*/
|
||||||
if (eval7(arg, rettv, flags, want_string) == FAIL)
|
if (eval7(arg, rettv, evalarg, want_string) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2404,11 +2489,17 @@ eval6(
|
|||||||
*/
|
*/
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
op = **arg;
|
int evaluate = evalarg == NULL ? 0
|
||||||
|
: (evalarg->eval_flags & EVAL_EVALUATE);
|
||||||
|
int getnext;
|
||||||
|
|
||||||
|
op = *eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
if (op != '*' && op != '/' && op != '%')
|
if (op != '*' && op != '/' && op != '%')
|
||||||
break;
|
break;
|
||||||
|
if (getnext)
|
||||||
|
*arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
|
||||||
|
|
||||||
if (flags & EVAL_EVALUATE)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
if (rettv->v_type == VAR_FLOAT)
|
if (rettv->v_type == VAR_FLOAT)
|
||||||
@@ -2431,10 +2522,10 @@ eval6(
|
|||||||
* Get the second variable.
|
* Get the second variable.
|
||||||
*/
|
*/
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (eval7(arg, &var2, flags, FALSE) == FAIL)
|
if (eval7(arg, &var2, evalarg, FALSE) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if (flags & EVAL_EVALUATE)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
if (var2.v_type == VAR_FLOAT)
|
if (var2.v_type == VAR_FLOAT)
|
||||||
@@ -2551,10 +2642,12 @@ eval6(
|
|||||||
eval7(
|
eval7(
|
||||||
char_u **arg,
|
char_u **arg,
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
int flags,
|
evalarg_T *evalarg,
|
||||||
int want_string) // after "." operator
|
int want_string) // after "." operator
|
||||||
{
|
{
|
||||||
int evaluate = flags & EVAL_EVALUATE;
|
int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
|
||||||
|
int evaluate = evalarg != NULL
|
||||||
|
&& (evalarg->eval_flags & EVAL_EVALUATE);
|
||||||
int len;
|
int len;
|
||||||
char_u *s;
|
char_u *s;
|
||||||
char_u *start_leader, *end_leader;
|
char_u *start_leader, *end_leader;
|
||||||
@@ -2672,15 +2765,17 @@ eval7(
|
|||||||
/*
|
/*
|
||||||
* nested expression: (expression).
|
* nested expression: (expression).
|
||||||
*/
|
*/
|
||||||
case '(': *arg = skipwhite(*arg + 1);
|
case '(': {
|
||||||
ret = eval1(arg, rettv, flags); // recursive!
|
*arg = skipwhite(*arg + 1);
|
||||||
if (**arg == ')')
|
ret = eval1(arg, rettv, evalarg); // recursive!
|
||||||
++*arg;
|
if (**arg == ')')
|
||||||
else if (ret == OK)
|
++*arg;
|
||||||
{
|
else if (ret == OK)
|
||||||
emsg(_(e_missing_close));
|
{
|
||||||
clear_tv(rettv);
|
emsg(_(e_missing_close));
|
||||||
ret = FAIL;
|
clear_tv(rettv);
|
||||||
|
ret = FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3030,6 +3125,11 @@ eval_index(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* something[idx]
|
* something[idx]
|
||||||
*
|
*
|
||||||
@@ -3038,7 +3138,7 @@ eval_index(
|
|||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (**arg == ':')
|
if (**arg == ':')
|
||||||
empty1 = TRUE;
|
empty1 = TRUE;
|
||||||
else if (eval1(arg, &var1, flags) == FAIL) // recursive!
|
else if (eval1(arg, &var1, &evalarg) == FAIL) // recursive!
|
||||||
return FAIL;
|
return FAIL;
|
||||||
else if (evaluate && tv_get_string_chk(&var1) == NULL)
|
else if (evaluate && tv_get_string_chk(&var1) == NULL)
|
||||||
{
|
{
|
||||||
@@ -3056,7 +3156,7 @@ eval_index(
|
|||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
if (**arg == ']')
|
if (**arg == ']')
|
||||||
empty2 = TRUE;
|
empty2 = TRUE;
|
||||||
else if (eval1(arg, &var2, flags) == FAIL) // recursive!
|
else if (eval1(arg, &var2, &evalarg) == FAIL) // recursive!
|
||||||
{
|
{
|
||||||
if (!empty1)
|
if (!empty1)
|
||||||
clear_tv(&var1);
|
clear_tv(&var1);
|
||||||
@@ -4947,6 +5047,10 @@ ex_echo(exarg_T *eap)
|
|||||||
int atstart = TRUE;
|
int atstart = TRUE;
|
||||||
int did_emsg_before = did_emsg;
|
int did_emsg_before = did_emsg;
|
||||||
int called_emsg_before = called_emsg;
|
int called_emsg_before = called_emsg;
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
|
||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
@@ -4957,7 +5061,7 @@ ex_echo(exarg_T *eap)
|
|||||||
need_clr_eos = needclr;
|
need_clr_eos = needclr;
|
||||||
|
|
||||||
p = arg;
|
p = arg;
|
||||||
if (eval1(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE) == FAIL)
|
if (eval1(&arg, &rettv, &evalarg) == FAIL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Report the invalid expression unless the expression evaluation
|
* Report the invalid expression unless the expression evaluation
|
||||||
|
|||||||
@@ -2084,7 +2084,7 @@ f_eval(typval_T *argvars, typval_T *rettv)
|
|||||||
s = skipwhite(s);
|
s = skipwhite(s);
|
||||||
|
|
||||||
p = s;
|
p = s;
|
||||||
if (s == NULL || eval1(&s, rettv, EVAL_EVALUATE) == FAIL)
|
if (s == NULL || eval1(&s, rettv, &EVALARG_EVALUATE) == FAIL)
|
||||||
{
|
{
|
||||||
if (p != NULL && !aborting())
|
if (p != NULL && !aborting())
|
||||||
semsg(_(e_invexpr2), p);
|
semsg(_(e_invexpr2), p);
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ eval_spell_expr(char_u *badword, char_u *expr)
|
|||||||
if (p_verbose == 0)
|
if (p_verbose == 0)
|
||||||
++emsg_off;
|
++emsg_off;
|
||||||
|
|
||||||
if (eval1(&p, &rettv, EVAL_EVALUATE) == OK)
|
if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK)
|
||||||
{
|
{
|
||||||
if (rettv.v_type != VAR_LIST)
|
if (rettv.v_type != VAR_LIST)
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
@@ -774,7 +774,7 @@ ex_let(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int eval_flags;
|
evalarg_T evalarg;
|
||||||
|
|
||||||
rettv.v_type = VAR_UNKNOWN;
|
rettv.v_type = VAR_UNKNOWN;
|
||||||
i = FAIL;
|
i = FAIL;
|
||||||
@@ -797,14 +797,17 @@ ex_let(exarg_T *eap)
|
|||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
|
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
|
||||||
i = eval0(expr, &rettv, &eap->nextcmd, eval_flags);
|
evalarg.eval_cookie = eap->getline == getsourceline
|
||||||
|
? eap->cookie : NULL;
|
||||||
|
i = eval0(expr, &rettv, &eap->nextcmd, &evalarg);
|
||||||
|
if (eap->skip)
|
||||||
|
--emsg_skip;
|
||||||
}
|
}
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
{
|
{
|
||||||
if (i != FAIL)
|
if (i != FAIL)
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
--emsg_skip;
|
|
||||||
}
|
}
|
||||||
else if (i != FAIL)
|
else if (i != FAIL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -895,9 +895,12 @@ report_discard_pending(int pending, void *value)
|
|||||||
ex_eval(exarg_T *eap)
|
ex_eval(exarg_T *eap)
|
||||||
{
|
{
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
if (eval0(eap->arg, &tv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE)
|
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
|
||||||
== OK)
|
evalarg.eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL;
|
||||||
|
|
||||||
|
if (eval0(eap->arg, &tv, &eap->nextcmd, &evalarg) == OK)
|
||||||
clear_tv(&tv);
|
clear_tv(&tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1880,6 +1880,9 @@ EXTERN char windowsVersion[20] INIT(= {0});
|
|||||||
|
|
||||||
// Used for lv_first in a non-materialized range() list.
|
// Used for lv_first in a non-materialized range() list.
|
||||||
EXTERN listitem_T range_list_item;
|
EXTERN listitem_T range_list_item;
|
||||||
|
|
||||||
|
// Passed to an eval() function to enable evaluation.
|
||||||
|
EXTERN evalarg_T EVALARG_EVALUATE INIT2(EVAL_EVALUATE, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MSWIN
|
#ifdef MSWIN
|
||||||
|
|||||||
@@ -1165,6 +1165,10 @@ get_list_tv(char_u **arg, typval_T *rettv, int flags, int do_error)
|
|||||||
list_T *l = NULL;
|
list_T *l = NULL;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = flags;
|
||||||
|
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
@@ -1176,7 +1180,7 @@ get_list_tv(char_u **arg, typval_T *rettv, int flags, int do_error)
|
|||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
while (**arg != ']' && **arg != NUL)
|
while (**arg != ']' && **arg != NUL)
|
||||||
{
|
{
|
||||||
if (eval1(arg, &tv, flags) == FAIL) // recursive!
|
if (eval1(arg, &tv, &evalarg) == FAIL) // recursive!
|
||||||
goto failret;
|
goto failret;
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ int next_for_item(void *fi_void, char_u *arg);
|
|||||||
void free_for_info(void *fi_void);
|
void free_for_info(void *fi_void);
|
||||||
void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx);
|
void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx);
|
||||||
int pattern_match(char_u *pat, char_u *text, int ic);
|
int pattern_match(char_u *pat, char_u *text, int ic);
|
||||||
int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int flags);
|
int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, evalarg_T *evalarg);
|
||||||
int eval1(char_u **arg, typval_T *rettv, int flags);
|
int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg_in);
|
||||||
void eval_addblob(typval_T *tv1, typval_T *tv2);
|
void eval_addblob(typval_T *tv1, typval_T *tv2);
|
||||||
int eval_addlist(typval_T *tv1, typval_T *tv2);
|
int eval_addlist(typval_T *tv1, typval_T *tv2);
|
||||||
char_u *partial_name(partial_T *pt);
|
char_u *partial_name(partial_T *pt);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ void ex_options(exarg_T *eap);
|
|||||||
linenr_T *source_breakpoint(void *cookie);
|
linenr_T *source_breakpoint(void *cookie);
|
||||||
int *source_dbg_tick(void *cookie);
|
int *source_dbg_tick(void *cookie);
|
||||||
int source_level(void *cookie);
|
int source_level(void *cookie);
|
||||||
|
char_u *source_nextline(void *cookie);
|
||||||
int do_source(char_u *fname, int check_other, int is_vimrc, int *ret_sid);
|
int do_source(char_u *fname, int check_other, int is_vimrc, int *ret_sid);
|
||||||
void ex_scriptnames(exarg_T *eap);
|
void ex_scriptnames(exarg_T *eap);
|
||||||
void scriptnames_slash_adjust(void);
|
void scriptnames_slash_adjust(void);
|
||||||
|
|||||||
@@ -1050,6 +1050,15 @@ source_level(void *cookie)
|
|||||||
{
|
{
|
||||||
return ((struct source_cookie *)cookie)->level;
|
return ((struct source_cookie *)cookie)->level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the readahead line.
|
||||||
|
*/
|
||||||
|
char_u *
|
||||||
|
source_nextline(void *cookie)
|
||||||
|
{
|
||||||
|
return ((struct source_cookie *)cookie)->nextline;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(MSWIN) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)
|
#if (defined(MSWIN) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC)
|
||||||
|
|||||||
@@ -1746,6 +1746,19 @@ typedef struct
|
|||||||
# endif
|
# endif
|
||||||
} scriptitem_T;
|
} scriptitem_T;
|
||||||
|
|
||||||
|
// Struct passed through eval() functions.
|
||||||
|
// See EVALARG_EVALUATE for a fixed value with eval_flags set to EVAL_EVALUATE.
|
||||||
|
typedef struct {
|
||||||
|
int eval_flags; // EVAL_ flag values below
|
||||||
|
|
||||||
|
// copied from exarg_T when "getline" is "getsourceline". Can be NULL.
|
||||||
|
void *eval_cookie; // argument for getline()
|
||||||
|
} evalarg_T;
|
||||||
|
|
||||||
|
// Flags for expression evaluation.
|
||||||
|
#define EVAL_EVALUATE 1 // when missing don't actually evaluate
|
||||||
|
#define EVAL_CONSTANT 2 // when not a constant return FAIL
|
||||||
|
|
||||||
# ifdef FEAT_PROFILE
|
# ifdef FEAT_PROFILE
|
||||||
/*
|
/*
|
||||||
* Struct used in sn_prl_ga for every line of a script.
|
* Struct used in sn_prl_ga for every line of a script.
|
||||||
|
|||||||
@@ -570,6 +570,26 @@ def Test_expr5()
|
|||||||
assert_equal(0z01ab01ab, g:ablob + g:ablob)
|
assert_equal(0z01ab01ab, g:ablob + g:ablob)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_expr5_vim9script()
|
||||||
|
" only checks line continuation
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
let var = 11
|
||||||
|
+ 77
|
||||||
|
- 22
|
||||||
|
assert_equal(66, var)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
let var = 'one'
|
||||||
|
.. 'two'
|
||||||
|
assert_equal('onetwo', var)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_expr5_float()
|
def Test_expr5_float()
|
||||||
if !has('float')
|
if !has('float')
|
||||||
MissingFeature 'float'
|
MissingFeature 'float'
|
||||||
@@ -661,6 +681,26 @@ def Test_expr6()
|
|||||||
call CheckDefFailure(["let x = 6 * xxx"], 'E1001')
|
call CheckDefFailure(["let x = 6 * xxx"], 'E1001')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_expr6_vim9script()
|
||||||
|
" only checks line continuation
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
let var = 11
|
||||||
|
* 22
|
||||||
|
/ 3
|
||||||
|
assert_equal(80, var)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
let var = 25
|
||||||
|
% 10
|
||||||
|
assert_equal(5, var)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_expr6_float()
|
def Test_expr6_float()
|
||||||
if !has('float')
|
if !has('float')
|
||||||
MissingFeature 'float'
|
MissingFeature 'float'
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ get_function_args(
|
|||||||
whitep = p;
|
whitep = p;
|
||||||
p = skipwhite(p);
|
p = skipwhite(p);
|
||||||
expr = p;
|
expr = p;
|
||||||
if (eval1(&p, &rettv, 0) != FAIL)
|
if (eval1(&p, &rettv, NULL) != FAIL)
|
||||||
{
|
{
|
||||||
if (ga_grow(default_args, 1) == FAIL)
|
if (ga_grow(default_args, 1) == FAIL)
|
||||||
goto err_ret;
|
goto err_ret;
|
||||||
@@ -561,6 +561,10 @@ get_func_tv(
|
|||||||
int ret = OK;
|
int ret = OK;
|
||||||
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
|
typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments
|
||||||
int argcount = 0; // number of arguments found
|
int argcount = 0; // number of arguments found
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = funcexe->evaluate ? EVAL_EVALUATE : 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the arguments.
|
* Get the arguments.
|
||||||
@@ -572,8 +576,7 @@ get_func_tv(
|
|||||||
argp = skipwhite(argp + 1); // skip the '(' or ','
|
argp = skipwhite(argp + 1); // skip the '(' or ','
|
||||||
if (*argp == ')' || *argp == ',' || *argp == NUL)
|
if (*argp == ')' || *argp == ',' || *argp == NUL)
|
||||||
break;
|
break;
|
||||||
if (eval1(&argp, &argvars[argcount],
|
if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL)
|
||||||
funcexe->evaluate ? EVAL_EVALUATE : 0) == FAIL)
|
|
||||||
{
|
{
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
break;
|
break;
|
||||||
@@ -1249,7 +1252,7 @@ call_user_func(
|
|||||||
|
|
||||||
default_expr = ((char_u **)(fp->uf_def_args.ga_data))
|
default_expr = ((char_u **)(fp->uf_def_args.ga_data))
|
||||||
[ai + fp->uf_def_args.ga_len];
|
[ai + fp->uf_def_args.ga_len];
|
||||||
if (eval1(&default_expr, &def_rettv, EVAL_EVALUATE) == FAIL)
|
if (eval1(&default_expr, &def_rettv, &EVALARG_EVALUATE) == FAIL)
|
||||||
{
|
{
|
||||||
default_arg_err = 1;
|
default_arg_err = 1;
|
||||||
break;
|
break;
|
||||||
@@ -1394,7 +1397,7 @@ call_user_func(
|
|||||||
// A Lambda always has the command "return {expr}". It is much faster
|
// A Lambda always has the command "return {expr}". It is much faster
|
||||||
// to evaluate {expr} directly.
|
// to evaluate {expr} directly.
|
||||||
++ex_nesting_level;
|
++ex_nesting_level;
|
||||||
(void)eval1(&p, rettv, EVAL_EVALUATE);
|
(void)eval1(&p, rettv, &EVALARG_EVALUATE);
|
||||||
--ex_nesting_level;
|
--ex_nesting_level;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3697,6 +3700,7 @@ ex_return(exarg_T *eap)
|
|||||||
char_u *arg = eap->arg;
|
char_u *arg = eap->arg;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int returning = FALSE;
|
int returning = FALSE;
|
||||||
|
evalarg_T evalarg;
|
||||||
|
|
||||||
if (current_funccal == NULL)
|
if (current_funccal == NULL)
|
||||||
{
|
{
|
||||||
@@ -3704,13 +3708,15 @@ ex_return(exarg_T *eap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLEAR_FIELD(evalarg);
|
||||||
|
evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
|
||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
|
|
||||||
eap->nextcmd = NULL;
|
eap->nextcmd = NULL;
|
||||||
if ((*arg != NUL && *arg != '|' && *arg != '\n')
|
if ((*arg != NUL && *arg != '|' && *arg != '\n')
|
||||||
&& eval0(arg, &rettv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE)
|
&& eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL)
|
||||||
!= FAIL)
|
|
||||||
{
|
{
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
returning = do_return(eap, FALSE, TRUE, &rettv);
|
returning = do_return(eap, FALSE, TRUE, &rettv);
|
||||||
@@ -3767,7 +3773,7 @@ ex_call(exarg_T *eap)
|
|||||||
// instead to skip to any following command, e.g. for:
|
// instead to skip to any following command, e.g. for:
|
||||||
// :if 0 | call dict.foo().bar() | endif
|
// :if 0 | call dict.foo().bar() | endif
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
if (eval0(eap->arg, &rettv, &eap->nextcmd, 0) != FAIL)
|
if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL)
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
--emsg_skip;
|
--emsg_skip;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -754,6 +754,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 */
|
||||||
|
/**/
|
||||||
|
1047,
|
||||||
/**/
|
/**/
|
||||||
1046,
|
1046,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
@@ -2665,10 +2665,6 @@ long elapsed(DWORD start_tick);
|
|||||||
#define REPTERM_SPECIAL 4
|
#define REPTERM_SPECIAL 4
|
||||||
#define REPTERM_NO_SIMPLIFY 8
|
#define REPTERM_NO_SIMPLIFY 8
|
||||||
|
|
||||||
// Flags for expression evaluation.
|
|
||||||
#define EVAL_EVALUATE 1 // when missing don't actually evaluate
|
|
||||||
#define EVAL_CONSTANT 2 // when not a constant return FAIL
|
|
||||||
|
|
||||||
// Flags for find_special_key()
|
// Flags for find_special_key()
|
||||||
#define FSK_KEYCODE 0x01 // prefer key code, e.g. K_DEL instead of DEL
|
#define FSK_KEYCODE 0x01 // prefer key code, e.g. K_DEL instead of DEL
|
||||||
#define FSK_KEEP_X_KEY 0x02 // don't translate xHome to Home key
|
#define FSK_KEEP_X_KEY 0x02 // don't translate xHome to Home key
|
||||||
|
|||||||
Reference in New Issue
Block a user