summaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-08-17 21:04:16 +0200
committerBram Moolenaar <Bram@vim.org>2019-08-17 21:04:16 +0200
commit9cfe8f6e68de4bfb5942d84f4465de914a747b3f (patch)
tree8931b5937762d4e85541ebb2bad68cc0bcc25816 /src/eval.c
parentffc0716af8e448ef8a2a3249edfd0260546933df (diff)
patch 8.1.1878: negative float before method not parsed correctlyv8.1.1878
Problem: Negative float before method not parsed correctly. Solution: Apply "!" and "-" in front of expression before using ->.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c129
1 files changed, 76 insertions, 53 deletions
diff --git a/src/eval.c b/src/eval.c
index 1967f9401c..b30f40490e 100644
--- a/src/eval.c
+++ b/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 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_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_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) */
arg_subsc = arg;
- if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
+ if (handle_subscript(&arg, &tv, TRUE, TRUE,
+ name, &name) == FAIL)
error = TRUE;
else
{
@@ -4756,68 +4758,80 @@ eval7(
/* Handle following '[', '(' and '.' for expr[expr], expr.name,
* expr(expr), expr->name(expr) */
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 '+'.
*/
if (ret == OK && evaluate && end_leader > start_leader)
- {
- int error = FALSE;
- varnumber_T val = 0;
+ ret = eval7_leader(rettv, start_leader, &end_leader);
+ return ret;
+}
+
+/*
+ * Apply the leading "!" and "-" before an eval7 expression to "rettv".
+ * 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;
+ float_T f = 0.0;
- if (rettv->v_type == VAR_FLOAT)
- f = rettv->vval.v_float;
- else
+ if (rettv->v_type == VAR_FLOAT)
+ f = rettv->vval.v_float;
+ else
#endif
- val = tv_get_number_chk(rettv, &error);
- if (error)
- {
- clear_tv(rettv);
- ret = FAIL;
- }
- else
+ val = tv_get_number_chk(rettv, &error);
+ if (error)
+ {
+ clear_tv(rettv);
+ ret = FAIL;
+ }
+ else
+ {
+ while (end_leader > start_leader)
{
- while (end_leader > start_leader)
+ --end_leader;
+ if (*end_leader == '!')
{
- --end_leader;
- if (*end_leader == '!')
- {
#ifdef FEAT_FLOAT
- if (rettv->v_type == VAR_FLOAT)
- f = !f;
- else
+ if (rettv->v_type == VAR_FLOAT)
+ f = !f;
+ else
#endif
- val = !val;
- }
- else if (*end_leader == '-')
- {
+ val = !val;
+ }
+ else if (*end_leader == '-')
+ {
#ifdef FEAT_FLOAT
- if (rettv->v_type == VAR_FLOAT)
- f = -f;
- else
+ if (rettv->v_type == VAR_FLOAT)
+ f = -f;
+ else
#endif
- val = -val;
- }
+ val = -val;
}
+ }
#ifdef FEAT_FLOAT
- if (rettv->v_type == VAR_FLOAT)
- {
- clear_tv(rettv);
- rettv->vval.v_float = f;
- }
- else
+ 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;
- }
+ {
+ clear_tv(rettv);
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = val;
}
}
-
+ *end_leaderp = end_leader;
return ret;
}
@@ -7539,8 +7553,10 @@ check_vars(char_u *name, int len)
handle_subscript(
char_u **arg,
typval_T *rettv,
- int evaluate, /* do more than finding the end */
- int verbose) /* give error messages */
+ int evaluate, // do more than finding the end
+ int verbose, // give error messages
+ char_u *start_leader, // start of '!' and '-' prefixes
+ char_u **end_leaderp) // end of '!' and '-' prefixes
{
int ret = OK;
dict_T *selfdict = NULL;
@@ -7576,12 +7592,19 @@ handle_subscript(
}
else if (**arg == '-')
{
- if ((*arg)[2] == '{')
- // expr->{lambda}()
- ret = eval_lambda(arg, rettv, evaluate, verbose);
- else
- // expr->name()
- ret = eval_method(arg, rettv, evaluate, verbose);
+ // 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 ((*arg)[2] == '{')
+ // expr->{lambda}()
+ ret = eval_lambda(arg, rettv, evaluate, verbose);
+ else
+ // expr->name()
+ ret = eval_method(arg, rettv, evaluate, verbose);
+ }
}
else /* **arg == '[' || **arg == '.' */
{
@@ -9803,7 +9826,7 @@ var_exists(char_u *var)
if (n)
{
/* 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)
clear_tv(&tv);
}