]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.1067: expression "!expr->func()" does not work v8.2.1067
authorBram Moolenaar <Bram@vim.org>
Sat, 27 Jun 2020 11:11:50 +0000 (13:11 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 27 Jun 2020 11:11:50 +0000 (13:11 +0200)
Problem:    Expression "!expr->func()" does not work.
Solution:   Apply plus and minus earlier. (closes #6348)

src/eval.c
src/evalvars.c
src/proto/eval.pro
src/testdir/test_expr.vim
src/testdir/test_vim9_expr.vim
src/userfunc.c
src/version.c

index 99003ced2c19043d96e2dc7d09cf3351bbbdeade..4bbf65b036f6d0f2804d32a4aae1da0d405a88cd 100644 (file)
@@ -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 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_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 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 '9':
     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;
 
     /*
@@ -2879,23 +2884,27 @@ eval7(
     // Handle following '[', '(' and '.' for expr[expr], expr.name,
     // expr(expr), expr->name(expr)
     if (ret == OK)
-       ret = handle_subscript(arg, rettv, flags, TRUE,
-                                                   start_leader, &end_leader);
+       ret = handle_subscript(arg, rettv, flags, TRUE);
 
     /*
      * Apply logical NOT and unary '-', from right to left, ignore '+'.
      */
     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;
 }
 
 /*
  * 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".
  */
     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;
     int                ret = OK;
@@ -2921,6 +2930,11 @@ eval7_leader(typval_T *rettv, char_u *start_leader, char_u **end_leaderp)
            --end_leader;
            if (*end_leader == '!')
            {
+               if (numeric_only)
+               {
+                   ++end_leader;
+                   break;
+               }
 #ifdef FEAT_FLOAT
                if (rettv->v_type == VAR_FLOAT)
                    f = !f;
@@ -4871,9 +4885,7 @@ handle_subscript(
     char_u     **arg,
     typval_T   *rettv,
     int                flags,          // 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                verbose)        // give error messages
 {
     int                evaluate = flags & EVAL_EVALUATE;
     int                ret = OK;
@@ -4910,10 +4922,6 @@ handle_subscript(
        }
        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 ((*arg)[2] == '{')
index e64b44ed139e1bbb2204001deca2916dfe255ae9..7de7c1d1ef8805b32d32a0fbd2e08ef3bdd8f2d6 100644 (file)
@@ -1125,8 +1125,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, EVAL_EVALUATE, TRUE,
-                                                         name, &name) == FAIL)
+                   if (handle_subscript(&arg, &tv, EVAL_EVALUATE, TRUE)
+                                                                      == FAIL)
                        error = TRUE;
                    else
                    {
@@ -3341,8 +3341,7 @@ var_exists(char_u *var)
        if (n)
        {
            // handle d.key, l[idx], f(expr)
-           n = (handle_subscript(&var, &tv, EVAL_EVALUATE,
-                                                   FALSE, name, &name) == OK);
+           n = (handle_subscript(&var, &tv, EVAL_EVALUATE, FALSE) == OK);
            if (n)
                clear_tv(&tv);
        }
index 6ae770ce252fe75ae8cfee7a208bf29e902894b3..16ba95b823e2ad6de266052a97660c66d0bbdacf 100644 (file)
@@ -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);
 int eval_isnamec(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);
 void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr);
 void ex_echo(exarg_T *eap);
index ec73aeaae4809d0dcef8e369af81661fa6056398..c5dd1f37c72cd5e7908aaff876fdee3a37aaf072 100644 (file)
@@ -110,6 +110,13 @@ func Test_special_char()
   call assert_fails('echo "\<C-">')
 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()
   " boolean
   set bri
index 33a282b061c893a8b6fbd12bbdb2db14490999bc..0976d9cdb14149449a65061bc57efa72b9c98279 100644 (file)
@@ -1081,6 +1081,8 @@ def Test_expr7_parens()
   assert_equal(6, --6)
   assert_equal(6, -+-6)
   assert_equal(-6, ---6)
+  assert_equal(false, !-3)
+  assert_equal(true, !+-+0)
 enddef
 
 def Test_expr7_negate()
@@ -1102,6 +1104,8 @@ enddef
 def Test_expr7_call()
   assert_equal('yes', 'yes'->Echo())
   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:')
 enddef
index 691c55c4fd14170ef5ffaa93ccd54369b3efba66..537c9ccd0f52d5d28c27d5893797335f28952294 100644 (file)
@@ -3926,7 +3926,7 @@ ex_call(exarg_T *eap)
 
        // Handle a function returning a Funcref, Dictionary or List.
        if (handle_subscript(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE,
-                                                   TRUE, name, &name) == FAIL)
+                                                                TRUE) == FAIL)
        {
            failed = TRUE;
            break;
index d152f9e7a1f546c86b490d453d1da20c51a2591c..0ab2b6ab4336796c757cc6cca4f75318b33c55b8 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1067,
 /**/
     1066,
 /**/