changeset 31758:85f93e094810 v9.0.1211

patch 9.0.1211: storing value in interface member does not always work Commit: https://github.com/vim/vim/commit/f7d1c6e1884c76680980571f1cf15e0928d247b5 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jan 16 20:47:57 2023 +0000 patch 9.0.1211: storing value in interface member does not always work Problem: Storing value in interface member does not always work. Solution: Convert the index on the interface to the index on the object.
author Bram Moolenaar <Bram@vim.org>
date Mon, 16 Jan 2023 22:00:03 +0100
parents 9050141c785f
children e68d2e63c218
files src/testdir/test_vim9_class.vim src/version.c src/vim9.h src/vim9compile.c src/vim9execute.c src/vim9instr.c
diffstat 6 files changed, 44 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -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()
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1211,
+/**/
     1210,
 /**/
     1209,
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -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;
 };
 
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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)
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -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 *
 	    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 *inst
 
 	    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:
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -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: