]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1211: storing value in interface member does not always work v9.0.1211
authorBram Moolenaar <Bram@vim.org>
Mon, 16 Jan 2023 20:47:57 +0000 (20:47 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 16 Jan 2023 20:47:57 +0000 (20:47 +0000)
Problem:    Storing value in interface member does not always work.
Solution:   Convert the index on the interface to the index on the object.

src/testdir/test_vim9_class.vim
src/version.c
src/vim9.h
src/vim9compile.c
src/vim9execute.c
src/vim9instr.c

index ee10a3c8de8ebd702fe2ec283330eda72385f771..dadd3e4df5691557d72a3fe13e84dfb70b3c15b6 100644 (file)
@@ -876,14 +876,14 @@ def Test_class_implements_interface()
       vim9script
 
       interface Result
-        this.label: string
+        public this.label: string
         this.errpos: number
       endinterface
 
       # order of members is opposite of interface
       class Failure implements Result
         this.errpos: number = 42
-        this.label: string = 'label'
+        public this.label: string = 'label'
       endclass
 
       def Test()
@@ -891,6 +891,10 @@ def Test_class_implements_interface()
 
         assert_equal('label', result.label)
         assert_equal(42, result.errpos)
+
+        result.label = 'different'
+        assert_equal('different', result.label)
+        assert_equal(42, result.errpos)
       enddef
 
       Test()
index c489dba9e242ed304956e9123ce35d3cb16c5879..a38801961534a8ca318f3f76ebc80bbbd4275017 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1211,
 /**/
     1210,
 /**/
index 68bef2eb5edc2a22530220f7dbdc7ab68c746df0..f1c453017532e3e37a69f852829910c970f018bd 100644 (file)
@@ -78,8 +78,8 @@ typedef enum {
     // ISN_STOREOTHER, // pop into other script variable isn_arg.other.
 
     ISN_STORENR,    // store number into local variable isn_arg.storenr.stnr_idx
-    ISN_STOREINDEX,    // store into list or dictionary, type isn_arg.vartype,
-                       // value/index/variable on stack
+    ISN_STOREINDEX,    // store into list or dictionary, using
+                       // isn_arg.storeindex; value/index/variable on stack
     ISN_STORERANGE,    // store into blob,
                        // value/index 1/index 2/variable on stack
 
@@ -486,6 +486,11 @@ typedef struct {
     class_T    *cm_class;
     int                cm_idx;
 } classmember_T;
+// arguments to ISN_STOREINDEX
+typedef struct {
+    vartype_T  si_vartype;
+    class_T    *si_class;
+} storeindex_T;
 
 /*
  * Instruction
@@ -540,6 +545,7 @@ struct isn_S {
        echowin_T           echowin;
        construct_T         construct;
        classmember_T       classmember;
+       storeindex_T        storeindex;
     } isn_arg;
 };
 
index 77945fbfd55389e130562b7875ee334142a8ecf1..c89c37aabf353deba8f915d1b9bc095a3d6885e2 100644 (file)
@@ -2178,7 +2178,22 @@ compile_assign_unlet(
 
                if (isn == NULL)
                    return FAIL;
-               isn->isn_arg.vartype = dest_type;
+               isn->isn_arg.storeindex.si_vartype = dest_type;
+               isn->isn_arg.storeindex.si_class = NULL;
+
+               if (dest_type == VAR_OBJECT)
+               {
+                   class_T *cl = (class_T *)lhs->lhs_type->tt_member;
+
+                   if (cl->class_flags & CLASS_INTERFACE)
+                   {
+                       // "this.value": load "this" object and get the value
+                       // at index for an object or class member get the type
+                       // of the member
+                       isn->isn_arg.storeindex.si_class = cl;
+                       ++cl->class_refcount;
+                   }
+               }
            }
        }
        else if (range)
index dd2dbe0aa5a1dc4c60346787ddfcca4b76132474..d0dbefc43bf87ca6c0b87870f69b81c552c31cd0 100644 (file)
@@ -2108,7 +2108,7 @@ handle_debug(isn_T *iptr, ectx_T *ectx)
     static int
 execute_storeindex(isn_T *iptr, ectx_T *ectx)
 {
-    vartype_T  dest_type = iptr->isn_arg.vartype;
+    vartype_T  dest_type = iptr->isn_arg.storeindex.si_vartype;
     typval_T   *tv;
     typval_T   *tv_idx = STACK_TV_BOT(-2);
     typval_T   *tv_dest = STACK_TV_BOT(-1);
@@ -2243,6 +2243,12 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
            long            idx = (long)tv_idx->vval.v_number;
            object_T        *obj = tv_dest->vval.v_object;
            typval_T        *otv = (typval_T *)(obj + 1);
+
+           class_T         *itf = iptr->isn_arg.storeindex.si_class;
+           if (itf != NULL)
+               // convert interface member index to class member index
+               idx = object_index_from_itf_index(itf, idx, obj->obj_class);
+
            clear_tv(&otv[idx]);
            otv[idx] = *tv;
        }
@@ -6475,7 +6481,7 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
 
            case ISN_STOREINDEX:
                smsg("%s%4d STOREINDEX %s", pfx, current,
-                                         vartype_name(iptr->isn_arg.vartype));
+                           vartype_name(iptr->isn_arg.storeindex.si_vartype));
                break;
 
            case ISN_STORERANGE:
index 89f12430a703af56d5ffef3e2f73eb06c45ab470..8b11705712cff3f8b7f88098f2501f04c571a70b 100644 (file)
@@ -2521,6 +2521,10 @@ delete_instr(isn_T *isn)
            class_unref(isn->isn_arg.classmember.cm_class);
            break;
 
+       case ISN_STOREINDEX:
+           class_unref(isn->isn_arg.storeindex.si_class);
+           break;
+
        case ISN_TRY:
            vim_free(isn->isn_arg.tryref.try_ref);
            break;
@@ -2622,7 +2626,6 @@ delete_instr(isn_T *isn)
        case ISN_SLICE:
        case ISN_SOURCE:
        case ISN_STORE:
-       case ISN_STOREINDEX:
        case ISN_STORENR:
        case ISN_STOREOUTER:
        case ISN_STORE_THIS: