Mercurial > vim
comparison src/vim9compile.c @ 19181:94eda51ba9ba v8.2.0149
patch 8.2.0149: maintaining a Vim9 branch separately is more work
Commit: https://github.com/vim/vim/commit/8a7d6542b33e5d2b352262305c3bfdb2d14e1cf8
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 26 15:56:19 2020 +0100
patch 8.2.0149: maintaining a Vim9 branch separately is more work
Problem: Maintaining a Vim9 branch separately is more work.
Solution: Merge the Vim9 script changes.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 26 Jan 2020 16:00:05 +0100 |
parents | |
children | 133ef7ba4e4e |
comparison
equal
deleted
inserted
replaced
19180:8edf0aeb71b9 | 19181:94eda51ba9ba |
---|---|
1 /* vi:set ts=8 sts=4 sw=4 noet: | |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 * See README.txt for an overview of the Vim source code. | |
8 */ | |
9 | |
10 /* | |
11 * vim9compile.c: :def and dealing with instructions | |
12 */ | |
13 | |
14 #define USING_FLOAT_STUFF | |
15 #include "vim.h" | |
16 | |
17 #if defined(FEAT_EVAL) || defined(PROTO) | |
18 | |
19 #ifdef VMS | |
20 # include <float.h> | |
21 #endif | |
22 | |
23 #define DEFINE_VIM9_GLOBALS | |
24 #include "vim9.h" | |
25 | |
26 /* | |
27 * Chain of jump instructions where the end label needs to be set. | |
28 */ | |
29 typedef struct endlabel_S endlabel_T; | |
30 struct endlabel_S { | |
31 endlabel_T *el_next; // chain end_label locations | |
32 int el_end_label; // instruction idx where to set end | |
33 }; | |
34 | |
35 /* | |
36 * info specific for the scope of :if / elseif / else | |
37 */ | |
38 typedef struct { | |
39 int is_if_label; // instruction idx at IF or ELSEIF | |
40 endlabel_T *is_end_label; // instructions to set end label | |
41 } ifscope_T; | |
42 | |
43 /* | |
44 * info specific for the scope of :while | |
45 */ | |
46 typedef struct { | |
47 int ws_top_label; // instruction idx at WHILE | |
48 endlabel_T *ws_end_label; // instructions to set end | |
49 } whilescope_T; | |
50 | |
51 /* | |
52 * info specific for the scope of :for | |
53 */ | |
54 typedef struct { | |
55 int fs_top_label; // instruction idx at FOR | |
56 endlabel_T *fs_end_label; // break instructions | |
57 } forscope_T; | |
58 | |
59 /* | |
60 * info specific for the scope of :try | |
61 */ | |
62 typedef struct { | |
63 int ts_try_label; // instruction idx at TRY | |
64 endlabel_T *ts_end_label; // jump to :finally or :endtry | |
65 int ts_catch_label; // instruction idx of last CATCH | |
66 int ts_caught_all; // "catch" without argument encountered | |
67 } tryscope_T; | |
68 | |
69 typedef enum { | |
70 NO_SCOPE, | |
71 IF_SCOPE, | |
72 WHILE_SCOPE, | |
73 FOR_SCOPE, | |
74 TRY_SCOPE, | |
75 BLOCK_SCOPE | |
76 } scopetype_T; | |
77 | |
78 /* | |
79 * Info for one scope, pointed to by "ctx_scope". | |
80 */ | |
81 typedef struct scope_S scope_T; | |
82 struct scope_S { | |
83 scope_T *se_outer; // scope containing this one | |
84 scopetype_T se_type; | |
85 int se_local_count; // ctx_locals.ga_len before scope | |
86 union { | |
87 ifscope_T se_if; | |
88 whilescope_T se_while; | |
89 forscope_T se_for; | |
90 tryscope_T se_try; | |
91 }; | |
92 }; | |
93 | |
94 /* | |
95 * Entry for "ctx_locals". Used for arguments and local variables. | |
96 */ | |
97 typedef struct { | |
98 char_u *lv_name; | |
99 type_T *lv_type; | |
100 int lv_const; // when TRUE cannot be assigned to | |
101 int lv_arg; // when TRUE this is an argument | |
102 } lvar_T; | |
103 | |
104 /* | |
105 * Context for compiling lines of Vim script. | |
106 * Stores info about the local variables and condition stack. | |
107 */ | |
108 struct cctx_S { | |
109 ufunc_T *ctx_ufunc; // current function | |
110 int ctx_lnum; // line number in current function | |
111 garray_T ctx_instr; // generated instructions | |
112 | |
113 garray_T ctx_locals; // currently visible local variables | |
114 int ctx_max_local; // maximum number of locals at one time | |
115 | |
116 garray_T ctx_imports; // imported items | |
117 | |
118 scope_T *ctx_scope; // current scope, NULL at toplevel | |
119 | |
120 garray_T ctx_type_stack; // type of each item on the stack | |
121 garray_T *ctx_type_list; // space for adding types | |
122 }; | |
123 | |
124 static char e_var_notfound[] = N_("E1001: variable not found: %s"); | |
125 static char e_syntax_at[] = N_("E1002: Syntax error at %s"); | |
126 | |
127 static int compile_expr1(char_u **arg, cctx_T *cctx); | |
128 static int compile_expr2(char_u **arg, cctx_T *cctx); | |
129 static int compile_expr3(char_u **arg, cctx_T *cctx); | |
130 | |
131 /* | |
132 * Lookup variable "name" in the local scope and return the index. | |
133 */ | |
134 static int | |
135 lookup_local(char_u *name, size_t len, cctx_T *cctx) | |
136 { | |
137 int idx; | |
138 | |
139 if (len <= 0) | |
140 return -1; | |
141 for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx) | |
142 { | |
143 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
144 | |
145 if (STRNCMP(name, lvar->lv_name, len) == 0 | |
146 && STRLEN(lvar->lv_name) == len) | |
147 return idx; | |
148 } | |
149 return -1; | |
150 } | |
151 | |
152 /* | |
153 * Lookup an argument in the current function. | |
154 * Returns the argument index or -1 if not found. | |
155 */ | |
156 static int | |
157 lookup_arg(char_u *name, size_t len, cctx_T *cctx) | |
158 { | |
159 int idx; | |
160 | |
161 if (len <= 0) | |
162 return -1; | |
163 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx) | |
164 { | |
165 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx); | |
166 | |
167 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len) | |
168 return idx; | |
169 } | |
170 return -1; | |
171 } | |
172 | |
173 /* | |
174 * Lookup a vararg argument in the current function. | |
175 * Returns TRUE if there is a match. | |
176 */ | |
177 static int | |
178 lookup_vararg(char_u *name, size_t len, cctx_T *cctx) | |
179 { | |
180 char_u *va_name = cctx->ctx_ufunc->uf_va_name; | |
181 | |
182 return len > 0 && va_name != NULL | |
183 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len; | |
184 } | |
185 | |
186 /* | |
187 * Lookup a variable in the current script. | |
188 * Returns OK or FAIL. | |
189 */ | |
190 static int | |
191 lookup_script(char_u *name, size_t len) | |
192 { | |
193 int cc; | |
194 hashtab_T *ht = &SCRIPT_VARS(current_sctx.sc_sid); | |
195 dictitem_T *di; | |
196 | |
197 cc = name[len]; | |
198 name[len] = NUL; | |
199 di = find_var_in_ht(ht, 0, name, TRUE); | |
200 name[len] = cc; | |
201 return di == NULL ? FAIL: OK; | |
202 } | |
203 | |
204 static type_T * | |
205 get_list_type(type_T *member_type, garray_T *type_list) | |
206 { | |
207 type_T *type; | |
208 | |
209 // recognize commonly used types | |
210 if (member_type->tt_type == VAR_UNKNOWN) | |
211 return &t_list_any; | |
212 if (member_type->tt_type == VAR_NUMBER) | |
213 return &t_list_number; | |
214 if (member_type->tt_type == VAR_STRING) | |
215 return &t_list_string; | |
216 | |
217 // Not a common type, create a new entry. | |
218 if (ga_grow(type_list, 1) == FAIL) | |
219 return FAIL; | |
220 type = ((type_T *)type_list->ga_data) + type_list->ga_len; | |
221 ++type_list->ga_len; | |
222 type->tt_type = VAR_LIST; | |
223 type->tt_member = member_type; | |
224 return type; | |
225 } | |
226 | |
227 static type_T * | |
228 get_dict_type(type_T *member_type, garray_T *type_list) | |
229 { | |
230 type_T *type; | |
231 | |
232 // recognize commonly used types | |
233 if (member_type->tt_type == VAR_UNKNOWN) | |
234 return &t_dict_any; | |
235 if (member_type->tt_type == VAR_NUMBER) | |
236 return &t_dict_number; | |
237 if (member_type->tt_type == VAR_STRING) | |
238 return &t_dict_string; | |
239 | |
240 // Not a common type, create a new entry. | |
241 if (ga_grow(type_list, 1) == FAIL) | |
242 return FAIL; | |
243 type = ((type_T *)type_list->ga_data) + type_list->ga_len; | |
244 ++type_list->ga_len; | |
245 type->tt_type = VAR_DICT; | |
246 type->tt_member = member_type; | |
247 return type; | |
248 } | |
249 | |
250 ///////////////////////////////////////////////////////////////////// | |
251 // Following generate_ functions expect the caller to call ga_grow(). | |
252 | |
253 /* | |
254 * Generate an instruction without arguments. | |
255 * Returns a pointer to the new instruction, NULL if failed. | |
256 */ | |
257 static isn_T * | |
258 generate_instr(cctx_T *cctx, isntype_T isn_type) | |
259 { | |
260 garray_T *instr = &cctx->ctx_instr; | |
261 isn_T *isn; | |
262 | |
263 if (ga_grow(instr, 1) == FAIL) | |
264 return NULL; | |
265 isn = ((isn_T *)instr->ga_data) + instr->ga_len; | |
266 isn->isn_type = isn_type; | |
267 isn->isn_lnum = cctx->ctx_lnum + 1; | |
268 ++instr->ga_len; | |
269 | |
270 return isn; | |
271 } | |
272 | |
273 /* | |
274 * Generate an instruction without arguments. | |
275 * "drop" will be removed from the stack. | |
276 * Returns a pointer to the new instruction, NULL if failed. | |
277 */ | |
278 static isn_T * | |
279 generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop) | |
280 { | |
281 garray_T *stack = &cctx->ctx_type_stack; | |
282 | |
283 stack->ga_len -= drop; | |
284 return generate_instr(cctx, isn_type); | |
285 } | |
286 | |
287 /* | |
288 * Generate instruction "isn_type" and put "type" on the type stack. | |
289 */ | |
290 static isn_T * | |
291 generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type) | |
292 { | |
293 isn_T *isn; | |
294 garray_T *stack = &cctx->ctx_type_stack; | |
295 | |
296 if ((isn = generate_instr(cctx, isn_type)) == NULL) | |
297 return NULL; | |
298 | |
299 if (ga_grow(stack, 1) == FAIL) | |
300 return NULL; | |
301 ((type_T **)stack->ga_data)[stack->ga_len] = type; | |
302 ++stack->ga_len; | |
303 | |
304 return isn; | |
305 } | |
306 | |
307 /* | |
308 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING. | |
309 */ | |
310 static int | |
311 may_generate_2STRING(int offset, cctx_T *cctx) | |
312 { | |
313 isn_T *isn; | |
314 garray_T *stack = &cctx->ctx_type_stack; | |
315 type_T **type = ((type_T **)stack->ga_data) + stack->ga_len + offset; | |
316 | |
317 if ((*type)->tt_type == VAR_STRING) | |
318 return OK; | |
319 *type = &t_string; | |
320 | |
321 if ((isn = generate_instr(cctx, ISN_2STRING)) == NULL) | |
322 return FAIL; | |
323 isn->isn_arg.number = offset; | |
324 | |
325 return OK; | |
326 } | |
327 | |
328 static int | |
329 check_number_or_float(vartype_T type1, vartype_T type2, char_u *op) | |
330 { | |
331 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT || type1 == VAR_UNKNOWN) | |
332 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT | |
333 || type2 == VAR_UNKNOWN))) | |
334 { | |
335 if (*op == '+') | |
336 semsg(_("E1035: wrong argument type for +")); | |
337 else | |
338 semsg(_("E1036: %c requires number or float arguments"), *op); | |
339 return FAIL; | |
340 } | |
341 return OK; | |
342 } | |
343 | |
344 /* | |
345 * Generate an instruction with two arguments. The instruction depends on the | |
346 * type of the arguments. | |
347 */ | |
348 static int | |
349 generate_two_op(cctx_T *cctx, char_u *op) | |
350 { | |
351 garray_T *stack = &cctx->ctx_type_stack; | |
352 type_T *type1; | |
353 type_T *type2; | |
354 vartype_T vartype; | |
355 isn_T *isn; | |
356 | |
357 // Get the known type of the two items on the stack. If they are matching | |
358 // use a type-specific instruction. Otherwise fall back to runtime type | |
359 // checking. | |
360 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]; | |
361 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
362 vartype = VAR_UNKNOWN; | |
363 if (type1->tt_type == type2->tt_type | |
364 && (type1->tt_type == VAR_NUMBER | |
365 || type1->tt_type == VAR_LIST | |
366 #ifdef FEAT_FLOAT | |
367 || type1->tt_type == VAR_FLOAT | |
368 #endif | |
369 || type1->tt_type == VAR_BLOB)) | |
370 vartype = type1->tt_type; | |
371 | |
372 switch (*op) | |
373 { | |
374 case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB | |
375 && check_number_or_float( | |
376 type1->tt_type, type2->tt_type, op) == FAIL) | |
377 return FAIL; | |
378 isn = generate_instr_drop(cctx, | |
379 vartype == VAR_NUMBER ? ISN_OPNR | |
380 : vartype == VAR_LIST ? ISN_ADDLIST | |
381 : vartype == VAR_BLOB ? ISN_ADDBLOB | |
382 #ifdef FEAT_FLOAT | |
383 : vartype == VAR_FLOAT ? ISN_OPFLOAT | |
384 #endif | |
385 : ISN_OPANY, 1); | |
386 if (isn != NULL) | |
387 isn->isn_arg.op.op_type = EXPR_ADD; | |
388 break; | |
389 | |
390 case '-': | |
391 case '*': | |
392 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type, | |
393 op) == FAIL) | |
394 return FAIL; | |
395 if (vartype == VAR_NUMBER) | |
396 isn = generate_instr_drop(cctx, ISN_OPNR, 1); | |
397 #ifdef FEAT_FLOAT | |
398 else if (vartype == VAR_FLOAT) | |
399 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1); | |
400 #endif | |
401 else | |
402 isn = generate_instr_drop(cctx, ISN_OPANY, 1); | |
403 if (isn != NULL) | |
404 isn->isn_arg.op.op_type = *op == '*' | |
405 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB; | |
406 break; | |
407 | |
408 case '%': if ((type1->tt_type != VAR_UNKNOWN | |
409 && type1->tt_type != VAR_NUMBER) | |
410 || (type2->tt_type != VAR_UNKNOWN | |
411 && type2->tt_type != VAR_NUMBER)) | |
412 { | |
413 emsg(_("E1035: % requires number arguments")); | |
414 return FAIL; | |
415 } | |
416 isn = generate_instr_drop(cctx, | |
417 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1); | |
418 if (isn != NULL) | |
419 isn->isn_arg.op.op_type = EXPR_REM; | |
420 break; | |
421 } | |
422 | |
423 // correct type of result | |
424 if (vartype == VAR_UNKNOWN) | |
425 { | |
426 type_T *type = &t_any; | |
427 | |
428 #ifdef FEAT_FLOAT | |
429 // float+number and number+float results in float | |
430 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT) | |
431 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT)) | |
432 type = &t_float; | |
433 #endif | |
434 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type; | |
435 } | |
436 | |
437 return OK; | |
438 } | |
439 | |
440 /* | |
441 * Generate an ISN_COMPARE* instruction with a boolean result. | |
442 */ | |
443 static int | |
444 generate_COMPARE(cctx_T *cctx, exptype_T exptype, int ic) | |
445 { | |
446 isntype_T isntype = ISN_DROP; | |
447 isn_T *isn; | |
448 garray_T *stack = &cctx->ctx_type_stack; | |
449 vartype_T type1; | |
450 vartype_T type2; | |
451 | |
452 // Get the known type of the two items on the stack. If they are matching | |
453 // use a type-specific instruction. Otherwise fall back to runtime type | |
454 // checking. | |
455 type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type; | |
456 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type; | |
457 if (type1 == type2) | |
458 { | |
459 switch (type1) | |
460 { | |
461 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break; | |
462 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break; | |
463 case VAR_NUMBER: isntype = ISN_COMPARENR; break; | |
464 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break; | |
465 case VAR_STRING: isntype = ISN_COMPARESTRING; break; | |
466 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break; | |
467 case VAR_LIST: isntype = ISN_COMPARELIST; break; | |
468 case VAR_DICT: isntype = ISN_COMPAREDICT; break; | |
469 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break; | |
470 case VAR_PARTIAL: isntype = ISN_COMPAREPARTIAL; break; | |
471 default: isntype = ISN_COMPAREANY; break; | |
472 } | |
473 } | |
474 else if (type1 == VAR_UNKNOWN || type2 == VAR_UNKNOWN | |
475 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT) | |
476 && (type2 == VAR_NUMBER || type2 ==VAR_FLOAT))) | |
477 isntype = ISN_COMPAREANY; | |
478 | |
479 if ((exptype == EXPR_IS || exptype == EXPR_ISNOT) | |
480 && (isntype == ISN_COMPAREBOOL | |
481 || isntype == ISN_COMPARESPECIAL | |
482 || isntype == ISN_COMPARENR | |
483 || isntype == ISN_COMPAREFLOAT)) | |
484 { | |
485 semsg(_("E1037: Cannot use \"%s\" with %s"), | |
486 exptype == EXPR_IS ? "is" : "isnot" , vartype_name(type1)); | |
487 return FAIL; | |
488 } | |
489 if (isntype == ISN_DROP | |
490 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL | |
491 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL | |
492 || type2 == VAR_BOOL || type2 == VAR_SPECIAL))) | |
493 || ((exptype != EXPR_EQUAL && exptype != EXPR_NEQUAL | |
494 && exptype != EXPR_IS && exptype != EXPR_ISNOT | |
495 && (type1 == VAR_BLOB || type2 == VAR_BLOB | |
496 || type1 == VAR_LIST || type2 == VAR_LIST)))) | |
497 { | |
498 semsg(_("E1037: Cannot compare %s with %s"), | |
499 vartype_name(type1), vartype_name(type2)); | |
500 return FAIL; | |
501 } | |
502 | |
503 if ((isn = generate_instr(cctx, isntype)) == NULL) | |
504 return FAIL; | |
505 isn->isn_arg.op.op_type = exptype; | |
506 isn->isn_arg.op.op_ic = ic; | |
507 | |
508 // takes two arguments, puts one bool back | |
509 if (stack->ga_len >= 2) | |
510 { | |
511 --stack->ga_len; | |
512 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool; | |
513 } | |
514 | |
515 return OK; | |
516 } | |
517 | |
518 /* | |
519 * Generate an ISN_2BOOL instruction. | |
520 */ | |
521 static int | |
522 generate_2BOOL(cctx_T *cctx, int invert) | |
523 { | |
524 isn_T *isn; | |
525 garray_T *stack = &cctx->ctx_type_stack; | |
526 | |
527 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL) | |
528 return FAIL; | |
529 isn->isn_arg.number = invert; | |
530 | |
531 // type becomes bool | |
532 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool; | |
533 | |
534 return OK; | |
535 } | |
536 | |
537 static int | |
538 generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset) | |
539 { | |
540 isn_T *isn; | |
541 garray_T *stack = &cctx->ctx_type_stack; | |
542 | |
543 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL) | |
544 return FAIL; | |
545 isn->isn_arg.type.ct_type = vartype->tt_type; // TODO: whole type | |
546 isn->isn_arg.type.ct_off = offset; | |
547 | |
548 // type becomes vartype | |
549 ((type_T **)stack->ga_data)[stack->ga_len - 1] = vartype; | |
550 | |
551 return OK; | |
552 } | |
553 | |
554 /* | |
555 * Generate an ISN_PUSHNR instruction. | |
556 */ | |
557 static int | |
558 generate_PUSHNR(cctx_T *cctx, varnumber_T number) | |
559 { | |
560 isn_T *isn; | |
561 | |
562 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL) | |
563 return FAIL; | |
564 isn->isn_arg.number = number; | |
565 | |
566 return OK; | |
567 } | |
568 | |
569 /* | |
570 * Generate an ISN_PUSHBOOL instruction. | |
571 */ | |
572 static int | |
573 generate_PUSHBOOL(cctx_T *cctx, varnumber_T number) | |
574 { | |
575 isn_T *isn; | |
576 | |
577 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL) | |
578 return FAIL; | |
579 isn->isn_arg.number = number; | |
580 | |
581 return OK; | |
582 } | |
583 | |
584 /* | |
585 * Generate an ISN_PUSHSPEC instruction. | |
586 */ | |
587 static int | |
588 generate_PUSHSPEC(cctx_T *cctx, varnumber_T number) | |
589 { | |
590 isn_T *isn; | |
591 | |
592 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL) | |
593 return FAIL; | |
594 isn->isn_arg.number = number; | |
595 | |
596 return OK; | |
597 } | |
598 | |
599 #ifdef FEAT_FLOAT | |
600 /* | |
601 * Generate an ISN_PUSHF instruction. | |
602 */ | |
603 static int | |
604 generate_PUSHF(cctx_T *cctx, float_T fnumber) | |
605 { | |
606 isn_T *isn; | |
607 | |
608 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL) | |
609 return FAIL; | |
610 isn->isn_arg.fnumber = fnumber; | |
611 | |
612 return OK; | |
613 } | |
614 #endif | |
615 | |
616 /* | |
617 * Generate an ISN_PUSHS instruction. | |
618 * Consumes "str". | |
619 */ | |
620 static int | |
621 generate_PUSHS(cctx_T *cctx, char_u *str) | |
622 { | |
623 isn_T *isn; | |
624 | |
625 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL) | |
626 return FAIL; | |
627 isn->isn_arg.string = str; | |
628 | |
629 return OK; | |
630 } | |
631 | |
632 /* | |
633 * Generate an ISN_PUSHBLOB instruction. | |
634 * Consumes "blob". | |
635 */ | |
636 static int | |
637 generate_PUSHBLOB(cctx_T *cctx, blob_T *blob) | |
638 { | |
639 isn_T *isn; | |
640 | |
641 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL) | |
642 return FAIL; | |
643 isn->isn_arg.blob = blob; | |
644 | |
645 return OK; | |
646 } | |
647 | |
648 /* | |
649 * Generate an ISN_STORE instruction. | |
650 */ | |
651 static int | |
652 generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name) | |
653 { | |
654 isn_T *isn; | |
655 | |
656 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL) | |
657 return FAIL; | |
658 if (name != NULL) | |
659 isn->isn_arg.string = vim_strsave(name); | |
660 else | |
661 isn->isn_arg.number = idx; | |
662 | |
663 return OK; | |
664 } | |
665 | |
666 /* | |
667 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE) | |
668 */ | |
669 static int | |
670 generate_STORENR(cctx_T *cctx, int idx, varnumber_T value) | |
671 { | |
672 isn_T *isn; | |
673 | |
674 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL) | |
675 return FAIL; | |
676 isn->isn_arg.storenr.str_idx = idx; | |
677 isn->isn_arg.storenr.str_val = value; | |
678 | |
679 return OK; | |
680 } | |
681 | |
682 /* | |
683 * Generate an ISN_STOREOPT instruction | |
684 */ | |
685 static int | |
686 generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags) | |
687 { | |
688 isn_T *isn; | |
689 | |
690 if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL) | |
691 return FAIL; | |
692 isn->isn_arg.storeopt.so_name = vim_strsave(name); | |
693 isn->isn_arg.storeopt.so_flags = opt_flags; | |
694 | |
695 return OK; | |
696 } | |
697 | |
698 /* | |
699 * Generate an ISN_LOAD or similar instruction. | |
700 */ | |
701 static int | |
702 generate_LOAD( | |
703 cctx_T *cctx, | |
704 isntype_T isn_type, | |
705 int idx, | |
706 char_u *name, | |
707 type_T *type) | |
708 { | |
709 isn_T *isn; | |
710 | |
711 if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL) | |
712 return FAIL; | |
713 if (name != NULL) | |
714 isn->isn_arg.string = vim_strsave(name); | |
715 else | |
716 isn->isn_arg.number = idx; | |
717 | |
718 return OK; | |
719 } | |
720 | |
721 /* | |
722 * Generate an ISN_LOADS instruction. | |
723 */ | |
724 static int | |
725 generate_LOADS( | |
726 cctx_T *cctx, | |
727 char_u *name, | |
728 int sid) | |
729 { | |
730 isn_T *isn; | |
731 | |
732 if ((isn = generate_instr_type(cctx, ISN_LOADS, &t_any)) == NULL) | |
733 return FAIL; | |
734 isn->isn_arg.loads.ls_name = vim_strsave(name); | |
735 isn->isn_arg.loads.ls_sid = sid; | |
736 | |
737 return OK; | |
738 } | |
739 | |
740 /* | |
741 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction. | |
742 */ | |
743 static int | |
744 generate_SCRIPT( | |
745 cctx_T *cctx, | |
746 isntype_T isn_type, | |
747 int sid, | |
748 int idx, | |
749 type_T *type) | |
750 { | |
751 isn_T *isn; | |
752 | |
753 if (isn_type == ISN_LOADSCRIPT) | |
754 isn = generate_instr_type(cctx, isn_type, type); | |
755 else | |
756 isn = generate_instr_drop(cctx, isn_type, 1); | |
757 if (isn == NULL) | |
758 return FAIL; | |
759 isn->isn_arg.script.script_sid = sid; | |
760 isn->isn_arg.script.script_idx = idx; | |
761 return OK; | |
762 } | |
763 | |
764 /* | |
765 * Generate an ISN_NEWLIST instruction. | |
766 */ | |
767 static int | |
768 generate_NEWLIST(cctx_T *cctx, int count) | |
769 { | |
770 isn_T *isn; | |
771 garray_T *stack = &cctx->ctx_type_stack; | |
772 garray_T *type_list = cctx->ctx_type_list; | |
773 type_T *type; | |
774 type_T *member; | |
775 | |
776 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL) | |
777 return FAIL; | |
778 isn->isn_arg.number = count; | |
779 | |
780 // drop the value types | |
781 stack->ga_len -= count; | |
782 | |
783 // use the first value type for the list member type | |
784 if (count > 0) | |
785 member = ((type_T **)stack->ga_data)[stack->ga_len]; | |
786 else | |
787 member = &t_any; | |
788 type = get_list_type(member, type_list); | |
789 | |
790 // add the list type to the type stack | |
791 if (ga_grow(stack, 1) == FAIL) | |
792 return FAIL; | |
793 ((type_T **)stack->ga_data)[stack->ga_len] = type; | |
794 ++stack->ga_len; | |
795 | |
796 return OK; | |
797 } | |
798 | |
799 /* | |
800 * Generate an ISN_NEWDICT instruction. | |
801 */ | |
802 static int | |
803 generate_NEWDICT(cctx_T *cctx, int count) | |
804 { | |
805 isn_T *isn; | |
806 garray_T *stack = &cctx->ctx_type_stack; | |
807 garray_T *type_list = cctx->ctx_type_list; | |
808 type_T *type; | |
809 type_T *member; | |
810 | |
811 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL) | |
812 return FAIL; | |
813 isn->isn_arg.number = count; | |
814 | |
815 // drop the key and value types | |
816 stack->ga_len -= 2 * count; | |
817 | |
818 // use the first value type for the list member type | |
819 if (count > 0) | |
820 member = ((type_T **)stack->ga_data)[stack->ga_len + 1]; | |
821 else | |
822 member = &t_any; | |
823 type = get_dict_type(member, type_list); | |
824 | |
825 // add the dict type to the type stack | |
826 if (ga_grow(stack, 1) == FAIL) | |
827 return FAIL; | |
828 ((type_T **)stack->ga_data)[stack->ga_len] = type; | |
829 ++stack->ga_len; | |
830 | |
831 return OK; | |
832 } | |
833 | |
834 /* | |
835 * Generate an ISN_FUNCREF instruction. | |
836 */ | |
837 static int | |
838 generate_FUNCREF(cctx_T *cctx, int dfunc_idx) | |
839 { | |
840 isn_T *isn; | |
841 garray_T *stack = &cctx->ctx_type_stack; | |
842 | |
843 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL) | |
844 return FAIL; | |
845 isn->isn_arg.number = dfunc_idx; | |
846 | |
847 if (ga_grow(stack, 1) == FAIL) | |
848 return FAIL; | |
849 ((type_T **)stack->ga_data)[stack->ga_len] = &t_partial_any; | |
850 // TODO: argument and return types | |
851 ++stack->ga_len; | |
852 | |
853 return OK; | |
854 } | |
855 | |
856 /* | |
857 * Generate an ISN_JUMP instruction. | |
858 */ | |
859 static int | |
860 generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where) | |
861 { | |
862 isn_T *isn; | |
863 garray_T *stack = &cctx->ctx_type_stack; | |
864 | |
865 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL) | |
866 return FAIL; | |
867 isn->isn_arg.jump.jump_when = when; | |
868 isn->isn_arg.jump.jump_where = where; | |
869 | |
870 if (when != JUMP_ALWAYS && stack->ga_len > 0) | |
871 --stack->ga_len; | |
872 | |
873 return OK; | |
874 } | |
875 | |
876 static int | |
877 generate_FOR(cctx_T *cctx, int loop_idx) | |
878 { | |
879 isn_T *isn; | |
880 garray_T *stack = &cctx->ctx_type_stack; | |
881 | |
882 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL) | |
883 return FAIL; | |
884 isn->isn_arg.forloop.for_idx = loop_idx; | |
885 | |
886 if (ga_grow(stack, 1) == FAIL) | |
887 return FAIL; | |
888 // type doesn't matter, will be stored next | |
889 ((type_T **)stack->ga_data)[stack->ga_len] = &t_any; | |
890 ++stack->ga_len; | |
891 | |
892 return OK; | |
893 } | |
894 | |
895 /* | |
896 * Generate an ISN_BCALL instruction. | |
897 * Return FAIL if the number of arguments is wrong. | |
898 */ | |
899 static int | |
900 generate_BCALL(cctx_T *cctx, int func_idx, int argcount) | |
901 { | |
902 isn_T *isn; | |
903 garray_T *stack = &cctx->ctx_type_stack; | |
904 | |
905 if (check_internal_func(func_idx, argcount) == FAIL) | |
906 return FAIL; | |
907 | |
908 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL) | |
909 return FAIL; | |
910 isn->isn_arg.bfunc.cbf_idx = func_idx; | |
911 isn->isn_arg.bfunc.cbf_argcount = argcount; | |
912 | |
913 stack->ga_len -= argcount; // drop the arguments | |
914 if (ga_grow(stack, 1) == FAIL) | |
915 return FAIL; | |
916 ((type_T **)stack->ga_data)[stack->ga_len] = | |
917 internal_func_ret_type(func_idx, argcount); | |
918 ++stack->ga_len; // add return value | |
919 | |
920 return OK; | |
921 } | |
922 | |
923 /* | |
924 * Generate an ISN_DCALL or ISN_UCALL instruction. | |
925 * Return FAIL if the number of arguments is wrong. | |
926 */ | |
927 static int | |
928 generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int argcount) | |
929 { | |
930 isn_T *isn; | |
931 garray_T *stack = &cctx->ctx_type_stack; | |
932 int regular_args = ufunc->uf_args.ga_len; | |
933 | |
934 if (argcount > regular_args && !has_varargs(ufunc)) | |
935 { | |
936 semsg(_(e_toomanyarg), ufunc->uf_name); | |
937 return FAIL; | |
938 } | |
939 if (argcount < regular_args - ufunc->uf_def_args.ga_len) | |
940 { | |
941 semsg(_(e_toofewarg), ufunc->uf_name); | |
942 return FAIL; | |
943 } | |
944 | |
945 // Turn varargs into a list. | |
946 if (ufunc->uf_va_name != NULL) | |
947 { | |
948 int count = argcount - regular_args; | |
949 | |
950 // TODO: add default values for optional arguments? | |
951 generate_NEWLIST(cctx, count < 0 ? 0 : count); | |
952 argcount = regular_args + 1; | |
953 } | |
954 | |
955 if ((isn = generate_instr(cctx, | |
956 ufunc->uf_dfunc_idx >= 0 ? ISN_DCALL : ISN_UCALL)) == NULL) | |
957 return FAIL; | |
958 if (ufunc->uf_dfunc_idx >= 0) | |
959 { | |
960 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; | |
961 isn->isn_arg.dfunc.cdf_argcount = argcount; | |
962 } | |
963 else | |
964 { | |
965 // A user function may be deleted and redefined later, can't use the | |
966 // ufunc pointer, need to look it up again at runtime. | |
967 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name); | |
968 isn->isn_arg.ufunc.cuf_argcount = argcount; | |
969 } | |
970 | |
971 stack->ga_len -= argcount; // drop the arguments | |
972 if (ga_grow(stack, 1) == FAIL) | |
973 return FAIL; | |
974 // add return value | |
975 ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type; | |
976 ++stack->ga_len; | |
977 | |
978 return OK; | |
979 } | |
980 | |
981 /* | |
982 * Generate an ISN_UCALL instruction when the function isn't defined yet. | |
983 */ | |
984 static int | |
985 generate_UCALL(cctx_T *cctx, char_u *name, int argcount) | |
986 { | |
987 isn_T *isn; | |
988 garray_T *stack = &cctx->ctx_type_stack; | |
989 | |
990 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL) | |
991 return FAIL; | |
992 isn->isn_arg.ufunc.cuf_name = vim_strsave(name); | |
993 isn->isn_arg.ufunc.cuf_argcount = argcount; | |
994 | |
995 stack->ga_len -= argcount; // drop the arguments | |
996 | |
997 // drop the funcref/partial, get back the return value | |
998 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any; | |
999 | |
1000 return OK; | |
1001 } | |
1002 | |
1003 /* | |
1004 * Generate an ISN_PCALL instruction. | |
1005 */ | |
1006 static int | |
1007 generate_PCALL(cctx_T *cctx, int argcount, int at_top) | |
1008 { | |
1009 isn_T *isn; | |
1010 garray_T *stack = &cctx->ctx_type_stack; | |
1011 | |
1012 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL) | |
1013 return FAIL; | |
1014 isn->isn_arg.pfunc.cpf_top = at_top; | |
1015 isn->isn_arg.pfunc.cpf_argcount = argcount; | |
1016 | |
1017 stack->ga_len -= argcount; // drop the arguments | |
1018 | |
1019 // drop the funcref/partial, get back the return value | |
1020 ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any; | |
1021 | |
1022 return OK; | |
1023 } | |
1024 | |
1025 /* | |
1026 * Generate an ISN_MEMBER instruction. | |
1027 */ | |
1028 static int | |
1029 generate_MEMBER(cctx_T *cctx, char_u *name, size_t len) | |
1030 { | |
1031 isn_T *isn; | |
1032 garray_T *stack = &cctx->ctx_type_stack; | |
1033 type_T *type; | |
1034 | |
1035 if ((isn = generate_instr(cctx, ISN_MEMBER)) == NULL) | |
1036 return FAIL; | |
1037 isn->isn_arg.string = vim_strnsave(name, (int)len); | |
1038 | |
1039 // change dict type to dict member type | |
1040 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
1041 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type->tt_member; | |
1042 | |
1043 return OK; | |
1044 } | |
1045 | |
1046 /* | |
1047 * Generate an ISN_ECHO instruction. | |
1048 */ | |
1049 static int | |
1050 generate_ECHO(cctx_T *cctx, int with_white, int count) | |
1051 { | |
1052 isn_T *isn; | |
1053 | |
1054 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL) | |
1055 return FAIL; | |
1056 isn->isn_arg.echo.echo_with_white = with_white; | |
1057 isn->isn_arg.echo.echo_count = count; | |
1058 | |
1059 return OK; | |
1060 } | |
1061 | |
1062 static int | |
1063 generate_EXEC(cctx_T *cctx, char_u *line) | |
1064 { | |
1065 isn_T *isn; | |
1066 | |
1067 if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL) | |
1068 return FAIL; | |
1069 isn->isn_arg.string = vim_strsave(line); | |
1070 return OK; | |
1071 } | |
1072 | |
1073 static char e_white_both[] = | |
1074 N_("E1004: white space required before and after '%s'"); | |
1075 | |
1076 /* | |
1077 * Reserve space for a local variable. | |
1078 * Return the index or -1 if it failed. | |
1079 */ | |
1080 static int | |
1081 reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type) | |
1082 { | |
1083 int idx; | |
1084 lvar_T *lvar; | |
1085 | |
1086 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx)) | |
1087 { | |
1088 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len); | |
1089 return -1; | |
1090 } | |
1091 | |
1092 if (ga_grow(&cctx->ctx_locals, 1) == FAIL) | |
1093 return -1; | |
1094 idx = cctx->ctx_locals.ga_len; | |
1095 if (cctx->ctx_max_local < idx + 1) | |
1096 cctx->ctx_max_local = idx + 1; | |
1097 ++cctx->ctx_locals.ga_len; | |
1098 | |
1099 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
1100 lvar->lv_name = vim_strnsave(name, (int)(len == 0 ? STRLEN(name) : len)); | |
1101 lvar->lv_const = isConst; | |
1102 lvar->lv_type = type; | |
1103 | |
1104 return idx; | |
1105 } | |
1106 | |
1107 /* | |
1108 * Skip over a type definition and return a pointer to just after it. | |
1109 */ | |
1110 char_u * | |
1111 skip_type(char_u *start) | |
1112 { | |
1113 char_u *p = start; | |
1114 | |
1115 while (ASCII_ISALNUM(*p) || *p == '_') | |
1116 ++p; | |
1117 | |
1118 // Skip over "<type>"; this is permissive about white space. | |
1119 if (*skipwhite(p) == '<') | |
1120 { | |
1121 p = skipwhite(p); | |
1122 p = skip_type(skipwhite(p + 1)); | |
1123 p = skipwhite(p); | |
1124 if (*p == '>') | |
1125 ++p; | |
1126 } | |
1127 return p; | |
1128 } | |
1129 | |
1130 /* | |
1131 * Parse the member type: "<type>" and return "type" with the member set. | |
1132 * Use "type_list" if a new type needs to be added. | |
1133 * Returns NULL in case of failure. | |
1134 */ | |
1135 static type_T * | |
1136 parse_type_member(char_u **arg, type_T *type, garray_T *type_list) | |
1137 { | |
1138 type_T *member_type; | |
1139 | |
1140 if (**arg != '<') | |
1141 { | |
1142 if (*skipwhite(*arg) == '<') | |
1143 emsg(_("E1007: No white space allowed before <")); | |
1144 else | |
1145 emsg(_("E1008: Missing <type>")); | |
1146 return NULL; | |
1147 } | |
1148 *arg = skipwhite(*arg + 1); | |
1149 | |
1150 member_type = parse_type(arg, type_list); | |
1151 if (member_type == NULL) | |
1152 return NULL; | |
1153 | |
1154 *arg = skipwhite(*arg); | |
1155 if (**arg != '>') | |
1156 { | |
1157 emsg(_("E1009: Missing > after type")); | |
1158 return NULL; | |
1159 } | |
1160 ++*arg; | |
1161 | |
1162 if (type->tt_type == VAR_LIST) | |
1163 return get_list_type(member_type, type_list); | |
1164 return get_dict_type(member_type, type_list); | |
1165 } | |
1166 | |
1167 /* | |
1168 * Parse a type at "arg" and advance over it. | |
1169 * Return NULL for failure. | |
1170 */ | |
1171 type_T * | |
1172 parse_type(char_u **arg, garray_T *type_list) | |
1173 { | |
1174 char_u *p = *arg; | |
1175 size_t len; | |
1176 | |
1177 // skip over the first word | |
1178 while (ASCII_ISALNUM(*p) || *p == '_') | |
1179 ++p; | |
1180 len = p - *arg; | |
1181 | |
1182 switch (**arg) | |
1183 { | |
1184 case 'a': | |
1185 if (len == 3 && STRNCMP(*arg, "any", len) == 0) | |
1186 { | |
1187 *arg += len; | |
1188 return &t_any; | |
1189 } | |
1190 break; | |
1191 case 'b': | |
1192 if (len == 4 && STRNCMP(*arg, "bool", len) == 0) | |
1193 { | |
1194 *arg += len; | |
1195 return &t_bool; | |
1196 } | |
1197 if (len == 4 && STRNCMP(*arg, "blob", len) == 0) | |
1198 { | |
1199 *arg += len; | |
1200 return &t_blob; | |
1201 } | |
1202 break; | |
1203 case 'c': | |
1204 if (len == 7 && STRNCMP(*arg, "channel", len) == 0) | |
1205 { | |
1206 *arg += len; | |
1207 return &t_channel; | |
1208 } | |
1209 break; | |
1210 case 'd': | |
1211 if (len == 4 && STRNCMP(*arg, "dict", len) == 0) | |
1212 { | |
1213 *arg += len; | |
1214 return parse_type_member(arg, &t_dict_any, type_list); | |
1215 } | |
1216 break; | |
1217 case 'f': | |
1218 if (len == 5 && STRNCMP(*arg, "float", len) == 0) | |
1219 { | |
1220 *arg += len; | |
1221 return &t_float; | |
1222 } | |
1223 if (len == 4 && STRNCMP(*arg, "func", len) == 0) | |
1224 { | |
1225 *arg += len; | |
1226 // TODO: arguments and return type | |
1227 return &t_func_any; | |
1228 } | |
1229 break; | |
1230 case 'j': | |
1231 if (len == 3 && STRNCMP(*arg, "job", len) == 0) | |
1232 { | |
1233 *arg += len; | |
1234 return &t_job; | |
1235 } | |
1236 break; | |
1237 case 'l': | |
1238 if (len == 4 && STRNCMP(*arg, "list", len) == 0) | |
1239 { | |
1240 *arg += len; | |
1241 return parse_type_member(arg, &t_list_any, type_list); | |
1242 } | |
1243 break; | |
1244 case 'n': | |
1245 if (len == 6 && STRNCMP(*arg, "number", len) == 0) | |
1246 { | |
1247 *arg += len; | |
1248 return &t_number; | |
1249 } | |
1250 break; | |
1251 case 'p': | |
1252 if (len == 4 && STRNCMP(*arg, "partial", len) == 0) | |
1253 { | |
1254 *arg += len; | |
1255 // TODO: arguments and return type | |
1256 return &t_partial_any; | |
1257 } | |
1258 break; | |
1259 case 's': | |
1260 if (len == 6 && STRNCMP(*arg, "string", len) == 0) | |
1261 { | |
1262 *arg += len; | |
1263 return &t_string; | |
1264 } | |
1265 break; | |
1266 case 'v': | |
1267 if (len == 4 && STRNCMP(*arg, "void", len) == 0) | |
1268 { | |
1269 *arg += len; | |
1270 return &t_void; | |
1271 } | |
1272 break; | |
1273 } | |
1274 | |
1275 semsg(_("E1010: Type not recognized: %s"), *arg); | |
1276 return &t_any; | |
1277 } | |
1278 | |
1279 /* | |
1280 * Check if "type1" and "type2" are exactly the same. | |
1281 */ | |
1282 static int | |
1283 equal_type(type_T *type1, type_T *type2) | |
1284 { | |
1285 if (type1->tt_type != type2->tt_type) | |
1286 return FALSE; | |
1287 switch (type1->tt_type) | |
1288 { | |
1289 case VAR_VOID: | |
1290 case VAR_UNKNOWN: | |
1291 case VAR_SPECIAL: | |
1292 case VAR_BOOL: | |
1293 case VAR_NUMBER: | |
1294 case VAR_FLOAT: | |
1295 case VAR_STRING: | |
1296 case VAR_BLOB: | |
1297 case VAR_JOB: | |
1298 case VAR_CHANNEL: | |
1299 return TRUE; // not composite is always OK | |
1300 case VAR_LIST: | |
1301 case VAR_DICT: | |
1302 return equal_type(type1->tt_member, type2->tt_member); | |
1303 case VAR_FUNC: | |
1304 case VAR_PARTIAL: | |
1305 // TODO; check argument types. | |
1306 return equal_type(type1->tt_member, type2->tt_member) | |
1307 && type1->tt_argcount == type2->tt_argcount; | |
1308 } | |
1309 return TRUE; | |
1310 } | |
1311 | |
1312 /* | |
1313 * Find the common type of "type1" and "type2" and put it in "dest". | |
1314 * "type2" and "dest" may be the same. | |
1315 */ | |
1316 static void | |
1317 common_type(type_T *type1, type_T *type2, type_T *dest) | |
1318 { | |
1319 if (equal_type(type1, type2)) | |
1320 { | |
1321 if (dest != type2) | |
1322 *dest = *type2; | |
1323 return; | |
1324 } | |
1325 | |
1326 if (type1->tt_type == type2->tt_type) | |
1327 { | |
1328 dest->tt_type = type1->tt_type; | |
1329 if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT) | |
1330 { | |
1331 common_type(type1->tt_member, type2->tt_member, dest->tt_member); | |
1332 return; | |
1333 } | |
1334 // TODO: VAR_FUNC and VAR_PARTIAL | |
1335 } | |
1336 | |
1337 dest->tt_type = VAR_UNKNOWN; // "any" | |
1338 } | |
1339 | |
1340 char * | |
1341 vartype_name(vartype_T type) | |
1342 { | |
1343 switch (type) | |
1344 { | |
1345 case VAR_VOID: return "void"; | |
1346 case VAR_UNKNOWN: return "any"; | |
1347 case VAR_SPECIAL: return "special"; | |
1348 case VAR_BOOL: return "bool"; | |
1349 case VAR_NUMBER: return "number"; | |
1350 case VAR_FLOAT: return "float"; | |
1351 case VAR_STRING: return "string"; | |
1352 case VAR_BLOB: return "blob"; | |
1353 case VAR_JOB: return "job"; | |
1354 case VAR_CHANNEL: return "channel"; | |
1355 case VAR_LIST: return "list"; | |
1356 case VAR_DICT: return "dict"; | |
1357 case VAR_FUNC: return "function"; | |
1358 case VAR_PARTIAL: return "partial"; | |
1359 } | |
1360 return "???"; | |
1361 } | |
1362 | |
1363 /* | |
1364 * Return the name of a type. | |
1365 * The result may be in allocated memory, in which case "tofree" is set. | |
1366 */ | |
1367 char * | |
1368 type_name(type_T *type, char **tofree) | |
1369 { | |
1370 char *name = vartype_name(type->tt_type); | |
1371 | |
1372 *tofree = NULL; | |
1373 if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT) | |
1374 { | |
1375 char *member_free; | |
1376 char *member_name = type_name(type->tt_member, &member_free); | |
1377 size_t len; | |
1378 | |
1379 len = STRLEN(name) + STRLEN(member_name) + 3; | |
1380 *tofree = alloc(len); | |
1381 if (*tofree != NULL) | |
1382 { | |
1383 vim_snprintf(*tofree, len, "%s<%s>", name, member_name); | |
1384 vim_free(member_free); | |
1385 return *tofree; | |
1386 } | |
1387 } | |
1388 // TODO: function and partial argument types | |
1389 | |
1390 return name; | |
1391 } | |
1392 | |
1393 /* | |
1394 * Find "name" in script-local items of script "sid". | |
1395 * Returns the index in "sn_var_vals" if found. | |
1396 * If found but not in "sn_var_vals" returns -1. | |
1397 * If not found returns -2. | |
1398 */ | |
1399 int | |
1400 get_script_item_idx(int sid, char_u *name, int check_writable) | |
1401 { | |
1402 hashtab_T *ht; | |
1403 dictitem_T *di; | |
1404 scriptitem_T *si = &SCRIPT_ITEM(sid); | |
1405 int idx; | |
1406 | |
1407 // First look the name up in the hashtable. | |
1408 if (sid <= 0 || sid > script_items.ga_len) | |
1409 return -1; | |
1410 ht = &SCRIPT_VARS(sid); | |
1411 di = find_var_in_ht(ht, 0, name, TRUE); | |
1412 if (di == NULL) | |
1413 return -2; | |
1414 | |
1415 // Now find the svar_T index in sn_var_vals. | |
1416 for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) | |
1417 { | |
1418 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; | |
1419 | |
1420 if (sv->sv_tv == &di->di_tv) | |
1421 { | |
1422 if (check_writable && sv->sv_const) | |
1423 semsg(_(e_readonlyvar), name); | |
1424 return idx; | |
1425 } | |
1426 } | |
1427 return -1; | |
1428 } | |
1429 | |
1430 /* | |
1431 * Find "name" in imported items of the current script/ | |
1432 */ | |
1433 imported_T * | |
1434 find_imported(char_u *name, cctx_T *cctx) | |
1435 { | |
1436 scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); | |
1437 int idx; | |
1438 | |
1439 if (cctx != NULL) | |
1440 for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx) | |
1441 { | |
1442 imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) | |
1443 + idx; | |
1444 | |
1445 if (STRCMP(name, import->imp_name) == 0) | |
1446 return import; | |
1447 } | |
1448 | |
1449 for (idx = 0; idx < si->sn_imports.ga_len; ++idx) | |
1450 { | |
1451 imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx; | |
1452 | |
1453 if (STRCMP(name, import->imp_name) == 0) | |
1454 return import; | |
1455 } | |
1456 return NULL; | |
1457 } | |
1458 | |
1459 /* | |
1460 * Generate an instruction to load script-local variable "name". | |
1461 */ | |
1462 static int | |
1463 compile_load_scriptvar(cctx_T *cctx, char_u *name) | |
1464 { | |
1465 scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); | |
1466 int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE); | |
1467 imported_T *import; | |
1468 | |
1469 if (idx == -1) | |
1470 { | |
1471 // variable exists but is not in sn_var_vals: old style script. | |
1472 return generate_LOADS(cctx, name, current_sctx.sc_sid); | |
1473 } | |
1474 if (idx >= 0) | |
1475 { | |
1476 svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; | |
1477 | |
1478 generate_SCRIPT(cctx, ISN_LOADSCRIPT, | |
1479 current_sctx.sc_sid, idx, sv->sv_type); | |
1480 return OK; | |
1481 } | |
1482 | |
1483 import = find_imported(name, cctx); | |
1484 if (import != NULL) | |
1485 { | |
1486 // TODO: check this is a variable, not a function | |
1487 generate_SCRIPT(cctx, ISN_LOADSCRIPT, | |
1488 import->imp_sid, | |
1489 import->imp_var_vals_idx, | |
1490 import->imp_type); | |
1491 return OK; | |
1492 } | |
1493 | |
1494 semsg(_("E1050: Item not found: %s"), name); | |
1495 return FAIL; | |
1496 } | |
1497 | |
1498 /* | |
1499 * Compile a variable name into a load instruction. | |
1500 * "end" points to just after the name. | |
1501 * When "error" is FALSE do not give an error when not found. | |
1502 */ | |
1503 static int | |
1504 compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error) | |
1505 { | |
1506 type_T *type; | |
1507 char_u *name; | |
1508 int res = FAIL; | |
1509 | |
1510 if (*(*arg + 1) == ':') | |
1511 { | |
1512 // load namespaced variable | |
1513 name = vim_strnsave(*arg + 2, end - (*arg + 2)); | |
1514 if (name == NULL) | |
1515 return FAIL; | |
1516 | |
1517 if (**arg == 'v') | |
1518 { | |
1519 // load v:var | |
1520 int vidx = find_vim_var(name); | |
1521 | |
1522 if (vidx < 0) | |
1523 { | |
1524 if (error) | |
1525 semsg(_(e_var_notfound), name); | |
1526 goto theend; | |
1527 } | |
1528 | |
1529 // TODO: get actual type | |
1530 res = generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any); | |
1531 } | |
1532 else if (**arg == 'g') | |
1533 { | |
1534 // Global variables can be defined later, thus we don't check if it | |
1535 // exists, give error at runtime. | |
1536 res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any); | |
1537 } | |
1538 else if (**arg == 's') | |
1539 { | |
1540 res = compile_load_scriptvar(cctx, name); | |
1541 } | |
1542 else | |
1543 { | |
1544 semsg("Namespace not supported yet: %s", **arg); | |
1545 goto theend; | |
1546 } | |
1547 } | |
1548 else | |
1549 { | |
1550 size_t len = end - *arg; | |
1551 int idx; | |
1552 int gen_load = FALSE; | |
1553 | |
1554 name = vim_strnsave(*arg, end - *arg); | |
1555 if (name == NULL) | |
1556 return FAIL; | |
1557 | |
1558 idx = lookup_arg(*arg, len, cctx); | |
1559 if (idx >= 0) | |
1560 { | |
1561 if (cctx->ctx_ufunc->uf_arg_types != NULL) | |
1562 type = cctx->ctx_ufunc->uf_arg_types[idx]; | |
1563 else | |
1564 type = &t_any; | |
1565 | |
1566 // Arguments are located above the frame pointer. | |
1567 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE; | |
1568 if (cctx->ctx_ufunc->uf_va_name != NULL) | |
1569 --idx; | |
1570 gen_load = TRUE; | |
1571 } | |
1572 else if (lookup_vararg(*arg, len, cctx)) | |
1573 { | |
1574 // varargs is always the last argument | |
1575 idx = -STACK_FRAME_SIZE - 1; | |
1576 type = cctx->ctx_ufunc->uf_va_type; | |
1577 gen_load = TRUE; | |
1578 } | |
1579 else | |
1580 { | |
1581 idx = lookup_local(*arg, len, cctx); | |
1582 if (idx >= 0) | |
1583 { | |
1584 type = (((lvar_T *)cctx->ctx_locals.ga_data) + idx)->lv_type; | |
1585 gen_load = TRUE; | |
1586 } | |
1587 else | |
1588 { | |
1589 if ((len == 4 && STRNCMP("true", *arg, 4) == 0) | |
1590 || (len == 5 && STRNCMP("false", *arg, 5) == 0)) | |
1591 res = generate_PUSHBOOL(cctx, **arg == 't' | |
1592 ? VVAL_TRUE : VVAL_FALSE); | |
1593 else | |
1594 res = compile_load_scriptvar(cctx, name); | |
1595 } | |
1596 } | |
1597 if (gen_load) | |
1598 res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type); | |
1599 } | |
1600 | |
1601 *arg = end; | |
1602 | |
1603 theend: | |
1604 if (res == FAIL && error) | |
1605 semsg(_(e_var_notfound), name); | |
1606 vim_free(name); | |
1607 return res; | |
1608 } | |
1609 | |
1610 /* | |
1611 * Compile the argument expressions. | |
1612 * "arg" points to just after the "(" and is advanced to after the ")" | |
1613 */ | |
1614 static int | |
1615 compile_arguments(char_u **arg, cctx_T *cctx, int *argcount) | |
1616 { | |
1617 char_u *p = *arg; | |
1618 | |
1619 while (*p != NUL && *p != ')') | |
1620 { | |
1621 if (compile_expr1(&p, cctx) == FAIL) | |
1622 return FAIL; | |
1623 ++*argcount; | |
1624 if (*p == ',') | |
1625 p = skipwhite(p + 1); | |
1626 } | |
1627 if (*p != ')') | |
1628 { | |
1629 emsg(_(e_missing_close)); | |
1630 return FAIL; | |
1631 } | |
1632 *arg = p + 1; | |
1633 return OK; | |
1634 } | |
1635 | |
1636 /* | |
1637 * Compile a function call: name(arg1, arg2) | |
1638 * "arg" points to "name", "arg + varlen" to the "(". | |
1639 * "argcount_init" is 1 for "value->method()" | |
1640 * Instructions: | |
1641 * EVAL arg1 | |
1642 * EVAL arg2 | |
1643 * BCALL / DCALL / UCALL | |
1644 */ | |
1645 static int | |
1646 compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init) | |
1647 { | |
1648 char_u *name = *arg; | |
1649 char_u *p = *arg + varlen + 1; | |
1650 int argcount = argcount_init; | |
1651 char_u namebuf[100]; | |
1652 ufunc_T *ufunc; | |
1653 | |
1654 if (varlen >= sizeof(namebuf)) | |
1655 { | |
1656 semsg(_("E1011: name too long: %s"), name); | |
1657 return FAIL; | |
1658 } | |
1659 vim_strncpy(namebuf, name, varlen); | |
1660 | |
1661 *arg = skipwhite(*arg + varlen + 1); | |
1662 if (compile_arguments(arg, cctx, &argcount) == FAIL) | |
1663 return FAIL; | |
1664 | |
1665 if (ASCII_ISLOWER(*name)) | |
1666 { | |
1667 int idx; | |
1668 | |
1669 // builtin function | |
1670 idx = find_internal_func(namebuf); | |
1671 if (idx >= 0) | |
1672 return generate_BCALL(cctx, idx, argcount); | |
1673 semsg(_(e_unknownfunc), namebuf); | |
1674 } | |
1675 | |
1676 // User defined function or variable must start with upper case. | |
1677 if (!ASCII_ISUPPER(*name)) | |
1678 { | |
1679 semsg(_("E1012: Invalid function name: %s"), namebuf); | |
1680 return FAIL; | |
1681 } | |
1682 | |
1683 // If we can find the function by name generate the right call. | |
1684 ufunc = find_func(namebuf, cctx); | |
1685 if (ufunc != NULL) | |
1686 return generate_CALL(cctx, ufunc, argcount); | |
1687 | |
1688 // If the name is a variable, load it and use PCALL. | |
1689 p = namebuf; | |
1690 if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) | |
1691 return generate_PCALL(cctx, argcount, FALSE); | |
1692 | |
1693 // The function may be defined only later. Need to figure out at runtime. | |
1694 return generate_UCALL(cctx, namebuf, argcount); | |
1695 } | |
1696 | |
1697 // like NAMESPACE_CHAR but with 'a' and 'l'. | |
1698 #define VIM9_NAMESPACE_CHAR (char_u *)"bgstvw" | |
1699 | |
1700 /* | |
1701 * Find the end of a variable or function name. Unlike find_name_end() this | |
1702 * does not recognize magic braces. | |
1703 * Return a pointer to just after the name. Equal to "arg" if there is no | |
1704 * valid name. | |
1705 */ | |
1706 char_u * | |
1707 to_name_end(char_u *arg) | |
1708 { | |
1709 char_u *p; | |
1710 | |
1711 // Quick check for valid starting character. | |
1712 if (!eval_isnamec1(*arg)) | |
1713 return arg; | |
1714 | |
1715 for (p = arg + 1; *p != NUL && eval_isnamec(*p); MB_PTR_ADV(p)) | |
1716 // Include a namespace such as "s:var" and "v:var". But "n:" is not | |
1717 // and can be used in slice "[n:]". | |
1718 if (*p == ':' && (p != arg + 1 | |
1719 || vim_strchr(VIM9_NAMESPACE_CHAR, *arg) == NULL)) | |
1720 break; | |
1721 return p; | |
1722 } | |
1723 | |
1724 /* | |
1725 * Like to_name_end() but also skip over a list or dict constant. | |
1726 */ | |
1727 char_u * | |
1728 to_name_const_end(char_u *arg) | |
1729 { | |
1730 char_u *p = to_name_end(arg); | |
1731 typval_T rettv; | |
1732 | |
1733 if (p == arg && *arg == '[') | |
1734 { | |
1735 | |
1736 // Can be "[1, 2, 3]->Func()". | |
1737 if (get_list_tv(&p, &rettv, FALSE, FALSE) == FAIL) | |
1738 p = arg; | |
1739 } | |
1740 else if (p == arg && *arg == '#' && arg[1] == '{') | |
1741 { | |
1742 ++p; | |
1743 if (eval_dict(&p, &rettv, FALSE, TRUE) == FAIL) | |
1744 p = arg; | |
1745 } | |
1746 else if (p == arg && *arg == '{') | |
1747 { | |
1748 int ret = get_lambda_tv(&p, &rettv, FALSE); | |
1749 | |
1750 if (ret == NOTDONE) | |
1751 ret = eval_dict(&p, &rettv, FALSE, FALSE); | |
1752 if (ret != OK) | |
1753 p = arg; | |
1754 } | |
1755 | |
1756 return p; | |
1757 } | |
1758 | |
1759 static void | |
1760 type_mismatch(type_T *expected, type_T *actual) | |
1761 { | |
1762 char *tofree1, *tofree2; | |
1763 | |
1764 semsg(_("E1013: type mismatch, expected %s but got %s"), | |
1765 type_name(expected, &tofree1), type_name(actual, &tofree2)); | |
1766 vim_free(tofree1); | |
1767 vim_free(tofree2); | |
1768 } | |
1769 | |
1770 /* | |
1771 * Check if the expected and actual types match. | |
1772 */ | |
1773 static int | |
1774 check_type(type_T *expected, type_T *actual, int give_msg) | |
1775 { | |
1776 if (expected->tt_type != VAR_UNKNOWN) | |
1777 { | |
1778 if (expected->tt_type != actual->tt_type) | |
1779 { | |
1780 if (give_msg) | |
1781 type_mismatch(expected, actual); | |
1782 return FAIL; | |
1783 } | |
1784 if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) | |
1785 { | |
1786 int ret = check_type(expected->tt_member, actual->tt_member, | |
1787 FALSE); | |
1788 if (ret == FAIL && give_msg) | |
1789 type_mismatch(expected, actual); | |
1790 return ret; | |
1791 } | |
1792 } | |
1793 return OK; | |
1794 } | |
1795 | |
1796 /* | |
1797 * Check that | |
1798 * - "actual" is "expected" type or | |
1799 * - "actual" is a type that can be "expected" type: add a runtime check; or | |
1800 * - return FAIL. | |
1801 */ | |
1802 static int | |
1803 need_type(type_T *actual, type_T *expected, int offset, cctx_T *cctx) | |
1804 { | |
1805 if (equal_type(actual, expected) || expected->tt_type == VAR_UNKNOWN) | |
1806 return OK; | |
1807 if (actual->tt_type != VAR_UNKNOWN) | |
1808 { | |
1809 type_mismatch(expected, actual); | |
1810 return FAIL; | |
1811 } | |
1812 generate_TYPECHECK(cctx, expected, offset); | |
1813 return OK; | |
1814 } | |
1815 | |
1816 /* | |
1817 * parse a list: [expr, expr] | |
1818 * "*arg" points to the '['. | |
1819 */ | |
1820 static int | |
1821 compile_list(char_u **arg, cctx_T *cctx) | |
1822 { | |
1823 char_u *p = skipwhite(*arg + 1); | |
1824 int count = 0; | |
1825 | |
1826 while (*p != ']') | |
1827 { | |
1828 if (*p == NUL) | |
1829 return FAIL; | |
1830 if (compile_expr1(&p, cctx) == FAIL) | |
1831 break; | |
1832 ++count; | |
1833 if (*p == ',') | |
1834 ++p; | |
1835 p = skipwhite(p); | |
1836 } | |
1837 *arg = p + 1; | |
1838 | |
1839 generate_NEWLIST(cctx, count); | |
1840 return OK; | |
1841 } | |
1842 | |
1843 /* | |
1844 * parse a lambda: {arg, arg -> expr} | |
1845 * "*arg" points to the '{'. | |
1846 */ | |
1847 static int | |
1848 compile_lambda(char_u **arg, cctx_T *cctx) | |
1849 { | |
1850 garray_T *instr = &cctx->ctx_instr; | |
1851 typval_T rettv; | |
1852 ufunc_T *ufunc; | |
1853 | |
1854 // Get the funcref in "rettv". | |
1855 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL) | |
1856 return FAIL; | |
1857 ufunc = rettv.vval.v_partial->pt_func; | |
1858 | |
1859 // The function will have one line: "return {expr}". | |
1860 // Compile it into instructions. | |
1861 compile_def_function(ufunc, TRUE); | |
1862 | |
1863 if (ufunc->uf_dfunc_idx >= 0) | |
1864 { | |
1865 if (ga_grow(instr, 1) == FAIL) | |
1866 return FAIL; | |
1867 generate_FUNCREF(cctx, ufunc->uf_dfunc_idx); | |
1868 return OK; | |
1869 } | |
1870 return FAIL; | |
1871 } | |
1872 | |
1873 /* | |
1874 * Compile a lamda call: expr->{lambda}(args) | |
1875 * "arg" points to the "{". | |
1876 */ | |
1877 static int | |
1878 compile_lambda_call(char_u **arg, cctx_T *cctx) | |
1879 { | |
1880 ufunc_T *ufunc; | |
1881 typval_T rettv; | |
1882 int argcount = 1; | |
1883 int ret = FAIL; | |
1884 | |
1885 // Get the funcref in "rettv". | |
1886 if (get_lambda_tv(arg, &rettv, TRUE) == FAIL) | |
1887 return FAIL; | |
1888 | |
1889 if (**arg != '(') | |
1890 { | |
1891 if (*skipwhite(*arg) == '(') | |
1892 semsg(_(e_nowhitespace)); | |
1893 else | |
1894 semsg(_(e_missing_paren), "lambda"); | |
1895 clear_tv(&rettv); | |
1896 return FAIL; | |
1897 } | |
1898 | |
1899 // The function will have one line: "return {expr}". | |
1900 // Compile it into instructions. | |
1901 ufunc = rettv.vval.v_partial->pt_func; | |
1902 ++ufunc->uf_refcount; | |
1903 compile_def_function(ufunc, TRUE); | |
1904 | |
1905 // compile the arguments | |
1906 *arg = skipwhite(*arg + 1); | |
1907 if (compile_arguments(arg, cctx, &argcount) == OK) | |
1908 // call the compiled function | |
1909 ret = generate_CALL(cctx, ufunc, argcount); | |
1910 | |
1911 clear_tv(&rettv); | |
1912 return ret; | |
1913 } | |
1914 | |
1915 /* | |
1916 * parse a dict: {'key': val} or #{key: val} | |
1917 * "*arg" points to the '{'. | |
1918 */ | |
1919 static int | |
1920 compile_dict(char_u **arg, cctx_T *cctx, int literal) | |
1921 { | |
1922 garray_T *instr = &cctx->ctx_instr; | |
1923 int count = 0; | |
1924 dict_T *d = dict_alloc(); | |
1925 dictitem_T *item; | |
1926 | |
1927 if (d == NULL) | |
1928 return FAIL; | |
1929 *arg = skipwhite(*arg + 1); | |
1930 while (**arg != '}' && **arg != NUL) | |
1931 { | |
1932 char_u *key = NULL; | |
1933 | |
1934 if (literal) | |
1935 { | |
1936 char_u *p = to_name_end(*arg); | |
1937 | |
1938 if (p == *arg) | |
1939 { | |
1940 semsg(_("E1014: Invalid key: %s"), *arg); | |
1941 return FAIL; | |
1942 } | |
1943 key = vim_strnsave(*arg, p - *arg); | |
1944 if (generate_PUSHS(cctx, key) == FAIL) | |
1945 return FAIL; | |
1946 *arg = p; | |
1947 } | |
1948 else | |
1949 { | |
1950 isn_T *isn; | |
1951 | |
1952 if (compile_expr1(arg, cctx) == FAIL) | |
1953 return FAIL; | |
1954 // TODO: check type is string | |
1955 isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1; | |
1956 if (isn->isn_type == ISN_PUSHS) | |
1957 key = isn->isn_arg.string; | |
1958 } | |
1959 | |
1960 // Check for duplicate keys, if using string keys. | |
1961 if (key != NULL) | |
1962 { | |
1963 item = dict_find(d, key, -1); | |
1964 if (item != NULL) | |
1965 { | |
1966 semsg(_(e_duplicate_key), key); | |
1967 goto failret; | |
1968 } | |
1969 item = dictitem_alloc(key); | |
1970 if (item != NULL) | |
1971 { | |
1972 item->di_tv.v_type = VAR_UNKNOWN; | |
1973 item->di_tv.v_lock = 0; | |
1974 if (dict_add(d, item) == FAIL) | |
1975 dictitem_free(item); | |
1976 } | |
1977 } | |
1978 | |
1979 *arg = skipwhite(*arg); | |
1980 if (**arg != ':') | |
1981 { | |
1982 semsg(_(e_missing_dict_colon), *arg); | |
1983 return FAIL; | |
1984 } | |
1985 | |
1986 *arg = skipwhite(*arg + 1); | |
1987 if (compile_expr1(arg, cctx) == FAIL) | |
1988 return FAIL; | |
1989 ++count; | |
1990 | |
1991 if (**arg == '}') | |
1992 break; | |
1993 if (**arg != ',') | |
1994 { | |
1995 semsg(_(e_missing_dict_comma), *arg); | |
1996 goto failret; | |
1997 } | |
1998 *arg = skipwhite(*arg + 1); | |
1999 } | |
2000 | |
2001 if (**arg != '}') | |
2002 { | |
2003 semsg(_(e_missing_dict_end), *arg); | |
2004 goto failret; | |
2005 } | |
2006 *arg = *arg + 1; | |
2007 | |
2008 dict_unref(d); | |
2009 return generate_NEWDICT(cctx, count); | |
2010 | |
2011 failret: | |
2012 dict_unref(d); | |
2013 return FAIL; | |
2014 } | |
2015 | |
2016 /* | |
2017 * Compile "&option". | |
2018 */ | |
2019 static int | |
2020 compile_get_option(char_u **arg, cctx_T *cctx) | |
2021 { | |
2022 typval_T rettv; | |
2023 char_u *start = *arg; | |
2024 int ret; | |
2025 | |
2026 // parse the option and get the current value to get the type. | |
2027 rettv.v_type = VAR_UNKNOWN; | |
2028 ret = get_option_tv(arg, &rettv, TRUE); | |
2029 if (ret == OK) | |
2030 { | |
2031 // include the '&' in the name, get_option_tv() expects it. | |
2032 char_u *name = vim_strnsave(start, *arg - start); | |
2033 type_T *type = rettv.v_type == VAR_NUMBER ? &t_number : &t_string; | |
2034 | |
2035 ret = generate_LOAD(cctx, ISN_LOADOPT, 0, name, type); | |
2036 vim_free(name); | |
2037 } | |
2038 clear_tv(&rettv); | |
2039 | |
2040 return ret; | |
2041 } | |
2042 | |
2043 /* | |
2044 * Compile "$VAR". | |
2045 */ | |
2046 static int | |
2047 compile_get_env(char_u **arg, cctx_T *cctx) | |
2048 { | |
2049 char_u *start = *arg; | |
2050 int len; | |
2051 int ret; | |
2052 char_u *name; | |
2053 | |
2054 start = *arg; | |
2055 ++*arg; | |
2056 len = get_env_len(arg); | |
2057 if (len == 0) | |
2058 { | |
2059 semsg(_(e_syntax_at), start - 1); | |
2060 return FAIL; | |
2061 } | |
2062 | |
2063 // include the '$' in the name, get_env_tv() expects it. | |
2064 name = vim_strnsave(start, len + 1); | |
2065 ret = generate_LOAD(cctx, ISN_LOADENV, 0, name, &t_string); | |
2066 vim_free(name); | |
2067 return ret; | |
2068 } | |
2069 | |
2070 /* | |
2071 * Compile "@r". | |
2072 */ | |
2073 static int | |
2074 compile_get_register(char_u **arg, cctx_T *cctx) | |
2075 { | |
2076 int ret; | |
2077 | |
2078 ++*arg; | |
2079 if (**arg == NUL) | |
2080 { | |
2081 semsg(_(e_syntax_at), *arg - 1); | |
2082 return FAIL; | |
2083 } | |
2084 if (!valid_yank_reg(**arg, TRUE)) | |
2085 { | |
2086 emsg_invreg(**arg); | |
2087 return FAIL; | |
2088 } | |
2089 ret = generate_LOAD(cctx, ISN_LOADREG, **arg, NULL, &t_string); | |
2090 ++*arg; | |
2091 return ret; | |
2092 } | |
2093 | |
2094 /* | |
2095 * Apply leading '!', '-' and '+' to constant "rettv". | |
2096 */ | |
2097 static int | |
2098 apply_leader(typval_T *rettv, char_u *start, char_u *end) | |
2099 { | |
2100 char_u *p = end; | |
2101 | |
2102 // this works from end to start | |
2103 while (p > start) | |
2104 { | |
2105 --p; | |
2106 if (*p == '-' || *p == '+') | |
2107 { | |
2108 // only '-' has an effect, for '+' we only check the type | |
2109 #ifdef FEAT_FLOAT | |
2110 if (rettv->v_type == VAR_FLOAT) | |
2111 { | |
2112 if (*p == '-') | |
2113 rettv->vval.v_float = -rettv->vval.v_float; | |
2114 } | |
2115 else | |
2116 #endif | |
2117 { | |
2118 varnumber_T val; | |
2119 int error = FALSE; | |
2120 | |
2121 // tv_get_number_chk() accepts a string, but we don't want that | |
2122 // here | |
2123 if (check_not_string(rettv) == FAIL) | |
2124 return FAIL; | |
2125 val = tv_get_number_chk(rettv, &error); | |
2126 clear_tv(rettv); | |
2127 if (error) | |
2128 return FAIL; | |
2129 if (*p == '-') | |
2130 val = -val; | |
2131 rettv->v_type = VAR_NUMBER; | |
2132 rettv->vval.v_number = val; | |
2133 } | |
2134 } | |
2135 else | |
2136 { | |
2137 int v = tv2bool(rettv); | |
2138 | |
2139 // '!' is permissive in the type. | |
2140 clear_tv(rettv); | |
2141 rettv->v_type = VAR_BOOL; | |
2142 rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE; | |
2143 } | |
2144 } | |
2145 return OK; | |
2146 } | |
2147 | |
2148 /* | |
2149 * Recognize v: variables that are constants and set "rettv". | |
2150 */ | |
2151 static void | |
2152 get_vim_constant(char_u **arg, typval_T *rettv) | |
2153 { | |
2154 if (STRNCMP(*arg, "v:true", 6) == 0) | |
2155 { | |
2156 rettv->v_type = VAR_BOOL; | |
2157 rettv->vval.v_number = VVAL_TRUE; | |
2158 *arg += 6; | |
2159 } | |
2160 else if (STRNCMP(*arg, "v:false", 7) == 0) | |
2161 { | |
2162 rettv->v_type = VAR_BOOL; | |
2163 rettv->vval.v_number = VVAL_FALSE; | |
2164 *arg += 7; | |
2165 } | |
2166 else if (STRNCMP(*arg, "v:null", 6) == 0) | |
2167 { | |
2168 rettv->v_type = VAR_SPECIAL; | |
2169 rettv->vval.v_number = VVAL_NULL; | |
2170 *arg += 6; | |
2171 } | |
2172 else if (STRNCMP(*arg, "v:none", 6) == 0) | |
2173 { | |
2174 rettv->v_type = VAR_SPECIAL; | |
2175 rettv->vval.v_number = VVAL_NONE; | |
2176 *arg += 6; | |
2177 } | |
2178 } | |
2179 | |
2180 /* | |
2181 * Compile code to apply '-', '+' and '!'. | |
2182 */ | |
2183 static int | |
2184 compile_leader(cctx_T *cctx, char_u *start, char_u *end) | |
2185 { | |
2186 char_u *p = end; | |
2187 | |
2188 // this works from end to start | |
2189 while (p > start) | |
2190 { | |
2191 --p; | |
2192 if (*p == '-' || *p == '+') | |
2193 { | |
2194 int negate = *p == '-'; | |
2195 isn_T *isn; | |
2196 | |
2197 // TODO: check type | |
2198 while (p > start && (p[-1] == '-' || p[-1] == '+')) | |
2199 { | |
2200 --p; | |
2201 if (*p == '-') | |
2202 negate = !negate; | |
2203 } | |
2204 // only '-' has an effect, for '+' we only check the type | |
2205 if (negate) | |
2206 isn = generate_instr(cctx, ISN_NEGATENR); | |
2207 else | |
2208 isn = generate_instr(cctx, ISN_CHECKNR); | |
2209 if (isn == NULL) | |
2210 return FAIL; | |
2211 } | |
2212 else | |
2213 { | |
2214 int invert = TRUE; | |
2215 | |
2216 while (p > start && p[-1] == '!') | |
2217 { | |
2218 --p; | |
2219 invert = !invert; | |
2220 } | |
2221 if (generate_2BOOL(cctx, invert) == FAIL) | |
2222 return FAIL; | |
2223 } | |
2224 } | |
2225 return OK; | |
2226 } | |
2227 | |
2228 /* | |
2229 * Compile whatever comes after "name" or "name()". | |
2230 */ | |
2231 static int | |
2232 compile_subscript( | |
2233 char_u **arg, | |
2234 cctx_T *cctx, | |
2235 char_u **start_leader, | |
2236 char_u *end_leader) | |
2237 { | |
2238 for (;;) | |
2239 { | |
2240 if (**arg == '(') | |
2241 { | |
2242 int argcount = 0; | |
2243 | |
2244 // funcref(arg) | |
2245 *arg = skipwhite(*arg + 1); | |
2246 if (compile_arguments(arg, cctx, &argcount) == FAIL) | |
2247 return FAIL; | |
2248 if (generate_PCALL(cctx, argcount, TRUE) == FAIL) | |
2249 return FAIL; | |
2250 } | |
2251 else if (**arg == '-' && (*arg)[1] == '>') | |
2252 { | |
2253 char_u *p; | |
2254 | |
2255 // something->method() | |
2256 // Apply the '!', '-' and '+' first: | |
2257 // -1.0->func() works like (-1.0)->func() | |
2258 if (compile_leader(cctx, *start_leader, end_leader) == FAIL) | |
2259 return FAIL; | |
2260 *start_leader = end_leader; // don't apply again later | |
2261 | |
2262 *arg = skipwhite(*arg + 2); | |
2263 if (**arg == '{') | |
2264 { | |
2265 // lambda call: list->{lambda} | |
2266 if (compile_lambda_call(arg, cctx) == FAIL) | |
2267 return FAIL; | |
2268 } | |
2269 else | |
2270 { | |
2271 // method call: list->method() | |
2272 for (p = *arg; eval_isnamec1(*p); ++p) | |
2273 ; | |
2274 if (*p != '(') | |
2275 { | |
2276 semsg(_(e_missing_paren), arg); | |
2277 return FAIL; | |
2278 } | |
2279 // TODO: base value may not be the first argument | |
2280 if (compile_call(arg, p - *arg, cctx, 1) == FAIL) | |
2281 return FAIL; | |
2282 } | |
2283 } | |
2284 else if (**arg == '[') | |
2285 { | |
2286 // list index: list[123] | |
2287 // TODO: more arguments | |
2288 // TODO: dict member dict['name'] | |
2289 *arg = skipwhite(*arg + 1); | |
2290 if (compile_expr1(arg, cctx) == FAIL) | |
2291 return FAIL; | |
2292 | |
2293 if (**arg != ']') | |
2294 { | |
2295 emsg(_(e_missbrac)); | |
2296 return FAIL; | |
2297 } | |
2298 *arg = skipwhite(*arg + 1); | |
2299 | |
2300 if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL) | |
2301 return FAIL; | |
2302 } | |
2303 else if (**arg == '.' && (*arg)[1] != '.') | |
2304 { | |
2305 char_u *p; | |
2306 | |
2307 ++*arg; | |
2308 p = *arg; | |
2309 // dictionary member: dict.name | |
2310 if (eval_isnamec1(*p)) | |
2311 while (eval_isnamec(*p)) | |
2312 MB_PTR_ADV(p); | |
2313 if (p == *arg) | |
2314 { | |
2315 semsg(_(e_syntax_at), *arg); | |
2316 return FAIL; | |
2317 } | |
2318 // TODO: check type is dict | |
2319 if (generate_MEMBER(cctx, *arg, p - *arg) == FAIL) | |
2320 return FAIL; | |
2321 *arg = p; | |
2322 } | |
2323 else | |
2324 break; | |
2325 } | |
2326 | |
2327 // TODO - see handle_subscript(): | |
2328 // Turn "dict.Func" into a partial for "Func" bound to "dict". | |
2329 // Don't do this when "Func" is already a partial that was bound | |
2330 // explicitly (pt_auto is FALSE). | |
2331 | |
2332 return OK; | |
2333 } | |
2334 | |
2335 /* | |
2336 * Compile an expression at "*p" and add instructions to "instr". | |
2337 * "p" is advanced until after the expression, skipping white space. | |
2338 * | |
2339 * This is the equivalent of eval1(), eval2(), etc. | |
2340 */ | |
2341 | |
2342 /* | |
2343 * number number constant | |
2344 * 0zFFFFFFFF Blob constant | |
2345 * "string" string constant | |
2346 * 'string' literal string constant | |
2347 * &option-name option value | |
2348 * @r register contents | |
2349 * identifier variable value | |
2350 * function() function call | |
2351 * $VAR environment variable | |
2352 * (expression) nested expression | |
2353 * [expr, expr] List | |
2354 * {key: val, key: val} Dictionary | |
2355 * #{key: val, key: val} Dictionary with literal keys | |
2356 * | |
2357 * Also handle: | |
2358 * ! in front logical NOT | |
2359 * - in front unary minus | |
2360 * + in front unary plus (ignored) | |
2361 * trailing (arg) funcref/partial call | |
2362 * trailing [] subscript in String or List | |
2363 * trailing .name entry in Dictionary | |
2364 * trailing ->name() method call | |
2365 */ | |
2366 static int | |
2367 compile_expr7(char_u **arg, cctx_T *cctx) | |
2368 { | |
2369 typval_T rettv; | |
2370 char_u *start_leader, *end_leader; | |
2371 int ret = OK; | |
2372 | |
2373 /* | |
2374 * Skip '!', '-' and '+' characters. They are handled later. | |
2375 */ | |
2376 start_leader = *arg; | |
2377 while (**arg == '!' || **arg == '-' || **arg == '+') | |
2378 *arg = skipwhite(*arg + 1); | |
2379 end_leader = *arg; | |
2380 | |
2381 rettv.v_type = VAR_UNKNOWN; | |
2382 switch (**arg) | |
2383 { | |
2384 /* | |
2385 * Number constant. | |
2386 */ | |
2387 case '0': // also for blob starting with 0z | |
2388 case '1': | |
2389 case '2': | |
2390 case '3': | |
2391 case '4': | |
2392 case '5': | |
2393 case '6': | |
2394 case '7': | |
2395 case '8': | |
2396 case '9': | |
2397 case '.': if (get_number_tv(arg, &rettv, TRUE, FALSE) == FAIL) | |
2398 return FAIL; | |
2399 break; | |
2400 | |
2401 /* | |
2402 * String constant: "string". | |
2403 */ | |
2404 case '"': if (get_string_tv(arg, &rettv, TRUE) == FAIL) | |
2405 return FAIL; | |
2406 break; | |
2407 | |
2408 /* | |
2409 * Literal string constant: 'str''ing'. | |
2410 */ | |
2411 case '\'': if (get_lit_string_tv(arg, &rettv, TRUE) == FAIL) | |
2412 return FAIL; | |
2413 break; | |
2414 | |
2415 /* | |
2416 * Constant Vim variable. | |
2417 */ | |
2418 case 'v': get_vim_constant(arg, &rettv); | |
2419 ret = NOTDONE; | |
2420 break; | |
2421 | |
2422 /* | |
2423 * List: [expr, expr] | |
2424 */ | |
2425 case '[': ret = compile_list(arg, cctx); | |
2426 break; | |
2427 | |
2428 /* | |
2429 * Dictionary: #{key: val, key: val} | |
2430 */ | |
2431 case '#': if ((*arg)[1] == '{') | |
2432 { | |
2433 ++*arg; | |
2434 ret = compile_dict(arg, cctx, TRUE); | |
2435 } | |
2436 else | |
2437 ret = NOTDONE; | |
2438 break; | |
2439 | |
2440 /* | |
2441 * Lambda: {arg, arg -> expr} | |
2442 * Dictionary: {'key': val, 'key': val} | |
2443 */ | |
2444 case '{': { | |
2445 char_u *start = skipwhite(*arg + 1); | |
2446 | |
2447 // Find out what comes after the arguments. | |
2448 ret = get_function_args(&start, '-', NULL, | |
2449 NULL, NULL, NULL, TRUE); | |
2450 if (ret != FAIL && *start == '>') | |
2451 ret = compile_lambda(arg, cctx); | |
2452 else | |
2453 ret = compile_dict(arg, cctx, FALSE); | |
2454 } | |
2455 break; | |
2456 | |
2457 /* | |
2458 * Option value: &name | |
2459 */ | |
2460 case '&': ret = compile_get_option(arg, cctx); | |
2461 break; | |
2462 | |
2463 /* | |
2464 * Environment variable: $VAR. | |
2465 */ | |
2466 case '$': ret = compile_get_env(arg, cctx); | |
2467 break; | |
2468 | |
2469 /* | |
2470 * Register contents: @r. | |
2471 */ | |
2472 case '@': ret = compile_get_register(arg, cctx); | |
2473 break; | |
2474 /* | |
2475 * nested expression: (expression). | |
2476 */ | |
2477 case '(': *arg = skipwhite(*arg + 1); | |
2478 ret = compile_expr1(arg, cctx); // recursive! | |
2479 *arg = skipwhite(*arg); | |
2480 if (**arg == ')') | |
2481 ++*arg; | |
2482 else if (ret == OK) | |
2483 { | |
2484 emsg(_(e_missing_close)); | |
2485 ret = FAIL; | |
2486 } | |
2487 break; | |
2488 | |
2489 default: ret = NOTDONE; | |
2490 break; | |
2491 } | |
2492 if (ret == FAIL) | |
2493 return FAIL; | |
2494 | |
2495 if (rettv.v_type != VAR_UNKNOWN) | |
2496 { | |
2497 // apply the '!', '-' and '+' before the constant | |
2498 if (apply_leader(&rettv, start_leader, end_leader) == FAIL) | |
2499 { | |
2500 clear_tv(&rettv); | |
2501 return FAIL; | |
2502 } | |
2503 start_leader = end_leader; // don't apply again below | |
2504 | |
2505 // push constant | |
2506 switch (rettv.v_type) | |
2507 { | |
2508 case VAR_BOOL: | |
2509 generate_PUSHBOOL(cctx, rettv.vval.v_number); | |
2510 break; | |
2511 case VAR_SPECIAL: | |
2512 generate_PUSHSPEC(cctx, rettv.vval.v_number); | |
2513 break; | |
2514 case VAR_NUMBER: | |
2515 generate_PUSHNR(cctx, rettv.vval.v_number); | |
2516 break; | |
2517 #ifdef FEAT_FLOAT | |
2518 case VAR_FLOAT: | |
2519 generate_PUSHF(cctx, rettv.vval.v_float); | |
2520 break; | |
2521 #endif | |
2522 case VAR_BLOB: | |
2523 generate_PUSHBLOB(cctx, rettv.vval.v_blob); | |
2524 rettv.vval.v_blob = NULL; | |
2525 break; | |
2526 case VAR_STRING: | |
2527 generate_PUSHS(cctx, rettv.vval.v_string); | |
2528 rettv.vval.v_string = NULL; | |
2529 break; | |
2530 default: | |
2531 iemsg("constant type missing"); | |
2532 return FAIL; | |
2533 } | |
2534 } | |
2535 else if (ret == NOTDONE) | |
2536 { | |
2537 char_u *p; | |
2538 int r; | |
2539 | |
2540 if (!eval_isnamec1(**arg)) | |
2541 { | |
2542 semsg(_("E1015: Name expected: %s"), *arg); | |
2543 return FAIL; | |
2544 } | |
2545 | |
2546 // "name" or "name()" | |
2547 p = to_name_end(*arg); | |
2548 if (*p == '(') | |
2549 r = compile_call(arg, p - *arg, cctx, 0); | |
2550 else | |
2551 r = compile_load(arg, p, cctx, TRUE); | |
2552 if (r == FAIL) | |
2553 return FAIL; | |
2554 } | |
2555 | |
2556 if (compile_subscript(arg, cctx, &start_leader, end_leader) == FAIL) | |
2557 return FAIL; | |
2558 | |
2559 // Now deal with prefixed '-', '+' and '!', if not done already. | |
2560 return compile_leader(cctx, start_leader, end_leader); | |
2561 } | |
2562 | |
2563 /* | |
2564 * * number multiplication | |
2565 * / number division | |
2566 * % number modulo | |
2567 */ | |
2568 static int | |
2569 compile_expr6(char_u **arg, cctx_T *cctx) | |
2570 { | |
2571 char_u *op; | |
2572 | |
2573 // get the first variable | |
2574 if (compile_expr7(arg, cctx) == FAIL) | |
2575 return FAIL; | |
2576 | |
2577 /* | |
2578 * Repeat computing, until no "*", "/" or "%" is following. | |
2579 */ | |
2580 for (;;) | |
2581 { | |
2582 op = skipwhite(*arg); | |
2583 if (*op != '*' && *op != '/' && *op != '%') | |
2584 break; | |
2585 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[1])) | |
2586 { | |
2587 char_u buf[3]; | |
2588 | |
2589 vim_strncpy(buf, op, 1); | |
2590 semsg(_(e_white_both), buf); | |
2591 } | |
2592 *arg = skipwhite(op + 1); | |
2593 | |
2594 // get the second variable | |
2595 if (compile_expr7(arg, cctx) == FAIL) | |
2596 return FAIL; | |
2597 | |
2598 generate_two_op(cctx, op); | |
2599 } | |
2600 | |
2601 return OK; | |
2602 } | |
2603 | |
2604 /* | |
2605 * + number addition | |
2606 * - number subtraction | |
2607 * .. string concatenation | |
2608 */ | |
2609 static int | |
2610 compile_expr5(char_u **arg, cctx_T *cctx) | |
2611 { | |
2612 char_u *op; | |
2613 int oplen; | |
2614 | |
2615 // get the first variable | |
2616 if (compile_expr6(arg, cctx) == FAIL) | |
2617 return FAIL; | |
2618 | |
2619 /* | |
2620 * Repeat computing, until no "+", "-" or ".." is following. | |
2621 */ | |
2622 for (;;) | |
2623 { | |
2624 op = skipwhite(*arg); | |
2625 if (*op != '+' && *op != '-' && !(*op == '.' && (*(*arg + 1) == '.'))) | |
2626 break; | |
2627 oplen = (*op == '.' ? 2 : 1); | |
2628 | |
2629 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(op[oplen])) | |
2630 { | |
2631 char_u buf[3]; | |
2632 | |
2633 vim_strncpy(buf, op, oplen); | |
2634 semsg(_(e_white_both), buf); | |
2635 } | |
2636 | |
2637 *arg = skipwhite(op + oplen); | |
2638 | |
2639 // get the second variable | |
2640 if (compile_expr6(arg, cctx) == FAIL) | |
2641 return FAIL; | |
2642 | |
2643 if (*op == '.') | |
2644 { | |
2645 if (may_generate_2STRING(-2, cctx) == FAIL | |
2646 || may_generate_2STRING(-1, cctx) == FAIL) | |
2647 return FAIL; | |
2648 generate_instr_drop(cctx, ISN_CONCAT, 1); | |
2649 } | |
2650 else | |
2651 generate_two_op(cctx, op); | |
2652 } | |
2653 | |
2654 return OK; | |
2655 } | |
2656 | |
2657 /* | |
2658 * expr5a == expr5b | |
2659 * expr5a =~ expr5b | |
2660 * expr5a != expr5b | |
2661 * expr5a !~ expr5b | |
2662 * expr5a > expr5b | |
2663 * expr5a >= expr5b | |
2664 * expr5a < expr5b | |
2665 * expr5a <= expr5b | |
2666 * expr5a is expr5b | |
2667 * expr5a isnot expr5b | |
2668 * | |
2669 * Produces instructions: | |
2670 * EVAL expr5a Push result of "expr5a" | |
2671 * EVAL expr5b Push result of "expr5b" | |
2672 * COMPARE one of the compare instructions | |
2673 */ | |
2674 static int | |
2675 compile_expr4(char_u **arg, cctx_T *cctx) | |
2676 { | |
2677 exptype_T type = EXPR_UNKNOWN; | |
2678 char_u *p; | |
2679 int len = 2; | |
2680 int i; | |
2681 int type_is = FALSE; | |
2682 | |
2683 // get the first variable | |
2684 if (compile_expr5(arg, cctx) == FAIL) | |
2685 return FAIL; | |
2686 | |
2687 p = skipwhite(*arg); | |
2688 switch (p[0]) | |
2689 { | |
2690 case '=': if (p[1] == '=') | |
2691 type = EXPR_EQUAL; | |
2692 else if (p[1] == '~') | |
2693 type = EXPR_MATCH; | |
2694 break; | |
2695 case '!': if (p[1] == '=') | |
2696 type = EXPR_NEQUAL; | |
2697 else if (p[1] == '~') | |
2698 type = EXPR_NOMATCH; | |
2699 break; | |
2700 case '>': if (p[1] != '=') | |
2701 { | |
2702 type = EXPR_GREATER; | |
2703 len = 1; | |
2704 } | |
2705 else | |
2706 type = EXPR_GEQUAL; | |
2707 break; | |
2708 case '<': if (p[1] != '=') | |
2709 { | |
2710 type = EXPR_SMALLER; | |
2711 len = 1; | |
2712 } | |
2713 else | |
2714 type = EXPR_SEQUAL; | |
2715 break; | |
2716 case 'i': if (p[1] == 's') | |
2717 { | |
2718 // "is" and "isnot"; but not a prefix of a name | |
2719 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') | |
2720 len = 5; | |
2721 i = p[len]; | |
2722 if (!isalnum(i) && i != '_') | |
2723 { | |
2724 type = len == 2 ? EXPR_IS : EXPR_ISNOT; | |
2725 type_is = TRUE; | |
2726 } | |
2727 } | |
2728 break; | |
2729 } | |
2730 | |
2731 /* | |
2732 * If there is a comparative operator, use it. | |
2733 */ | |
2734 if (type != EXPR_UNKNOWN) | |
2735 { | |
2736 int ic = FALSE; // Default: do not ignore case | |
2737 | |
2738 if (type_is && (p[len] == '?' || p[len] == '#')) | |
2739 { | |
2740 semsg(_(e_invexpr2), *arg); | |
2741 return FAIL; | |
2742 } | |
2743 // extra question mark appended: ignore case | |
2744 if (p[len] == '?') | |
2745 { | |
2746 ic = TRUE; | |
2747 ++len; | |
2748 } | |
2749 // extra '#' appended: match case (ignored) | |
2750 else if (p[len] == '#') | |
2751 ++len; | |
2752 // nothing appended: match case | |
2753 | |
2754 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[len])) | |
2755 { | |
2756 char_u buf[7]; | |
2757 | |
2758 vim_strncpy(buf, p, len); | |
2759 semsg(_(e_white_both), buf); | |
2760 } | |
2761 | |
2762 // get the second variable | |
2763 *arg = skipwhite(p + len); | |
2764 if (compile_expr5(arg, cctx) == FAIL) | |
2765 return FAIL; | |
2766 | |
2767 generate_COMPARE(cctx, type, ic); | |
2768 } | |
2769 | |
2770 return OK; | |
2771 } | |
2772 | |
2773 /* | |
2774 * Compile || or &&. | |
2775 */ | |
2776 static int | |
2777 compile_and_or(char_u **arg, cctx_T *cctx, char *op) | |
2778 { | |
2779 char_u *p = skipwhite(*arg); | |
2780 int opchar = *op; | |
2781 | |
2782 if (p[0] == opchar && p[1] == opchar) | |
2783 { | |
2784 garray_T *instr = &cctx->ctx_instr; | |
2785 garray_T end_ga; | |
2786 | |
2787 /* | |
2788 * Repeat until there is no following "||" or "&&" | |
2789 */ | |
2790 ga_init2(&end_ga, sizeof(int), 10); | |
2791 while (p[0] == opchar && p[1] == opchar) | |
2792 { | |
2793 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[2])) | |
2794 semsg(_(e_white_both), op); | |
2795 | |
2796 if (ga_grow(&end_ga, 1) == FAIL) | |
2797 { | |
2798 ga_clear(&end_ga); | |
2799 return FAIL; | |
2800 } | |
2801 *(((int *)end_ga.ga_data) + end_ga.ga_len) = instr->ga_len; | |
2802 ++end_ga.ga_len; | |
2803 generate_JUMP(cctx, opchar == '|' | |
2804 ? JUMP_AND_KEEP_IF_TRUE : JUMP_AND_KEEP_IF_FALSE, 0); | |
2805 | |
2806 // eval the next expression | |
2807 *arg = skipwhite(p + 2); | |
2808 if ((opchar == '|' ? compile_expr3(arg, cctx) | |
2809 : compile_expr4(arg, cctx)) == FAIL) | |
2810 { | |
2811 ga_clear(&end_ga); | |
2812 return FAIL; | |
2813 } | |
2814 p = skipwhite(*arg); | |
2815 } | |
2816 | |
2817 // Fill in the end label in all jumps. | |
2818 while (end_ga.ga_len > 0) | |
2819 { | |
2820 isn_T *isn; | |
2821 | |
2822 --end_ga.ga_len; | |
2823 isn = ((isn_T *)instr->ga_data) | |
2824 + *(((int *)end_ga.ga_data) + end_ga.ga_len); | |
2825 isn->isn_arg.jump.jump_where = instr->ga_len; | |
2826 } | |
2827 ga_clear(&end_ga); | |
2828 } | |
2829 | |
2830 return OK; | |
2831 } | |
2832 | |
2833 /* | |
2834 * expr4a && expr4a && expr4a logical AND | |
2835 * | |
2836 * Produces instructions: | |
2837 * EVAL expr4a Push result of "expr4a" | |
2838 * JUMP_AND_KEEP_IF_FALSE end | |
2839 * EVAL expr4b Push result of "expr4b" | |
2840 * JUMP_AND_KEEP_IF_FALSE end | |
2841 * EVAL expr4c Push result of "expr4c" | |
2842 * end: | |
2843 */ | |
2844 static int | |
2845 compile_expr3(char_u **arg, cctx_T *cctx) | |
2846 { | |
2847 // get the first variable | |
2848 if (compile_expr4(arg, cctx) == FAIL) | |
2849 return FAIL; | |
2850 | |
2851 // || and && work almost the same | |
2852 return compile_and_or(arg, cctx, "&&"); | |
2853 } | |
2854 | |
2855 /* | |
2856 * expr3a || expr3b || expr3c logical OR | |
2857 * | |
2858 * Produces instructions: | |
2859 * EVAL expr3a Push result of "expr3a" | |
2860 * JUMP_AND_KEEP_IF_TRUE end | |
2861 * EVAL expr3b Push result of "expr3b" | |
2862 * JUMP_AND_KEEP_IF_TRUE end | |
2863 * EVAL expr3c Push result of "expr3c" | |
2864 * end: | |
2865 */ | |
2866 static int | |
2867 compile_expr2(char_u **arg, cctx_T *cctx) | |
2868 { | |
2869 // eval the first expression | |
2870 if (compile_expr3(arg, cctx) == FAIL) | |
2871 return FAIL; | |
2872 | |
2873 // || and && work almost the same | |
2874 return compile_and_or(arg, cctx, "||"); | |
2875 } | |
2876 | |
2877 /* | |
2878 * Toplevel expression: expr2 ? expr1a : expr1b | |
2879 * | |
2880 * Produces instructions: | |
2881 * EVAL expr2 Push result of "expr" | |
2882 * JUMP_IF_FALSE alt jump if false | |
2883 * EVAL expr1a | |
2884 * JUMP_ALWAYS end | |
2885 * alt: EVAL expr1b | |
2886 * end: | |
2887 */ | |
2888 static int | |
2889 compile_expr1(char_u **arg, cctx_T *cctx) | |
2890 { | |
2891 char_u *p; | |
2892 | |
2893 // evaluate the first expression | |
2894 if (compile_expr2(arg, cctx) == FAIL) | |
2895 return FAIL; | |
2896 | |
2897 p = skipwhite(*arg); | |
2898 if (*p == '?') | |
2899 { | |
2900 garray_T *instr = &cctx->ctx_instr; | |
2901 garray_T *stack = &cctx->ctx_type_stack; | |
2902 int alt_idx = instr->ga_len; | |
2903 int end_idx; | |
2904 isn_T *isn; | |
2905 type_T *type1; | |
2906 type_T *type2; | |
2907 | |
2908 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1])) | |
2909 semsg(_(e_white_both), "?"); | |
2910 | |
2911 generate_JUMP(cctx, JUMP_IF_FALSE, 0); | |
2912 | |
2913 // evaluate the second expression; any type is accepted | |
2914 *arg = skipwhite(p + 1); | |
2915 compile_expr1(arg, cctx); | |
2916 | |
2917 // remember the type and drop it | |
2918 --stack->ga_len; | |
2919 type1 = ((type_T **)stack->ga_data)[stack->ga_len]; | |
2920 | |
2921 end_idx = instr->ga_len; | |
2922 generate_JUMP(cctx, JUMP_ALWAYS, 0); | |
2923 | |
2924 // jump here from JUMP_IF_FALSE | |
2925 isn = ((isn_T *)instr->ga_data) + alt_idx; | |
2926 isn->isn_arg.jump.jump_where = instr->ga_len; | |
2927 | |
2928 // Check for the ":". | |
2929 p = skipwhite(*arg); | |
2930 if (*p != ':') | |
2931 { | |
2932 emsg(_(e_missing_colon)); | |
2933 return FAIL; | |
2934 } | |
2935 if (!VIM_ISWHITE(**arg) || !VIM_ISWHITE(p[1])) | |
2936 semsg(_(e_white_both), ":"); | |
2937 | |
2938 // evaluate the third expression | |
2939 *arg = skipwhite(p + 1); | |
2940 compile_expr1(arg, cctx); | |
2941 | |
2942 // If the types differ, the result has a more generic type. | |
2943 type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
2944 common_type(type1, type2, type2); | |
2945 | |
2946 // jump here from JUMP_ALWAYS | |
2947 isn = ((isn_T *)instr->ga_data) + end_idx; | |
2948 isn->isn_arg.jump.jump_where = instr->ga_len; | |
2949 } | |
2950 return OK; | |
2951 } | |
2952 | |
2953 /* | |
2954 * compile "return [expr]" | |
2955 */ | |
2956 static char_u * | |
2957 compile_return(char_u *arg, int set_return_type, cctx_T *cctx) | |
2958 { | |
2959 char_u *p = arg; | |
2960 garray_T *stack = &cctx->ctx_type_stack; | |
2961 type_T *stack_type; | |
2962 | |
2963 if (*p != NUL && *p != '|' && *p != '\n') | |
2964 { | |
2965 // compile return argument into instructions | |
2966 if (compile_expr1(&p, cctx) == FAIL) | |
2967 return NULL; | |
2968 | |
2969 stack_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
2970 if (set_return_type) | |
2971 cctx->ctx_ufunc->uf_ret_type = stack_type; | |
2972 else if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, cctx) | |
2973 == FAIL) | |
2974 return NULL; | |
2975 } | |
2976 else | |
2977 { | |
2978 if (set_return_type) | |
2979 cctx->ctx_ufunc->uf_ret_type = &t_void; | |
2980 else if (cctx->ctx_ufunc->uf_ret_type->tt_type != VAR_VOID) | |
2981 { | |
2982 emsg(_("E1003: Missing return value")); | |
2983 return NULL; | |
2984 } | |
2985 | |
2986 // No argument, return zero. | |
2987 generate_PUSHNR(cctx, 0); | |
2988 } | |
2989 | |
2990 if (generate_instr(cctx, ISN_RETURN) == NULL) | |
2991 return NULL; | |
2992 | |
2993 // "return val | endif" is possible | |
2994 return skipwhite(p); | |
2995 } | |
2996 | |
2997 /* | |
2998 * Return the length of an assignment operator, or zero if there isn't one. | |
2999 */ | |
3000 int | |
3001 assignment_len(char_u *p, int *heredoc) | |
3002 { | |
3003 if (*p == '=') | |
3004 { | |
3005 if (p[1] == '<' && p[2] == '<') | |
3006 { | |
3007 *heredoc = TRUE; | |
3008 return 3; | |
3009 } | |
3010 return 1; | |
3011 } | |
3012 if (vim_strchr((char_u *)"+-*/%", *p) != NULL && p[1] == '=') | |
3013 return 2; | |
3014 if (STRNCMP(p, "..=", 3) == 0) | |
3015 return 3; | |
3016 return 0; | |
3017 } | |
3018 | |
3019 // words that cannot be used as a variable | |
3020 static char *reserved[] = { | |
3021 "true", | |
3022 "false", | |
3023 NULL | |
3024 }; | |
3025 | |
3026 /* | |
3027 * Get a line for "=<<". | |
3028 * Return a pointer to the line in allocated memory. | |
3029 * Return NULL for end-of-file or some error. | |
3030 */ | |
3031 static char_u * | |
3032 heredoc_getline( | |
3033 int c UNUSED, | |
3034 void *cookie, | |
3035 int indent UNUSED, | |
3036 int do_concat UNUSED) | |
3037 { | |
3038 cctx_T *cctx = (cctx_T *)cookie; | |
3039 | |
3040 if (cctx->ctx_lnum == cctx->ctx_ufunc->uf_lines.ga_len) | |
3041 NULL; | |
3042 ++cctx->ctx_lnum; | |
3043 return vim_strsave(((char_u **)cctx->ctx_ufunc->uf_lines.ga_data) | |
3044 [cctx->ctx_lnum]); | |
3045 } | |
3046 | |
3047 /* | |
3048 * compile "let var [= expr]", "const var = expr" and "var = expr" | |
3049 * "arg" points to "var". | |
3050 */ | |
3051 static char_u * | |
3052 compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) | |
3053 { | |
3054 char_u *p; | |
3055 char_u *ret = NULL; | |
3056 int var_count = 0; | |
3057 int semicolon = 0; | |
3058 size_t varlen; | |
3059 garray_T *instr = &cctx->ctx_instr; | |
3060 int idx = -1; | |
3061 char_u *op; | |
3062 int option = FALSE; | |
3063 int opt_type; | |
3064 int opt_flags = 0; | |
3065 int global = FALSE; | |
3066 int script = FALSE; | |
3067 int oplen = 0; | |
3068 int heredoc = FALSE; | |
3069 type_T *type; | |
3070 lvar_T *lvar; | |
3071 char_u *name; | |
3072 char_u *sp; | |
3073 int has_type = FALSE; | |
3074 int is_decl = cmdidx == CMD_let || cmdidx == CMD_const; | |
3075 int instr_count = -1; | |
3076 | |
3077 p = skip_var_list(arg, FALSE, &var_count, &semicolon); | |
3078 if (p == NULL) | |
3079 return NULL; | |
3080 if (var_count > 0) | |
3081 { | |
3082 // TODO: let [var, var] = list | |
3083 emsg("Cannot handle a list yet"); | |
3084 return NULL; | |
3085 } | |
3086 | |
3087 varlen = p - arg; | |
3088 name = vim_strnsave(arg, (int)varlen); | |
3089 if (name == NULL) | |
3090 return NULL; | |
3091 | |
3092 if (*arg == '&') | |
3093 { | |
3094 int cc; | |
3095 long numval; | |
3096 char_u *stringval = NULL; | |
3097 | |
3098 option = TRUE; | |
3099 if (cmdidx == CMD_const) | |
3100 { | |
3101 emsg(_(e_const_option)); | |
3102 return NULL; | |
3103 } | |
3104 if (is_decl) | |
3105 { | |
3106 semsg(_("E1052: Cannot declare an option: %s"), arg); | |
3107 goto theend; | |
3108 } | |
3109 p = arg; | |
3110 p = find_option_end(&p, &opt_flags); | |
3111 if (p == NULL) | |
3112 { | |
3113 emsg(_(e_letunexp)); | |
3114 return NULL; | |
3115 } | |
3116 cc = *p; | |
3117 *p = NUL; | |
3118 opt_type = get_option_value(arg + 1, &numval, &stringval, opt_flags); | |
3119 *p = cc; | |
3120 if (opt_type == -3) | |
3121 { | |
3122 semsg(_(e_unknown_option), *arg); | |
3123 return NULL; | |
3124 } | |
3125 if (opt_type == -2 || opt_type == 0) | |
3126 type = &t_string; | |
3127 else | |
3128 type = &t_number; // both number and boolean option | |
3129 } | |
3130 else if (STRNCMP(arg, "g:", 2) == 0) | |
3131 { | |
3132 global = TRUE; | |
3133 if (is_decl) | |
3134 { | |
3135 semsg(_("E1016: Cannot declare a global variable: %s"), name); | |
3136 goto theend; | |
3137 } | |
3138 } | |
3139 else | |
3140 { | |
3141 for (idx = 0; reserved[idx] != NULL; ++idx) | |
3142 if (STRCMP(reserved[idx], name) == 0) | |
3143 { | |
3144 semsg(_("E1034: Cannot use reserved name %s"), name); | |
3145 goto theend; | |
3146 } | |
3147 | |
3148 idx = lookup_local(arg, varlen, cctx); | |
3149 if (idx >= 0) | |
3150 { | |
3151 if (is_decl) | |
3152 { | |
3153 semsg(_("E1017: Variable already declared: %s"), name); | |
3154 goto theend; | |
3155 } | |
3156 else | |
3157 { | |
3158 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
3159 if (lvar->lv_const) | |
3160 { | |
3161 semsg(_("E1018: Cannot assign to a constant: %s"), name); | |
3162 goto theend; | |
3163 } | |
3164 } | |
3165 } | |
3166 else if (lookup_script(arg, varlen) == OK) | |
3167 { | |
3168 script = TRUE; | |
3169 if (is_decl) | |
3170 { | |
3171 semsg(_("E1054: Variable already declared in the script: %s"), | |
3172 name); | |
3173 goto theend; | |
3174 } | |
3175 } | |
3176 } | |
3177 | |
3178 if (!option) | |
3179 { | |
3180 if (is_decl && *p == ':') | |
3181 { | |
3182 // parse optional type: "let var: type = expr" | |
3183 p = skipwhite(p + 1); | |
3184 type = parse_type(&p, cctx->ctx_type_list); | |
3185 if (type == NULL) | |
3186 goto theend; | |
3187 has_type = TRUE; | |
3188 } | |
3189 else if (idx < 0) | |
3190 { | |
3191 // global and new local default to "any" type | |
3192 type = &t_any; | |
3193 } | |
3194 else | |
3195 { | |
3196 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
3197 type = lvar->lv_type; | |
3198 } | |
3199 } | |
3200 | |
3201 sp = p; | |
3202 p = skipwhite(p); | |
3203 op = p; | |
3204 oplen = assignment_len(p, &heredoc); | |
3205 if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen]))) | |
3206 { | |
3207 char_u buf[4]; | |
3208 | |
3209 vim_strncpy(buf, op, oplen); | |
3210 semsg(_(e_white_both), buf); | |
3211 } | |
3212 | |
3213 if (oplen == 3 && !heredoc && !global && type->tt_type != VAR_STRING | |
3214 && type->tt_type != VAR_UNKNOWN) | |
3215 { | |
3216 emsg("E1019: Can only concatenate to string"); | |
3217 goto theend; | |
3218 } | |
3219 | |
3220 // +=, /=, etc. require an existing variable | |
3221 if (idx < 0 && !global && !option) | |
3222 { | |
3223 if (oplen > 1 && !heredoc) | |
3224 { | |
3225 semsg(_("E1020: cannot use an operator on a new variable: %s"), | |
3226 name); | |
3227 goto theend; | |
3228 } | |
3229 | |
3230 // new local variable | |
3231 idx = reserve_local(cctx, arg, varlen, cmdidx == CMD_const, type); | |
3232 if (idx < 0) | |
3233 goto theend; | |
3234 } | |
3235 | |
3236 if (heredoc) | |
3237 { | |
3238 list_T *l; | |
3239 listitem_T *li; | |
3240 | |
3241 // [let] varname =<< [trim] {end} | |
3242 eap->getline = heredoc_getline; | |
3243 eap->cookie = cctx; | |
3244 l = heredoc_get(eap, op + 3); | |
3245 | |
3246 // Push each line and the create the list. | |
3247 for (li = l->lv_first; li != NULL; li = li->li_next) | |
3248 { | |
3249 generate_PUSHS(cctx, li->li_tv.vval.v_string); | |
3250 li->li_tv.vval.v_string = NULL; | |
3251 } | |
3252 generate_NEWLIST(cctx, l->lv_len); | |
3253 type = &t_list_string; | |
3254 list_free(l); | |
3255 p += STRLEN(p); | |
3256 } | |
3257 else if (oplen > 0) | |
3258 { | |
3259 // for "+=", "*=", "..=" etc. first load the current value | |
3260 if (*op != '=') | |
3261 { | |
3262 if (option) | |
3263 generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type); | |
3264 else if (global) | |
3265 generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type); | |
3266 else | |
3267 generate_LOAD(cctx, ISN_LOAD, idx, NULL, type); | |
3268 } | |
3269 | |
3270 // compile the expression | |
3271 instr_count = instr->ga_len; | |
3272 p = skipwhite(p + oplen); | |
3273 if (compile_expr1(&p, cctx) == FAIL) | |
3274 goto theend; | |
3275 | |
3276 if (idx >= 0 && (is_decl || !has_type)) | |
3277 { | |
3278 garray_T *stack = &cctx->ctx_type_stack; | |
3279 type_T *stacktype = | |
3280 ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
3281 | |
3282 lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; | |
3283 if (!has_type) | |
3284 { | |
3285 if (stacktype->tt_type == VAR_VOID) | |
3286 { | |
3287 emsg(_("E1031: Cannot use void value")); | |
3288 goto theend; | |
3289 } | |
3290 else | |
3291 lvar->lv_type = stacktype; | |
3292 } | |
3293 else | |
3294 if (check_type(lvar->lv_type, stacktype, TRUE) == FAIL) | |
3295 goto theend; | |
3296 } | |
3297 } | |
3298 else if (cmdidx == CMD_const) | |
3299 { | |
3300 emsg(_("E1021: const requires a value")); | |
3301 goto theend; | |
3302 } | |
3303 else if (!has_type || option) | |
3304 { | |
3305 emsg(_("E1022: type or initialization required")); | |
3306 goto theend; | |
3307 } | |
3308 else | |
3309 { | |
3310 // variables are always initialized | |
3311 // TODO: support more types | |
3312 if (ga_grow(instr, 1) == FAIL) | |
3313 goto theend; | |
3314 if (type->tt_type == VAR_STRING) | |
3315 generate_PUSHS(cctx, vim_strsave((char_u *)"")); | |
3316 else | |
3317 generate_PUSHNR(cctx, 0); | |
3318 } | |
3319 | |
3320 if (oplen > 0 && *op != '=') | |
3321 { | |
3322 type_T *expected = &t_number; | |
3323 garray_T *stack = &cctx->ctx_type_stack; | |
3324 type_T *stacktype; | |
3325 | |
3326 // TODO: if type is known use float or any operation | |
3327 | |
3328 if (*op == '.') | |
3329 expected = &t_string; | |
3330 stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
3331 if (need_type(stacktype, expected, -1, cctx) == FAIL) | |
3332 goto theend; | |
3333 | |
3334 if (*op == '.') | |
3335 generate_instr_drop(cctx, ISN_CONCAT, 1); | |
3336 else | |
3337 { | |
3338 isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1); | |
3339 | |
3340 if (isn == NULL) | |
3341 goto theend; | |
3342 switch (*op) | |
3343 { | |
3344 case '+': isn->isn_arg.op.op_type = EXPR_ADD; break; | |
3345 case '-': isn->isn_arg.op.op_type = EXPR_SUB; break; | |
3346 case '*': isn->isn_arg.op.op_type = EXPR_MULT; break; | |
3347 case '/': isn->isn_arg.op.op_type = EXPR_DIV; break; | |
3348 case '%': isn->isn_arg.op.op_type = EXPR_REM; break; | |
3349 } | |
3350 } | |
3351 } | |
3352 | |
3353 if (option) | |
3354 generate_STOREOPT(cctx, name + 1, opt_flags); | |
3355 else if (global) | |
3356 generate_STORE(cctx, ISN_STOREG, 0, name + 2); | |
3357 else if (script) | |
3358 { | |
3359 idx = get_script_item_idx(current_sctx.sc_sid, name, TRUE); | |
3360 // TODO: specific type | |
3361 generate_SCRIPT(cctx, ISN_STORESCRIPT, | |
3362 current_sctx.sc_sid, idx, &t_any); | |
3363 } | |
3364 else | |
3365 { | |
3366 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1; | |
3367 | |
3368 // optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE into | |
3369 // ISN_STORENR | |
3370 if (instr->ga_len == instr_count + 1 && isn->isn_type == ISN_PUSHNR) | |
3371 { | |
3372 varnumber_T val = isn->isn_arg.number; | |
3373 garray_T *stack = &cctx->ctx_type_stack; | |
3374 | |
3375 isn->isn_type = ISN_STORENR; | |
3376 isn->isn_arg.storenr.str_idx = idx; | |
3377 isn->isn_arg.storenr.str_val = val; | |
3378 if (stack->ga_len > 0) | |
3379 --stack->ga_len; | |
3380 } | |
3381 else | |
3382 generate_STORE(cctx, ISN_STORE, idx, NULL); | |
3383 } | |
3384 ret = p; | |
3385 | |
3386 theend: | |
3387 vim_free(name); | |
3388 return ret; | |
3389 } | |
3390 | |
3391 /* | |
3392 * Compile an :import command. | |
3393 */ | |
3394 static char_u * | |
3395 compile_import(char_u *arg, cctx_T *cctx) | |
3396 { | |
3397 return handle_import(arg, &cctx->ctx_imports, 0); | |
3398 } | |
3399 | |
3400 /* | |
3401 * generate a jump to the ":endif"/":endfor"/":endwhile"/":finally"/":endtry". | |
3402 */ | |
3403 static int | |
3404 compile_jump_to_end(endlabel_T **el, jumpwhen_T when, cctx_T *cctx) | |
3405 { | |
3406 garray_T *instr = &cctx->ctx_instr; | |
3407 endlabel_T *endlabel = ALLOC_CLEAR_ONE(endlabel_T); | |
3408 | |
3409 if (endlabel == NULL) | |
3410 return FAIL; | |
3411 endlabel->el_next = *el; | |
3412 *el = endlabel; | |
3413 endlabel->el_end_label = instr->ga_len; | |
3414 | |
3415 generate_JUMP(cctx, when, 0); | |
3416 return OK; | |
3417 } | |
3418 | |
3419 static void | |
3420 compile_fill_jump_to_end(endlabel_T **el, cctx_T *cctx) | |
3421 { | |
3422 garray_T *instr = &cctx->ctx_instr; | |
3423 | |
3424 while (*el != NULL) | |
3425 { | |
3426 endlabel_T *cur = (*el); | |
3427 isn_T *isn; | |
3428 | |
3429 isn = ((isn_T *)instr->ga_data) + cur->el_end_label; | |
3430 isn->isn_arg.jump.jump_where = instr->ga_len; | |
3431 *el = cur->el_next; | |
3432 vim_free(cur); | |
3433 } | |
3434 } | |
3435 | |
3436 /* | |
3437 * Create a new scope and set up the generic items. | |
3438 */ | |
3439 static scope_T * | |
3440 new_scope(cctx_T *cctx, scopetype_T type) | |
3441 { | |
3442 scope_T *scope = ALLOC_CLEAR_ONE(scope_T); | |
3443 | |
3444 if (scope == NULL) | |
3445 return NULL; | |
3446 scope->se_outer = cctx->ctx_scope; | |
3447 cctx->ctx_scope = scope; | |
3448 scope->se_type = type; | |
3449 scope->se_local_count = cctx->ctx_locals.ga_len; | |
3450 return scope; | |
3451 } | |
3452 | |
3453 /* | |
3454 * compile "if expr" | |
3455 * | |
3456 * "if expr" Produces instructions: | |
3457 * EVAL expr Push result of "expr" | |
3458 * JUMP_IF_FALSE end | |
3459 * ... body ... | |
3460 * end: | |
3461 * | |
3462 * "if expr | else" Produces instructions: | |
3463 * EVAL expr Push result of "expr" | |
3464 * JUMP_IF_FALSE else | |
3465 * ... body ... | |
3466 * JUMP_ALWAYS end | |
3467 * else: | |
3468 * ... body ... | |
3469 * end: | |
3470 * | |
3471 * "if expr1 | elseif expr2 | else" Produces instructions: | |
3472 * EVAL expr Push result of "expr" | |
3473 * JUMP_IF_FALSE elseif | |
3474 * ... body ... | |
3475 * JUMP_ALWAYS end | |
3476 * elseif: | |
3477 * EVAL expr Push result of "expr" | |
3478 * JUMP_IF_FALSE else | |
3479 * ... body ... | |
3480 * JUMP_ALWAYS end | |
3481 * else: | |
3482 * ... body ... | |
3483 * end: | |
3484 */ | |
3485 static char_u * | |
3486 compile_if(char_u *arg, cctx_T *cctx) | |
3487 { | |
3488 char_u *p = arg; | |
3489 garray_T *instr = &cctx->ctx_instr; | |
3490 scope_T *scope; | |
3491 | |
3492 // compile "expr" | |
3493 if (compile_expr1(&p, cctx) == FAIL) | |
3494 return NULL; | |
3495 | |
3496 scope = new_scope(cctx, IF_SCOPE); | |
3497 if (scope == NULL) | |
3498 return NULL; | |
3499 | |
3500 // "where" is set when ":elseif", "else" or ":endif" is found | |
3501 scope->se_if.is_if_label = instr->ga_len; | |
3502 generate_JUMP(cctx, JUMP_IF_FALSE, 0); | |
3503 | |
3504 return p; | |
3505 } | |
3506 | |
3507 static char_u * | |
3508 compile_elseif(char_u *arg, cctx_T *cctx) | |
3509 { | |
3510 char_u *p = arg; | |
3511 garray_T *instr = &cctx->ctx_instr; | |
3512 isn_T *isn; | |
3513 scope_T *scope = cctx->ctx_scope; | |
3514 | |
3515 if (scope == NULL || scope->se_type != IF_SCOPE) | |
3516 { | |
3517 emsg(_(e_elseif_without_if)); | |
3518 return NULL; | |
3519 } | |
3520 cctx->ctx_locals.ga_len = scope->se_local_count; | |
3521 | |
3522 // jump from previous block to the end | |
3523 if (compile_jump_to_end(&scope->se_if.is_end_label, | |
3524 JUMP_ALWAYS, cctx) == FAIL) | |
3525 return NULL; | |
3526 | |
3527 // previous "if" or "elseif" jumps here | |
3528 isn = ((isn_T *)instr->ga_data) + scope->se_if.is_if_label; | |
3529 isn->isn_arg.jump.jump_where = instr->ga_len; | |
3530 | |
3531 // compile "expr" | |
3532 if (compile_expr1(&p, cctx) == FAIL) | |
3533 return NULL; | |
3534 | |
3535 // "where" is set when ":elseif", "else" or ":endif" is found | |
3536 scope->se_if.is_if_label = instr->ga_len; | |
3537 generate_JUMP(cctx, JUMP_IF_FALSE, 0); | |
3538 | |
3539 return p; | |
3540 } | |
3541 | |
3542 static char_u * | |
3543 compile_else(char_u *arg, cctx_T *cctx) | |
3544 { | |
3545 char_u *p = arg; | |
3546 garray_T *instr = &cctx->ctx_instr; | |
3547 isn_T *isn; | |
3548 scope_T *scope = cctx->ctx_scope; | |
3549 | |
3550 if (scope == NULL || scope->se_type != IF_SCOPE) | |
3551 { | |
3552 emsg(_(e_else_without_if)); | |
3553 return NULL; | |
3554 } | |
3555 cctx->ctx_locals.ga_len = scope->se_local_count; | |
3556 | |
3557 // jump from previous block to the end | |
3558 if (compile_jump_to_end(&scope->se_if.is_end_label, | |
3559 JUMP_ALWAYS, cctx) == FAIL) | |
3560 return NULL; | |
3561 | |
3562 // previous "if" or "elseif" jumps here | |
3563 isn = ((isn_T *)instr->ga_data) + scope->se_if.is_if_label; | |
3564 isn->isn_arg.jump.jump_where = instr->ga_len; | |
3565 | |
3566 return p; | |
3567 } | |
3568 | |
3569 static char_u * | |
3570 compile_endif(char_u *arg, cctx_T *cctx) | |
3571 { | |
3572 scope_T *scope = cctx->ctx_scope; | |
3573 ifscope_T *ifscope; | |
3574 garray_T *instr = &cctx->ctx_instr; | |
3575 isn_T *isn; | |
3576 | |
3577 if (scope == NULL || scope->se_type != IF_SCOPE) | |
3578 { | |
3579 emsg(_(e_endif_without_if)); | |
3580 return NULL; | |
3581 } | |
3582 ifscope = &scope->se_if; | |
3583 cctx->ctx_scope = scope->se_outer; | |
3584 cctx->ctx_locals.ga_len = scope->se_local_count; | |
3585 | |
3586 // previous "if" or "elseif" jumps here | |
3587 isn = ((isn_T *)instr->ga_data) + scope->se_if.is_if_label; | |
3588 isn->isn_arg.jump.jump_where = instr->ga_len; | |
3589 | |
3590 // Fill in the "end" label in jumps at the end of the blocks. | |
3591 compile_fill_jump_to_end(&ifscope->is_end_label, cctx); | |
3592 | |
3593 vim_free(scope); | |
3594 return arg; | |
3595 } | |
3596 | |
3597 /* | |
3598 * compile "for var in expr" | |
3599 * | |
3600 * Produces instructions: | |
3601 * PUSHNR -1 | |
3602 * STORE loop-idx Set index to -1 | |
3603 * EVAL expr Push result of "expr" | |
3604 * top: FOR loop-idx, end Increment index, use list on bottom of stack | |
3605 * - if beyond end, jump to "end" | |
3606 * - otherwise get item from list and push it | |
3607 * STORE var Store item in "var" | |
3608 * ... body ... | |
3609 * JUMP top Jump back to repeat | |
3610 * end: DROP Drop the result of "expr" | |
3611 * | |
3612 */ | |
3613 static char_u * | |
3614 compile_for(char_u *arg, cctx_T *cctx) | |
3615 { | |
3616 char_u *p; | |
3617 size_t varlen; | |
3618 garray_T *instr = &cctx->ctx_instr; | |
3619 garray_T *stack = &cctx->ctx_type_stack; | |
3620 scope_T *scope; | |
3621 int loop_idx; // index of loop iteration variable | |
3622 int var_idx; // index of "var" | |
3623 type_T *vartype; | |
3624 | |
3625 // TODO: list of variables: "for [key, value] in dict" | |
3626 // parse "var" | |
3627 for (p = arg; eval_isnamec1(*p); ++p) | |
3628 ; | |
3629 varlen = p - arg; | |
3630 var_idx = lookup_local(arg, varlen, cctx); | |
3631 if (var_idx >= 0) | |
3632 { | |
3633 semsg(_("E1023: variable already defined: %s"), arg); | |
3634 return NULL; | |
3635 } | |
3636 | |
3637 // consume "in" | |
3638 p = skipwhite(p); | |
3639 if (STRNCMP(p, "in", 2) != 0 || !VIM_ISWHITE(p[2])) | |
3640 { | |
3641 emsg(_(e_missing_in)); | |
3642 return NULL; | |
3643 } | |
3644 p = skipwhite(p + 2); | |
3645 | |
3646 | |
3647 scope = new_scope(cctx, FOR_SCOPE); | |
3648 if (scope == NULL) | |
3649 return NULL; | |
3650 | |
3651 // Reserve a variable to store the loop iteration counter. | |
3652 loop_idx = reserve_local(cctx, (char_u *)"", 0, FALSE, &t_number); | |
3653 if (loop_idx < 0) | |
3654 return NULL; | |
3655 | |
3656 // Reserve a variable to store "var" | |
3657 var_idx = reserve_local(cctx, arg, varlen, FALSE, &t_any); | |
3658 if (var_idx < 0) | |
3659 return NULL; | |
3660 | |
3661 generate_STORENR(cctx, loop_idx, -1); | |
3662 | |
3663 // compile "expr", it remains on the stack until "endfor" | |
3664 arg = p; | |
3665 if (compile_expr1(&arg, cctx) == FAIL) | |
3666 return NULL; | |
3667 | |
3668 // now we know the type of "var" | |
3669 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
3670 if (vartype->tt_type != VAR_LIST) | |
3671 { | |
3672 emsg(_("E1024: need a List to iterate over")); | |
3673 return NULL; | |
3674 } | |
3675 if (vartype->tt_member->tt_type != VAR_UNKNOWN) | |
3676 { | |
3677 lvar_T *lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + var_idx; | |
3678 | |
3679 lvar->lv_type = vartype->tt_member; | |
3680 } | |
3681 | |
3682 // "for_end" is set when ":endfor" is found | |
3683 scope->se_for.fs_top_label = instr->ga_len; | |
3684 | |
3685 generate_FOR(cctx, loop_idx); | |
3686 generate_STORE(cctx, ISN_STORE, var_idx, NULL); | |
3687 | |
3688 return arg; | |
3689 } | |
3690 | |
3691 /* | |
3692 * compile "endfor" | |
3693 */ | |
3694 static char_u * | |
3695 compile_endfor(char_u *arg, cctx_T *cctx) | |
3696 { | |
3697 garray_T *instr = &cctx->ctx_instr; | |
3698 scope_T *scope = cctx->ctx_scope; | |
3699 forscope_T *forscope; | |
3700 isn_T *isn; | |
3701 | |
3702 if (scope == NULL || scope->se_type != FOR_SCOPE) | |
3703 { | |
3704 emsg(_(e_for)); | |
3705 return NULL; | |
3706 } | |
3707 forscope = &scope->se_for; | |
3708 cctx->ctx_scope = scope->se_outer; | |
3709 cctx->ctx_locals.ga_len = scope->se_local_count; | |
3710 | |
3711 // At end of ":for" scope jump back to the FOR instruction. | |
3712 generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label); | |
3713 | |
3714 // Fill in the "end" label in the FOR statement so it can jump here | |
3715 isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label; | |
3716 isn->isn_arg.forloop.for_end = instr->ga_len; | |
3717 | |
3718 // Fill in the "end" label any BREAK statements | |
3719 compile_fill_jump_to_end(&forscope->fs_end_label, cctx); | |
3720 | |
3721 // Below the ":for" scope drop the "expr" list from the stack. | |
3722 if (generate_instr_drop(cctx, ISN_DROP, 1) == NULL) | |
3723 return NULL; | |
3724 | |
3725 vim_free(scope); | |
3726 | |
3727 return arg; | |
3728 } | |
3729 | |
3730 /* | |
3731 * compile "while expr" | |
3732 * | |
3733 * Produces instructions: | |
3734 * top: EVAL expr Push result of "expr" | |
3735 * JUMP_IF_FALSE end jump if false | |
3736 * ... body ... | |
3737 * JUMP top Jump back to repeat | |
3738 * end: | |
3739 * | |
3740 */ | |
3741 static char_u * | |
3742 compile_while(char_u *arg, cctx_T *cctx) | |
3743 { | |
3744 char_u *p = arg; | |
3745 garray_T *instr = &cctx->ctx_instr; | |
3746 scope_T *scope; | |
3747 | |
3748 scope = new_scope(cctx, WHILE_SCOPE); | |
3749 if (scope == NULL) | |
3750 return NULL; | |
3751 | |
3752 scope->se_while.ws_top_label = instr->ga_len; | |
3753 | |
3754 // compile "expr" | |
3755 if (compile_expr1(&p, cctx) == FAIL) | |
3756 return NULL; | |
3757 | |
3758 // "while_end" is set when ":endwhile" is found | |
3759 if (compile_jump_to_end(&scope->se_while.ws_end_label, | |
3760 JUMP_IF_FALSE, cctx) == FAIL) | |
3761 return FAIL; | |
3762 | |
3763 return p; | |
3764 } | |
3765 | |
3766 /* | |
3767 * compile "endwhile" | |
3768 */ | |
3769 static char_u * | |
3770 compile_endwhile(char_u *arg, cctx_T *cctx) | |
3771 { | |
3772 scope_T *scope = cctx->ctx_scope; | |
3773 | |
3774 if (scope == NULL || scope->se_type != WHILE_SCOPE) | |
3775 { | |
3776 emsg(_(e_while)); | |
3777 return NULL; | |
3778 } | |
3779 cctx->ctx_scope = scope->se_outer; | |
3780 cctx->ctx_locals.ga_len = scope->se_local_count; | |
3781 | |
3782 // At end of ":for" scope jump back to the FOR instruction. | |
3783 generate_JUMP(cctx, JUMP_ALWAYS, scope->se_while.ws_top_label); | |
3784 | |
3785 // Fill in the "end" label in the WHILE statement so it can jump here. | |
3786 // And in any jumps for ":break" | |
3787 compile_fill_jump_to_end(&scope->se_while.ws_end_label, cctx); | |
3788 | |
3789 vim_free(scope); | |
3790 | |
3791 return arg; | |
3792 } | |
3793 | |
3794 /* | |
3795 * compile "continue" | |
3796 */ | |
3797 static char_u * | |
3798 compile_continue(char_u *arg, cctx_T *cctx) | |
3799 { | |
3800 scope_T *scope = cctx->ctx_scope; | |
3801 | |
3802 for (;;) | |
3803 { | |
3804 if (scope == NULL) | |
3805 { | |
3806 emsg(_(e_continue)); | |
3807 return NULL; | |
3808 } | |
3809 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE) | |
3810 break; | |
3811 scope = scope->se_outer; | |
3812 } | |
3813 | |
3814 // Jump back to the FOR or WHILE instruction. | |
3815 generate_JUMP(cctx, JUMP_ALWAYS, | |
3816 scope->se_type == FOR_SCOPE ? scope->se_for.fs_top_label | |
3817 : scope->se_while.ws_top_label); | |
3818 return arg; | |
3819 } | |
3820 | |
3821 /* | |
3822 * compile "break" | |
3823 */ | |
3824 static char_u * | |
3825 compile_break(char_u *arg, cctx_T *cctx) | |
3826 { | |
3827 scope_T *scope = cctx->ctx_scope; | |
3828 endlabel_T **el; | |
3829 | |
3830 for (;;) | |
3831 { | |
3832 if (scope == NULL) | |
3833 { | |
3834 emsg(_(e_break)); | |
3835 return NULL; | |
3836 } | |
3837 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE) | |
3838 break; | |
3839 scope = scope->se_outer; | |
3840 } | |
3841 | |
3842 // Jump to the end of the FOR or WHILE loop. | |
3843 if (scope->se_type == FOR_SCOPE) | |
3844 el = &scope->se_for.fs_end_label; | |
3845 else | |
3846 el = &scope->se_while.ws_end_label; | |
3847 if (compile_jump_to_end(el, JUMP_ALWAYS, cctx) == FAIL) | |
3848 return FAIL; | |
3849 | |
3850 return arg; | |
3851 } | |
3852 | |
3853 /* | |
3854 * compile "{" start of block | |
3855 */ | |
3856 static char_u * | |
3857 compile_block(char_u *arg, cctx_T *cctx) | |
3858 { | |
3859 if (new_scope(cctx, BLOCK_SCOPE) == NULL) | |
3860 return NULL; | |
3861 return skipwhite(arg + 1); | |
3862 } | |
3863 | |
3864 /* | |
3865 * compile end of block: drop one scope | |
3866 */ | |
3867 static void | |
3868 compile_endblock(cctx_T *cctx) | |
3869 { | |
3870 scope_T *scope = cctx->ctx_scope; | |
3871 | |
3872 cctx->ctx_scope = scope->se_outer; | |
3873 cctx->ctx_locals.ga_len = scope->se_local_count; | |
3874 vim_free(scope); | |
3875 } | |
3876 | |
3877 /* | |
3878 * compile "try" | |
3879 * Creates a new scope for the try-endtry, pointing to the first catch and | |
3880 * finally. | |
3881 * Creates another scope for the "try" block itself. | |
3882 * TRY instruction sets up exception handling at runtime. | |
3883 * | |
3884 * "try" | |
3885 * TRY -> catch1, -> finally push trystack entry | |
3886 * ... try block | |
3887 * "throw {exception}" | |
3888 * EVAL {exception} | |
3889 * THROW create exception | |
3890 * ... try block | |
3891 * " catch {expr}" | |
3892 * JUMP -> finally | |
3893 * catch1: PUSH exeception | |
3894 * EVAL {expr} | |
3895 * MATCH | |
3896 * JUMP nomatch -> catch2 | |
3897 * CATCH remove exception | |
3898 * ... catch block | |
3899 * " catch" | |
3900 * JUMP -> finally | |
3901 * catch2: CATCH remove exception | |
3902 * ... catch block | |
3903 * " finally" | |
3904 * finally: | |
3905 * ... finally block | |
3906 * " endtry" | |
3907 * ENDTRY pop trystack entry, may rethrow | |
3908 */ | |
3909 static char_u * | |
3910 compile_try(char_u *arg, cctx_T *cctx) | |
3911 { | |
3912 garray_T *instr = &cctx->ctx_instr; | |
3913 scope_T *try_scope; | |
3914 scope_T *scope; | |
3915 | |
3916 // scope that holds the jumps that go to catch/finally/endtry | |
3917 try_scope = new_scope(cctx, TRY_SCOPE); | |
3918 if (try_scope == NULL) | |
3919 return NULL; | |
3920 | |
3921 // "catch" is set when the first ":catch" is found. | |
3922 // "finally" is set when ":finally" or ":endtry" is found | |
3923 try_scope->se_try.ts_try_label = instr->ga_len; | |
3924 if (generate_instr(cctx, ISN_TRY) == NULL) | |
3925 return NULL; | |
3926 | |
3927 // scope for the try block itself | |
3928 scope = new_scope(cctx, BLOCK_SCOPE); | |
3929 if (scope == NULL) | |
3930 return NULL; | |
3931 | |
3932 return arg; | |
3933 } | |
3934 | |
3935 /* | |
3936 * compile "catch {expr}" | |
3937 */ | |
3938 static char_u * | |
3939 compile_catch(char_u *arg, cctx_T *cctx UNUSED) | |
3940 { | |
3941 scope_T *scope = cctx->ctx_scope; | |
3942 garray_T *instr = &cctx->ctx_instr; | |
3943 char_u *p; | |
3944 isn_T *isn; | |
3945 | |
3946 // end block scope from :try or :catch | |
3947 if (scope != NULL && scope->se_type == BLOCK_SCOPE) | |
3948 compile_endblock(cctx); | |
3949 scope = cctx->ctx_scope; | |
3950 | |
3951 // Error if not in a :try scope | |
3952 if (scope == NULL || scope->se_type != TRY_SCOPE) | |
3953 { | |
3954 emsg(_(e_catch)); | |
3955 return NULL; | |
3956 } | |
3957 | |
3958 if (scope->se_try.ts_caught_all) | |
3959 { | |
3960 emsg(_("E1033: catch unreachable after catch-all")); | |
3961 return NULL; | |
3962 } | |
3963 | |
3964 // Jump from end of previous block to :finally or :endtry | |
3965 if (compile_jump_to_end(&scope->se_try.ts_end_label, | |
3966 JUMP_ALWAYS, cctx) == FAIL) | |
3967 return NULL; | |
3968 | |
3969 // End :try or :catch scope: set value in ISN_TRY instruction | |
3970 isn = ((isn_T *)instr->ga_data) + scope->se_try.ts_try_label; | |
3971 if (isn->isn_arg.try.try_catch == 0) | |
3972 isn->isn_arg.try.try_catch = instr->ga_len; | |
3973 if (scope->se_try.ts_catch_label != 0) | |
3974 { | |
3975 // Previous catch without match jumps here | |
3976 isn = ((isn_T *)instr->ga_data) + scope->se_try.ts_catch_label; | |
3977 isn->isn_arg.jump.jump_where = instr->ga_len; | |
3978 } | |
3979 | |
3980 p = skipwhite(arg); | |
3981 if (ends_excmd(*p)) | |
3982 { | |
3983 scope->se_try.ts_caught_all = TRUE; | |
3984 scope->se_try.ts_catch_label = 0; | |
3985 } | |
3986 else | |
3987 { | |
3988 // Push v:exception, push {expr} and MATCH | |
3989 generate_instr_type(cctx, ISN_PUSHEXC, &t_string); | |
3990 | |
3991 if (compile_expr1(&p, cctx) == FAIL) | |
3992 return NULL; | |
3993 | |
3994 // TODO: check for strings? | |
3995 if (generate_COMPARE(cctx, EXPR_MATCH, FALSE) == FAIL) | |
3996 return NULL; | |
3997 | |
3998 scope->se_try.ts_catch_label = instr->ga_len; | |
3999 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL) | |
4000 return NULL; | |
4001 } | |
4002 | |
4003 if (generate_instr(cctx, ISN_CATCH) == NULL) | |
4004 return NULL; | |
4005 | |
4006 if (new_scope(cctx, BLOCK_SCOPE) == NULL) | |
4007 return NULL; | |
4008 return p; | |
4009 } | |
4010 | |
4011 static char_u * | |
4012 compile_finally(char_u *arg, cctx_T *cctx) | |
4013 { | |
4014 scope_T *scope = cctx->ctx_scope; | |
4015 garray_T *instr = &cctx->ctx_instr; | |
4016 isn_T *isn; | |
4017 | |
4018 // end block scope from :try or :catch | |
4019 if (scope != NULL && scope->se_type == BLOCK_SCOPE) | |
4020 compile_endblock(cctx); | |
4021 scope = cctx->ctx_scope; | |
4022 | |
4023 // Error if not in a :try scope | |
4024 if (scope == NULL || scope->se_type != TRY_SCOPE) | |
4025 { | |
4026 emsg(_(e_finally)); | |
4027 return NULL; | |
4028 } | |
4029 | |
4030 // End :catch or :finally scope: set value in ISN_TRY instruction | |
4031 isn = ((isn_T *)instr->ga_data) + scope->se_try.ts_try_label; | |
4032 if (isn->isn_arg.try.try_finally != 0) | |
4033 { | |
4034 emsg(_(e_finally_dup)); | |
4035 return NULL; | |
4036 } | |
4037 | |
4038 // Fill in the "end" label in jumps at the end of the blocks. | |
4039 compile_fill_jump_to_end(&scope->se_try.ts_end_label, cctx); | |
4040 | |
4041 if (scope->se_try.ts_catch_label != 0) | |
4042 { | |
4043 // Previous catch without match jumps here | |
4044 isn = ((isn_T *)instr->ga_data) + scope->se_try.ts_catch_label; | |
4045 isn->isn_arg.jump.jump_where = instr->ga_len; | |
4046 } | |
4047 | |
4048 isn->isn_arg.try.try_finally = instr->ga_len; | |
4049 // TODO: set index in ts_finally_label jumps | |
4050 | |
4051 return arg; | |
4052 } | |
4053 | |
4054 static char_u * | |
4055 compile_endtry(char_u *arg, cctx_T *cctx) | |
4056 { | |
4057 scope_T *scope = cctx->ctx_scope; | |
4058 garray_T *instr = &cctx->ctx_instr; | |
4059 isn_T *isn; | |
4060 | |
4061 // end block scope from :catch or :finally | |
4062 if (scope != NULL && scope->se_type == BLOCK_SCOPE) | |
4063 compile_endblock(cctx); | |
4064 scope = cctx->ctx_scope; | |
4065 | |
4066 // Error if not in a :try scope | |
4067 if (scope == NULL || scope->se_type != TRY_SCOPE) | |
4068 { | |
4069 if (scope == NULL) | |
4070 emsg(_(e_no_endtry)); | |
4071 else if (scope->se_type == WHILE_SCOPE) | |
4072 emsg(_(e_endwhile)); | |
4073 if (scope->se_type == FOR_SCOPE) | |
4074 emsg(_(e_endfor)); | |
4075 else | |
4076 emsg(_(e_endif)); | |
4077 return NULL; | |
4078 } | |
4079 | |
4080 isn = ((isn_T *)instr->ga_data) + scope->se_try.ts_try_label; | |
4081 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0) | |
4082 { | |
4083 emsg(_("E1032: missing :catch or :finally")); | |
4084 return NULL; | |
4085 } | |
4086 | |
4087 // Fill in the "end" label in jumps at the end of the blocks, if not done | |
4088 // by ":finally". | |
4089 compile_fill_jump_to_end(&scope->se_try.ts_end_label, cctx); | |
4090 | |
4091 // End :catch or :finally scope: set value in ISN_TRY instruction | |
4092 if (isn->isn_arg.try.try_finally == 0) | |
4093 isn->isn_arg.try.try_finally = instr->ga_len; | |
4094 compile_endblock(cctx); | |
4095 | |
4096 if (generate_instr(cctx, ISN_ENDTRY) == NULL) | |
4097 return NULL; | |
4098 return arg; | |
4099 } | |
4100 | |
4101 /* | |
4102 * compile "throw {expr}" | |
4103 */ | |
4104 static char_u * | |
4105 compile_throw(char_u *arg, cctx_T *cctx UNUSED) | |
4106 { | |
4107 char_u *p = skipwhite(arg); | |
4108 | |
4109 if (ends_excmd(*p)) | |
4110 { | |
4111 emsg(_(e_argreq)); | |
4112 return NULL; | |
4113 } | |
4114 if (compile_expr1(&p, cctx) == FAIL) | |
4115 return NULL; | |
4116 if (may_generate_2STRING(-1, cctx) == FAIL) | |
4117 return NULL; | |
4118 if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL) | |
4119 return NULL; | |
4120 | |
4121 return p; | |
4122 } | |
4123 | |
4124 /* | |
4125 * compile "echo expr" | |
4126 */ | |
4127 static char_u * | |
4128 compile_echo(char_u *arg, int with_white, cctx_T *cctx) | |
4129 { | |
4130 char_u *p = arg; | |
4131 int count = 0; | |
4132 | |
4133 // for () | |
4134 { | |
4135 if (compile_expr1(&p, cctx) == FAIL) | |
4136 return NULL; | |
4137 ++count; | |
4138 } | |
4139 | |
4140 generate_ECHO(cctx, with_white, count); | |
4141 | |
4142 return p; | |
4143 } | |
4144 | |
4145 /* | |
4146 * After ex_function() has collected all the function lines: parse and compile | |
4147 * the lines into instructions. | |
4148 * Adds the function to "def_functions". | |
4149 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the | |
4150 * return statement (used for lambda). | |
4151 */ | |
4152 void | |
4153 compile_def_function(ufunc_T *ufunc, int set_return_type) | |
4154 { | |
4155 dfunc_T *dfunc; | |
4156 char_u *line = NULL; | |
4157 char_u *p; | |
4158 exarg_T ea; | |
4159 char *errormsg = NULL; // error message | |
4160 int had_return = FALSE; | |
4161 cctx_T cctx; | |
4162 garray_T *instr; | |
4163 int called_emsg_before = called_emsg; | |
4164 int ret = FAIL; | |
4165 sctx_T save_current_sctx = current_sctx; | |
4166 | |
4167 if (ufunc->uf_dfunc_idx >= 0) | |
4168 { | |
4169 // redefining a function that was compiled before | |
4170 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; | |
4171 dfunc->df_deleted = FALSE; | |
4172 } | |
4173 else | |
4174 { | |
4175 // Add the function to "def_functions". | |
4176 if (ga_grow(&def_functions, 1) == FAIL) | |
4177 return; | |
4178 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len; | |
4179 vim_memset(dfunc, 0, sizeof(dfunc_T)); | |
4180 dfunc->df_idx = def_functions.ga_len; | |
4181 ufunc->uf_dfunc_idx = dfunc->df_idx; | |
4182 dfunc->df_ufunc = ufunc; | |
4183 ++def_functions.ga_len; | |
4184 } | |
4185 | |
4186 vim_memset(&cctx, 0, sizeof(cctx)); | |
4187 cctx.ctx_ufunc = ufunc; | |
4188 cctx.ctx_lnum = -1; | |
4189 ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10); | |
4190 ga_init2(&cctx.ctx_type_stack, sizeof(type_T *), 50); | |
4191 ga_init2(&cctx.ctx_imports, sizeof(imported_T), 10); | |
4192 cctx.ctx_type_list = &ufunc->uf_type_list; | |
4193 ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50); | |
4194 instr = &cctx.ctx_instr; | |
4195 | |
4196 // Most modern script version. | |
4197 current_sctx.sc_version = SCRIPT_VERSION_VIM9; | |
4198 | |
4199 for (;;) | |
4200 { | |
4201 if (line != NULL && *line == '|') | |
4202 // the line continues after a '|' | |
4203 ++line; | |
4204 else if (line != NULL && *line != NUL) | |
4205 { | |
4206 semsg(_("E488: Trailing characters: %s"), line); | |
4207 goto erret; | |
4208 } | |
4209 else | |
4210 { | |
4211 do | |
4212 { | |
4213 ++cctx.ctx_lnum; | |
4214 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len) | |
4215 break; | |
4216 line = ((char_u **)ufunc->uf_lines.ga_data)[cctx.ctx_lnum]; | |
4217 } while (line == NULL); | |
4218 if (cctx.ctx_lnum == ufunc->uf_lines.ga_len) | |
4219 break; | |
4220 SOURCING_LNUM = ufunc->uf_script_ctx.sc_lnum + cctx.ctx_lnum + 1; | |
4221 } | |
4222 | |
4223 had_return = FALSE; | |
4224 vim_memset(&ea, 0, sizeof(ea)); | |
4225 ea.cmdlinep = &line; | |
4226 ea.cmd = skipwhite(line); | |
4227 | |
4228 // "}" ends a block scope | |
4229 if (*ea.cmd == '}') | |
4230 { | |
4231 scopetype_T stype = cctx.ctx_scope == NULL | |
4232 ? NO_SCOPE : cctx.ctx_scope->se_type; | |
4233 | |
4234 if (stype == BLOCK_SCOPE) | |
4235 { | |
4236 compile_endblock(&cctx); | |
4237 line = ea.cmd; | |
4238 } | |
4239 else | |
4240 { | |
4241 emsg("E1025: using } outside of a block scope"); | |
4242 goto erret; | |
4243 } | |
4244 if (line != NULL) | |
4245 line = skipwhite(ea.cmd + 1); | |
4246 continue; | |
4247 } | |
4248 | |
4249 // "{" starts a block scope | |
4250 if (*ea.cmd == '{') | |
4251 { | |
4252 line = compile_block(ea.cmd, &cctx); | |
4253 continue; | |
4254 } | |
4255 | |
4256 /* | |
4257 * COMMAND MODIFIERS | |
4258 */ | |
4259 if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL) | |
4260 { | |
4261 if (errormsg != NULL) | |
4262 goto erret; | |
4263 // empty line or comment | |
4264 line = (char_u *)""; | |
4265 continue; | |
4266 } | |
4267 | |
4268 // Skip ":call" to get to the function name. | |
4269 if (checkforcmd(&ea.cmd, "call", 3)) | |
4270 ea.cmd = skipwhite(ea.cmd); | |
4271 | |
4272 // Assuming the command starts with a variable or function name, find | |
4273 // what follows. Also "&opt = value". | |
4274 p = (*ea.cmd == '&') ? ea.cmd + 1 : ea.cmd; | |
4275 p = to_name_end(p); | |
4276 if (p > ea.cmd && *p != NUL) | |
4277 { | |
4278 int oplen; | |
4279 int heredoc; | |
4280 | |
4281 // "funcname(" is always a function call. | |
4282 // "varname[]" is an expression. | |
4283 // "g:varname" is an expression. | |
4284 // "varname->expr" is an expression. | |
4285 if (*p == '(' | |
4286 || *p == '[' | |
4287 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':') | |
4288 || (*p == '-' && p[1] == '>')) | |
4289 { | |
4290 // TODO | |
4291 } | |
4292 | |
4293 oplen = assignment_len(skipwhite(p), &heredoc); | |
4294 if (oplen > 0) | |
4295 { | |
4296 // Recognize an assignment if we recognize the variable name: | |
4297 // "g:var = expr" | |
4298 // "var = expr" where "var" is a local var name. | |
4299 // "&opt = expr" | |
4300 if (*ea.cmd == '&' | |
4301 || ((p - ea.cmd) > 2 && ea.cmd[1] == ':') | |
4302 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0 | |
4303 || lookup_script(ea.cmd, p - ea.cmd) == OK) | |
4304 { | |
4305 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx); | |
4306 if (line == NULL) | |
4307 goto erret; | |
4308 continue; | |
4309 } | |
4310 } | |
4311 } | |
4312 | |
4313 /* | |
4314 * COMMAND after range | |
4315 */ | |
4316 ea.cmd = skip_range(ea.cmd, NULL); | |
4317 p = find_ex_command(&ea, NULL, lookup_local, &cctx); | |
4318 | |
4319 if (p == ea.cmd && ea.cmdidx != CMD_SIZE) | |
4320 { | |
4321 // Expression or function call. | |
4322 if (ea.cmdidx == CMD_eval) | |
4323 { | |
4324 p = ea.cmd; | |
4325 if (compile_expr1(&p, &cctx) == FAIL) | |
4326 goto erret; | |
4327 | |
4328 // drop the return value | |
4329 generate_instr_drop(&cctx, ISN_DROP, 1); | |
4330 line = p; | |
4331 continue; | |
4332 } | |
4333 if (ea.cmdidx == CMD_let) | |
4334 { | |
4335 line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx); | |
4336 if (line == NULL) | |
4337 goto erret; | |
4338 continue; | |
4339 } | |
4340 iemsg("Command from find_ex_command() not handled"); | |
4341 goto erret; | |
4342 } | |
4343 | |
4344 p = skipwhite(p); | |
4345 | |
4346 switch (ea.cmdidx) | |
4347 { | |
4348 case CMD_def: | |
4349 case CMD_function: | |
4350 // TODO: Nested function | |
4351 emsg("Nested function not implemented yet"); | |
4352 goto erret; | |
4353 | |
4354 case CMD_return: | |
4355 line = compile_return(p, set_return_type, &cctx); | |
4356 had_return = TRUE; | |
4357 break; | |
4358 | |
4359 case CMD_let: | |
4360 case CMD_const: | |
4361 line = compile_assignment(p, &ea, ea.cmdidx, &cctx); | |
4362 break; | |
4363 | |
4364 case CMD_import: | |
4365 line = compile_import(p, &cctx); | |
4366 break; | |
4367 | |
4368 case CMD_if: | |
4369 line = compile_if(p, &cctx); | |
4370 break; | |
4371 case CMD_elseif: | |
4372 line = compile_elseif(p, &cctx); | |
4373 break; | |
4374 case CMD_else: | |
4375 line = compile_else(p, &cctx); | |
4376 break; | |
4377 case CMD_endif: | |
4378 line = compile_endif(p, &cctx); | |
4379 break; | |
4380 | |
4381 case CMD_while: | |
4382 line = compile_while(p, &cctx); | |
4383 break; | |
4384 case CMD_endwhile: | |
4385 line = compile_endwhile(p, &cctx); | |
4386 break; | |
4387 | |
4388 case CMD_for: | |
4389 line = compile_for(p, &cctx); | |
4390 break; | |
4391 case CMD_endfor: | |
4392 line = compile_endfor(p, &cctx); | |
4393 break; | |
4394 case CMD_continue: | |
4395 line = compile_continue(p, &cctx); | |
4396 break; | |
4397 case CMD_break: | |
4398 line = compile_break(p, &cctx); | |
4399 break; | |
4400 | |
4401 case CMD_try: | |
4402 line = compile_try(p, &cctx); | |
4403 break; | |
4404 case CMD_catch: | |
4405 line = compile_catch(p, &cctx); | |
4406 break; | |
4407 case CMD_finally: | |
4408 line = compile_finally(p, &cctx); | |
4409 break; | |
4410 case CMD_endtry: | |
4411 line = compile_endtry(p, &cctx); | |
4412 break; | |
4413 case CMD_throw: | |
4414 line = compile_throw(p, &cctx); | |
4415 break; | |
4416 | |
4417 case CMD_echo: | |
4418 line = compile_echo(p, TRUE, &cctx); | |
4419 break; | |
4420 case CMD_echon: | |
4421 line = compile_echo(p, FALSE, &cctx); | |
4422 break; | |
4423 | |
4424 default: | |
4425 // Not recognized, execute with do_cmdline_cmd(). | |
4426 generate_EXEC(&cctx, line); | |
4427 line = (char_u *)""; | |
4428 break; | |
4429 } | |
4430 if (line == NULL) | |
4431 goto erret; | |
4432 | |
4433 if (cctx.ctx_type_stack.ga_len < 0) | |
4434 { | |
4435 iemsg("Type stack underflow"); | |
4436 goto erret; | |
4437 } | |
4438 } | |
4439 | |
4440 if (cctx.ctx_scope != NULL) | |
4441 { | |
4442 if (cctx.ctx_scope->se_type == IF_SCOPE) | |
4443 emsg(_(e_endif)); | |
4444 else if (cctx.ctx_scope->se_type == WHILE_SCOPE) | |
4445 emsg(_(e_endwhile)); | |
4446 else if (cctx.ctx_scope->se_type == FOR_SCOPE) | |
4447 emsg(_(e_endfor)); | |
4448 else | |
4449 emsg(_("E1026: Missing }")); | |
4450 goto erret; | |
4451 } | |
4452 | |
4453 if (!had_return) | |
4454 { | |
4455 if (ufunc->uf_ret_type->tt_type != VAR_VOID) | |
4456 { | |
4457 emsg(_("E1027: Missing return statement")); | |
4458 goto erret; | |
4459 } | |
4460 | |
4461 // Return zero if there is no return at the end. | |
4462 generate_PUSHNR(&cctx, 0); | |
4463 generate_instr(&cctx, ISN_RETURN); | |
4464 } | |
4465 | |
4466 dfunc->df_instr = instr->ga_data; | |
4467 dfunc->df_instr_count = instr->ga_len; | |
4468 dfunc->df_varcount = cctx.ctx_max_local; | |
4469 | |
4470 ret = OK; | |
4471 | |
4472 erret: | |
4473 if (ret == FAIL) | |
4474 { | |
4475 ga_clear(instr); | |
4476 ufunc->uf_dfunc_idx = -1; | |
4477 --def_functions.ga_len; | |
4478 if (errormsg != NULL) | |
4479 emsg(errormsg); | |
4480 else if (called_emsg == called_emsg_before) | |
4481 emsg("E1028: compile_def_function failed"); | |
4482 | |
4483 // don't execute this function body | |
4484 ufunc->uf_lines.ga_len = 0; | |
4485 } | |
4486 | |
4487 current_sctx = save_current_sctx; | |
4488 ga_clear(&cctx.ctx_type_stack); | |
4489 ga_clear(&cctx.ctx_locals); | |
4490 } | |
4491 | |
4492 /* | |
4493 * Delete an instruction, free what it contains. | |
4494 */ | |
4495 static void | |
4496 delete_instr(isn_T *isn) | |
4497 { | |
4498 switch (isn->isn_type) | |
4499 { | |
4500 case ISN_EXEC: | |
4501 case ISN_LOADENV: | |
4502 case ISN_LOADG: | |
4503 case ISN_LOADOPT: | |
4504 case ISN_MEMBER: | |
4505 case ISN_PUSHEXC: | |
4506 case ISN_PUSHS: | |
4507 case ISN_STOREG: | |
4508 vim_free(isn->isn_arg.string); | |
4509 break; | |
4510 | |
4511 case ISN_LOADS: | |
4512 vim_free(isn->isn_arg.loads.ls_name); | |
4513 break; | |
4514 | |
4515 case ISN_STOREOPT: | |
4516 vim_free(isn->isn_arg.storeopt.so_name); | |
4517 break; | |
4518 | |
4519 case ISN_PUSHBLOB: // push blob isn_arg.blob | |
4520 blob_unref(isn->isn_arg.blob); | |
4521 break; | |
4522 | |
4523 case ISN_UCALL: | |
4524 vim_free(isn->isn_arg.ufunc.cuf_name); | |
4525 break; | |
4526 | |
4527 case ISN_2BOOL: | |
4528 case ISN_2STRING: | |
4529 case ISN_ADDBLOB: | |
4530 case ISN_ADDLIST: | |
4531 case ISN_BCALL: | |
4532 case ISN_CATCH: | |
4533 case ISN_CHECKNR: | |
4534 case ISN_CHECKTYPE: | |
4535 case ISN_COMPAREANY: | |
4536 case ISN_COMPAREBLOB: | |
4537 case ISN_COMPAREBOOL: | |
4538 case ISN_COMPAREDICT: | |
4539 case ISN_COMPAREFLOAT: | |
4540 case ISN_COMPAREFUNC: | |
4541 case ISN_COMPARELIST: | |
4542 case ISN_COMPARENR: | |
4543 case ISN_COMPAREPARTIAL: | |
4544 case ISN_COMPARESPECIAL: | |
4545 case ISN_COMPARESTRING: | |
4546 case ISN_CONCAT: | |
4547 case ISN_DCALL: | |
4548 case ISN_DROP: | |
4549 case ISN_ECHO: | |
4550 case ISN_ENDTRY: | |
4551 case ISN_FOR: | |
4552 case ISN_FUNCREF: | |
4553 case ISN_INDEX: | |
4554 case ISN_JUMP: | |
4555 case ISN_LOAD: | |
4556 case ISN_LOADSCRIPT: | |
4557 case ISN_LOADREG: | |
4558 case ISN_LOADV: | |
4559 case ISN_NEGATENR: | |
4560 case ISN_NEWDICT: | |
4561 case ISN_NEWLIST: | |
4562 case ISN_OPNR: | |
4563 case ISN_OPFLOAT: | |
4564 case ISN_OPANY: | |
4565 case ISN_PCALL: | |
4566 case ISN_PUSHF: | |
4567 case ISN_PUSHNR: | |
4568 case ISN_PUSHBOOL: | |
4569 case ISN_PUSHSPEC: | |
4570 case ISN_RETURN: | |
4571 case ISN_STORE: | |
4572 case ISN_STORENR: | |
4573 case ISN_STORESCRIPT: | |
4574 case ISN_THROW: | |
4575 case ISN_TRY: | |
4576 // nothing allocated | |
4577 break; | |
4578 } | |
4579 } | |
4580 | |
4581 /* | |
4582 * When a user function is deleted, delete any associated def function. | |
4583 */ | |
4584 void | |
4585 delete_def_function(ufunc_T *ufunc) | |
4586 { | |
4587 int idx; | |
4588 | |
4589 if (ufunc->uf_dfunc_idx >= 0) | |
4590 { | |
4591 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) | |
4592 + ufunc->uf_dfunc_idx; | |
4593 ga_clear(&dfunc->df_def_args_isn); | |
4594 | |
4595 for (idx = 0; idx < dfunc->df_instr_count; ++idx) | |
4596 delete_instr(dfunc->df_instr + idx); | |
4597 VIM_CLEAR(dfunc->df_instr); | |
4598 | |
4599 dfunc->df_deleted = TRUE; | |
4600 } | |
4601 } | |
4602 | |
4603 #if defined(EXITFREE) || defined(PROTO) | |
4604 void | |
4605 free_def_functions(void) | |
4606 { | |
4607 vim_free(def_functions.ga_data); | |
4608 } | |
4609 #endif | |
4610 | |
4611 | |
4612 #endif // FEAT_EVAL |