Mercurial > vim
comparison src/userfunc.c @ 9721:79862f44c647 v7.4.2136
commit https://github.com/vim/vim/commit/580164481924ed8611eb79f0247a0eb1ca0b3b9a
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jul 31 18:30:22 2016 +0200
patch 7.4.2136
Problem: Closure function fails.
Solution: Don't reset uf_scoped when it points to another funccal.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 31 Jul 2016 18:45:06 +0200 |
parents | 6226de5f8137 |
children | 80ac9cf77c9b |
comparison
equal
deleted
inserted
replaced
9720:8c110d08b87f | 9721:79862f44c647 |
---|---|
148 # ifdef __BORLANDC__ | 148 # ifdef __BORLANDC__ |
149 _RTLENTRYF | 149 _RTLENTRYF |
150 # endif | 150 # endif |
151 prof_self_cmp(const void *s1, const void *s2); | 151 prof_self_cmp(const void *s1, const void *s2); |
152 #endif | 152 #endif |
153 static void funccal_unref(funccall_T *fc, ufunc_T *fp); | |
153 | 154 |
154 void | 155 void |
155 func_init() | 156 func_init() |
156 { | 157 { |
157 hash_init(&func_hashtab); | 158 hash_init(&func_hashtab); |
256 ga_clear_strings(newargs); | 257 ga_clear_strings(newargs); |
257 return FAIL; | 258 return FAIL; |
258 } | 259 } |
259 | 260 |
260 /* | 261 /* |
262 * Register function "fp" as using "current_funccal" as its scope. | |
263 */ | |
264 static int | |
265 register_closure(ufunc_T *fp) | |
266 { | |
267 funccal_unref(fp->uf_scoped, NULL); | |
268 fp->uf_scoped = current_funccal; | |
269 current_funccal->fc_refcount++; | |
270 if (ga_grow(¤t_funccal->fc_funcs, 1) == FAIL) | |
271 return FAIL; | |
272 ((ufunc_T **)current_funccal->fc_funcs.ga_data) | |
273 [current_funccal->fc_funcs.ga_len++] = fp; | |
274 func_ref(current_funccal->func->uf_name); | |
275 return OK; | |
276 } | |
277 | |
278 /* | |
261 * Parse a lambda expression and get a Funcref from "*arg". | 279 * Parse a lambda expression and get a Funcref from "*arg". |
262 * Return OK or FAIL. Returns NOTDONE for dict or {expr}. | 280 * Return OK or FAIL. Returns NOTDONE for dict or {expr}. |
263 */ | 281 */ |
264 int | 282 int |
265 get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate) | 283 get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate) |
316 int len, flags = 0; | 334 int len, flags = 0; |
317 char_u *p; | 335 char_u *p; |
318 | 336 |
319 sprintf((char*)name, "<lambda>%d", ++lambda_no); | 337 sprintf((char*)name, "<lambda>%d", ++lambda_no); |
320 | 338 |
321 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name))); | 339 fp = (ufunc_T *)alloc_clear((unsigned)(sizeof(ufunc_T) + STRLEN(name))); |
322 if (fp == NULL) | 340 if (fp == NULL) |
323 goto errret; | 341 goto errret; |
324 | 342 |
325 ga_init2(&newlines, (int)sizeof(char_u *), 1); | 343 ga_init2(&newlines, (int)sizeof(char_u *), 1); |
326 if (ga_grow(&newlines, 1) == FAIL) | 344 if (ga_grow(&newlines, 1) == FAIL) |
341 fp->uf_args = newargs; | 359 fp->uf_args = newargs; |
342 fp->uf_lines = newlines; | 360 fp->uf_lines = newlines; |
343 if (current_funccal != NULL && eval_lavars) | 361 if (current_funccal != NULL && eval_lavars) |
344 { | 362 { |
345 flags |= FC_CLOSURE; | 363 flags |= FC_CLOSURE; |
346 fp->uf_scoped = current_funccal; | 364 if (register_closure(fp) == FAIL) |
347 current_funccal->fc_refcount++; | |
348 if (ga_grow(¤t_funccal->fc_funcs, 1) == FAIL) | |
349 goto errret; | 365 goto errret; |
350 ((ufunc_T **)current_funccal->fc_funcs.ga_data) | |
351 [current_funccal->fc_funcs.ga_len++] = fp; | |
352 func_ref(current_funccal->func->uf_name); | |
353 } | 366 } |
354 else | 367 else |
355 fp->uf_scoped = NULL; | 368 fp->uf_scoped = NULL; |
356 | 369 |
357 #ifdef FEAT_PROFILE | 370 #ifdef FEAT_PROFILE |
658 for (i = 0; i < fc->fc_funcs.ga_len; ++i) | 671 for (i = 0; i < fc->fc_funcs.ga_len; ++i) |
659 { | 672 { |
660 ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i]; | 673 ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i]; |
661 | 674 |
662 if (fp != NULL) | 675 if (fp != NULL) |
663 fp->uf_scoped = NULL; | 676 { |
664 } | 677 /* Function may have been redefined and point to another |
678 * funccall_T, don't clear it then. */ | |
679 if (fp->uf_scoped == fc) | |
680 fp->uf_scoped = NULL; | |
681 func_unref(fc->func->uf_name); | |
682 } | |
683 } | |
684 ga_clear(&fc->fc_funcs); | |
665 | 685 |
666 /* The a: variables typevals may not have been allocated, only free the | 686 /* The a: variables typevals may not have been allocated, only free the |
667 * allocated variables. */ | 687 * allocated variables. */ |
668 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); | 688 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); |
669 | 689 |
672 | 692 |
673 /* Free the a:000 variables if they were allocated. */ | 693 /* Free the a:000 variables if they were allocated. */ |
674 if (free_val) | 694 if (free_val) |
675 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) | 695 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) |
676 clear_tv(&li->li_tv); | 696 clear_tv(&li->li_tv); |
677 | |
678 for (i = 0; i < fc->fc_funcs.ga_len; ++i) | |
679 { | |
680 ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i]; | |
681 | |
682 if (fp != NULL) | |
683 func_unref(fc->func->uf_name); | |
684 } | |
685 ga_clear(&fc->fc_funcs); | |
686 | 697 |
687 func_unref(fc->func->uf_name); | 698 func_unref(fc->func->uf_name); |
688 vim_free(fc); | 699 vim_free(fc); |
689 } | 700 } |
690 | 701 |
1044 | 1055 |
1045 did_emsg |= save_did_emsg; | 1056 did_emsg |= save_did_emsg; |
1046 current_funccal = fc->caller; | 1057 current_funccal = fc->caller; |
1047 --depth; | 1058 --depth; |
1048 | 1059 |
1049 /* If the a:000 list and the l: and a: dicts are not referenced we can | 1060 /* If the a:000 list and the l: and a: dicts are not referenced and there |
1050 * free the funccall_T and what's in it. */ | 1061 * is no closure using it, we can free the funccall_T and what's in it. */ |
1051 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT | 1062 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT |
1052 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT | 1063 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT |
1053 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT | 1064 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT |
1054 && fc->fc_refcount <= 0) | 1065 && fc->fc_refcount <= 0) |
1055 { | 1066 { |
1059 { | 1070 { |
1060 hashitem_T *hi; | 1071 hashitem_T *hi; |
1061 listitem_T *li; | 1072 listitem_T *li; |
1062 int todo; | 1073 int todo; |
1063 | 1074 |
1064 /* "fc" is still in use. This can happen when returning "a:000" or | 1075 /* "fc" is still in use. This can happen when returning "a:000", |
1065 * assigning "l:" to a global variable. | 1076 * assigning "l:" to a global variable or defining a closure. |
1066 * Link "fc" in the list for garbage collection later. */ | 1077 * Link "fc" in the list for garbage collection later. */ |
1067 fc->caller = previous_funccal; | 1078 fc->caller = previous_funccal; |
1068 previous_funccal = fc; | 1079 previous_funccal = fc; |
1069 | 1080 |
1070 /* Make a copy of the a: variables, since we didn't do that above. */ | 1081 /* Make a copy of the a: variables, since we didn't do that above. */ |
1119 if (!freed) | 1130 if (!freed) |
1120 { | 1131 { |
1121 func_unref(fc->func->uf_name); | 1132 func_unref(fc->func->uf_name); |
1122 | 1133 |
1123 if (fp != NULL) | 1134 if (fp != NULL) |
1124 { | |
1125 for (i = 0; i < fc->fc_funcs.ga_len; ++i) | 1135 for (i = 0; i < fc->fc_funcs.ga_len; ++i) |
1126 { | 1136 { |
1127 if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp) | 1137 if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp) |
1128 ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL; | 1138 ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL; |
1129 } | 1139 } |
1130 } | |
1131 } | 1140 } |
1132 } | 1141 } |
1133 | 1142 |
1134 /* | 1143 /* |
1135 * Free a function and remove it from the list of functions. | 1144 * Free a function and remove it from the list of functions. |
1974 } | 1983 } |
1975 else if (STRNCMP(p, "closure", 7) == 0) | 1984 else if (STRNCMP(p, "closure", 7) == 0) |
1976 { | 1985 { |
1977 flags |= FC_CLOSURE; | 1986 flags |= FC_CLOSURE; |
1978 p += 7; | 1987 p += 7; |
1988 if (current_funccal == NULL) | |
1989 { | |
1990 emsg_funcname(N_("E932 Closure function should not be at top level: %s"), | |
1991 name == NULL ? (char_u *)"" : name); | |
1992 goto erret; | |
1993 } | |
1979 } | 1994 } |
1980 else | 1995 else |
1981 break; | 1996 break; |
1982 } | 1997 } |
1983 | 1998 |
2263 EMSG2(_("E746: Function name does not match script file name: %s"), name); | 2278 EMSG2(_("E746: Function name does not match script file name: %s"), name); |
2264 goto erret; | 2279 goto erret; |
2265 } | 2280 } |
2266 } | 2281 } |
2267 | 2282 |
2268 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name))); | 2283 fp = (ufunc_T *)alloc_clear((unsigned)(sizeof(ufunc_T) + STRLEN(name))); |
2269 if (fp == NULL) | 2284 if (fp == NULL) |
2270 goto erret; | 2285 goto erret; |
2271 | 2286 |
2272 if (fudi.fd_dict != NULL) | 2287 if (fudi.fd_dict != NULL) |
2273 { | 2288 { |
2309 } | 2324 } |
2310 fp->uf_args = newargs; | 2325 fp->uf_args = newargs; |
2311 fp->uf_lines = newlines; | 2326 fp->uf_lines = newlines; |
2312 if ((flags & FC_CLOSURE) != 0) | 2327 if ((flags & FC_CLOSURE) != 0) |
2313 { | 2328 { |
2314 if (current_funccal == NULL) | 2329 ++fp->uf_refcount; |
2315 { | 2330 if (register_closure(fp) == FAIL) |
2316 emsg_funcname(N_("E932 Closure function should not be at top level: %s"), | |
2317 name); | |
2318 goto erret; | 2331 goto erret; |
2319 } | |
2320 fp->uf_scoped = current_funccal; | |
2321 current_funccal->fc_refcount++; | |
2322 if (ga_grow(¤t_funccal->fc_funcs, 1) == FAIL) | |
2323 goto erret; | |
2324 ((ufunc_T **)current_funccal->fc_funcs.ga_data) | |
2325 [current_funccal->fc_funcs.ga_len++] = fp; | |
2326 func_ref(current_funccal->func->uf_name); | |
2327 } | 2332 } |
2328 else | 2333 else |
2329 fp->uf_scoped = NULL; | 2334 fp->uf_scoped = NULL; |
2330 | 2335 |
2331 #ifdef FEAT_PROFILE | 2336 #ifdef FEAT_PROFILE |
3580 if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) | 3585 if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) |
3581 return NULL; | 3586 return NULL; |
3582 | 3587 |
3583 /* Search in parent scope which is possible to reference from lambda */ | 3588 /* Search in parent scope which is possible to reference from lambda */ |
3584 current_funccal = current_funccal->func->uf_scoped; | 3589 current_funccal = current_funccal->func->uf_scoped; |
3585 while (current_funccal) | 3590 while (current_funccal != NULL) |
3586 { | 3591 { |
3587 ht = find_var_ht(name, varname); | 3592 ht = find_var_ht(name, varname); |
3588 if (ht != NULL && **varname != NUL) | 3593 if (ht != NULL && **varname != NUL) |
3589 { | 3594 { |
3590 hi = hash_find(ht, *varname); | 3595 hi = hash_find(ht, *varname); |
3591 if (!HASHITEM_EMPTY(hi)) | 3596 if (!HASHITEM_EMPTY(hi)) |
3592 { | 3597 { |
3593 *pht = ht; | 3598 *pht = ht; |
3594 break; | 3599 break; |
3595 } | 3600 } |
3596 } | 3601 } |
3597 if (current_funccal == current_funccal->func->uf_scoped) | 3602 if (current_funccal == current_funccal->func->uf_scoped) |
3598 break; | 3603 break; |
3599 current_funccal = current_funccal->func->uf_scoped; | 3604 current_funccal = current_funccal->func->uf_scoped; |
3600 } | 3605 } |
3601 current_funccal = old_current_funccal; | 3606 current_funccal = old_current_funccal; |
3602 | 3607 |
3603 return hi; | 3608 return hi; |
3604 } | 3609 } |