comparison src/userfunc.c @ 9686:8c2553beff0f v7.4.2119

commit https://github.com/vim/vim/commit/1e96d9bf98f9ab84d5af7f98d6a961d91b17364f Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jul 29 22:15:09 2016 +0200 patch 7.4.2119 Problem: Closures are not supported. Solution: Capture variables in lambdas from the outer scope. (Yasuhiro Matsumoto, Ken Takata)
author Christian Brabandt <cb@256bit.org>
date Fri, 29 Jul 2016 22:30:08 +0200
parents f1920505bc16
children 2ea935bdd1a1
comparison
equal deleted inserted replaced
9685:fee40b9f4989 9686:8c2553beff0f
12 */ 12 */
13 13
14 #include "vim.h" 14 #include "vim.h"
15 15
16 #if defined(FEAT_EVAL) || defined(PROTO) 16 #if defined(FEAT_EVAL) || defined(PROTO)
17
18 typedef struct funccall_S funccall_T;
17 19
18 /* 20 /*
19 * Structure to hold info for a user function. 21 * Structure to hold info for a user function.
20 */ 22 */
21 typedef struct ufunc ufunc_T; 23 typedef struct ufunc ufunc_T;
45 int uf_tml_execed; /* line being timed was executed */ 47 int uf_tml_execed; /* line being timed was executed */
46 #endif 48 #endif
47 scid_T uf_script_ID; /* ID of script where function was defined, 49 scid_T uf_script_ID; /* ID of script where function was defined,
48 used for s: variables */ 50 used for s: variables */
49 int uf_refcount; /* for numbered function: reference count */ 51 int uf_refcount; /* for numbered function: reference count */
52 funccall_T *uf_scoped; /* l: local variables for closure */
50 char_u uf_name[1]; /* name of function (actually longer); can 53 char_u uf_name[1]; /* name of function (actually longer); can
51 start with <SNR>123_ (<SNR> is K_SPECIAL 54 start with <SNR>123_ (<SNR> is K_SPECIAL
52 KS_EXTRA KE_SNR) */ 55 KS_EXTRA KE_SNR) */
53 }; 56 };
54 57
68 #define MAX_FUNC_ARGS 20 /* maximum number of function arguments */ 71 #define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
69 #define VAR_SHORT_LEN 20 /* short variable name length */ 72 #define VAR_SHORT_LEN 20 /* short variable name length */
70 #define FIXVAR_CNT 12 /* number of fixed variables */ 73 #define FIXVAR_CNT 12 /* number of fixed variables */
71 74
72 /* structure to hold info for a function that is currently being executed. */ 75 /* structure to hold info for a function that is currently being executed. */
73 typedef struct funccall_S funccall_T;
74
75 struct funccall_S 76 struct funccall_S
76 { 77 {
77 ufunc_T *func; /* function being called */ 78 ufunc_T *func; /* function being called */
78 int linenr; /* next line to be executed */ 79 int linenr; /* next line to be executed */
79 int returned; /* ":return" used */ 80 int returned; /* ":return" used */
94 int level; /* top nesting level of executed function */ 95 int level; /* top nesting level of executed function */
95 #ifdef FEAT_PROFILE 96 #ifdef FEAT_PROFILE
96 proftime_T prof_child; /* time spent in a child */ 97 proftime_T prof_child; /* time spent in a child */
97 #endif 98 #endif
98 funccall_T *caller; /* calling function or NULL */ 99 funccall_T *caller; /* calling function or NULL */
100
101 /* for closure */
102 int fc_refcount;
103 int fc_copyID; /* for garbage collection */
104 garray_T fc_funcs; /* list of ufunc_T* which refer this */
99 }; 105 };
100 106
101 /* 107 /*
102 * Struct used by trans_function_name() 108 * Struct used by trans_function_name()
103 */ 109 */
257 int 263 int
258 get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate) 264 get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
259 { 265 {
260 garray_T newargs; 266 garray_T newargs;
261 garray_T newlines; 267 garray_T newlines;
268 garray_T *pnewargs;
262 ufunc_T *fp = NULL; 269 ufunc_T *fp = NULL;
263 int varargs; 270 int varargs;
264 int ret; 271 int ret;
265 char_u name[20]; 272 char_u name[20];
266 char_u *start = skipwhite(*arg + 1); 273 char_u *start = skipwhite(*arg + 1);
267 char_u *s, *e; 274 char_u *s, *e;
268 static int lambda_no = 0; 275 static int lambda_no = 0;
276 int *old_eval_lavars = eval_lavars_used;
277 int eval_lavars = FALSE;
269 278
270 ga_init(&newargs); 279 ga_init(&newargs);
271 ga_init(&newlines); 280 ga_init(&newlines);
272 281
273 /* First, check if this is a lambda expression. "->" must exist. */ 282 /* First, check if this is a lambda expression. "->" must exist. */
274 ret = get_function_args(&start, '-', NULL, NULL, TRUE); 283 ret = get_function_args(&start, '-', NULL, NULL, TRUE);
275 if (ret == FAIL || *start != '>') 284 if (ret == FAIL || *start != '>')
276 return NOTDONE; 285 return NOTDONE;
277 286
278 /* Parse the arguments again. */ 287 /* Parse the arguments again. */
288 if (evaluate)
289 pnewargs = &newargs;
290 else
291 pnewargs = NULL;
279 *arg = skipwhite(*arg + 1); 292 *arg = skipwhite(*arg + 1);
280 ret = get_function_args(arg, '-', &newargs, &varargs, FALSE); 293 ret = get_function_args(arg, '-', pnewargs, &varargs, FALSE);
281 if (ret == FAIL || **arg != '>') 294 if (ret == FAIL || **arg != '>')
282 goto errret; 295 goto errret;
296
297 /* Set up dictionaries for checking local variables and arguments. */
298 if (evaluate)
299 eval_lavars_used = &eval_lavars;
283 300
284 /* Get the start and the end of the expression. */ 301 /* Get the start and the end of the expression. */
285 *arg = skipwhite(*arg + 1); 302 *arg = skipwhite(*arg + 1);
286 s = *arg; 303 s = *arg;
287 ret = skip_expr(arg); 304 ret = skip_expr(arg);
296 if (evaluate) 313 if (evaluate)
297 { 314 {
298 int len; 315 int len;
299 char_u *p; 316 char_u *p;
300 317
301 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + 20)); 318 sprintf((char*)name, "<lambda>%d", ++lambda_no);
319
320 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
302 if (fp == NULL) 321 if (fp == NULL)
303 goto errret; 322 goto errret;
304
305 sprintf((char*)name, "<lambda>%d", ++lambda_no);
306 323
307 ga_init2(&newlines, (int)sizeof(char_u *), 1); 324 ga_init2(&newlines, (int)sizeof(char_u *), 1);
308 if (ga_grow(&newlines, 1) == FAIL) 325 if (ga_grow(&newlines, 1) == FAIL)
309 goto errret; 326 goto errret;
310 327
311 /* Add "return " before the expression. 328 /* Add "return " before the expression. */
312 * TODO: Support multiple expressions. */
313 len = 7 + e - s + 1; 329 len = 7 + e - s + 1;
314 p = (char_u *)alloc(len); 330 p = (char_u *)alloc(len);
315 if (p == NULL) 331 if (p == NULL)
316 goto errret; 332 goto errret;
317 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = p; 333 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = p;
318 STRCPY(p, "return "); 334 STRCPY(p, "return ");
319 STRNCPY(p + 7, s, e - s); 335 vim_strncpy(p + 7, s, e - s);
320 p[7 + e - s] = NUL;
321 336
322 fp->uf_refcount = 1; 337 fp->uf_refcount = 1;
323 STRCPY(fp->uf_name, name); 338 STRCPY(fp->uf_name, name);
324 hash_add(&func_hashtab, UF2HIKEY(fp)); 339 hash_add(&func_hashtab, UF2HIKEY(fp));
325 fp->uf_args = newargs; 340 fp->uf_args = newargs;
326 fp->uf_lines = newlines; 341 fp->uf_lines = newlines;
342 if (current_funccal != NULL && eval_lavars)
343 {
344 fp->uf_scoped = current_funccal;
345 current_funccal->fc_refcount++;
346 if (ga_grow(&current_funccal->fc_funcs, 1) == FAIL)
347 goto errret;
348 ((ufunc_T **)current_funccal->fc_funcs.ga_data)
349 [current_funccal->fc_funcs.ga_len++] = fp;
350 func_ref(current_funccal->func->uf_name);
351 }
352 else
353 fp->uf_scoped = NULL;
327 354
328 #ifdef FEAT_PROFILE 355 #ifdef FEAT_PROFILE
329 fp->uf_tml_count = NULL; 356 fp->uf_tml_count = NULL;
330 fp->uf_tml_total = NULL; 357 fp->uf_tml_total = NULL;
331 fp->uf_tml_self = NULL; 358 fp->uf_tml_self = NULL;
339 fp->uf_script_ID = current_SID; 366 fp->uf_script_ID = current_SID;
340 367
341 rettv->vval.v_string = vim_strsave(name); 368 rettv->vval.v_string = vim_strsave(name);
342 rettv->v_type = VAR_FUNC; 369 rettv->v_type = VAR_FUNC;
343 } 370 }
344 else 371
345 ga_clear_strings(&newargs); 372 eval_lavars_used = old_eval_lavars;
346
347 return OK; 373 return OK;
348 374
349 errret: 375 errret:
350 ga_clear_strings(&newargs); 376 ga_clear_strings(&newargs);
351 ga_clear_strings(&newlines); 377 ga_clear_strings(&newlines);
352 vim_free(fp); 378 vim_free(fp);
379 eval_lavars_used = old_eval_lavars;
353 return FAIL; 380 return FAIL;
354 } 381 }
355 382
356 /* 383 /*
357 * Check if "name" is a variable of type VAR_FUNC. If so, return the function 384 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
622 free_funccal( 649 free_funccal(
623 funccall_T *fc, 650 funccall_T *fc,
624 int free_val) /* a: vars were allocated */ 651 int free_val) /* a: vars were allocated */
625 { 652 {
626 listitem_T *li; 653 listitem_T *li;
654 int i;
655
656 for (i = 0; i < fc->fc_funcs.ga_len; ++i)
657 {
658 ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i];
659
660 if (fp != NULL)
661 fp->uf_scoped = NULL;
662 }
627 663
628 /* The a: variables typevals may not have been allocated, only free the 664 /* The a: variables typevals may not have been allocated, only free the
629 * allocated variables. */ 665 * allocated variables. */
630 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); 666 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val);
631 667
635 /* Free the a:000 variables if they were allocated. */ 671 /* Free the a:000 variables if they were allocated. */
636 if (free_val) 672 if (free_val)
637 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) 673 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
638 clear_tv(&li->li_tv); 674 clear_tv(&li->li_tv);
639 675
676 for (i = 0; i < fc->fc_funcs.ga_len; ++i)
677 {
678 ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i];
679
680 if (fp != NULL)
681 func_unref(fc->func->uf_name);
682 }
683 ga_clear(&fc->fc_funcs);
684
685 func_unref(fc->func->uf_name);
640 vim_free(fc); 686 vim_free(fc);
641 } 687 }
642 688
643 /* 689 /*
644 * Call a user function. 690 * Call a user function.
694 fc->returned = FALSE; 740 fc->returned = FALSE;
695 fc->level = ex_nesting_level; 741 fc->level = ex_nesting_level;
696 /* Check if this function has a breakpoint. */ 742 /* Check if this function has a breakpoint. */
697 fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0); 743 fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
698 fc->dbg_tick = debug_tick; 744 fc->dbg_tick = debug_tick;
745 /* Set up fields for closure. */
746 fc->fc_refcount = 0;
747 fc->fc_copyID = 0;
748 ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1);
749 func_ref(fp->uf_name);
699 750
700 if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0) 751 if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
701 islambda = TRUE; 752 islambda = TRUE;
702 753
703 /* 754 /*
756 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", 807 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
757 (varnumber_T)lastline); 808 (varnumber_T)lastline);
758 for (i = 0; i < argcount; ++i) 809 for (i = 0; i < argcount; ++i)
759 { 810 {
760 int addlocal = FALSE; 811 int addlocal = FALSE;
761 dictitem_T *v2;
762 812
763 ai = i - fp->uf_args.ga_len; 813 ai = i - fp->uf_args.ga_len;
764 if (ai < 0) 814 if (ai < 0)
765 { 815 {
766 /* named argument a:name */ 816 /* named argument a:name */
776 } 826 }
777 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) 827 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
778 { 828 {
779 v = &fc->fixvar[fixvar_idx++].var; 829 v = &fc->fixvar[fixvar_idx++].var;
780 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 830 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
781
782 if (addlocal)
783 v2 = v;
784 } 831 }
785 else 832 else
786 { 833 {
787 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) 834 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
788 + STRLEN(name))); 835 + STRLEN(name)));
789 if (v == NULL) 836 if (v == NULL)
790 break; 837 break;
791 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC; 838 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
792
793 if (addlocal)
794 {
795 v2 = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
796 + STRLEN(name)));
797 if (v2 == NULL)
798 {
799 vim_free(v);
800 break;
801 }
802 v2->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
803 }
804 } 839 }
805 STRCPY(v->di_key, name); 840 STRCPY(v->di_key, name);
806 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
807 841
808 /* Note: the values are copied directly to avoid alloc/free. 842 /* Note: the values are copied directly to avoid alloc/free.
809 * "argvars" must have VAR_FIXED for v_lock. */ 843 * "argvars" must have VAR_FIXED for v_lock. */
810 v->di_tv = argvars[i]; 844 v->di_tv = argvars[i];
811 v->di_tv.v_lock = VAR_FIXED; 845 v->di_tv.v_lock = VAR_FIXED;
812 846
813 /* Named arguments can be accessed without the "a:" prefix in lambda
814 * expressions. Add to the l: dict. */
815 if (addlocal) 847 if (addlocal)
816 { 848 {
817 STRCPY(v2->di_key, name); 849 /* Named arguments should be accessed without the "a:" prefix in
818 copy_tv(&v->di_tv, &v2->di_tv); 850 * lambda expressions. Add to the l: dict. */
819 v2->di_tv.v_lock = VAR_FIXED; 851 copy_tv(&v->di_tv, &v->di_tv);
820 hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v2)); 852 hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
821 } 853 }
854 else
855 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
822 856
823 if (ai >= 0 && ai < MAX_FUNC_ARGS) 857 if (ai >= 0 && ai < MAX_FUNC_ARGS)
824 { 858 {
825 list_append(&fc->l_varlist, &fc->l_listitems[ai]); 859 list_append(&fc->l_varlist, &fc->l_listitems[ai]);
826 fc->l_listitems[ai].li_tv = argvars[i]; 860 fc->l_listitems[ai].li_tv = argvars[i];
1012 1046
1013 /* If the a:000 list and the l: and a: dicts are not referenced we can 1047 /* If the a:000 list and the l: and a: dicts are not referenced we can
1014 * free the funccall_T and what's in it. */ 1048 * free the funccall_T and what's in it. */
1015 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT 1049 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
1016 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT 1050 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
1017 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) 1051 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT
1052 && fc->fc_refcount <= 0)
1018 { 1053 {
1019 free_funccal(fc, FALSE); 1054 free_funccal(fc, FALSE);
1020 } 1055 }
1021 else 1056 else
1022 { 1057 {
1043 } 1078 }
1044 1079
1045 /* Make a copy of the a:000 items, since we didn't do that above. */ 1080 /* Make a copy of the a:000 items, since we didn't do that above. */
1046 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) 1081 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
1047 copy_tv(&li->li_tv, &li->li_tv); 1082 copy_tv(&li->li_tv, &li->li_tv);
1083 }
1084 }
1085
1086 /*
1087 * Unreference "fc": decrement the reference count and free it when it
1088 * becomes zero. If "fp" is not NULL, "fp" is detached from "fc".
1089 */
1090 static void
1091 funccal_unref(funccall_T *fc, ufunc_T *fp)
1092 {
1093 funccall_T **pfc;
1094 int i;
1095 int freed = FALSE;
1096
1097 if (fc == NULL)
1098 return;
1099
1100 if (--fc->fc_refcount <= 0)
1101 {
1102 for (pfc = &previous_funccal; *pfc != NULL; )
1103 {
1104 if (fc == *pfc
1105 && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
1106 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
1107 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
1108 {
1109 *pfc = fc->caller;
1110 free_funccal(fc, TRUE);
1111 freed = TRUE;
1112 }
1113 else
1114 pfc = &(*pfc)->caller;
1115 }
1116 }
1117 if (!freed)
1118 {
1119 func_unref(fc->func->uf_name);
1120
1121 if (fp != NULL)
1122 {
1123 for (i = 0; i < fc->fc_funcs.ga_len; ++i)
1124 {
1125 if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp)
1126 ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL;
1127 }
1128 }
1048 } 1129 }
1049 } 1130 }
1050 1131
1051 /* 1132 /*
1052 * Free a function and remove it from the list of functions. 1133 * Free a function and remove it from the list of functions.
1069 hi = hash_find(&func_hashtab, UF2HIKEY(fp)); 1150 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
1070 if (HASHITEM_EMPTY(hi)) 1151 if (HASHITEM_EMPTY(hi))
1071 EMSG2(_(e_intern2), "func_free()"); 1152 EMSG2(_(e_intern2), "func_free()");
1072 else 1153 else
1073 hash_remove(&func_hashtab, hi); 1154 hash_remove(&func_hashtab, hi);
1155
1156 funccal_unref(fp->uf_scoped, fp);
1074 1157
1075 vim_free(fp); 1158 vim_free(fp);
1076 } 1159 }
1077 1160
1078 #if defined(EXITFREE) || defined(PROTO) 1161 #if defined(EXITFREE) || defined(PROTO)
2214 goto erret; 2297 goto erret;
2215 } 2298 }
2216 } 2299 }
2217 fp->uf_args = newargs; 2300 fp->uf_args = newargs;
2218 fp->uf_lines = newlines; 2301 fp->uf_lines = newlines;
2302 fp->uf_scoped = NULL;
2219 #ifdef FEAT_PROFILE 2303 #ifdef FEAT_PROFILE
2220 fp->uf_tml_count = NULL; 2304 fp->uf_tml_count = NULL;
2221 fp->uf_tml_total = NULL; 2305 fp->uf_tml_total = NULL;
2222 fp->uf_tml_self = NULL; 2306 fp->uf_tml_self = NULL;
2223 fp->uf_profiling = FALSE; 2307 fp->uf_profiling = FALSE;
2703 static int 2787 static int
2704 can_free_funccal(funccall_T *fc, int copyID) 2788 can_free_funccal(funccall_T *fc, int copyID)
2705 { 2789 {
2706 return (fc->l_varlist.lv_copyID != copyID 2790 return (fc->l_varlist.lv_copyID != copyID
2707 && fc->l_vars.dv_copyID != copyID 2791 && fc->l_vars.dv_copyID != copyID
2708 && fc->l_avars.dv_copyID != copyID); 2792 && fc->l_avars.dv_copyID != copyID
2793 && fc->fc_copyID != copyID);
2709 } 2794 }
2710 2795
2711 /* 2796 /*
2712 * ":return [expr]" 2797 * ":return [expr]"
2713 */ 2798 */
3449 return &current_funccal->l_vars; 3534 return &current_funccal->l_vars;
3450 return NULL; 3535 return NULL;
3451 } 3536 }
3452 3537
3453 /* 3538 /*
3539 * Search variable in parent scope.
3540 */
3541 dictitem_T *
3542 find_var_in_scoped_ht(char_u *name, char_u **varname, int no_autoload)
3543 {
3544 dictitem_T *v = NULL;
3545 funccall_T *old_current_funccal = current_funccal;
3546 hashtab_T *ht;
3547
3548 if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
3549 return NULL;
3550
3551 /* Search in parent scope which is possible to reference from lambda */
3552 current_funccal = current_funccal->func->uf_scoped;
3553 while (current_funccal)
3554 {
3555 ht = find_var_ht(name, varname ? &(*varname) : NULL);
3556 if (ht != NULL)
3557 {
3558 v = find_var_in_ht(ht, *name,
3559 varname ? *varname : NULL, no_autoload);
3560 if (v != NULL)
3561 break;
3562 }
3563 if (current_funccal == current_funccal->func->uf_scoped)
3564 break;
3565 current_funccal = current_funccal->func->uf_scoped;
3566 }
3567 current_funccal = old_current_funccal;
3568
3569 return v;
3570 }
3571
3572 /*
3454 * Set "copyID + 1" in previous_funccal and callers. 3573 * Set "copyID + 1" in previous_funccal and callers.
3455 */ 3574 */
3456 int 3575 int
3457 set_ref_in_previous_funccal(int copyID) 3576 set_ref_in_previous_funccal(int copyID)
3458 { 3577 {
3459 int abort = FALSE; 3578 int abort = FALSE;
3460 funccall_T *fc; 3579 funccall_T *fc;
3461 3580
3462 for (fc = previous_funccal; fc != NULL; fc = fc->caller) 3581 for (fc = previous_funccal; fc != NULL; fc = fc->caller)
3463 { 3582 {
3583 fc->fc_copyID = copyID + 1;
3464 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, 3584 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1,
3465 NULL); 3585 NULL);
3466 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, 3586 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1,
3467 NULL); 3587 NULL);
3468 } 3588 }
3478 int abort = FALSE; 3598 int abort = FALSE;
3479 funccall_T *fc; 3599 funccall_T *fc;
3480 3600
3481 for (fc = current_funccal; fc != NULL; fc = fc->caller) 3601 for (fc = current_funccal; fc != NULL; fc = fc->caller)
3482 { 3602 {
3603 fc->fc_copyID = copyID;
3483 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); 3604 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
3484 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); 3605 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
3485 } 3606 }
3486 return abort; 3607 return abort;
3487 } 3608 }
3499 abort = abort || set_ref_in_item(((typval_T **)funcargs.ga_data)[i], 3620 abort = abort || set_ref_in_item(((typval_T **)funcargs.ga_data)[i],
3500 copyID, NULL, NULL); 3621 copyID, NULL, NULL);
3501 return abort; 3622 return abort;
3502 } 3623 }
3503 3624
3625 /*
3626 * Mark all lists and dicts referenced through function "name" with "copyID".
3627 * "list_stack" is used to add lists to be marked. Can be NULL.
3628 * "ht_stack" is used to add hashtabs to be marked. Can be NULL.
3629 *
3630 * Returns TRUE if setting references failed somehow.
3631 */
3632 int
3633 set_ref_in_func(char_u *name, int copyID)
3634 {
3635 ufunc_T *fp;
3636 funccall_T *fc;
3637 int error = ERROR_NONE;
3638 char_u fname_buf[FLEN_FIXED + 1];
3639 char_u *tofree = NULL;
3640 char_u *fname;
3641
3642 if (name == NULL)
3643 return FALSE;
3644
3645 fname = fname_trans_sid(name, fname_buf, &tofree, &error);
3646 fp = find_func(fname);
3647 if (fp != NULL)
3648 {
3649 for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped)
3650 {
3651 if (fc->fc_copyID != copyID)
3652 {
3653 fc->fc_copyID = copyID;
3654 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
3655 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
3656 }
3657 }
3658 }
3659 vim_free(tofree);
3660 return FALSE;
3661 }
3662
3504 #endif /* FEAT_EVAL */ 3663 #endif /* FEAT_EVAL */