comparison src/vim9execute.c @ 31843:ffa11e2757e7 v9.0.1254

patch 9.0.1254: calling a method on an interface does not work Commit: https://github.com/vim/vim/commit/d0200c8631582bbb16a9b585e2ca7adccc84ccdd Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 28 15:19:40 2023 +0000 patch 9.0.1254: calling a method on an interface does not work Problem: Calling a method on an interface does not work. Solution: At runtime figure out what method to call. (closes https://github.com/vim/vim/issues/11901)
author Bram Moolenaar <Bram@vim.org>
date Sat, 28 Jan 2023 16:30:04 +0100
parents 5ce5d78afcc9
children f1a5e67e9a1b
comparison
equal deleted inserted replaced
31842:1b6543beb560 31843:ffa11e2757e7
2260 typval_T *otv = (typval_T *)(obj + 1); 2260 typval_T *otv = (typval_T *)(obj + 1);
2261 2261
2262 class_T *itf = iptr->isn_arg.storeindex.si_class; 2262 class_T *itf = iptr->isn_arg.storeindex.si_class;
2263 if (itf != NULL) 2263 if (itf != NULL)
2264 // convert interface member index to class member index 2264 // convert interface member index to class member index
2265 idx = object_index_from_itf_index(itf, idx, obj->obj_class); 2265 idx = object_index_from_itf_index(itf, FALSE,
2266 idx, obj->obj_class);
2266 2267
2267 clear_tv(&otv[idx]); 2268 clear_tv(&otv[idx]);
2268 otv[idx] = *tv; 2269 otv[idx] = *tv;
2269 } 2270 }
2270 else 2271 else
2946 { 2947 {
2947 copy_tv(&di->di_tv, STACK_TV_BOT(0)); 2948 copy_tv(&di->di_tv, STACK_TV_BOT(0));
2948 ++ectx->ec_stack.ga_len; 2949 ++ectx->ec_stack.ga_len;
2949 } 2950 }
2950 return OK; 2951 return OK;
2952 }
2953
2954
2955 static void
2956 object_required_error(typval_T *tv)
2957 {
2958 garray_T type_list;
2959 ga_init2(&type_list, sizeof(type_T *), 10);
2960 type_T *type = typval2type(tv, get_copyID(), &type_list, TVTT_DO_MEMBER);
2961 char *tofree = NULL;
2962 char *typename = type_name(type, &tofree);
2963 semsg(_(e_object_required_found_str), typename);
2964 vim_free(tofree);
2965 clear_type_list(&type_list);
2951 } 2966 }
2952 2967
2953 /* 2968 /*
2954 * Execute instructions in execution context "ectx". 2969 * Execute instructions in execution context "ectx".
2955 * Return OK or FAIL; 2970 * Return OK or FAIL;
4123 iptr->isn_arg.dfunc.cdf_argcount, 4138 iptr->isn_arg.dfunc.cdf_argcount,
4124 ectx) == FAIL) 4139 ectx) == FAIL)
4125 goto on_error; 4140 goto on_error;
4126 break; 4141 break;
4127 4142
4143 // call a method on an interface
4144 case ISN_METHODCALL:
4145 {
4146 SOURCING_LNUM = iptr->isn_lnum;
4147 tv = STACK_TV_BOT(-1);
4148 if (tv->v_type != VAR_OBJECT)
4149 {
4150 object_required_error(tv);
4151 goto on_error;
4152 }
4153 object_T *obj = tv->vval.v_object;
4154 class_T *cl = obj->obj_class;
4155
4156 // convert the interface index to the object index
4157 cmfunc_T *mfunc = iptr->isn_arg.mfunc;
4158 int idx = object_index_from_itf_index(mfunc->cmf_itf,
4159 TRUE, mfunc->cmf_idx, cl);
4160
4161 if (call_ufunc(cl->class_obj_methods[idx], NULL,
4162 mfunc->cmf_argcount, ectx, NULL, NULL) == FAIL)
4163 goto on_error;
4164 }
4165 break;
4166
4128 // call a builtin function 4167 // call a builtin function
4129 case ISN_BCALL: 4168 case ISN_BCALL:
4130 SOURCING_LNUM = iptr->isn_lnum; 4169 SOURCING_LNUM = iptr->isn_lnum;
4131 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, 4170 if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx,
4132 iptr->isn_arg.bfunc.cbf_argcount, 4171 iptr->isn_arg.bfunc.cbf_argcount,
5211 { 5250 {
5212 tv = STACK_TV_BOT(-1); 5251 tv = STACK_TV_BOT(-1);
5213 if (tv->v_type != VAR_OBJECT) 5252 if (tv->v_type != VAR_OBJECT)
5214 { 5253 {
5215 SOURCING_LNUM = iptr->isn_lnum; 5254 SOURCING_LNUM = iptr->isn_lnum;
5216 garray_T type_list; 5255 object_required_error(tv);
5217 ga_init2(&type_list, sizeof(type_T *), 10);
5218 type_T *type = typval2type(tv, get_copyID(),
5219 &type_list, TVTT_DO_MEMBER);
5220 char *tofree = NULL;
5221 char *typename = type_name(type, &tofree);
5222 semsg(_(e_object_required_found_str), typename);
5223 vim_free(tofree);
5224 clear_type_list(&type_list);
5225 goto on_error; 5256 goto on_error;
5226 } 5257 }
5227 5258
5228 object_T *obj = tv->vval.v_object; 5259 object_T *obj = tv->vval.v_object;
5229 int idx; 5260 int idx;
5232 else 5263 else
5233 { 5264 {
5234 idx = iptr->isn_arg.classmember.cm_idx; 5265 idx = iptr->isn_arg.classmember.cm_idx;
5235 // convert the interface index to the object index 5266 // convert the interface index to the object index
5236 idx = object_index_from_itf_index( 5267 idx = object_index_from_itf_index(
5237 iptr->isn_arg.classmember.cm_class, 5268 iptr->isn_arg.classmember.cm_class,
5238 idx, obj->obj_class); 5269 FALSE, idx, obj->obj_class);
5239 } 5270 }
5240 5271
5241 // the members are located right after the object struct 5272 // the members are located right after the object struct
5242 typval_T *mtv = ((typval_T *)(obj + 1)) + idx; 5273 typval_T *mtv = ((typval_T *)(obj + 1)) + idx;
5243 copy_tv(mtv, tv); 5274 copy_tv(mtv, tv);
6633 + cdfunc->cdf_idx; 6664 + cdfunc->cdf_idx;
6634 6665
6635 smsg("%s%4d DCALL %s(argc %d)", pfx, current, 6666 smsg("%s%4d DCALL %s(argc %d)", pfx, current,
6636 printable_func_name(df->df_ufunc), 6667 printable_func_name(df->df_ufunc),
6637 cdfunc->cdf_argcount); 6668 cdfunc->cdf_argcount);
6669 }
6670 break;
6671 case ISN_METHODCALL:
6672 {
6673 cmfunc_T *mfunc = iptr->isn_arg.mfunc;
6674
6675 smsg("%s%4d METHODCALL %s.%s(argc %d)", pfx, current,
6676 mfunc->cmf_itf->class_name,
6677 mfunc->cmf_itf->class_obj_methods[
6678 mfunc->cmf_idx]->uf_name,
6679 mfunc->cmf_argcount);
6638 } 6680 }
6639 break; 6681 break;
6640 case ISN_UCALL: 6682 case ISN_UCALL:
6641 { 6683 {
6642 cufunc_T *cufunc = &iptr->isn_arg.ufunc; 6684 cufunc_T *cufunc = &iptr->isn_arg.ufunc;