# HG changeset patch # User Bram Moolenaar # Date 1566069303 -7200 # Node ID 117c7795a979de27de090efb681a281da6557dbc # Parent 87d3311b3401b4121e4513c022c3175090fb0419 patch 8.1.1878: negative float before method not parsed correctly commit https://github.com/vim/vim/commit/9cfe8f6e68de4bfb5942d84f4465de914a747b3f Author: Bram Moolenaar Date: Sat Aug 17 21:04:16 2019 +0200 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 ->. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -241,6 +241,7 @@ static int eval4(char_u **arg, typval_T 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, { /* 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 +#endif + val = tv_get_number_chk(rettv, &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) - f = rettv->vval.v_float; - else -#endif - val = tv_get_number_chk(rettv, &error); - if (error) { clear_tv(rettv); - ret = FAIL; + rettv->vval.v_float = f; } 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); - 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); } diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -85,7 +85,7 @@ char_u *v_exception(char_u *oldval); char_u *v_throwpoint(char_u *oldval); 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 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); void free_tv(typval_T *varp); void clear_tv(typval_T *varp); diff --git a/src/testdir/test_method.vim b/src/testdir/test_method.vim --- a/src/testdir/test_method.vim +++ b/src/testdir/test_method.vim @@ -115,6 +115,11 @@ func Test_method_funcref() delfunc Concat 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() eval [1, 2, 3] ->sort( ) eval [1, 2, 3] diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3165,8 +3165,9 @@ ex_call(exarg_T *eap) if (has_watchexpr()) dbg_check_breakpoint(eap); - /* Handle a function returning a Funcref, Dictionary or List. */ - if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) + // Handle a function returning a Funcref, Dictionary or List. + if (handle_subscript(&arg, &rettv, !eap->skip, TRUE, + name, &name) == FAIL) { failed = TRUE; break; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1878, +/**/ 1877, /**/ 1876,