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:
parent
ffc0716af8
commit
9cfe8f6e68
139
src/eval.c
139
src/eval.c
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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]
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user