Mirror of the Vim source from https://github.com/vim/vim
Revision | 9f921ba86d05609d0cd45d2304c86dd2ef414eaf (tree) |
---|---|
Zeit | 2020-05-26 05:45:03 |
Autor | Bram Moolenaar <Bram@vim....> |
Commiter | Bram Moolenaar |
patch 8.2.0823: Vim9: script reload test is disabled
Commit: https://github.com/vim/vim/commit/25e0f5863e9010a75a1ff0d04e8f886403968755
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon May 25 22:36:50 2020 +0200
@@ -634,8 +634,8 @@ | ||
634 | 634 | int *dbg_tick = NULL; // ptr to dbg_tick field in cookie |
635 | 635 | struct dbg_stuff debug_saved; // saved things for debug mode |
636 | 636 | int initial_trylevel; |
637 | - struct msglist **saved_msg_list = NULL; | |
638 | - struct msglist *private_msg_list; | |
637 | + msglist_T **saved_msg_list = NULL; | |
638 | + msglist_T *private_msg_list; | |
639 | 639 | |
640 | 640 | // "fgetline" and "cookie" passed to do_one_cmd() |
641 | 641 | char_u *(*cmd_getline)(int, void *, int, int); |
@@ -1238,7 +1238,7 @@ | ||
1238 | 1238 | if (did_throw) |
1239 | 1239 | { |
1240 | 1240 | void *p = NULL; |
1241 | - struct msglist *messages = NULL, *next; | |
1241 | + msglist_T *messages = NULL, *next; | |
1242 | 1242 | |
1243 | 1243 | /* |
1244 | 1244 | * If the uncaught exception is a user exception, report it as an |
@@ -146,8 +146,8 @@ | ||
146 | 146 | int severe, |
147 | 147 | int *ignore) |
148 | 148 | { |
149 | - struct msglist *elem; | |
150 | - struct msglist **plist; | |
149 | + msglist_T *elem; | |
150 | + msglist_T **plist; | |
151 | 151 | |
152 | 152 | /* |
153 | 153 | * Do nothing when displaying the interrupt message or reporting an |
@@ -251,7 +251,7 @@ | ||
251 | 251 | while (*plist != NULL) |
252 | 252 | plist = &(*plist)->next; |
253 | 253 | |
254 | - elem = ALLOC_ONE(struct msglist); | |
254 | + elem = ALLOC_CLEAR_ONE(msglist_T); | |
255 | 255 | if (elem == NULL) |
256 | 256 | { |
257 | 257 | suppress_errthrow = TRUE; |
@@ -287,6 +287,11 @@ | ||
287 | 287 | else |
288 | 288 | (*msg_list)->throw_msg = tmsg; |
289 | 289 | } |
290 | + | |
291 | + // Get the source name and lnum now, it may change before | |
292 | + // reaching do_errthrow(). | |
293 | + elem->sfile = estack_sfile(); | |
294 | + elem->slnum = SOURCING_LNUM; | |
290 | 295 | } |
291 | 296 | } |
292 | 297 | } |
@@ -298,15 +303,16 @@ | ||
298 | 303 | * Free a "msg_list" and the messages it contains. |
299 | 304 | */ |
300 | 305 | static void |
301 | -free_msglist(struct msglist *l) | |
306 | +free_msglist(msglist_T *l) | |
302 | 307 | { |
303 | - struct msglist *messages, *next; | |
308 | + msglist_T *messages, *next; | |
304 | 309 | |
305 | 310 | messages = l; |
306 | 311 | while (messages != NULL) |
307 | 312 | { |
308 | 313 | next = messages->next; |
309 | 314 | vim_free(messages->msg); |
315 | + vim_free(messages->sfile); | |
310 | 316 | vim_free(messages); |
311 | 317 | messages = next; |
312 | 318 | } |
@@ -428,7 +434,7 @@ | ||
428 | 434 | if (type == ET_ERROR) |
429 | 435 | { |
430 | 436 | *should_free = TRUE; |
431 | - mesg = ((struct msglist *)value)->throw_msg; | |
437 | + mesg = ((msglist_T *)value)->throw_msg; | |
432 | 438 | if (cmdname != NULL && *cmdname != NUL) |
433 | 439 | { |
434 | 440 | cmdlen = (int)STRLEN(cmdname); |
@@ -526,23 +532,34 @@ | ||
526 | 532 | if (type == ET_ERROR) |
527 | 533 | // Store the original message and prefix the exception value with |
528 | 534 | // "Vim:" or, if a command name is given, "Vim(cmdname):". |
529 | - excp->messages = (struct msglist *)value; | |
535 | + excp->messages = (msglist_T *)value; | |
530 | 536 | |
531 | 537 | excp->value = get_exception_string(value, type, cmdname, &should_free); |
532 | 538 | if (excp->value == NULL && should_free) |
533 | 539 | goto nomem; |
534 | 540 | |
535 | 541 | excp->type = type; |
536 | - excp->throw_name = estack_sfile(); | |
537 | - if (excp->throw_name == NULL) | |
538 | - excp->throw_name = vim_strsave((char_u *)""); | |
539 | - if (excp->throw_name == NULL) | |
542 | + if (type == ET_ERROR && ((msglist_T *)value)->sfile != NULL) | |
540 | 543 | { |
541 | - if (should_free) | |
542 | - vim_free(excp->value); | |
543 | - goto nomem; | |
544 | + msglist_T *entry = (msglist_T *)value; | |
545 | + | |
546 | + excp->throw_name = entry->sfile; | |
547 | + entry->sfile = NULL; | |
548 | + excp->throw_lnum = entry->slnum; | |
544 | 549 | } |
545 | - excp->throw_lnum = SOURCING_LNUM; | |
550 | + else | |
551 | + { | |
552 | + excp->throw_name = estack_sfile(); | |
553 | + if (excp->throw_name == NULL) | |
554 | + excp->throw_name = vim_strsave((char_u *)""); | |
555 | + if (excp->throw_name == NULL) | |
556 | + { | |
557 | + if (should_free) | |
558 | + vim_free(excp->value); | |
559 | + goto nomem; | |
560 | + } | |
561 | + excp->throw_lnum = SOURCING_LNUM; | |
562 | + } | |
546 | 563 | |
547 | 564 | if (p_verbose >= 13 || debug_break_level > 0) |
548 | 565 | { |
@@ -344,7 +344,7 @@ | ||
344 | 344 | * field of a later list element, when the "emsg_severe" flag was set when the |
345 | 345 | * emsg() call was made. |
346 | 346 | */ |
347 | -EXTERN struct msglist **msg_list INIT(= NULL); | |
347 | +EXTERN msglist_T **msg_list INIT(= NULL); | |
348 | 348 | |
349 | 349 | /* |
350 | 350 | * suppress_errthrow: When TRUE, don't convert an error to an exception. Used |
@@ -1,7 +1,8 @@ | ||
1 | 1 | /* scriptfile.c */ |
2 | 2 | void estack_init(void); |
3 | 3 | estack_T *estack_push(etype_T type, char_u *name, long lnum); |
4 | -void estack_push_ufunc(etype_T type, ufunc_T *ufunc, long lnum); | |
4 | +void estack_push_ufunc(ufunc_T *ufunc, long lnum); | |
5 | +int estack_top_is_ufunc(ufunc_T *ufunc, long lnum); | |
5 | 6 | void estack_pop(void); |
6 | 7 | char_u *estack_sfile(void); |
7 | 8 | void ex_runtime(exarg_T *eap); |
@@ -69,14 +69,31 @@ | ||
69 | 69 | * Add a user function to the execution stack. |
70 | 70 | */ |
71 | 71 | void |
72 | -estack_push_ufunc(etype_T type, ufunc_T *ufunc, long lnum) | |
72 | +estack_push_ufunc(ufunc_T *ufunc, long lnum) | |
73 | 73 | { |
74 | - estack_T *entry = estack_push(type, | |
74 | + estack_T *entry = estack_push(ETYPE_UFUNC, | |
75 | 75 | ufunc->uf_name_exp != NULL |
76 | 76 | ? ufunc->uf_name_exp : ufunc->uf_name, lnum); |
77 | 77 | if (entry != NULL) |
78 | 78 | entry->es_info.ufunc = ufunc; |
79 | 79 | } |
80 | + | |
81 | +/* | |
82 | + * Return TRUE if "ufunc" with "lnum" is already at the top of the exe stack. | |
83 | + */ | |
84 | + int | |
85 | +estack_top_is_ufunc(ufunc_T *ufunc, long lnum) | |
86 | +{ | |
87 | + estack_T *entry; | |
88 | + | |
89 | + if (exestack.ga_len == 0) | |
90 | + return FALSE; | |
91 | + entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; | |
92 | + return entry->es_type == ETYPE_UFUNC | |
93 | + && STRCMP( entry->es_name, ufunc->uf_name_exp != NULL | |
94 | + ? ufunc->uf_name_exp : ufunc->uf_name) == 0 | |
95 | + && entry->es_lnum == lnum; | |
96 | +} | |
80 | 97 | #endif |
81 | 98 | |
82 | 99 | /* |
@@ -927,13 +927,16 @@ | ||
927 | 927 | * A list of error messages that can be converted to an exception. "throw_msg" |
928 | 928 | * is only set in the first element of the list. Usually, it points to the |
929 | 929 | * original message stored in that element, but sometimes it points to a later |
930 | - * message in the list. See cause_errthrow() below. | |
930 | + * message in the list. See cause_errthrow(). | |
931 | 931 | */ |
932 | +typedef struct msglist msglist_T; | |
932 | 933 | struct msglist |
933 | 934 | { |
934 | - char *msg; // original message | |
935 | - char *throw_msg; // msg to throw: usually original one | |
936 | - struct msglist *next; // next of several messages in a row | |
935 | + char *msg; // original message, allocated | |
936 | + char *throw_msg; // msg to throw: usually original one | |
937 | + char_u *sfile; // value from estack_sfile(), allocated | |
938 | + long slnum; // line number for "sfile" | |
939 | + msglist_T *next; // next of several messages in a row | |
937 | 940 | }; |
938 | 941 | |
939 | 942 | /* |
@@ -1516,6 +1519,7 @@ | ||
1516 | 1519 | #if defined(FEAT_EVAL) || defined(PROTO) |
1517 | 1520 | typedef struct funccall_S funccall_T; |
1518 | 1521 | |
1522 | +// values used for "uf_dfunc_idx" | |
1519 | 1523 | # define UF_NOT_COMPILED -2 |
1520 | 1524 | # define UF_TO_BE_COMPILED -1 |
1521 | 1525 |
@@ -745,9 +745,6 @@ | ||
745 | 745 | enddef |
746 | 746 | |
747 | 747 | def Test_vim9script_reload_import() |
748 | - " TODO: make it work to compile when not in the script context anymore | |
749 | - return | |
750 | - | |
751 | 748 | let lines =<< trim END |
752 | 749 | vim9script |
753 | 750 | const var = '' |
@@ -797,9 +794,6 @@ | ||
797 | 794 | enddef |
798 | 795 | |
799 | 796 | def Test_vim9script_reload_delfunc() |
800 | - " TODO: make it work to compile when not in the script context anymore | |
801 | - return | |
802 | - | |
803 | 797 | let first_lines =<< trim END |
804 | 798 | vim9script |
805 | 799 | def FuncYes(): string |
@@ -920,6 +914,37 @@ | ||
920 | 914 | delete('import', 'rf') |
921 | 915 | enddef |
922 | 916 | |
917 | +def Test_import_compile_error() | |
918 | + let export_lines = [ | |
919 | + 'vim9script', | |
920 | + 'export def ExpFunc(): string', | |
921 | + ' return notDefined', | |
922 | + 'enddef', | |
923 | + ] | |
924 | + writefile(export_lines, 'Xexported.vim') | |
925 | + | |
926 | + let import_lines = [ | |
927 | + 'vim9script', | |
928 | + 'import ExpFunc from "./Xexported.vim"', | |
929 | + 'def ImpFunc()', | |
930 | + ' echo ExpFunc()', | |
931 | + 'enddef', | |
932 | + 'defcompile', | |
933 | + ] | |
934 | + writefile(import_lines, 'Ximport.vim') | |
935 | + | |
936 | + try | |
937 | + source Ximport.vim | |
938 | + catch /E1001/ | |
939 | + " Error should be fore the Xexported.vim file. | |
940 | + assert_match('E1001: variable not found: notDefined', v:exception) | |
941 | + assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint) | |
942 | + endtry | |
943 | + | |
944 | + delete('Xexported.vim') | |
945 | + delete('Ximport.vim') | |
946 | +enddef | |
947 | + | |
923 | 948 | def Test_fixed_size_list() |
924 | 949 | " will be allocated as one piece of memory, check that changes work |
925 | 950 | let l = [1, 2, 3, 4] |
@@ -1114,11 +1114,11 @@ | ||
1114 | 1114 | |
1115 | 1115 | if (fp->uf_dfunc_idx != UF_NOT_COMPILED) |
1116 | 1116 | { |
1117 | - estack_push_ufunc(ETYPE_UFUNC, fp, 1); | |
1117 | + estack_push_ufunc(fp, 1); | |
1118 | 1118 | save_current_sctx = current_sctx; |
1119 | 1119 | current_sctx = fp->uf_script_ctx; |
1120 | 1120 | |
1121 | - // Execute the compiled function. | |
1121 | + // Execute the function, possibly compiling it first. | |
1122 | 1122 | call_def_function(fp, argcount, argvars, funcexe->partial, rettv); |
1123 | 1123 | --depth; |
1124 | 1124 | current_funccal = fc->caller; |
@@ -1288,7 +1288,7 @@ | ||
1288 | 1288 | ++sandbox; |
1289 | 1289 | } |
1290 | 1290 | |
1291 | - estack_push_ufunc(ETYPE_UFUNC, fp, 1); | |
1291 | + estack_push_ufunc(fp, 1); | |
1292 | 1292 | ESTACK_CHECK_SETUP |
1293 | 1293 | if (p_verbose >= 12) |
1294 | 1294 | { |
@@ -747,6 +747,8 @@ | ||
747 | 747 | static int included_patches[] = |
748 | 748 | { /* Add new patch number below this line */ |
749 | 749 | /**/ |
750 | + 823, | |
751 | +/**/ | |
750 | 752 | 822, |
751 | 753 | /**/ |
752 | 754 | 821, |
@@ -2323,8 +2323,7 @@ | ||
2323 | 2323 | } |
2324 | 2324 | line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]; |
2325 | 2325 | cctx->ctx_line_start = line; |
2326 | - SOURCING_LNUM = cctx->ctx_ufunc->uf_script_ctx.sc_lnum | |
2327 | - + cctx->ctx_lnum + 1; | |
2326 | + SOURCING_LNUM = cctx->ctx_lnum + 1; | |
2328 | 2327 | } while (line == NULL || *skipwhite(line) == NUL); |
2329 | 2328 | return line; |
2330 | 2329 | } |
@@ -6349,14 +6348,15 @@ | ||
6349 | 6348 | int called_emsg_before = called_emsg; |
6350 | 6349 | int ret = FAIL; |
6351 | 6350 | sctx_T save_current_sctx = current_sctx; |
6351 | + int do_estack_push; | |
6352 | 6352 | int emsg_before = called_emsg; |
6353 | 6353 | |
6354 | + // When using a function that was compiled before: Free old instructions. | |
6355 | + // Otherwise add a new entry in "def_functions". | |
6354 | 6356 | if (ufunc->uf_dfunc_idx >= 0) |
6355 | 6357 | { |
6356 | - // Redefining a function that was compiled before. | |
6357 | 6358 | dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) |
6358 | 6359 | + ufunc->uf_dfunc_idx; |
6359 | - // Free old instructions. | |
6360 | 6360 | delete_def_function_contents(dfunc); |
6361 | 6361 | } |
6362 | 6362 | else if (add_def_function(ufunc) == FAIL) |
@@ -6373,9 +6373,17 @@ | ||
6373 | 6373 | ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50); |
6374 | 6374 | instr = &cctx.ctx_instr; |
6375 | 6375 | |
6376 | - // Most modern script version. | |
6376 | + // Set the context to the function, it may be compiled when called from | |
6377 | + // another script. Set the script version to the most modern one. | |
6378 | + // The line number will be set in next_line_from_context(). | |
6379 | + current_sctx = ufunc->uf_script_ctx; | |
6377 | 6380 | current_sctx.sc_version = SCRIPT_VERSION_VIM9; |
6378 | 6381 | |
6382 | + // Make sure error messages are OK. | |
6383 | + do_estack_push = !estack_top_is_ufunc(ufunc, 1); | |
6384 | + if (do_estack_push) | |
6385 | + estack_push_ufunc(ufunc, 1); | |
6386 | + | |
6379 | 6387 | if (ufunc->uf_def_args.ga_len > 0) |
6380 | 6388 | { |
6381 | 6389 | int count = ufunc->uf_def_args.ga_len; |
@@ -6795,6 +6803,9 @@ | ||
6795 | 6803 | } |
6796 | 6804 | |
6797 | 6805 | current_sctx = save_current_sctx; |
6806 | + if (do_estack_push) | |
6807 | + estack_pop(); | |
6808 | + | |
6798 | 6809 | free_imported(&cctx); |
6799 | 6810 | free_locals(&cctx); |
6800 | 6811 | ga_clear(&cctx.ctx_type_stack); |
@@ -230,7 +230,7 @@ | ||
230 | 230 | // Set execution state to the start of the called function. |
231 | 231 | ectx->ec_dfunc_idx = cdf_idx; |
232 | 232 | ectx->ec_instr = dfunc->df_instr; |
233 | - estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1); | |
233 | + estack_push_ufunc(dfunc->df_ufunc, 1); | |
234 | 234 | |
235 | 235 | // Decide where to start execution, handles optional arguments. |
236 | 236 | init_instr_idx(ufunc, argcount, ectx); |
@@ -656,6 +656,7 @@ | ||
656 | 656 | int defcount = ufunc->uf_args.ga_len - argc; |
657 | 657 | int save_sc_version = current_sctx.sc_version; |
658 | 658 | int breakcheck_count = 0; |
659 | + int called_emsg_before = called_emsg; | |
659 | 660 | |
660 | 661 | // Get pointer to item in the stack. |
661 | 662 | #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) |
@@ -673,7 +674,13 @@ | ||
673 | 674 | if (ufunc->uf_dfunc_idx == UF_NOT_COMPILED |
674 | 675 | || (ufunc->uf_dfunc_idx == UF_TO_BE_COMPILED |
675 | 676 | && compile_def_function(ufunc, FALSE, NULL) == FAIL)) |
677 | + { | |
678 | + if (called_emsg == called_emsg_before) | |
679 | + semsg(_("E1091: Function is not compiled: %s"), | |
680 | + ufunc->uf_name_exp == NULL | |
681 | + ? ufunc->uf_name : ufunc->uf_name_exp); | |
676 | 682 | return FAIL; |
683 | + } | |
677 | 684 | |
678 | 685 | { |
679 | 686 | // Check the function was really compiled. |