Mercurial > vim
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; |