Skip to content

Commit f7d1c6e

Browse files
committed
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.
1 parent b391e1f commit f7d1c6e

6 files changed

Lines changed: 44 additions & 8 deletions

File tree

src/testdir/test_vim9_class.vim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,21 +876,25 @@ def Test_class_implements_interface()
876876
vim9script
877877

878878
interface Result
879-
this.label: string
879+
public this.label: string
880880
this.errpos: number
881881
endinterface
882882

883883
# order of members is opposite of interface
884884
class Failure implements Result
885885
this.errpos: number = 42
886-
this.label: string = 'label'
886+
public this.label: string = 'label'
887887
endclass
888888

889889
def Test()
890890
var result: Result = Failure.new()
891891

892892
assert_equal('label', result.label)
893893
assert_equal(42, result.errpos)
894+
895+
result.label = 'different'
896+
assert_equal('different', result.label)
897+
assert_equal(42, result.errpos)
894898
enddef
895899

896900
Test()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ static char *(features[]) =
695695

696696
static int included_patches[] =
697697
{ /* Add new patch number below this line */
698+
/**/
699+
1211,
698700
/**/
699701
1210,
700702
/**/

src/vim9.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ typedef enum {
7878
// ISN_STOREOTHER, // pop into other script variable isn_arg.other.
7979

8080
ISN_STORENR, // store number into local variable isn_arg.storenr.stnr_idx
81-
ISN_STOREINDEX, // store into list or dictionary, type isn_arg.vartype,
82-
// value/index/variable on stack
81+
ISN_STOREINDEX, // store into list or dictionary, using
82+
// isn_arg.storeindex; value/index/variable on stack
8383
ISN_STORERANGE, // store into blob,
8484
// value/index 1/index 2/variable on stack
8585

@@ -486,6 +486,11 @@ typedef struct {
486486
class_T *cm_class;
487487
int cm_idx;
488488
} classmember_T;
489+
// arguments to ISN_STOREINDEX
490+
typedef struct {
491+
vartype_T si_vartype;
492+
class_T *si_class;
493+
} storeindex_T;
489494

490495
/*
491496
* Instruction
@@ -540,6 +545,7 @@ struct isn_S {
540545
echowin_T echowin;
541546
construct_T construct;
542547
classmember_T classmember;
548+
storeindex_T storeindex;
543549
} isn_arg;
544550
};
545551

src/vim9compile.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2178,7 +2178,22 @@ compile_assign_unlet(
21782178

21792179
if (isn == NULL)
21802180
return FAIL;
2181-
isn->isn_arg.vartype = dest_type;
2181+
isn->isn_arg.storeindex.si_vartype = dest_type;
2182+
isn->isn_arg.storeindex.si_class = NULL;
2183+
2184+
if (dest_type == VAR_OBJECT)
2185+
{
2186+
class_T *cl = (class_T *)lhs->lhs_type->tt_member;
2187+
2188+
if (cl->class_flags & CLASS_INTERFACE)
2189+
{
2190+
// "this.value": load "this" object and get the value
2191+
// at index for an object or class member get the type
2192+
// of the member
2193+
isn->isn_arg.storeindex.si_class = cl;
2194+
++cl->class_refcount;
2195+
}
2196+
}
21822197
}
21832198
}
21842199
else if (range)

src/vim9execute.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,7 +2108,7 @@ handle_debug(isn_T *iptr, ectx_T *ectx)
21082108
static int
21092109
execute_storeindex(isn_T *iptr, ectx_T *ectx)
21102110
{
2111-
vartype_T dest_type = iptr->isn_arg.vartype;
2111+
vartype_T dest_type = iptr->isn_arg.storeindex.si_vartype;
21122112
typval_T *tv;
21132113
typval_T *tv_idx = STACK_TV_BOT(-2);
21142114
typval_T *tv_dest = STACK_TV_BOT(-1);
@@ -2243,6 +2243,12 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
22432243
long idx = (long)tv_idx->vval.v_number;
22442244
object_T *obj = tv_dest->vval.v_object;
22452245
typval_T *otv = (typval_T *)(obj + 1);
2246+
2247+
class_T *itf = iptr->isn_arg.storeindex.si_class;
2248+
if (itf != NULL)
2249+
// convert interface member index to class member index
2250+
idx = object_index_from_itf_index(itf, idx, obj->obj_class);
2251+
22462252
clear_tv(&otv[idx]);
22472253
otv[idx] = *tv;
22482254
}
@@ -6475,7 +6481,7 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
64756481

64766482
case ISN_STOREINDEX:
64776483
smsg("%s%4d STOREINDEX %s", pfx, current,
6478-
vartype_name(iptr->isn_arg.vartype));
6484+
vartype_name(iptr->isn_arg.storeindex.si_vartype));
64796485
break;
64806486

64816487
case ISN_STORERANGE:

src/vim9instr.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2521,6 +2521,10 @@ delete_instr(isn_T *isn)
25212521
class_unref(isn->isn_arg.classmember.cm_class);
25222522
break;
25232523

2524+
case ISN_STOREINDEX:
2525+
class_unref(isn->isn_arg.storeindex.si_class);
2526+
break;
2527+
25242528
case ISN_TRY:
25252529
vim_free(isn->isn_arg.tryref.try_ref);
25262530
break;
@@ -2622,7 +2626,6 @@ delete_instr(isn_T *isn)
26222626
case ISN_SLICE:
26232627
case ISN_SOURCE:
26242628
case ISN_STORE:
2625-
case ISN_STOREINDEX:
26262629
case ISN_STORENR:
26272630
case ISN_STOREOUTER:
26282631
case ISN_STORE_THIS:

0 commit comments

Comments
 (0)