comparison src/vim9execute.c @ 23249:43532077b5ff v8.2.2170

patch 8.2.2170: Vim9: a global function defined in a :def function fails Commit: https://github.com/vim/vim/commit/f112f30a82f17114d8b08a0fb90928cd19440581 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Dec 20 17:47:52 2020 +0100 patch 8.2.2170: Vim9: a global function defined in a :def function fails Problem: Vim9: a global function defined in a :def function fails if it uses the context. Solution: Create a partial to store the closure context. (see #7410)
author Bram Moolenaar <Bram@vim.org>
date Sun, 20 Dec 2020 18:00:06 +0100
parents 657216220293
children 35583da6397e
comparison
equal deleted inserted replaced
23248:a0e114c6b39e 23249:43532077b5ff
840 return FAIL; 840 return FAIL;
841 } 841 }
842 return call_partial(&v->di_tv, argcount, ectx); 842 return call_partial(&v->di_tv, argcount, ectx);
843 } 843 }
844 return res; 844 return res;
845 }
846
847 /*
848 * When a function reference is used, fill a partial with the information
849 * needed, especially when it is used as a closure.
850 */
851 static int
852 fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
853 {
854 pt->pt_func = ufunc;
855 pt->pt_refcount = 1;
856
857 if (pt->pt_func->uf_flags & FC_CLOSURE)
858 {
859 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
860 + ectx->ec_dfunc_idx;
861
862 // The closure needs to find arguments and local
863 // variables in the current stack.
864 pt->pt_ectx_stack = &ectx->ec_stack;
865 pt->pt_ectx_frame = ectx->ec_frame_idx;
866
867 // If this function returns and the closure is still
868 // being used, we need to make a copy of the context
869 // (arguments and local variables). Store a reference
870 // to the partial so we can handle that.
871 if (ga_grow(&ectx->ec_funcrefs, 1) == FAIL)
872 {
873 vim_free(pt);
874 return FAIL;
875 }
876 // Extra variable keeps the count of closures created
877 // in the current function call.
878 ++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx
879 + STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number;
880
881 ((partial_T **)ectx->ec_funcrefs.ga_data)
882 [ectx->ec_funcrefs.ga_len] = pt;
883 ++pt->pt_refcount;
884 ++ectx->ec_funcrefs.ga_len;
885 }
886 ++pt->pt_func->uf_refcount;
887 return OK;
845 } 888 }
846 889
847 /* 890 /*
848 * Call a "def" function from old Vim script. 891 * Call a "def" function from old Vim script.
849 * Return OK or FAIL. 892 * Return OK or FAIL.
1000 else 1043 else
1001 { 1044 {
1002 ectx.ec_outer_stack = partial->pt_ectx_stack; 1045 ectx.ec_outer_stack = partial->pt_ectx_stack;
1003 ectx.ec_outer_frame = partial->pt_ectx_frame; 1046 ectx.ec_outer_frame = partial->pt_ectx_frame;
1004 } 1047 }
1048 }
1049 else if (ufunc->uf_partial != NULL)
1050 {
1051 ectx.ec_outer_stack = ufunc->uf_partial->pt_ectx_stack;
1052 ectx.ec_outer_frame = ufunc->uf_partial->pt_ectx_frame;
1005 } 1053 }
1006 1054
1007 // dummy frame entries 1055 // dummy frame entries
1008 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 1056 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
1009 { 1057 {
1967 break; 2015 break;
1968 2016
1969 // push a function reference to a compiled function 2017 // push a function reference to a compiled function
1970 case ISN_FUNCREF: 2018 case ISN_FUNCREF:
1971 { 2019 {
1972 partial_T *pt = NULL; 2020 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
1973 dfunc_T *pt_dfunc; 2021 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data)
1974 2022 + iptr->isn_arg.funcref.fr_func;
1975 pt = ALLOC_CLEAR_ONE(partial_T); 2023
1976 if (pt == NULL) 2024 if (pt == NULL)
1977 goto failed; 2025 goto failed;
1978 if (GA_GROW(&ectx.ec_stack, 1) == FAIL) 2026 if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
1979 { 2027 {
1980 vim_free(pt); 2028 vim_free(pt);
1981 goto failed; 2029 goto failed;
1982 } 2030 }
1983 pt_dfunc = ((dfunc_T *)def_functions.ga_data) 2031 if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc,
1984 + iptr->isn_arg.funcref.fr_func; 2032 &ectx) == FAIL)
1985 pt->pt_func = pt_dfunc->df_ufunc; 2033 goto failed;
1986 pt->pt_refcount = 1;
1987
1988 if (pt_dfunc->df_ufunc->uf_flags & FC_CLOSURE)
1989 {
1990 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1991 + ectx.ec_dfunc_idx;
1992
1993 // The closure needs to find arguments and local
1994 // variables in the current stack.
1995 pt->pt_ectx_stack = &ectx.ec_stack;
1996 pt->pt_ectx_frame = ectx.ec_frame_idx;
1997
1998 // If this function returns and the closure is still
1999 // being used, we need to make a copy of the context
2000 // (arguments and local variables). Store a reference
2001 // to the partial so we can handle that.
2002 if (ga_grow(&ectx.ec_funcrefs, 1) == FAIL)
2003 {
2004 vim_free(pt);
2005 goto failed;
2006 }
2007 // Extra variable keeps the count of closures created
2008 // in the current function call.
2009 tv = STACK_TV_VAR(dfunc->df_varcount);
2010 ++tv->vval.v_number;
2011
2012 ((partial_T **)ectx.ec_funcrefs.ga_data)
2013 [ectx.ec_funcrefs.ga_len] = pt;
2014 ++pt->pt_refcount;
2015 ++ectx.ec_funcrefs.ga_len;
2016 }
2017 ++pt_dfunc->df_ufunc->uf_refcount;
2018 2034
2019 tv = STACK_TV_BOT(0); 2035 tv = STACK_TV_BOT(0);
2020 ++ectx.ec_stack.ga_len; 2036 ++ectx.ec_stack.ga_len;
2021 tv->vval.v_partial = pt; 2037 tv->vval.v_partial = pt;
2022 tv->v_type = VAR_PARTIAL; 2038 tv->v_type = VAR_PARTIAL;
2026 2042
2027 // Create a global function from a lambda. 2043 // Create a global function from a lambda.
2028 case ISN_NEWFUNC: 2044 case ISN_NEWFUNC:
2029 { 2045 {
2030 newfunc_T *newfunc = &iptr->isn_arg.newfunc; 2046 newfunc_T *newfunc = &iptr->isn_arg.newfunc;
2031 2047 ufunc_T *new_ufunc;
2032 copy_func(newfunc->nf_lambda, newfunc->nf_global); 2048
2049 new_ufunc = copy_func(
2050 newfunc->nf_lambda, newfunc->nf_global);
2051 if (new_ufunc != NULL
2052 && (new_ufunc->uf_flags & FC_CLOSURE))
2053 {
2054 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
2055
2056 // Need to create a partial to store the context of the
2057 // function.
2058 if (pt == NULL)
2059 goto failed;
2060 if (fill_partial_and_closure(pt, new_ufunc,
2061 &ectx) == FAIL)
2062 goto failed;
2063 new_ufunc->uf_partial = pt;
2064 --pt->pt_refcount; // not referenced here
2065 }
2033 } 2066 }
2034 break; 2067 break;
2035 2068
2036 // List functions 2069 // List functions
2037 case ISN_DEF: 2070 case ISN_DEF:
3112 while (ectx.ec_frame_idx != initial_frame_idx) 3145 while (ectx.ec_frame_idx != initial_frame_idx)
3113 func_return(&ectx); 3146 func_return(&ectx);
3114 3147
3115 // Deal with any remaining closures, they may be in use somewhere. 3148 // Deal with any remaining closures, they may be in use somewhere.
3116 if (ectx.ec_funcrefs.ga_len > 0) 3149 if (ectx.ec_funcrefs.ga_len > 0)
3150 {
3117 handle_closure_in_use(&ectx, FALSE); 3151 handle_closure_in_use(&ectx, FALSE);
3152 ga_clear(&ectx.ec_funcrefs); // TODO: should not be needed?
3153 }
3118 3154
3119 estack_pop(); 3155 estack_pop();
3120 current_sctx = save_current_sctx; 3156 current_sctx = save_current_sctx;
3121 3157
3122 if (*msg_list != NULL && saved_msg_list != NULL) 3158 if (*msg_list != NULL && saved_msg_list != NULL)