# HG changeset patch # User Bram Moolenaar # Date 1673902803 -3600 # Node ID 85f93e094810555bb9efc81d09bdb7262012ec5f # Parent 9050141c785fa0c6f854f1a9525c2be17572f6a0 patch 9.0.1211: storing value in interface member does not always work Commit: https://github.com/vim/vim/commit/f7d1c6e1884c76680980571f1cf15e0928d247b5 Author: Bram Moolenaar 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. diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim --- 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 --- 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 --- 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 --- 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 --- 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: diff --git a/src/vim9instr.c b/src/vim9instr.c --- 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: