aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/user_funcs.c
diff options
context:
space:
mode:
authorJakub Łuczyński <doubleloop@o2.pl>2020-02-10 13:49:30 +0100
committerJakub Łuczyński <doubleloop@o2.pl>2020-02-13 14:11:40 +0100
commit423fcbee4a0edb6b89180e0097b59a8e6c0fc23f (patch)
tree2a4de304a17dd6b777b63f9ce10a172fb562aac1 /src/nvim/eval/user_funcs.c
parentb683957763f4c804d343aec9242ff5e67e0b8653 (diff)
downloadrneovim-423fcbee4a0edb6b89180e0097b59a8e6c0fc23f.tar.gz
rneovim-423fcbee4a0edb6b89180e0097b59a8e6c0fc23f.tar.bz2
rneovim-423fcbee4a0edb6b89180e0097b59a8e6c0fc23f.zip
fix: factor out make_partial
Diffstat (limited to 'src/nvim/eval/user_funcs.c')
-rw-r--r--src/nvim/eval/user_funcs.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/nvim/eval/user_funcs.c b/src/nvim/eval/user_funcs.c
index 1b8d714566..72313c3bd7 100644
--- a/src/nvim/eval/user_funcs.c
+++ b/src/nvim/eval/user_funcs.c
@@ -2981,6 +2981,67 @@ int func_has_abort(void *cookie)
return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
}
+/// Turn "dict.Func" into a partial for "Func" bound to "dict".
+/// Changes "rettv" in-place.
+void make_partial(dict_T *const selfdict, typval_T *const rettv)
+{
+ char_u *fname;
+ char_u *tofree = NULL;
+ ufunc_T *fp;
+ char_u fname_buf[FLEN_FIXED + 1];
+ int error;
+
+ if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL) {
+ fp = rettv->vval.v_partial->pt_func;
+ } else {
+ fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING
+ ? rettv->vval.v_string
+ : rettv->vval.v_partial->pt_name;
+ // Translate "s:func" to the stored function name.
+ fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
+ fp = find_func(fname);
+ xfree(tofree);
+ }
+
+ // Turn "dict.Func" into a partial for "Func" with "dict".
+ if (fp != NULL && (fp->uf_flags & FC_DICT)) {
+ partial_T *pt = (partial_T *)xcalloc(1, sizeof(partial_T));
+ pt->pt_refcount = 1;
+ pt->pt_dict = selfdict;
+ (selfdict->dv_refcount)++;
+ pt->pt_auto = true;
+ if (rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING) {
+ // Just a function: Take over the function name and use selfdict.
+ pt->pt_name = rettv->vval.v_string;
+ } else {
+ partial_T *ret_pt = rettv->vval.v_partial;
+ int i;
+
+ // Partial: copy the function name, use selfdict and copy
+ // args. Can't take over name or args, the partial might
+ // be referenced elsewhere.
+ if (ret_pt->pt_name != NULL) {
+ pt->pt_name = vim_strsave(ret_pt->pt_name);
+ func_ref(pt->pt_name);
+ } else {
+ pt->pt_func = ret_pt->pt_func;
+ func_ptr_ref(pt->pt_func);
+ }
+ if (ret_pt->pt_argc > 0) {
+ size_t arg_size = sizeof(typval_T) * ret_pt->pt_argc;
+ pt->pt_argv = (typval_T *)xmalloc(arg_size);
+ pt->pt_argc = ret_pt->pt_argc;
+ for (i = 0; i < pt->pt_argc; i++) {
+ tv_copy(&ret_pt->pt_argv[i], &pt->pt_argv[i]);
+ }
+ }
+ partial_unref(ret_pt);
+ }
+ rettv->v_type = VAR_PARTIAL;
+ rettv->vval.v_partial = pt;
+ }
+}
+
/*
* Return the name of the executed function.
*/