comparison src/vim9script.c @ 20339:7587d892c00c v8.2.0725

patch 8.2.0725: Vim9: cannot call a function declared later in Vim9 script Commit: https://github.com/vim/vim/commit/09689a02840be40fa7bb10b1921fb5bc5b2908f1 Author: Bram Moolenaar <Bram@vim.org> Date: Sat May 9 22:50:08 2020 +0200 patch 8.2.0725: Vim9: cannot call a function declared later in Vim9 script Problem: Vim9: cannot call a function declared later in Vim9 script. Solution: Make two passes through the script file.
author Bram Moolenaar <Bram@vim.org>
date Sat, 09 May 2020 23:00:04 +0200
parents 63cc54100ae4
children 680296770464
comparison
equal deleted inserted replaced
20338:ff4ae3f09307 20339:7587d892c00c
30 * ":vim9script". 30 * ":vim9script".
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;
36 40
37 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 41 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
38 { 42 {
39 emsg(_("E1038: vim9script can only be used in a script")); 43 emsg(_("E1038: vim9script can only be used in a script"));
40 return; 44 return;
45 return; 49 return;
46 } 50 }
47 current_sctx.sc_version = SCRIPT_VERSION_VIM9; 51 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
48 si->sn_version = SCRIPT_VERSION_VIM9; 52 si->sn_version = SCRIPT_VERSION_VIM9;
49 si->sn_had_command = TRUE; 53 si->sn_had_command = TRUE;
54 ga_init2(&func_ga, sizeof(ufunc_T *), 20);
50 55
51 if (STRCMP(p_cpo, CPO_VIM) != 0) 56 if (STRCMP(p_cpo, CPO_VIM) != 0)
52 { 57 {
53 si->sn_save_cpo = p_cpo; 58 si->sn_save_cpo = p_cpo;
54 p_cpo = vim_strsave((char_u *)CPO_VIM); 59 p_cpo = vim_strsave((char_u *)CPO_VIM);
55 } 60 }
61
62 // Make a pass through the script to find:
63 // - function declarations
64 // - variable and constant declarations
65 // - imports
66 // The types are recognized, so that they can be used when compiling a
67 // function.
68 gap = source_get_line_ga(eap->cookie);
69 for (;;)
70 {
71 char_u *line;
72 char_u *p;
73
74 if (ga_grow(gap, 1) == FAIL)
75 return;
76 line = eap->getline(':', eap->cookie, 0, TRUE);
77 if (line == NULL)
78 break;
79 ((char_u **)(gap->ga_data))[gap->ga_len++] = line;
80 line = skipwhite(line);
81 p = line;
82 if (checkforcmd(&p, "function", 2) || checkforcmd(&p, "def", 3))
83 {
84 int lnum_start = SOURCING_LNUM - 1;
85
86 // Handle :function and :def by calling def_function().
87 // It will read upto the matching :endded or :endfunction.
88 eap->cmdidx = *line == 'f' ? CMD_function : CMD_def;
89 eap->cmd = line;
90 eap->arg = p;
91 eap->forceit = FALSE;
92 ufunc = def_function(eap, NULL, NULL, FALSE);
93
94 if (ufunc != NULL && *line == 'd' && ga_grow(&func_ga, 1) == OK)
95 {
96 // Add the function to the list of :def functions, so that it
97 // can be referenced by index. It's compiled below.
98 add_def_function(ufunc);
99 ((ufunc_T **)(func_ga.ga_data))[func_ga.ga_len++] = ufunc;
100 }
101
102 // Store empty lines in place of the function, we don't need to
103 // process it again.
104 vim_free(((char_u **)(gap->ga_data))[--gap->ga_len]);
105 if (ga_grow(gap, SOURCING_LNUM - lnum_start) == OK)
106 while (lnum_start < SOURCING_LNUM)
107 {
108 // getsourceline() will skip over NULL lines.
109 ((char_u **)(gap->ga_data))[gap->ga_len++] = NULL;
110 ++lnum_start;
111 }
112 }
113 else if (checkforcmd(&p, "let", 3) || checkforcmd(&p, "const", 4))
114 {
115 eap->cmd = line;
116 eap->arg = p;
117 eap->forceit = FALSE;
118 eap->cmdidx = *line == 'l' ? CMD_let: CMD_const;
119
120 // The command will be executed again, it's OK to redefine the
121 // variable then.
122 ex_let_const(eap, TRUE);
123 }
124 else if (checkforcmd(&p, "import", 3))
125 {
126 eap->arg = p;
127 ex_import(eap);
128
129 // Store empty line, we don't need to process the command again.
130 vim_free(((char_u **)(gap->ga_data))[--gap->ga_len]);
131 ((char_u **)(gap->ga_data))[gap->ga_len++] = NULL;
132 }
133 }
134
135 // Compile the :def functions.
136 for (idx = 0; idx < func_ga.ga_len; ++idx)
137 {
138 ufunc = ((ufunc_T **)(func_ga.ga_data))[idx];
139 compile_def_function(ufunc, FALSE, NULL);
140 }
141 ga_clear(&func_ga);
142
143 // Return to process the commands at the script level.
144 source_use_line_ga(eap->cookie);
56 } 145 }
57 146
58 /* 147 /*
59 * ":export let Name: type" 148 * ":export let Name: type"
60 * ":export const Name: type" 149 * ":export const Name: type"
62 * ":export class Name ..." 151 * ":export class Name ..."
63 * 152 *
64 * ":export {Name, ...}" 153 * ":export {Name, ...}"
65 */ 154 */
66 void 155 void
67 ex_export(exarg_T *eap UNUSED) 156 ex_export(exarg_T *eap)
68 { 157 {
69 if (current_sctx.sc_version != SCRIPT_VERSION_VIM9) 158 if (current_sctx.sc_version != SCRIPT_VERSION_VIM9)
70 { 159 {
71 emsg(_(e_needs_vim9)); 160 emsg(_(e_needs_vim9));
72 return; 161 return;