Mercurial > vim
diff src/vim9instr.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 | b7a8611dd9fc |
line wrap: on
line diff
--- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -1709,11 +1709,18 @@ generate_BLOBAPPEND(cctx_T *cctx) } /* - * Generate an ISN_DCALL or ISN_UCALL instruction. + * Generate an ISN_DCALL, ISN_UCALL or ISN_METHODCALL instruction. + * When calling a method on an object, of which we know the interface only, + * then "cl" is the interface and "mi" the method index on the interface. * Return FAIL if the number of arguments is wrong. */ int -generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) +generate_CALL( + cctx_T *cctx, + ufunc_T *ufunc, + class_T *cl, + int mi, + int pushed_argcount) { isn_T *isn; int regular_args = ufunc->uf_args.ga_len; @@ -1783,11 +1790,21 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu return FAIL; } - if ((isn = generate_instr(cctx, - ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL - : ISN_UCALL)) == NULL) + if ((isn = generate_instr(cctx, cl != NULL ? ISN_METHODCALL + : ufunc->uf_def_status != UF_NOT_COMPILED + ? ISN_DCALL : ISN_UCALL)) == NULL) return FAIL; - if (isn->isn_type == ISN_DCALL) + if (isn->isn_type == ISN_METHODCALL) + { + isn->isn_arg.mfunc = ALLOC_ONE(cmfunc_T); + if (isn->isn_arg.mfunc == NULL) + return FAIL; + isn->isn_arg.mfunc->cmf_itf = cl; + ++cl->class_refcount; + isn->isn_arg.mfunc->cmf_idx = mi; + isn->isn_arg.mfunc->cmf_argcount = argcount; + } + else if (isn->isn_type == ISN_DCALL) { isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; isn->isn_arg.dfunc.cdf_argcount = argcount; @@ -2483,6 +2500,14 @@ delete_instr(isn_T *isn) } break; + case ISN_METHODCALL: + { + cmfunc_T *mfunc = isn->isn_arg.mfunc; + class_unref(mfunc->cmf_itf); + vim_free(mfunc); + } + break; + case ISN_NEWFUNC: { newfuncarg_T *arg = isn->isn_arg.newfunc.nf_arg;