1
0
forked from aniani/vim

patch 8.1.1878: negative float before method not parsed correctly

Problem:    Negative float before method not parsed correctly.
Solution:   Apply "!" and "-" in front of expression before using ->.
This commit is contained in:
Bram Moolenaar 2019-08-17 21:04:16 +02:00
parent ffc0716af8
commit 9cfe8f6e68
5 changed files with 92 additions and 61 deletions

View File

@ -241,6 +241,7 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate);
static int eval5(char_u **arg, typval_T *rettv, int evaluate); static int eval5(char_u **arg, typval_T *rettv, int evaluate);
static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string);
static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string);
static int eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp);
static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate);
static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate);
@ -1810,7 +1811,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, TRUE, TRUE) == FAIL) if (handle_subscript(&arg, &tv, TRUE, TRUE,
name, &name) == FAIL)
error = TRUE; error = TRUE;
else else
{ {
@ -4756,68 +4758,80 @@ 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, evaluate, TRUE); ret = handle_subscript(arg, rettv, evaluate, 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);
int error = FALSE; return ret;
varnumber_T val = 0; }
#ifdef FEAT_FLOAT
float_T f = 0.0;
if (rettv->v_type == VAR_FLOAT) /*
f = rettv->vval.v_float; * Apply the leading "!" and "-" before an eval7 expression to "rettv".
else * Adjusts "end_leaderp" until it is at "start_leader".
*/
static int
eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp)
{
char_u *end_leader = *end_leaderp;
int ret = OK;
int error = FALSE;
varnumber_T val = 0;
#ifdef FEAT_FLOAT
float_T f = 0.0;
if (rettv->v_type == VAR_FLOAT)
f = rettv->vval.v_float;
else
#endif #endif
val = tv_get_number_chk(rettv, &error); val = tv_get_number_chk(rettv, &error);
if (error) if (error)
{
clear_tv(rettv);
ret = FAIL;
}
else
{
while (end_leader > start_leader)
{
--end_leader;
if (*end_leader == '!')
{
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
f = !f;
else
#endif
val = !val;
}
else if (*end_leader == '-')
{
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
f = -f;
else
#endif
val = -val;
}
}
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
{ {
clear_tv(rettv); clear_tv(rettv);
ret = FAIL; rettv->vval.v_float = f;
} }
else else
#endif
{ {
while (end_leader > start_leader) clear_tv(rettv);
{ rettv->v_type = VAR_NUMBER;
--end_leader; rettv->vval.v_number = val;
if (*end_leader == '!')
{
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
f = !f;
else
#endif
val = !val;
}
else if (*end_leader == '-')
{
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
f = -f;
else
#endif
val = -val;
}
}
#ifdef FEAT_FLOAT
if (rettv->v_type == VAR_FLOAT)
{
clear_tv(rettv);
rettv->vval.v_float = f;
}
else
#endif
{
clear_tv(rettv);
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = val;
}
} }
} }
*end_leaderp = end_leader;
return ret; return ret;
} }
@ -7539,8 +7553,10 @@ check_vars(char_u *name, int len)
handle_subscript( handle_subscript(
char_u **arg, char_u **arg,
typval_T *rettv, typval_T *rettv,
int evaluate, /* do more than finding the end */ int evaluate, // 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 ret = OK; int ret = OK;
dict_T *selfdict = NULL; dict_T *selfdict = NULL;
@ -7576,12 +7592,19 @@ handle_subscript(
} }
else if (**arg == '-') else if (**arg == '-')
{ {
if ((*arg)[2] == '{') // Expression "-1.0->method()" applies the leader "-" before
// expr->{lambda}() // applying ->.
ret = eval_lambda(arg, rettv, evaluate, verbose); if (evaluate && *end_leaderp > start_leader)
else ret = eval7_leader(rettv, start_leader, end_leaderp);
// expr->name() if (ret == OK)
ret = eval_method(arg, rettv, evaluate, verbose); {
if ((*arg)[2] == '{')
// expr->{lambda}()
ret = eval_lambda(arg, rettv, evaluate, verbose);
else
// expr->name()
ret = eval_method(arg, rettv, evaluate, verbose);
}
} }
else /* **arg == '[' || **arg == '.' */ else /* **arg == '[' || **arg == '.' */
{ {
@ -9803,7 +9826,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, TRUE, FALSE) == OK); n = (handle_subscript(&var, &tv, TRUE, FALSE, name, &name) == OK);
if (n) if (n)
clear_tv(&tv); clear_tv(&tv);
} }

View File

@ -85,7 +85,7 @@ char_u *v_exception(char_u *oldval);
char_u *v_throwpoint(char_u *oldval); char_u *v_throwpoint(char_u *oldval);
char_u *set_cmdarg(exarg_T *eap, char_u *oldarg); char_u *set_cmdarg(exarg_T *eap, char_u *oldarg);
int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload); int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload);
int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose); int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose, char_u *start_leader, char_u **end_leaderp);
typval_T *alloc_tv(void); typval_T *alloc_tv(void);
void free_tv(typval_T *varp); void free_tv(typval_T *varp);
void clear_tv(typval_T *varp); void clear_tv(typval_T *varp);

View File

@ -115,6 +115,11 @@ func Test_method_funcref()
delfunc Concat delfunc Concat
endfunc endfunc
func Test_method_float()
eval 1.234->string()->assert_equal('1.234')
eval -1.234->string()->assert_equal('-1.234')
endfunc
func Test_method_syntax() func Test_method_syntax()
eval [1, 2, 3] ->sort( ) eval [1, 2, 3] ->sort( )
eval [1, 2, 3] eval [1, 2, 3]

View File

@ -3165,8 +3165,9 @@ ex_call(exarg_T *eap)
if (has_watchexpr()) if (has_watchexpr())
dbg_check_breakpoint(eap); dbg_check_breakpoint(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, TRUE) == FAIL) if (handle_subscript(&arg, &rettv, !eap->skip, TRUE,
name, &name) == FAIL)
{ {
failed = TRUE; failed = TRUE;
break; break;

View File

@ -769,6 +769,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 */
/**/
1878,
/**/ /**/
1877, 1877,
/**/ /**/