Mercurial > vim
comparison src/evalvars.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 | c225be44692a |
children | e6908750a122 |
comparison
equal
deleted
inserted
replaced
20527:37ac4c5b4d27 | 20528:489cb75c76b6 |
---|---|
162 #define vimvarht vimvardict.dv_hashtab | 162 #define vimvarht vimvardict.dv_hashtab |
163 | 163 |
164 // for VIM_VERSION_ defines | 164 // for VIM_VERSION_ defines |
165 #include "version.h" | 165 #include "version.h" |
166 | 166 |
167 static void ex_let_const(exarg_T *eap); | |
167 static char_u *skip_var_one(char_u *arg, int include_type); | 168 static char_u *skip_var_one(char_u *arg, int include_type); |
168 static void list_glob_vars(int *first); | 169 static void list_glob_vars(int *first); |
169 static void list_buf_vars(int *first); | 170 static void list_buf_vars(int *first); |
170 static void list_win_vars(int *first); | 171 static void list_win_vars(int *first); |
171 static void list_tab_vars(int *first); | 172 static void list_tab_vars(int *first); |
683 * ":let var: string" Vim9 declaration | 684 * ":let var: string" Vim9 declaration |
684 */ | 685 */ |
685 void | 686 void |
686 ex_let(exarg_T *eap) | 687 ex_let(exarg_T *eap) |
687 { | 688 { |
688 ex_let_const(eap, FALSE); | 689 ex_let_const(eap); |
689 } | 690 } |
690 | 691 |
691 /* | 692 /* |
692 * ":const" list all variable values | 693 * ":const" list all variable values |
693 * ":const var1 var2" list variable values | 694 * ":const var1 var2" list variable values |
695 * ":const [var1, var2] = expr" unpack list. | 696 * ":const [var1, var2] = expr" unpack list. |
696 */ | 697 */ |
697 void | 698 void |
698 ex_const(exarg_T *eap) | 699 ex_const(exarg_T *eap) |
699 { | 700 { |
700 ex_let_const(eap, FALSE); | 701 ex_let_const(eap); |
701 } | 702 } |
702 | 703 |
703 /* | 704 static void |
704 * When "discovery" is TRUE the ":let" or ":const" is encountered during the | 705 ex_let_const(exarg_T *eap) |
705 * discovery phase of vim9script: | |
706 * - The command will be executed again, redefining the variable is OK then. | |
707 * - The expresion argument must be a constant. | |
708 * - If no constant expression a type must be specified. | |
709 */ | |
710 void | |
711 ex_let_const(exarg_T *eap, int discovery) | |
712 { | 706 { |
713 char_u *arg = eap->arg; | 707 char_u *arg = eap->arg; |
714 char_u *expr = NULL; | 708 char_u *expr = NULL; |
715 typval_T rettv; | 709 typval_T rettv; |
716 int i; | 710 int i; |
724 int flags = eap->cmdidx == CMD_const ? LET_IS_CONST : 0; | 718 int flags = eap->cmdidx == CMD_const ? LET_IS_CONST : 0; |
725 | 719 |
726 // detect Vim9 assignment without ":let" or ":const" | 720 // detect Vim9 assignment without ":let" or ":const" |
727 if (eap->arg == eap->cmd) | 721 if (eap->arg == eap->cmd) |
728 flags |= LET_NO_COMMAND; | 722 flags |= LET_NO_COMMAND; |
729 if (discovery) | |
730 flags |= LET_DISCOVERY; | |
731 | 723 |
732 argend = skip_var_list(arg, TRUE, &var_count, &semicolon); | 724 argend = skip_var_list(arg, TRUE, &var_count, &semicolon); |
733 if (argend == NULL) | 725 if (argend == NULL) |
734 return; | 726 return; |
735 if (argend > arg && argend[-1] == '.') // for var.='str' | 727 if (argend > arg && argend[-1] == '.') // for var.='str' |
738 concat = expr[0] == '.' | 730 concat = expr[0] == '.' |
739 && ((expr[1] == '=' && current_sctx.sc_version < 2) | 731 && ((expr[1] == '=' && current_sctx.sc_version < 2) |
740 || (expr[1] == '.' && expr[2] == '=')); | 732 || (expr[1] == '.' && expr[2] == '=')); |
741 has_assign = *expr == '=' || (vim_strchr((char_u *)"+-*/%", *expr) != NULL | 733 has_assign = *expr == '=' || (vim_strchr((char_u *)"+-*/%", *expr) != NULL |
742 && expr[1] == '='); | 734 && expr[1] == '='); |
743 if (!has_assign && !concat && !discovery) | 735 if (!has_assign && !concat) |
744 { | 736 { |
745 // ":let" without "=": list variables | 737 // ":let" without "=": list variables |
746 if (*arg == '[') | 738 if (*arg == '[') |
747 emsg(_(e_invarg)); | 739 emsg(_(e_invarg)); |
748 else if (expr[0] == '.') | 740 else if (expr[0] == '.') |
807 expr = skipwhite(expr + 1); | 799 expr = skipwhite(expr + 1); |
808 | 800 |
809 if (eap->skip) | 801 if (eap->skip) |
810 ++emsg_skip; | 802 ++emsg_skip; |
811 eval_flags = eap->skip ? 0 : EVAL_EVALUATE; | 803 eval_flags = eap->skip ? 0 : EVAL_EVALUATE; |
812 if (discovery) | |
813 eval_flags |= EVAL_CONSTANT; | |
814 i = eval0(expr, &rettv, &eap->nextcmd, eval_flags); | 804 i = eval0(expr, &rettv, &eap->nextcmd, eval_flags); |
815 } | 805 } |
816 if (eap->skip) | 806 if (eap->skip) |
817 { | 807 { |
818 if (i != FAIL) | 808 if (i != FAIL) |
819 clear_tv(&rettv); | 809 clear_tv(&rettv); |
820 --emsg_skip; | 810 --emsg_skip; |
821 } | 811 } |
822 else if (i != FAIL || (discovery && save_called_emsg == called_emsg)) | 812 else if (i != FAIL) |
823 { | 813 { |
824 // In Vim9 script discovery "let v: bool = Func()" fails but is | |
825 // still a valid declaration. | |
826 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, | 814 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, |
827 flags, op); | 815 flags, op); |
828 clear_tv(&rettv); | 816 clear_tv(&rettv); |
829 } | 817 } |
830 } | 818 } |
1369 else if (eval_isnamec1(*arg) || *arg == '{') | 1357 else if (eval_isnamec1(*arg) || *arg == '{') |
1370 { | 1358 { |
1371 lval_T lv; | 1359 lval_T lv; |
1372 | 1360 |
1373 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START); | 1361 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START); |
1374 if ((flags & LET_DISCOVERY) && tv->v_type == VAR_UNKNOWN | 1362 if (p != NULL && lv.ll_name != NULL) |
1375 && lv.ll_type == NULL) | |
1376 { | |
1377 semsg(_("E1091: type missing for %s"), arg); | |
1378 } | |
1379 else if (p != NULL && lv.ll_name != NULL) | |
1380 { | 1363 { |
1381 if (endchars != NULL && vim_strchr(endchars, | 1364 if (endchars != NULL && vim_strchr(endchars, |
1382 *skipwhite(lv.ll_name_end)) == NULL) | 1365 *skipwhite(lv.ll_name_end)) == NULL) |
1383 emsg(_(e_letunexp)); | 1366 emsg(_(e_letunexp)); |
1384 else | 1367 else |
2619 if (*name == 't') // tab page variable | 2602 if (*name == 't') // tab page variable |
2620 return &curtab->tp_vars->dv_hashtab; | 2603 return &curtab->tp_vars->dv_hashtab; |
2621 if (*name == 'v') // v: variable | 2604 if (*name == 'v') // v: variable |
2622 return &vimvarht; | 2605 return &vimvarht; |
2623 if (get_current_funccal() != NULL | 2606 if (get_current_funccal() != NULL |
2624 && get_current_funccal()->func->uf_dfunc_idx < 0) | 2607 && get_current_funccal()->func->uf_dfunc_idx == UF_NOT_COMPILED) |
2625 { | 2608 { |
2626 // a: and l: are only used in functions defined with ":function" | 2609 // a: and l: are only used in functions defined with ":function" |
2627 if (*name == 'a') // a: function argument | 2610 if (*name == 'a') // a: function argument |
2628 return get_funccal_args_ht(); | 2611 return get_funccal_args_ht(); |
2629 if (*name == 'l') // l: local function variable | 2612 if (*name == 'l') // l: local function variable |
3002 init_tv(tv); | 2985 init_tv(tv); |
3003 } | 2986 } |
3004 | 2987 |
3005 if (flags & LET_IS_CONST) | 2988 if (flags & LET_IS_CONST) |
3006 di->di_tv.v_lock |= VAR_LOCKED; | 2989 di->di_tv.v_lock |= VAR_LOCKED; |
3007 if (flags & LET_DISCOVERY) | |
3008 di->di_flags |= DI_FLAGS_RELOAD; | |
3009 } | 2990 } |
3010 | 2991 |
3011 /* | 2992 /* |
3012 * Return TRUE if di_flags "flags" indicates variable "name" is read-only. | 2993 * Return TRUE if di_flags "flags" indicates variable "name" is read-only. |
3013 * Also give an error message. | 2994 * Also give an error message. |