comparison src/vim9script.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 7fb80f486aad
children 9faab49c880f
comparison
equal deleted inserted replaced
20527:37ac4c5b4d27 20528:489cb75c76b6
31 */ 31 */
32 void 32 void
33 ex_vim9script(exarg_T *eap) 33 ex_vim9script(exarg_T *eap)
34 { 34 {
35 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 35 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
36 garray_T *gap;
37 garray_T func_ga;
38 int idx;
39 ufunc_T *ufunc;
40 int start_called_emsg = called_emsg;
41 36
42 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 37 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
43 { 38 {
44 emsg(_("E1038: vim9script can only be used in a script")); 39 emsg(_("E1038: vim9script can only be used in a script"));
45 return; 40 return;
50 return; 45 return;
51 } 46 }
52 current_sctx.sc_version = SCRIPT_VERSION_VIM9; 47 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
53 si->sn_version = SCRIPT_VERSION_VIM9; 48 si->sn_version = SCRIPT_VERSION_VIM9;
54 si->sn_had_command = TRUE; 49 si->sn_had_command = TRUE;
55 ga_init2(&func_ga, sizeof(ufunc_T *), 20);
56 50
57 if (STRCMP(p_cpo, CPO_VIM) != 0) 51 if (STRCMP(p_cpo, CPO_VIM) != 0)
58 { 52 {
59 si->sn_save_cpo = p_cpo; 53 si->sn_save_cpo = p_cpo;
60 p_cpo = vim_strsave((char_u *)CPO_VIM); 54 p_cpo = vim_strsave((char_u *)CPO_VIM);
61 }
62
63 // Make a pass through the script to find:
64 // - function declarations
65 // - variable and constant declarations
66 // - imports
67 // The types are recognized, so that they can be used when compiling a
68 // function.
69 gap = source_get_line_ga(eap->cookie);
70 while (called_emsg == start_called_emsg)
71 {
72 char_u *line;
73 char_u *p;
74
75 if (ga_grow(gap, 1) == FAIL)
76 return;
77 line = eap->getline(':', eap->cookie, 0, TRUE);
78 if (line == NULL)
79 break;
80 ((char_u **)(gap->ga_data))[gap->ga_len++] = line;
81 line = skipwhite(line);
82 p = line;
83 if (checkforcmd(&p, "function", 2) || checkforcmd(&p, "def", 3))
84 {
85 int lnum_start = SOURCING_LNUM - 1;
86
87 if (*p == '!')
88 {
89 emsg(_(e_nobang));
90 break;
91 }
92
93 // Handle :function and :def by calling def_function().
94 // It will read upto the matching :endded or :endfunction.
95 eap->cmdidx = *line == 'f' ? CMD_function : CMD_def;
96 eap->cmd = line;
97 eap->arg = p;
98 eap->forceit = FALSE;
99 ufunc = def_function(eap, NULL, NULL, FALSE);
100
101 if (ufunc != NULL && *line == 'd' && ga_grow(&func_ga, 1) == OK)
102 {
103 // Add the function to the list of :def functions, so that it
104 // can be referenced by index. It's compiled below.
105 add_def_function(ufunc);
106 ((ufunc_T **)(func_ga.ga_data))[func_ga.ga_len++] = ufunc;
107 }
108
109 // Store empty lines in place of the function, we don't need to
110 // process it again.
111 vim_free(((char_u **)(gap->ga_data))[--gap->ga_len]);
112 if (ga_grow(gap, SOURCING_LNUM - lnum_start) == OK)
113 while (lnum_start < SOURCING_LNUM)
114 {
115 // getsourceline() will skip over NULL lines.
116 ((char_u **)(gap->ga_data))[gap->ga_len++] = NULL;
117 ++lnum_start;
118 }
119 }
120 else if (checkforcmd(&p, "let", 3) || checkforcmd(&p, "const", 4))
121 {
122 eap->cmd = line;
123 eap->arg = p;
124 eap->forceit = FALSE;
125 eap->cmdidx = *line == 'l' ? CMD_let: CMD_const;
126
127 // The command will be executed again, it's OK to redefine the
128 // variable then.
129 ex_let_const(eap, TRUE);
130 }
131 else if (checkforcmd(&p, "import", 3))
132 {
133 eap->arg = p;
134 ex_import(eap);
135
136 // Store empty line, we don't need to process the command again.
137 vim_free(((char_u **)(gap->ga_data))[--gap->ga_len]);
138 ((char_u **)(gap->ga_data))[gap->ga_len++] = NULL;
139 }
140 else if (checkforcmd(&p, "finish", 4))
141 {
142 break;
143 }
144 }
145
146 // Compile the :def functions.
147 for (idx = 0; idx < func_ga.ga_len && called_emsg == start_called_emsg; ++idx)
148 {
149 ufunc = ((ufunc_T **)(func_ga.ga_data))[idx];
150 compile_def_function(ufunc, FALSE, NULL);
151 }
152 ga_clear(&func_ga);
153
154 if (called_emsg == start_called_emsg)
155 {
156 // Return to process the commands at the script level.
157 source_use_line_ga(eap->cookie);
158 }
159 else
160 {
161 // If there was an error in the first or second phase then don't
162 // execute the script lines.
163 do_finish(eap, FALSE);
164 } 55 }
165 } 56 }
166 57
167 /* 58 /*
168 * ":export let Name: type" 59 * ":export let Name: type"