Mercurial > vim
comparison src/userfunc.c @ 20528:489cb75c76b6 v8.2.0818
patch 8.2.0818: Vim9: using a discovery phase doesn't work well
Commit: https://github.com/vim/vim/commit/822ba24743af9ee1b5e7f656a7a61a38f3638bca
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun May 24 23:00:18 2020 +0200
patch 8.2.0818: Vim9: using a discovery phase doesn't work well
Problem: Vim9: using a discovery phase doesn't work well.
Solution: Remove the discovery phase, instead compile a function only when
it is used. Add :defcompile to compile def functions earlier.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 24 May 2020 23:15:04 +0200 |
parents | 5950284a517f |
children | cb4831fa7e25 |
comparison
equal
deleted
inserted
replaced
20527:37ac4c5b4d27 | 20528:489cb75c76b6 |
---|---|
407 char_u *name = get_lambda_name(); | 407 char_u *name = get_lambda_name(); |
408 | 408 |
409 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); | 409 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); |
410 if (fp == NULL) | 410 if (fp == NULL) |
411 goto errret; | 411 goto errret; |
412 fp->uf_dfunc_idx = -1; | 412 fp->uf_dfunc_idx = UF_NOT_COMPILED; |
413 pt = ALLOC_CLEAR_ONE(partial_T); | 413 pt = ALLOC_CLEAR_ONE(partial_T); |
414 if (pt == NULL) | 414 if (pt == NULL) |
415 goto errret; | 415 goto errret; |
416 | 416 |
417 ga_init2(&newlines, (int)sizeof(char_u *), 1); | 417 ga_init2(&newlines, (int)sizeof(char_u *), 1); |
1110 fc->dbg_tick = debug_tick; | 1110 fc->dbg_tick = debug_tick; |
1111 // Set up fields for closure. | 1111 // Set up fields for closure. |
1112 ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1); | 1112 ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1); |
1113 func_ptr_ref(fp); | 1113 func_ptr_ref(fp); |
1114 | 1114 |
1115 if (fp->uf_dfunc_idx >= 0) | 1115 if (fp->uf_dfunc_idx != UF_NOT_COMPILED) |
1116 { | 1116 { |
1117 estack_push_ufunc(ETYPE_UFUNC, fp, 1); | 1117 estack_push_ufunc(ETYPE_UFUNC, fp, 1); |
1118 save_current_sctx = current_sctx; | 1118 save_current_sctx = current_sctx; |
1119 current_sctx = fp->uf_script_ctx; | 1119 current_sctx = fp->uf_script_ctx; |
1120 | 1120 |
1635 if (!HASHITEM_EMPTY(hi)) | 1635 if (!HASHITEM_EMPTY(hi)) |
1636 { | 1636 { |
1637 // clear the def function index now | 1637 // clear the def function index now |
1638 fp = HI2UF(hi); | 1638 fp = HI2UF(hi); |
1639 fp->uf_flags &= ~FC_DEAD; | 1639 fp->uf_flags &= ~FC_DEAD; |
1640 fp->uf_dfunc_idx = -1; | 1640 fp->uf_dfunc_idx = UF_NOT_COMPILED; |
1641 | 1641 |
1642 // Only free functions that are not refcounted, those are | 1642 // Only free functions that are not refcounted, those are |
1643 // supposed to be freed when no longer referenced. | 1643 // supposed to be freed when no longer referenced. |
1644 if (func_name_refcount(fp->uf_name)) | 1644 if (func_name_refcount(fp->uf_name)) |
1645 ++skipped; | 1645 ++skipped; |
2031 int j; | 2031 int j; |
2032 | 2032 |
2033 msg_start(); | 2033 msg_start(); |
2034 if (indent) | 2034 if (indent) |
2035 msg_puts(" "); | 2035 msg_puts(" "); |
2036 if (fp->uf_dfunc_idx >= 0) | 2036 if (fp->uf_dfunc_idx != UF_NOT_COMPILED) |
2037 msg_puts("def "); | 2037 msg_puts("def "); |
2038 else | 2038 else |
2039 msg_puts("function "); | 2039 msg_puts("function "); |
2040 msg_puts((char *)printable_func_name(fp)); | 2040 msg_puts((char *)printable_func_name(fp)); |
2041 msg_putchar('('); | 2041 msg_putchar('('); |
2080 vim_free(tofree); | 2080 vim_free(tofree); |
2081 } | 2081 } |
2082 } | 2082 } |
2083 msg_putchar(')'); | 2083 msg_putchar(')'); |
2084 | 2084 |
2085 if (fp->uf_dfunc_idx >= 0) | 2085 if (fp->uf_dfunc_idx != UF_NOT_COMPILED) |
2086 { | 2086 { |
2087 if (fp->uf_ret_type != &t_void) | 2087 if (fp->uf_ret_type != &t_void) |
2088 { | 2088 { |
2089 char *tofree; | 2089 char *tofree; |
2090 | 2090 |
2375 /* | 2375 /* |
2376 * ":function" also supporting nested ":def". | 2376 * ":function" also supporting nested ":def". |
2377 * Returns a pointer to the function or NULL if no function defined. | 2377 * Returns a pointer to the function or NULL if no function defined. |
2378 */ | 2378 */ |
2379 ufunc_T * | 2379 ufunc_T * |
2380 def_function(exarg_T *eap, char_u *name_arg, void *context, int compile) | 2380 def_function(exarg_T *eap, char_u *name_arg) |
2381 { | 2381 { |
2382 char_u *theline; | 2382 char_u *theline; |
2383 char_u *line_to_free = NULL; | 2383 char_u *line_to_free = NULL; |
2384 int j; | 2384 int j; |
2385 int c; | 2385 int c; |
2414 linenr_T sourcing_lnum_top; | 2414 linenr_T sourcing_lnum_top; |
2415 int is_heredoc = FALSE; | 2415 int is_heredoc = FALSE; |
2416 char_u *skip_until = NULL; | 2416 char_u *skip_until = NULL; |
2417 char_u *heredoc_trimmed = NULL; | 2417 char_u *heredoc_trimmed = NULL; |
2418 | 2418 |
2419 if (in_vim9script() && eap->forceit) | |
2420 { | |
2421 emsg(_(e_nobang)); | |
2422 return NULL; | |
2423 } | |
2424 | |
2419 /* | 2425 /* |
2420 * ":function" without argument: list functions. | 2426 * ":function" without argument: list functions. |
2421 */ | 2427 */ |
2422 if (ends_excmd2(eap->cmd, eap->arg)) | 2428 if (ends_excmd2(eap->cmd, eap->arg)) |
2423 { | 2429 { |
2582 ui_breakcheck(); | 2588 ui_breakcheck(); |
2583 } | 2589 } |
2584 if (!got_int) | 2590 if (!got_int) |
2585 { | 2591 { |
2586 msg_putchar('\n'); | 2592 msg_putchar('\n'); |
2587 if (fp->uf_dfunc_idx >= 0) | 2593 if (fp->uf_dfunc_idx != UF_NOT_COMPILED) |
2588 msg_puts(" enddef"); | 2594 msg_puts(" enddef"); |
2589 else | 2595 else |
2590 msg_puts(" endfunction"); | 2596 msg_puts(" endfunction"); |
2591 } | 2597 } |
2592 } | 2598 } |
3120 } | 3126 } |
3121 | 3127 |
3122 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); | 3128 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); |
3123 if (fp == NULL) | 3129 if (fp == NULL) |
3124 goto erret; | 3130 goto erret; |
3125 fp->uf_dfunc_idx = -1; | 3131 fp->uf_dfunc_idx = eap->cmdidx == CMD_def ? UF_TO_BE_COMPILED |
3132 : UF_NOT_COMPILED; | |
3126 | 3133 |
3127 if (fudi.fd_dict != NULL) | 3134 if (fudi.fd_dict != NULL) |
3128 { | 3135 { |
3129 if (fudi.fd_di == NULL) | 3136 if (fudi.fd_di == NULL) |
3130 { | 3137 { |
3172 fp->uf_func_type = &t_func_any; | 3179 fp->uf_func_type = &t_func_any; |
3173 | 3180 |
3174 if (eap->cmdidx == CMD_def) | 3181 if (eap->cmdidx == CMD_def) |
3175 { | 3182 { |
3176 int lnum_save = SOURCING_LNUM; | 3183 int lnum_save = SOURCING_LNUM; |
3184 | |
3185 fp->uf_dfunc_idx = UF_TO_BE_COMPILED; | |
3177 | 3186 |
3178 // error messages are for the first function line | 3187 // error messages are for the first function line |
3179 SOURCING_LNUM = sourcing_lnum_top; | 3188 SOURCING_LNUM = sourcing_lnum_top; |
3180 | 3189 |
3181 // parse the argument types | 3190 // parse the argument types |
3240 p = ret_type; | 3249 p = ret_type; |
3241 fp->uf_ret_type = parse_type(&p, &fp->uf_type_list); | 3250 fp->uf_ret_type = parse_type(&p, &fp->uf_type_list); |
3242 } | 3251 } |
3243 SOURCING_LNUM = lnum_save; | 3252 SOURCING_LNUM = lnum_save; |
3244 } | 3253 } |
3254 else | |
3255 fp->uf_dfunc_idx = UF_NOT_COMPILED; | |
3245 | 3256 |
3246 fp->uf_lines = newlines; | 3257 fp->uf_lines = newlines; |
3247 if ((flags & FC_CLOSURE) != 0) | 3258 if ((flags & FC_CLOSURE) != 0) |
3248 { | 3259 { |
3249 if (register_closure(fp) == FAIL) | 3260 if (register_closure(fp) == FAIL) |
3271 fp->uf_flags |= FC_EXPORT; | 3282 fp->uf_flags |= FC_EXPORT; |
3272 // let ex_export() know the export worked. | 3283 // let ex_export() know the export worked. |
3273 is_export = FALSE; | 3284 is_export = FALSE; |
3274 } | 3285 } |
3275 | 3286 |
3276 // ":def Func()" may need to be compiled | |
3277 if (eap->cmdidx == CMD_def && compile) | |
3278 compile_def_function(fp, FALSE, context); | |
3279 | |
3280 goto ret_free; | 3287 goto ret_free; |
3281 | 3288 |
3282 erret: | 3289 erret: |
3283 ga_clear_strings(&newargs); | 3290 ga_clear_strings(&newargs); |
3284 ga_clear_strings(&default_args); | 3291 ga_clear_strings(&default_args); |
3302 * ":function" | 3309 * ":function" |
3303 */ | 3310 */ |
3304 void | 3311 void |
3305 ex_function(exarg_T *eap) | 3312 ex_function(exarg_T *eap) |
3306 { | 3313 { |
3307 (void)def_function(eap, NULL, NULL, TRUE); | 3314 (void)def_function(eap, NULL); |
3315 } | |
3316 | |
3317 /* | |
3318 * :defcompile - compile all :def functions in the current script. | |
3319 */ | |
3320 void | |
3321 ex_defcompile(exarg_T *eap UNUSED) | |
3322 { | |
3323 int todo = (int)func_hashtab.ht_used; | |
3324 hashitem_T *hi; | |
3325 ufunc_T *ufunc; | |
3326 | |
3327 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) | |
3328 { | |
3329 if (!HASHITEM_EMPTY(hi)) | |
3330 { | |
3331 --todo; | |
3332 ufunc = HI2UF(hi); | |
3333 if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid | |
3334 && ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED) | |
3335 compile_def_function(ufunc, FALSE, NULL); | |
3336 } | |
3337 } | |
3308 } | 3338 } |
3309 | 3339 |
3310 /* | 3340 /* |
3311 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). | 3341 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). |
3312 * Return 2 if "p" starts with "s:". | 3342 * Return 2 if "p" starts with "s:". |