forked from aniani/vim
patch 8.2.1067: expression "!expr->func()" does not work
Problem: Expression "!expr->func()" does not work. Solution: Apply plus and minus earlier. (closes #6348)
This commit is contained in:
32
src/eval.c
32
src/eval.c
@@ -51,7 +51,7 @@ static int eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
|||||||
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
static int eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
static int eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg, 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, evalarg_T *evalarg, 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, int numeric_only, char_u *start_leader, char_u **end_leaderp);
|
||||||
|
|
||||||
static int free_unref_items(int copyID);
|
static int free_unref_items(int copyID);
|
||||||
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
|
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end);
|
||||||
@@ -2756,6 +2756,11 @@ eval7(
|
|||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
case '.': ret = get_number_tv(arg, rettv, evaluate, want_string);
|
case '.': ret = get_number_tv(arg, rettv, evaluate, want_string);
|
||||||
|
|
||||||
|
// Apply prefixed "-" and "+" now. Matters especially when
|
||||||
|
// "->" follows.
|
||||||
|
if (ret == OK && evaluate && end_leader > start_leader)
|
||||||
|
ret = eval7_leader(rettv, TRUE, start_leader, &end_leader);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2879,23 +2884,27 @@ eval7(
|
|||||||
// Handle following '[', '(' and '.' for expr[expr], expr.name,
|
// Handle following '[', '(' and '.' for expr[expr], expr.name,
|
||||||
// expr(expr), expr->name(expr)
|
// expr(expr), expr->name(expr)
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
ret = handle_subscript(arg, rettv, flags, TRUE,
|
ret = handle_subscript(arg, rettv, flags, TRUE);
|
||||||
start_leader, &end_leader);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply logical NOT and unary '-', from right to left, ignore '+'.
|
* Apply logical NOT and unary '-', from right to left, ignore '+'.
|
||||||
*/
|
*/
|
||||||
if (ret == OK && evaluate && end_leader > start_leader)
|
if (ret == OK && evaluate && end_leader > start_leader)
|
||||||
ret = eval7_leader(rettv, start_leader, &end_leader);
|
ret = eval7_leader(rettv, FALSE, start_leader, &end_leader);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply the leading "!" and "-" before an eval7 expression to "rettv".
|
* Apply the leading "!" and "-" before an eval7 expression to "rettv".
|
||||||
|
* When "numeric_only" is TRUE only handle "+" and "-".
|
||||||
* Adjusts "end_leaderp" until it is at "start_leader".
|
* Adjusts "end_leaderp" until it is at "start_leader".
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp)
|
eval7_leader(
|
||||||
|
typval_T *rettv,
|
||||||
|
int numeric_only,
|
||||||
|
char_u *start_leader,
|
||||||
|
char_u **end_leaderp)
|
||||||
{
|
{
|
||||||
char_u *end_leader = *end_leaderp;
|
char_u *end_leader = *end_leaderp;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@@ -2921,6 +2930,11 @@ eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp)
|
|||||||
--end_leader;
|
--end_leader;
|
||||||
if (*end_leader == '!')
|
if (*end_leader == '!')
|
||||||
{
|
{
|
||||||
|
if (numeric_only)
|
||||||
|
{
|
||||||
|
++end_leader;
|
||||||
|
break;
|
||||||
|
}
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
if (rettv->v_type == VAR_FLOAT)
|
if (rettv->v_type == VAR_FLOAT)
|
||||||
f = !f;
|
f = !f;
|
||||||
@@ -4871,9 +4885,7 @@ handle_subscript(
|
|||||||
char_u **arg,
|
char_u **arg,
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
int flags, // do more than finding the end
|
int flags, // do more than finding the end
|
||||||
int verbose, // give error messages
|
int verbose) // give error messages
|
||||||
char_u *start_leader, // start of '!' and '-' prefixes
|
|
||||||
char_u **end_leaderp) // end of '!' and '-' prefixes
|
|
||||||
{
|
{
|
||||||
int evaluate = flags & EVAL_EVALUATE;
|
int evaluate = flags & EVAL_EVALUATE;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@@ -4910,10 +4922,6 @@ handle_subscript(
|
|||||||
}
|
}
|
||||||
else if (**arg == '-')
|
else if (**arg == '-')
|
||||||
{
|
{
|
||||||
// Expression "-1.0->method()" applies the leader "-" before
|
|
||||||
// applying ->.
|
|
||||||
if (evaluate && *end_leaderp > start_leader)
|
|
||||||
ret = eval7_leader(rettv, start_leader, end_leaderp);
|
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
{
|
{
|
||||||
if ((*arg)[2] == '{')
|
if ((*arg)[2] == '{')
|
||||||
|
@@ -1125,8 +1125,8 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first)
|
|||||||
{
|
{
|
||||||
// handle d.key, l[idx], f(expr)
|
// handle d.key, l[idx], f(expr)
|
||||||
arg_subsc = arg;
|
arg_subsc = arg;
|
||||||
if (handle_subscript(&arg, &tv, EVAL_EVALUATE, TRUE,
|
if (handle_subscript(&arg, &tv, EVAL_EVALUATE, TRUE)
|
||||||
name, &name) == FAIL)
|
== FAIL)
|
||||||
error = TRUE;
|
error = TRUE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3341,8 +3341,7 @@ var_exists(char_u *var)
|
|||||||
if (n)
|
if (n)
|
||||||
{
|
{
|
||||||
// handle d.key, l[idx], f(expr)
|
// handle d.key, l[idx], f(expr)
|
||||||
n = (handle_subscript(&var, &tv, EVAL_EVALUATE,
|
n = (handle_subscript(&var, &tv, EVAL_EVALUATE, FALSE) == OK);
|
||||||
FALSE, name, &name) == OK);
|
|
||||||
if (n)
|
if (n)
|
||||||
clear_tv(&tv);
|
clear_tv(&tv);
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,7 @@ int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose);
|
|||||||
char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags);
|
char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags);
|
||||||
int eval_isnamec(int c);
|
int eval_isnamec(int c);
|
||||||
int eval_isnamec1(int c);
|
int eval_isnamec1(int c);
|
||||||
int handle_subscript(char_u **arg, typval_T *rettv, int flags, int verbose, char_u *start_leader, char_u **end_leaderp);
|
int handle_subscript(char_u **arg, typval_T *rettv, int flags, int verbose);
|
||||||
int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
|
int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
|
||||||
void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr);
|
void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr);
|
||||||
void ex_echo(exarg_T *eap);
|
void ex_echo(exarg_T *eap);
|
||||||
|
@@ -110,6 +110,13 @@ func Test_special_char()
|
|||||||
call assert_fails('echo "\<C-">')
|
call assert_fails('echo "\<C-">')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_method_with_prefix()
|
||||||
|
call assert_equal(1, !range(5)->empty())
|
||||||
|
call assert_equal([0, 1, 2], --3->range())
|
||||||
|
call assert_equal(0, !-3)
|
||||||
|
call assert_equal(1, !+-+0)
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_option_value()
|
func Test_option_value()
|
||||||
" boolean
|
" boolean
|
||||||
set bri
|
set bri
|
||||||
|
@@ -1081,6 +1081,8 @@ def Test_expr7_parens()
|
|||||||
assert_equal(6, --6)
|
assert_equal(6, --6)
|
||||||
assert_equal(6, -+-6)
|
assert_equal(6, -+-6)
|
||||||
assert_equal(-6, ---6)
|
assert_equal(-6, ---6)
|
||||||
|
assert_equal(false, !-3)
|
||||||
|
assert_equal(true, !+-+0)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_expr7_negate()
|
def Test_expr7_negate()
|
||||||
@@ -1102,6 +1104,8 @@ enddef
|
|||||||
def Test_expr7_call()
|
def Test_expr7_call()
|
||||||
assert_equal('yes', 'yes'->Echo())
|
assert_equal('yes', 'yes'->Echo())
|
||||||
assert_equal('yes', 'yes'->s:EchoArg())
|
assert_equal('yes', 'yes'->s:EchoArg())
|
||||||
|
assert_equal(1, !range(5)->empty())
|
||||||
|
assert_equal([0, 1, 2], --3->range())
|
||||||
|
|
||||||
call CheckDefFailure(["let x = 'yes'->Echo"], 'E107:')
|
call CheckDefFailure(["let x = 'yes'->Echo"], 'E107:')
|
||||||
enddef
|
enddef
|
||||||
|
@@ -3926,7 +3926,7 @@ ex_call(exarg_T *eap)
|
|||||||
|
|
||||||
// Handle a function returning a Funcref, Dictionary or List.
|
// Handle a function returning a Funcref, Dictionary or List.
|
||||||
if (handle_subscript(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE,
|
if (handle_subscript(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE,
|
||||||
TRUE, name, &name) == FAIL)
|
TRUE) == FAIL)
|
||||||
{
|
{
|
||||||
failed = TRUE;
|
failed = TRUE;
|
||||||
break;
|
break;
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
1067,
|
||||||
/**/
|
/**/
|
||||||
1066,
|
1066,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user