summaryrefslogtreecommitdiffstats
path: root/src/vim9instr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vim9instr.c')
-rw-r--r--src/vim9instr.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/src/vim9instr.c b/src/vim9instr.c
index ae03044356..cc0d8ad8b4 100644
--- 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 *ufunc, int pushed_argcount)
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;