]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.2016: Vim9: assignment operators don't work for class vars v9.0.2016
authorYegappan Lakshmanan <yegappan@yahoo.com>
Wed, 11 Oct 2023 19:43:52 +0000 (21:43 +0200)
committerChristian Brabandt <cb@256bit.org>
Wed, 11 Oct 2023 19:43:52 +0000 (21:43 +0200)
Problem:  Vim9: assignment operators don't work for class vars
Solution: implement it

closes: #13306

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
src/proto/vim9class.pro
src/testdir/test_vim9_class.vim
src/version.c
src/vim9class.c
src/vim9compile.c

index c9e19d0067bbadaf56ca2864c78ee89e64cbc29d..362e2cac5e269dce391d68d092ed922b3f5a071f 100644 (file)
@@ -1,8 +1,8 @@
 /* vim9class.c */
 int object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl);
 void ex_class(exarg_T *eap);
-type_T *class_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx);
-type_T *class_member_type_by_idx(class_T *cl, int is_object, int member_idx);
+type_T *oc_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx);
+type_T *oc_member_type_by_idx(class_T *cl, int is_object, int member_idx);
 void ex_enum(exarg_T *eap);
 void ex_type(exarg_T *eap);
 int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
index eead19283a11b56b7095f6b4aacccfb43c1cd115..1aa9de7b99ac6ad2ac06dda14888d8e67ed97003 100644 (file)
@@ -7431,4 +7431,50 @@ def Test_funcref_argtype_returntype_check()
   v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object<A>): object<A> but got func(object<B>): object<B>', 1)
 enddef
 
+" Test for using an operator (e.g. +) with an assignment
+def Test_op_and_assignment()
+  # Using += with a class variable
+  var lines =<< trim END
+    vim9script
+    class A
+      public static val: list<number> = []
+      static def Foo(): list<number>
+        val += [1]
+        return val
+      enddef
+    endclass
+    def Bar(): list<number>
+      A.val += [2]
+      return A.val
+    enddef
+    assert_equal([1], A.Foo())
+    assert_equal([1, 2], Bar())
+    A.val += [3]
+    assert_equal([1, 2, 3], A.val)
+  END
+  v9.CheckSourceSuccess(lines)
+
+  # Using += with an object variable
+  lines =<< trim END
+    vim9script
+    class A
+      public this.val: list<number> = []
+      def Foo(): list<number>
+        this.val += [1]
+        return this.val
+      enddef
+    endclass
+    def Bar(bar_a: A): list<number>
+      bar_a.val += [2]
+      return bar_a.val
+    enddef
+    var a = A.new()
+    assert_equal([1], a.Foo())
+    assert_equal([1, 2], Bar(a))
+    a.val += [3]
+    assert_equal([1, 2, 3], a.val)
+  END
+  v9.CheckSourceSuccess(lines)
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
index 61f6289e2879c286db1d9ec36f3a98baebedad00..4031debd86bf2a9d22d9a721cb6dd2f4a75964fb 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2016,
 /**/
     2015,
 /**/
index 0cb353bb57f08dd7f4ac2b95ccae28dd824a8f92..5dda700fa3e40837ceb47ef28cec5ed267ffec13 100644 (file)
@@ -2032,7 +2032,7 @@ cleanup:
  * Set *p_m ocmmember_T if not NULL
  */
     type_T *
-class_member_type(
+oc_member_type(
     class_T    *cl,
     int                is_object,
     char_u     *name,
@@ -2060,7 +2060,7 @@ class_member_type(
  * Given a class or object variable index, return the variable type
  */
     type_T *
-class_member_type_by_idx(
+oc_member_type_by_idx(
     class_T    *cl,
     int                is_object,
     int                member_idx)
index 7e1914b69478b8e705c90f0154f2fe14aece325e..544ad17e101f29dc9655bb85c5430d328fc997dc 100644 (file)
@@ -1770,7 +1770,7 @@ compile_lhs(
                lhs->lhs_dest = dest_class_member;
                lhs->lhs_class = cctx->ctx_ufunc->uf_class;
                lhs->lhs_type =
-                   class_member_type_by_idx(cctx->ctx_ufunc->uf_class,
+                   oc_member_type_by_idx(cctx->ctx_ufunc->uf_class,
                                        FALSE, lhs->lhs_classmember_idx);
            }
            else
@@ -2254,7 +2254,7 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
           return FAIL;
 
        class_T *cl = lhs->lhs_type->tt_class;
-       type_T  *type = class_member_type(cl, TRUE, dot + 1,
+       type_T  *type = oc_member_type(cl, TRUE, dot + 1,
                                          lhs->lhs_end, &lhs->lhs_member_idx);
        if (lhs->lhs_member_idx < 0)
            return FAIL;
@@ -2275,6 +2275,22 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
            return generate_GET_ITF_MEMBER(cctx, cl, lhs->lhs_member_idx, type);
        return generate_GET_OBJ_MEMBER(cctx, lhs->lhs_member_idx, type);
     }
+    else if (lhs->lhs_type->tt_type == VAR_CLASS)
+    {
+       // "<classname>.value": load class variable "classname.value"
+       char_u *dot = vim_strchr(var_start, '.');
+       if (dot == NULL)
+          return FAIL;
+
+       class_T *cl = lhs->lhs_type->tt_class;
+       ocmember_T *m = class_member_lookup(cl, dot + 1,
+                                               lhs->lhs_end - dot - 1,
+                                               &lhs->lhs_member_idx);
+       if (m == NULL)
+           return FAIL;
+
+       return generate_CLASSMEMBER(cctx, TRUE, cl, lhs->lhs_member_idx);
+    }
 
     compile_load_lhs(lhs, var_start, NULL, cctx);