summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2023-01-16 20:47:57 +0000
committerBram Moolenaar <Bram@vim.org>2023-01-16 20:47:57 +0000
commitf7d1c6e1884c76680980571f1cf15e0928d247b5 (patch)
tree15b36b84c50a3a6c9aa0a7cf407c2e11abf6dce0
parentb391e1f805fdd288cbe9103d92c21eff5dcc97c4 (diff)
patch 9.0.1211: storing value in interface member does not always workv9.0.1211
Problem: Storing value in interface member does not always work. Solution: Convert the index on the interface to the index on the object.
-rw-r--r--src/testdir/test_vim9_class.vim8
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h10
-rw-r--r--src/vim9compile.c17
-rw-r--r--src/vim9execute.c10
-rw-r--r--src/vim9instr.c5
6 files changed, 44 insertions, 8 deletions
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index ee10a3c8de..dadd3e4df5 100644
--- 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()
diff --git a/src/version.c b/src/version.c
index c489dba9e2..a388019615 100644
--- 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,
diff --git a/src/vim9.h b/src/vim9.h
index 68bef2eb5e..f1c4530175 100644
--- 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;
};
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 77945fbfd5..c89c37aabf 100644
--- 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)
diff --git a/src/vim9execute.c b/src/vim9execute.c
index dd2dbe0aa5..d0dbefc43b 100644
--- 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 *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:
diff --git a/src/vim9instr.c b/src/vim9instr.c
index 89f12430a7..8b11705712 100644
--- 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: