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.