blob: 2c76fadc3acb7414dafb9ad9511f3e679aa03f4a [file] [log] [blame]
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001/* 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 * vim9instr.c: Dealing with instructions of a compiled function
12 */
13
14#define USING_FLOAT_STUFF
15#include "vim.h"
16
17#if defined(FEAT_EVAL) || defined(PROTO)
18
19// When not generating protos this is included in proto.h
20#ifdef PROTO
21# include "vim9.h"
22#endif
23
24
25/////////////////////////////////////////////////////////////////////
26// Following generate_ functions expect the caller to call ga_grow().
27
28#define RETURN_NULL_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return NULL
29#define RETURN_OK_IF_SKIP(cctx) if (cctx->ctx_skip == SKIP_YES) return OK
30
31/*
32 * Generate an instruction without arguments.
33 * Returns a pointer to the new instruction, NULL if failed.
34 */
35 isn_T *
36generate_instr(cctx_T *cctx, isntype_T isn_type)
37{
38 garray_T *instr = &cctx->ctx_instr;
39 isn_T *isn;
40
41 RETURN_NULL_IF_SKIP(cctx);
42 if (GA_GROW_FAILS(instr, 1))
43 return NULL;
44 isn = ((isn_T *)instr->ga_data) + instr->ga_len;
45 isn->isn_type = isn_type;
46 isn->isn_lnum = cctx->ctx_lnum + 1;
47 ++instr->ga_len;
48
49 return isn;
50}
51
52/*
53 * Generate an instruction without arguments.
54 * "drop" will be removed from the stack.
55 * Returns a pointer to the new instruction, NULL if failed.
56 */
57 isn_T *
58generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
59{
Bram Moolenaardc7c3662021-12-20 15:04:29 +000060 RETURN_NULL_IF_SKIP(cctx);
Bram Moolenaar078a4612022-01-04 15:17:03 +000061 cctx->ctx_type_stack.ga_len -= drop;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000062 return generate_instr(cctx, isn_type);
63}
64
65/*
Bram Moolenaar078a4612022-01-04 15:17:03 +000066 * Generate instruction "isn_type" and put "type" on the type stack,
67 * use "decl_type" for the declared type.
Bram Moolenaardc7c3662021-12-20 15:04:29 +000068 */
Yegappan Lakshmanan782b43d2022-01-08 18:43:40 +000069 static isn_T *
Bram Moolenaar078a4612022-01-04 15:17:03 +000070generate_instr_type2(
71 cctx_T *cctx,
72 isntype_T isn_type,
73 type_T *type,
74 type_T *decl_type)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000075{
76 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000077
78 if ((isn = generate_instr(cctx, isn_type)) == NULL)
79 return NULL;
80
Bram Moolenaar078a4612022-01-04 15:17:03 +000081 if (push_type_stack2(cctx, type == NULL ? &t_any : type,
82 decl_type == NULL ? &t_any : decl_type) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +000083 return NULL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +000084
85 return isn;
86}
87
88/*
Bram Moolenaar078a4612022-01-04 15:17:03 +000089 * Generate instruction "isn_type" and put "type" on the type stack.
90 * Uses "any" for the declared type, which works for constants. For declared
91 * variables use generate_instr_type2().
92 */
93 isn_T *
94generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
95{
96 return generate_instr_type2(cctx, isn_type, type, &t_any);
97}
98
99/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000100 * Generate an ISN_DEBUG instruction.
101 */
102 isn_T *
103generate_instr_debug(cctx_T *cctx)
104{
105 isn_T *isn;
106 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
107 + cctx->ctx_ufunc->uf_dfunc_idx;
108
109 if ((isn = generate_instr(cctx, ISN_DEBUG)) == NULL)
110 return NULL;
111 isn->isn_arg.debug.dbg_var_names_len = dfunc->df_var_names.ga_len;
112 isn->isn_arg.debug.dbg_break_lnum = cctx->ctx_prev_lnum;
113 return isn;
114}
115
116/*
117 * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING.
118 * But only for simple types.
119 * When "tolerant" is TRUE convert most types to string, e.g. a List.
120 */
121 int
122may_generate_2STRING(int offset, int tolerant, cctx_T *cctx)
123{
124 isn_T *isn;
125 isntype_T isntype = ISN_2STRING;
Bram Moolenaar078a4612022-01-04 15:17:03 +0000126 type_T *type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000127
128 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar078a4612022-01-04 15:17:03 +0000129 type = get_type_on_stack(cctx, -1 - offset);
130 switch (type->tt_type)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000131 {
132 // nothing to be done
133 case VAR_STRING: return OK;
134
135 // conversion possible
136 case VAR_SPECIAL:
137 case VAR_BOOL:
138 case VAR_NUMBER:
139 case VAR_FLOAT:
140 break;
141
142 // conversion possible (with runtime check)
143 case VAR_ANY:
144 case VAR_UNKNOWN:
145 isntype = ISN_2STRING_ANY;
146 break;
147
148 // conversion possible when tolerant
149 case VAR_LIST:
150 if (tolerant)
151 {
152 isntype = ISN_2STRING_ANY;
153 break;
154 }
155 // FALLTHROUGH
156
157 // conversion not possible
158 case VAR_VOID:
159 case VAR_BLOB:
160 case VAR_FUNC:
161 case VAR_PARTIAL:
162 case VAR_DICT:
163 case VAR_JOB:
164 case VAR_CHANNEL:
165 case VAR_INSTR:
Bram Moolenaar078a4612022-01-04 15:17:03 +0000166 to_string_error(type->tt_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000167 return FAIL;
168 }
169
Bram Moolenaar078a4612022-01-04 15:17:03 +0000170 set_type_on_stack(cctx, &t_string, -1 - offset);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000171 if ((isn = generate_instr(cctx, isntype)) == NULL)
172 return FAIL;
173 isn->isn_arg.tostring.offset = offset;
174 isn->isn_arg.tostring.tolerant = tolerant;
175
176 return OK;
177}
178
179 static int
180check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
181{
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000182 if (!((type1 == VAR_NUMBER || type1 == VAR_FLOAT
183 || type1 == VAR_ANY || type1 == VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000184 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000185 || type2 == VAR_ANY || type2 == VAR_UNKNOWN)))
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000186 {
187 if (*op == '+')
188 emsg(_(e_wrong_argument_type_for_plus));
189 else
190 semsg(_(e_char_requires_number_or_float_arguments), *op);
191 return FAIL;
192 }
193 return OK;
194}
195
196/*
197 * Generate instruction for "+". For a list this creates a new list.
198 */
199 int
200generate_add_instr(
201 cctx_T *cctx,
202 vartype_T vartype,
203 type_T *type1,
204 type_T *type2,
205 exprtype_T expr_type)
206{
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000207 isn_T *isn = generate_instr_drop(cctx,
208 vartype == VAR_NUMBER ? ISN_OPNR
209 : vartype == VAR_LIST ? ISN_ADDLIST
210 : vartype == VAR_BLOB ? ISN_ADDBLOB
211#ifdef FEAT_FLOAT
212 : vartype == VAR_FLOAT ? ISN_OPFLOAT
213#endif
214 : ISN_OPANY, 1);
215
216 if (vartype != VAR_LIST && vartype != VAR_BLOB
217 && type1->tt_type != VAR_ANY
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000218 && type1->tt_type != VAR_UNKNOWN
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000219 && type2->tt_type != VAR_ANY
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000220 && type2->tt_type != VAR_UNKNOWN
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000221 && check_number_or_float(
222 type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL)
223 return FAIL;
224
225 if (isn != NULL)
226 {
227 if (isn->isn_type == ISN_ADDLIST)
228 isn->isn_arg.op.op_type = expr_type;
229 else
230 isn->isn_arg.op.op_type = EXPR_ADD;
231 }
232
233 // When concatenating two lists with different member types the member type
234 // becomes "any".
235 if (vartype == VAR_LIST
236 && type1->tt_type == VAR_LIST && type2->tt_type == VAR_LIST
237 && type1->tt_member != type2->tt_member)
Bram Moolenaar078a4612022-01-04 15:17:03 +0000238 set_type_on_stack(cctx, &t_list_any, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000239
240 return isn == NULL ? FAIL : OK;
241}
242
243/*
244 * Get the type to use for an instruction for an operation on "type1" and
245 * "type2". If they are matching use a type-specific instruction. Otherwise
246 * fall back to runtime type checking.
247 */
248 vartype_T
249operator_type(type_T *type1, type_T *type2)
250{
251 if (type1->tt_type == type2->tt_type
252 && (type1->tt_type == VAR_NUMBER
253 || type1->tt_type == VAR_LIST
254#ifdef FEAT_FLOAT
255 || type1->tt_type == VAR_FLOAT
256#endif
257 || type1->tt_type == VAR_BLOB))
258 return type1->tt_type;
259 return VAR_ANY;
260}
261
262/*
263 * Generate an instruction with two arguments. The instruction depends on the
264 * type of the arguments.
265 */
266 int
267generate_two_op(cctx_T *cctx, char_u *op)
268{
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000269 type_T *type1;
270 type_T *type2;
271 vartype_T vartype;
272 isn_T *isn;
273
274 RETURN_OK_IF_SKIP(cctx);
275
276 // Get the known type of the two items on the stack.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000277 type1 = get_type_on_stack(cctx, 1);
278 type2 = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000279 vartype = operator_type(type1, type2);
280
281 switch (*op)
282 {
283 case '+':
284 if (generate_add_instr(cctx, vartype, type1, type2,
285 EXPR_COPY) == FAIL)
286 return FAIL;
287 break;
288
289 case '-':
290 case '*':
291 case '/': if (check_number_or_float(type1->tt_type, type2->tt_type,
292 op) == FAIL)
293 return FAIL;
294 if (vartype == VAR_NUMBER)
295 isn = generate_instr_drop(cctx, ISN_OPNR, 1);
296#ifdef FEAT_FLOAT
297 else if (vartype == VAR_FLOAT)
298 isn = generate_instr_drop(cctx, ISN_OPFLOAT, 1);
299#endif
300 else
301 isn = generate_instr_drop(cctx, ISN_OPANY, 1);
302 if (isn != NULL)
303 isn->isn_arg.op.op_type = *op == '*'
304 ? EXPR_MULT : *op == '/'? EXPR_DIV : EXPR_SUB;
305 break;
306
307 case '%': if ((type1->tt_type != VAR_ANY
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000308 && type1->tt_type != VAR_UNKNOWN
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000309 && type1->tt_type != VAR_NUMBER)
310 || (type2->tt_type != VAR_ANY
Bram Moolenaar59618fe2021-12-21 12:32:17 +0000311 && type2->tt_type != VAR_UNKNOWN
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000312 && type2->tt_type != VAR_NUMBER))
313 {
314 emsg(_(e_percent_requires_number_arguments));
315 return FAIL;
316 }
317 isn = generate_instr_drop(cctx,
318 vartype == VAR_NUMBER ? ISN_OPNR : ISN_OPANY, 1);
319 if (isn != NULL)
320 isn->isn_arg.op.op_type = EXPR_REM;
321 break;
322 }
323
324 // correct type of result
325 if (vartype == VAR_ANY)
326 {
327 type_T *type = &t_any;
328
329#ifdef FEAT_FLOAT
330 // float+number and number+float results in float
331 if ((type1->tt_type == VAR_NUMBER || type1->tt_type == VAR_FLOAT)
332 && (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
333 type = &t_float;
334#endif
Bram Moolenaar078a4612022-01-04 15:17:03 +0000335 set_type_on_stack(cctx, type, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000336 }
337
338 return OK;
339}
340
341/*
342 * Get the instruction to use for comparing "type1" with "type2"
343 * Return ISN_DROP when failed.
344 */
345 static isntype_T
346get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
347{
348 isntype_T isntype = ISN_DROP;
349
350 if (type1 == VAR_UNKNOWN)
351 type1 = VAR_ANY;
352 if (type2 == VAR_UNKNOWN)
353 type2 = VAR_ANY;
354
355 if (type1 == type2)
356 {
357 switch (type1)
358 {
359 case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
360 case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
361 case VAR_NUMBER: isntype = ISN_COMPARENR; break;
362 case VAR_FLOAT: isntype = ISN_COMPAREFLOAT; break;
363 case VAR_STRING: isntype = ISN_COMPARESTRING; break;
364 case VAR_BLOB: isntype = ISN_COMPAREBLOB; break;
365 case VAR_LIST: isntype = ISN_COMPARELIST; break;
366 case VAR_DICT: isntype = ISN_COMPAREDICT; break;
367 case VAR_FUNC: isntype = ISN_COMPAREFUNC; break;
368 default: isntype = ISN_COMPAREANY; break;
369 }
370 }
371 else if (type1 == VAR_ANY || type2 == VAR_ANY
372 || ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
373 && (type2 == VAR_NUMBER || type2 == VAR_FLOAT)))
374 isntype = ISN_COMPAREANY;
Bram Moolenaar7a222242022-03-01 19:23:24 +0000375 else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL)
376 {
377 switch (type1 == VAR_SPECIAL ? type2 : type1)
378 {
379 case VAR_BLOB: break;
380 case VAR_CHANNEL: break;
381 case VAR_DICT: break;
382 case VAR_FUNC: break;
383 case VAR_JOB: break;
384 case VAR_LIST: break;
385 case VAR_PARTIAL: break;
386 case VAR_STRING: break;
387 default: semsg(_(e_cannot_compare_str_with_str),
388 vartype_name(type1), vartype_name(type2));
389 return ISN_DROP;
390 }
391 isntype = ISN_COMPARENULL;
392 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000393
394 if ((exprtype == EXPR_IS || exprtype == EXPR_ISNOT)
395 && (isntype == ISN_COMPAREBOOL
396 || isntype == ISN_COMPARESPECIAL
397 || isntype == ISN_COMPARENR
398 || isntype == ISN_COMPAREFLOAT))
399 {
400 semsg(_(e_cannot_use_str_with_str),
401 exprtype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
402 return ISN_DROP;
403 }
404 if (isntype == ISN_DROP
405 || ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
406 && (type1 == VAR_BOOL || type1 == VAR_SPECIAL
407 || type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
408 || ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
Bram Moolenaar7a222242022-03-01 19:23:24 +0000409 && exprtype != EXPR_IS && exprtype != EXPR_ISNOT
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000410 && (type1 == VAR_BLOB || type2 == VAR_BLOB
411 || type1 == VAR_LIST || type2 == VAR_LIST))))
412 {
413 semsg(_(e_cannot_compare_str_with_str),
414 vartype_name(type1), vartype_name(type2));
415 return ISN_DROP;
416 }
417 return isntype;
418}
419
420 int
421check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2)
422{
423 if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
424 return FAIL;
425 return OK;
426}
427
428/*
429 * Generate an ISN_COMPARE* instruction with a boolean result.
430 */
431 int
432generate_COMPARE(cctx_T *cctx, exprtype_T exprtype, int ic)
433{
434 isntype_T isntype;
435 isn_T *isn;
436 garray_T *stack = &cctx->ctx_type_stack;
437 vartype_T type1;
438 vartype_T type2;
439
440 RETURN_OK_IF_SKIP(cctx);
441
442 // Get the known type of the two items on the stack. If they are matching
443 // use a type-specific instruction. Otherwise fall back to runtime type
444 // checking.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000445 type1 = get_type_on_stack(cctx, 1)->tt_type;
446 type2 = get_type_on_stack(cctx, 0)->tt_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000447 isntype = get_compare_isn(exprtype, type1, type2);
448 if (isntype == ISN_DROP)
449 return FAIL;
450
451 if ((isn = generate_instr(cctx, isntype)) == NULL)
452 return FAIL;
453 isn->isn_arg.op.op_type = exprtype;
454 isn->isn_arg.op.op_ic = ic;
455
456 // takes two arguments, puts one bool back
457 if (stack->ga_len >= 2)
458 {
459 --stack->ga_len;
Bram Moolenaar078a4612022-01-04 15:17:03 +0000460 set_type_on_stack(cctx, &t_bool, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000461 }
462
463 return OK;
464}
465
466/*
467 * Generate an ISN_2BOOL instruction.
468 * "offset" is the offset in the type stack.
469 */
470 int
471generate_2BOOL(cctx_T *cctx, int invert, int offset)
472{
473 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000474
475 RETURN_OK_IF_SKIP(cctx);
476 if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
477 return FAIL;
478 isn->isn_arg.tobool.invert = invert;
479 isn->isn_arg.tobool.offset = offset;
480
481 // type becomes bool
Bram Moolenaar078a4612022-01-04 15:17:03 +0000482 set_type_on_stack(cctx, &t_bool, -1 - offset);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000483
484 return OK;
485}
486
487/*
488 * Generate an ISN_COND2BOOL instruction.
489 */
490 int
491generate_COND2BOOL(cctx_T *cctx)
492{
493 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000494
495 RETURN_OK_IF_SKIP(cctx);
496 if ((isn = generate_instr(cctx, ISN_COND2BOOL)) == NULL)
497 return FAIL;
498
499 // type becomes bool
Bram Moolenaar078a4612022-01-04 15:17:03 +0000500 set_type_on_stack(cctx, &t_bool, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000501
502 return OK;
503}
504
505 int
506generate_TYPECHECK(
507 cctx_T *cctx,
508 type_T *expected,
509 int offset,
510 int argidx)
511{
512 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000513
514 RETURN_OK_IF_SKIP(cctx);
515 if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
516 return FAIL;
517 isn->isn_arg.type.ct_type = alloc_type(expected);
518 isn->isn_arg.type.ct_off = (int8_T)offset;
519 isn->isn_arg.type.ct_arg_idx = (int8_T)argidx;
520
521 // type becomes expected
Bram Moolenaar078a4612022-01-04 15:17:03 +0000522 set_type_on_stack(cctx, expected, -1 - offset);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000523
524 return OK;
525}
526
527 int
528generate_SETTYPE(
529 cctx_T *cctx,
530 type_T *expected)
531{
532 isn_T *isn;
533
534 RETURN_OK_IF_SKIP(cctx);
535 if ((isn = generate_instr(cctx, ISN_SETTYPE)) == NULL)
536 return FAIL;
537 isn->isn_arg.type.ct_type = alloc_type(expected);
538 return OK;
539}
540
541/*
542 * Generate a PUSH instruction for "tv".
543 * "tv" will be consumed or cleared.
544 * Nothing happens if "tv" is NULL or of type VAR_UNKNOWN;
545 */
546 int
547generate_tv_PUSH(cctx_T *cctx, typval_T *tv)
548{
549 if (tv != NULL)
550 {
551 switch (tv->v_type)
552 {
553 case VAR_UNKNOWN:
554 break;
555 case VAR_BOOL:
556 generate_PUSHBOOL(cctx, tv->vval.v_number);
557 break;
558 case VAR_SPECIAL:
559 generate_PUSHSPEC(cctx, tv->vval.v_number);
560 break;
561 case VAR_NUMBER:
562 generate_PUSHNR(cctx, tv->vval.v_number);
563 break;
564#ifdef FEAT_FLOAT
565 case VAR_FLOAT:
566 generate_PUSHF(cctx, tv->vval.v_float);
567 break;
568#endif
569 case VAR_BLOB:
570 generate_PUSHBLOB(cctx, tv->vval.v_blob);
571 tv->vval.v_blob = NULL;
572 break;
573 case VAR_STRING:
574 generate_PUSHS(cctx, &tv->vval.v_string);
575 tv->vval.v_string = NULL;
576 break;
577 default:
578 iemsg("constant type not supported");
579 clear_tv(tv);
580 return FAIL;
581 }
582 tv->v_type = VAR_UNKNOWN;
583 }
584 return OK;
585}
586
587/*
588 * Generate an ISN_PUSHNR instruction.
589 */
590 int
591generate_PUSHNR(cctx_T *cctx, varnumber_T number)
592{
593 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000594
595 RETURN_OK_IF_SKIP(cctx);
596 if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
597 return FAIL;
598 isn->isn_arg.number = number;
599
600 if (number == 0 || number == 1)
601 // A 0 or 1 number can also be used as a bool.
Bram Moolenaar078a4612022-01-04 15:17:03 +0000602 set_type_on_stack(cctx, &t_number_bool, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000603 return OK;
604}
605
606/*
607 * Generate an ISN_PUSHBOOL instruction.
608 */
609 int
610generate_PUSHBOOL(cctx_T *cctx, varnumber_T number)
611{
612 isn_T *isn;
613
614 RETURN_OK_IF_SKIP(cctx);
615 if ((isn = generate_instr_type(cctx, ISN_PUSHBOOL, &t_bool)) == NULL)
616 return FAIL;
617 isn->isn_arg.number = number;
618
619 return OK;
620}
621
622/*
623 * Generate an ISN_PUSHSPEC instruction.
624 */
625 int
626generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
627{
628 isn_T *isn;
629
630 RETURN_OK_IF_SKIP(cctx);
631 if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
632 return FAIL;
633 isn->isn_arg.number = number;
634
635 return OK;
636}
637
638#if defined(FEAT_FLOAT) || defined(PROTO)
639/*
640 * Generate an ISN_PUSHF instruction.
641 */
642 int
643generate_PUSHF(cctx_T *cctx, float_T fnumber)
644{
645 isn_T *isn;
646
647 RETURN_OK_IF_SKIP(cctx);
648 if ((isn = generate_instr_type(cctx, ISN_PUSHF, &t_float)) == NULL)
649 return FAIL;
650 isn->isn_arg.fnumber = fnumber;
651
652 return OK;
653}
654#endif
655
656/*
657 * Generate an ISN_PUSHS instruction.
658 * Consumes "*str". When freed *str is set to NULL, unless "str" is NULL.
659 */
660 int
661generate_PUSHS(cctx_T *cctx, char_u **str)
662{
663 isn_T *isn;
664
665 if (cctx->ctx_skip == SKIP_YES)
666 {
667 if (str != NULL)
668 VIM_CLEAR(*str);
669 return OK;
670 }
671 if ((isn = generate_instr_type(cctx, ISN_PUSHS, &t_string)) == NULL)
672 {
673 if (str != NULL)
674 VIM_CLEAR(*str);
675 return FAIL;
676 }
677 isn->isn_arg.string = str == NULL ? NULL : *str;
678
679 return OK;
680}
681
682/*
683 * Generate an ISN_PUSHCHANNEL instruction.
684 * Consumes "channel".
685 */
686 int
687generate_PUSHCHANNEL(cctx_T *cctx, channel_T *channel)
688{
689 isn_T *isn;
690
691 RETURN_OK_IF_SKIP(cctx);
692 if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
693 return FAIL;
694 isn->isn_arg.channel = channel;
695
696 return OK;
697}
698
699/*
700 * Generate an ISN_PUSHJOB instruction.
701 * Consumes "job".
702 */
703 int
704generate_PUSHJOB(cctx_T *cctx, job_T *job)
705{
706 isn_T *isn;
707
708 RETURN_OK_IF_SKIP(cctx);
709 if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_channel)) == NULL)
710 return FAIL;
711 isn->isn_arg.job = job;
712
713 return OK;
714}
715
716/*
717 * Generate an ISN_PUSHBLOB instruction.
718 * Consumes "blob".
719 */
720 int
721generate_PUSHBLOB(cctx_T *cctx, blob_T *blob)
722{
723 isn_T *isn;
724
725 RETURN_OK_IF_SKIP(cctx);
726 if ((isn = generate_instr_type(cctx, ISN_PUSHBLOB, &t_blob)) == NULL)
727 return FAIL;
728 isn->isn_arg.blob = blob;
729
730 return OK;
731}
732
733/*
734 * Generate an ISN_PUSHFUNC instruction with name "name".
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000735 */
736 int
737generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
738{
739 isn_T *isn;
740 char_u *funcname;
741
742 RETURN_OK_IF_SKIP(cctx);
743 if ((isn = generate_instr_type(cctx, ISN_PUSHFUNC, type)) == NULL)
744 return FAIL;
745 if (name == NULL)
746 funcname = NULL;
Bram Moolenaard041f422022-01-12 19:54:00 +0000747 else if (*name == K_SPECIAL // script-local
748 || vim_strchr(name, AUTOLOAD_CHAR) != NULL) // autoload
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000749 funcname = vim_strsave(name);
750 else
751 {
752 funcname = alloc(STRLEN(name) + 3);
753 if (funcname != NULL)
754 {
755 STRCPY(funcname, "g:");
756 STRCPY(funcname + 2, name);
757 }
758 }
759
760 isn->isn_arg.string = funcname;
761 return OK;
762}
763
764/*
Bram Moolenaar06b77222022-01-25 15:51:56 +0000765 * Generate an ISN_AUTOLOAD instruction.
766 */
767 int
768generate_AUTOLOAD(cctx_T *cctx, char_u *name, type_T *type)
769{
770 isn_T *isn;
771
772 RETURN_OK_IF_SKIP(cctx);
773 if ((isn = generate_instr_type(cctx, ISN_AUTOLOAD, type)) == NULL)
774 return FAIL;
775 isn->isn_arg.string = vim_strsave(name);
776 if (isn->isn_arg.string == NULL)
777 return FAIL;
778 return OK;
779}
780
781/*
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000782 * Generate an ISN_GETITEM instruction with "index".
783 * "with_op" is TRUE for "+=" and other operators, the stack has the current
784 * value below the list with values.
785 */
786 int
787generate_GETITEM(cctx_T *cctx, int index, int with_op)
788{
789 isn_T *isn;
Bram Moolenaar078a4612022-01-04 15:17:03 +0000790 type_T *type = get_type_on_stack(cctx, with_op ? 1 : 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000791 type_T *item_type = &t_any;
792
793 RETURN_OK_IF_SKIP(cctx);
794
795 if (type->tt_type != VAR_LIST)
796 {
797 // cannot happen, caller has checked the type
Bram Moolenaar460ae5d2022-01-01 14:19:49 +0000798 emsg(_(e_list_required));
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000799 return FAIL;
800 }
801 item_type = type->tt_member;
802 if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
803 return FAIL;
804 isn->isn_arg.getitem.gi_index = index;
805 isn->isn_arg.getitem.gi_with_op = with_op;
806
807 // add the item type to the type stack
Bram Moolenaar078a4612022-01-04 15:17:03 +0000808 return push_type_stack(cctx, item_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000809}
810
811/*
812 * Generate an ISN_SLICE instruction with "count".
813 */
814 int
815generate_SLICE(cctx_T *cctx, int count)
816{
817 isn_T *isn;
818
819 RETURN_OK_IF_SKIP(cctx);
820 if ((isn = generate_instr(cctx, ISN_SLICE)) == NULL)
821 return FAIL;
822 isn->isn_arg.number = count;
823 return OK;
824}
825
826/*
827 * Generate an ISN_CHECKLEN instruction with "min_len".
828 */
829 int
830generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK)
831{
832 isn_T *isn;
833
834 RETURN_OK_IF_SKIP(cctx);
835
836 if ((isn = generate_instr(cctx, ISN_CHECKLEN)) == NULL)
837 return FAIL;
838 isn->isn_arg.checklen.cl_min_len = min_len;
839 isn->isn_arg.checklen.cl_more_OK = more_OK;
840
841 return OK;
842}
843
844/*
845 * Generate an ISN_STORE instruction.
846 */
847 int
848generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
849{
850 isn_T *isn;
851
852 RETURN_OK_IF_SKIP(cctx);
853 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
854 return FAIL;
855 if (name != NULL)
856 isn->isn_arg.string = vim_strsave(name);
857 else
858 isn->isn_arg.number = idx;
859
860 return OK;
861}
862
863/*
864 * Generate an ISN_STOREOUTER instruction.
865 */
Yegappan Lakshmanan782b43d2022-01-08 18:43:40 +0000866 static int
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000867generate_STOREOUTER(cctx_T *cctx, int idx, int level)
868{
869 isn_T *isn;
870
871 RETURN_OK_IF_SKIP(cctx);
872 if ((isn = generate_instr_drop(cctx, ISN_STOREOUTER, 1)) == NULL)
873 return FAIL;
874 isn->isn_arg.outer.outer_idx = idx;
875 isn->isn_arg.outer.outer_depth = level;
876
877 return OK;
878}
879
880/*
881 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
882 */
883 int
884generate_STORENR(cctx_T *cctx, int idx, varnumber_T value)
885{
886 isn_T *isn;
887
888 RETURN_OK_IF_SKIP(cctx);
889 if ((isn = generate_instr(cctx, ISN_STORENR)) == NULL)
890 return FAIL;
891 isn->isn_arg.storenr.stnr_idx = idx;
892 isn->isn_arg.storenr.stnr_val = value;
893
894 return OK;
895}
896
897/*
898 * Generate an ISN_STOREOPT or ISN_STOREFUNCOPT instruction
899 */
Yegappan Lakshmanan782b43d2022-01-08 18:43:40 +0000900 static int
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000901generate_STOREOPT(
902 cctx_T *cctx,
903 isntype_T isn_type,
904 char_u *name,
905 int opt_flags)
906{
907 isn_T *isn;
908
909 RETURN_OK_IF_SKIP(cctx);
910 if ((isn = generate_instr_drop(cctx, isn_type, 1)) == NULL)
911 return FAIL;
912 isn->isn_arg.storeopt.so_name = vim_strsave(name);
913 isn->isn_arg.storeopt.so_flags = opt_flags;
914
915 return OK;
916}
917
918/*
919 * Generate an ISN_LOAD or similar instruction.
920 */
921 int
922generate_LOAD(
923 cctx_T *cctx,
924 isntype_T isn_type,
925 int idx,
926 char_u *name,
927 type_T *type)
928{
929 isn_T *isn;
930
931 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar078a4612022-01-04 15:17:03 +0000932 if ((isn = generate_instr_type2(cctx, isn_type, type, type)) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000933 return FAIL;
934 if (name != NULL)
935 isn->isn_arg.string = vim_strsave(name);
936 else
937 isn->isn_arg.number = idx;
938
939 return OK;
940}
941
942/*
943 * Generate an ISN_LOADOUTER instruction
944 */
945 int
946generate_LOADOUTER(
947 cctx_T *cctx,
948 int idx,
949 int nesting,
950 type_T *type)
951{
952 isn_T *isn;
953
954 RETURN_OK_IF_SKIP(cctx);
Bram Moolenaar078a4612022-01-04 15:17:03 +0000955 if ((isn = generate_instr_type2(cctx, ISN_LOADOUTER, type, type)) == NULL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000956 return FAIL;
957 isn->isn_arg.outer.outer_idx = idx;
958 isn->isn_arg.outer.outer_depth = nesting;
959
960 return OK;
961}
962
963/*
964 * Generate an ISN_LOADV instruction for v:var.
965 */
966 int
967generate_LOADV(
968 cctx_T *cctx,
969 char_u *name,
970 int error)
971{
972 int di_flags;
973 int vidx = find_vim_var(name, &di_flags);
974 type_T *type;
975
976 RETURN_OK_IF_SKIP(cctx);
977 if (vidx < 0)
978 {
979 if (error)
980 semsg(_(e_variable_not_found_str), name);
981 return FAIL;
982 }
Bram Moolenaard787e402021-12-24 21:36:12 +0000983 type = get_vim_var_type(vidx, cctx->ctx_type_list);
Bram Moolenaardc7c3662021-12-20 15:04:29 +0000984 return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, type);
985}
986
987/*
988 * Generate an ISN_UNLET instruction.
989 */
990 int
991generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit)
992{
993 isn_T *isn;
994
995 RETURN_OK_IF_SKIP(cctx);
996 if ((isn = generate_instr(cctx, isn_type)) == NULL)
997 return FAIL;
998 isn->isn_arg.unlet.ul_name = vim_strsave(name);
999 isn->isn_arg.unlet.ul_forceit = forceit;
1000
1001 return OK;
1002}
1003
1004/*
1005 * Generate an ISN_LOCKCONST instruction.
1006 */
1007 int
1008generate_LOCKCONST(cctx_T *cctx)
1009{
1010 isn_T *isn;
1011
1012 RETURN_OK_IF_SKIP(cctx);
1013 if ((isn = generate_instr(cctx, ISN_LOCKCONST)) == NULL)
1014 return FAIL;
1015 return OK;
1016}
1017
1018/*
1019 * Generate an ISN_LOADS instruction.
1020 */
1021 int
1022generate_OLDSCRIPT(
1023 cctx_T *cctx,
1024 isntype_T isn_type,
1025 char_u *name,
1026 int sid,
1027 type_T *type)
1028{
1029 isn_T *isn;
1030
1031 RETURN_OK_IF_SKIP(cctx);
1032 if (isn_type == ISN_LOADS)
1033 isn = generate_instr_type(cctx, isn_type, type);
1034 else
1035 isn = generate_instr_drop(cctx, isn_type, 1);
1036 if (isn == NULL)
1037 return FAIL;
1038 isn->isn_arg.loadstore.ls_name = vim_strsave(name);
1039 isn->isn_arg.loadstore.ls_sid = sid;
1040
1041 return OK;
1042}
1043
1044/*
1045 * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
1046 */
1047 int
1048generate_VIM9SCRIPT(
1049 cctx_T *cctx,
1050 isntype_T isn_type,
1051 int sid,
1052 int idx,
1053 type_T *type)
1054{
1055 isn_T *isn;
1056 scriptref_T *sref;
1057 scriptitem_T *si = SCRIPT_ITEM(sid);
1058
1059 RETURN_OK_IF_SKIP(cctx);
1060 if (isn_type == ISN_LOADSCRIPT)
Bram Moolenaar160afdb2022-02-06 17:17:02 +00001061 isn = generate_instr_type2(cctx, isn_type, type, type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001062 else
1063 isn = generate_instr_drop(cctx, isn_type, 1);
1064 if (isn == NULL)
1065 return FAIL;
1066
1067 // This requires three arguments, which doesn't fit in an instruction, thus
1068 // we need to allocate a struct for this.
1069 sref = ALLOC_ONE(scriptref_T);
1070 if (sref == NULL)
1071 return FAIL;
1072 isn->isn_arg.script.scriptref = sref;
1073 sref->sref_sid = sid;
1074 sref->sref_idx = idx;
1075 sref->sref_seq = si->sn_script_seq;
1076 sref->sref_type = type;
1077 return OK;
1078}
1079
1080/*
1081 * Generate an ISN_NEWLIST instruction.
1082 */
1083 int
1084generate_NEWLIST(cctx_T *cctx, int count)
1085{
1086 isn_T *isn;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001087 type_T *member_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001088 type_T *type;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001089 type_T *decl_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001090
1091 RETURN_OK_IF_SKIP(cctx);
1092 if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
1093 return FAIL;
1094 isn->isn_arg.number = count;
1095
Bram Moolenaar078a4612022-01-04 15:17:03 +00001096 // Get the member type and the declared member type from all the items on
1097 // the stack.
Bram Moolenaar2626d6a2022-02-06 15:49:35 +00001098 member_type = get_member_type_from_stack(count, 1, cctx);
Bram Moolenaar078a4612022-01-04 15:17:03 +00001099 type = get_list_type(member_type, cctx->ctx_type_list);
Bram Moolenaar2626d6a2022-02-06 15:49:35 +00001100 decl_type = get_list_type(&t_any, cctx->ctx_type_list);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001101
1102 // drop the value types
Bram Moolenaar078a4612022-01-04 15:17:03 +00001103 cctx->ctx_type_stack.ga_len -= count;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001104
1105 // add the list type to the type stack
Bram Moolenaar078a4612022-01-04 15:17:03 +00001106 return push_type_stack2(cctx, type, decl_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001107}
1108
1109/*
1110 * Generate an ISN_NEWDICT instruction.
1111 */
1112 int
1113generate_NEWDICT(cctx_T *cctx, int count)
1114{
1115 isn_T *isn;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001116 type_T *member_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001117 type_T *type;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001118 type_T *decl_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001119
1120 RETURN_OK_IF_SKIP(cctx);
1121 if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
1122 return FAIL;
1123 isn->isn_arg.number = count;
1124
Bram Moolenaar2626d6a2022-02-06 15:49:35 +00001125 member_type = get_member_type_from_stack(count, 2, cctx);
Bram Moolenaar078a4612022-01-04 15:17:03 +00001126 type = get_dict_type(member_type, cctx->ctx_type_list);
Bram Moolenaar2626d6a2022-02-06 15:49:35 +00001127 decl_type = get_dict_type(&t_any, cctx->ctx_type_list);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001128
1129 // drop the key and value types
Bram Moolenaar078a4612022-01-04 15:17:03 +00001130 cctx->ctx_type_stack.ga_len -= 2 * count;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001131
1132 // add the dict type to the type stack
Bram Moolenaar078a4612022-01-04 15:17:03 +00001133 return push_type_stack2(cctx, type, decl_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001134}
1135
1136/*
1137 * Generate an ISN_FUNCREF instruction.
1138 */
1139 int
1140generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
1141{
1142 isn_T *isn;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001143 type_T *type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001144
1145 RETURN_OK_IF_SKIP(cctx);
1146 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1147 return FAIL;
1148 if (ufunc->uf_def_status == UF_NOT_COMPILED)
1149 isn->isn_arg.funcref.fr_func_name = vim_strsave(ufunc->uf_name);
1150 else
1151 isn->isn_arg.funcref.fr_dfunc_idx = ufunc->uf_dfunc_idx;
1152 cctx->ctx_has_closure = 1;
1153
1154 // If the referenced function is a closure, it may use items further up in
1155 // the nested context, including this one.
1156 if (ufunc->uf_flags & FC_CLOSURE)
1157 cctx->ctx_ufunc->uf_flags |= FC_CLOSURE;
1158
Bram Moolenaar078a4612022-01-04 15:17:03 +00001159 type = ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type;
1160 return push_type_stack(cctx, type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001161}
1162
1163/*
1164 * Generate an ISN_NEWFUNC instruction.
1165 * "lambda_name" and "func_name" must be in allocated memory and will be
1166 * consumed.
1167 */
1168 int
1169generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
1170{
1171 isn_T *isn;
1172
1173 if (cctx->ctx_skip == SKIP_YES)
1174 {
1175 vim_free(lambda_name);
1176 vim_free(func_name);
1177 return OK;
1178 }
1179 if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
1180 {
1181 vim_free(lambda_name);
1182 vim_free(func_name);
1183 return FAIL;
1184 }
1185 isn->isn_arg.newfunc.nf_lambda = lambda_name;
1186 isn->isn_arg.newfunc.nf_global = func_name;
1187
1188 return OK;
1189}
1190
1191/*
1192 * Generate an ISN_DEF instruction: list functions
1193 */
1194 int
1195generate_DEF(cctx_T *cctx, char_u *name, size_t len)
1196{
1197 isn_T *isn;
1198
1199 RETURN_OK_IF_SKIP(cctx);
1200 if ((isn = generate_instr(cctx, ISN_DEF)) == NULL)
1201 return FAIL;
1202 if (len > 0)
1203 {
1204 isn->isn_arg.string = vim_strnsave(name, len);
1205 if (isn->isn_arg.string == NULL)
1206 return FAIL;
1207 }
1208 return OK;
1209}
1210
1211/*
1212 * Generate an ISN_JUMP instruction.
1213 */
1214 int
1215generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where)
1216{
1217 isn_T *isn;
1218 garray_T *stack = &cctx->ctx_type_stack;
1219
1220 RETURN_OK_IF_SKIP(cctx);
1221 if ((isn = generate_instr(cctx, ISN_JUMP)) == NULL)
1222 return FAIL;
1223 isn->isn_arg.jump.jump_when = when;
1224 isn->isn_arg.jump.jump_where = where;
1225
1226 if (when != JUMP_ALWAYS && stack->ga_len > 0)
1227 --stack->ga_len;
1228
1229 return OK;
1230}
1231
1232/*
1233 * Generate an ISN_JUMP_IF_ARG_SET instruction.
1234 */
1235 int
1236generate_JUMP_IF_ARG_SET(cctx_T *cctx, int arg_off)
1237{
1238 isn_T *isn;
1239
1240 RETURN_OK_IF_SKIP(cctx);
1241 if ((isn = generate_instr(cctx, ISN_JUMP_IF_ARG_SET)) == NULL)
1242 return FAIL;
1243 isn->isn_arg.jumparg.jump_arg_off = arg_off;
1244 // jump_where is set later
1245 return OK;
1246}
1247
1248 int
1249generate_FOR(cctx_T *cctx, int loop_idx)
1250{
1251 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001252
1253 RETURN_OK_IF_SKIP(cctx);
1254 if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
1255 return FAIL;
1256 isn->isn_arg.forloop.for_idx = loop_idx;
1257
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001258 // type doesn't matter, will be stored next
Bram Moolenaar078a4612022-01-04 15:17:03 +00001259 return push_type_stack(cctx, &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001260}
1261/*
1262 * Generate an ISN_TRYCONT instruction.
1263 */
1264 int
1265generate_TRYCONT(cctx_T *cctx, int levels, int where)
1266{
1267 isn_T *isn;
1268
1269 RETURN_OK_IF_SKIP(cctx);
1270 if ((isn = generate_instr(cctx, ISN_TRYCONT)) == NULL)
1271 return FAIL;
1272 isn->isn_arg.trycont.tct_levels = levels;
1273 isn->isn_arg.trycont.tct_where = where;
1274
1275 return OK;
1276}
1277
1278
1279/*
1280 * Generate an ISN_BCALL instruction.
1281 * "method_call" is TRUE for "value->method()"
1282 * Return FAIL if the number of arguments is wrong.
1283 */
1284 int
1285generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
1286{
1287 isn_T *isn;
1288 garray_T *stack = &cctx->ctx_type_stack;
1289 int argoff;
Bram Moolenaar078a4612022-01-04 15:17:03 +00001290 type2_T *typep;
1291 type2_T *argtypes = NULL;
1292 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1293 type2_T *maptype = NULL;
1294 type_T *type;
Bram Moolenaar81330182022-02-01 12:11:58 +00001295 type_T *decl_type;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001296
1297 RETURN_OK_IF_SKIP(cctx);
1298 argoff = check_internal_func(func_idx, argcount);
1299 if (argoff < 0)
1300 return FAIL;
1301
1302 if (method_call && argoff > 1)
1303 {
1304 if ((isn = generate_instr(cctx, ISN_SHUFFLE)) == NULL)
1305 return FAIL;
1306 isn->isn_arg.shuffle.shfl_item = argcount;
1307 isn->isn_arg.shuffle.shfl_up = argoff - 1;
1308 }
1309
1310 if (argcount > 0)
1311 {
1312 // Check the types of the arguments.
Bram Moolenaar078a4612022-01-04 15:17:03 +00001313 typep = ((type2_T *)stack->ga_data) + stack->ga_len - argcount;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001314 if (method_call && argoff > 1)
1315 {
1316 int i;
1317
1318 for (i = 0; i < argcount; ++i)
1319 shuffled_argtypes[i] = (i < argoff - 1)
Bram Moolenaar078a4612022-01-04 15:17:03 +00001320 ? typep[i + 1]
1321 : (i == argoff - 1) ? typep[0] : typep[i];
1322 argtypes = shuffled_argtypes;
1323 }
1324 else
1325 {
1326 int i;
1327
1328 for (i = 0; i < argcount; ++i)
1329 shuffled_argtypes[i] = typep[i];
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001330 argtypes = shuffled_argtypes;
1331 }
1332 if (internal_func_check_arg_types(argtypes, func_idx, argcount,
1333 cctx) == FAIL)
1334 return FAIL;
1335 if (internal_func_is_map(func_idx))
Bram Moolenaar078a4612022-01-04 15:17:03 +00001336 maptype = argtypes;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001337 }
1338
1339 if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
1340 return FAIL;
1341 isn->isn_arg.bfunc.cbf_idx = func_idx;
1342 isn->isn_arg.bfunc.cbf_argcount = argcount;
1343
1344 // Drop the argument types and push the return type.
1345 stack->ga_len -= argcount;
Bram Moolenaar81330182022-02-01 12:11:58 +00001346 type = internal_func_ret_type(func_idx, argcount, argtypes, &decl_type);
1347 if (push_type_stack2(cctx, type, decl_type) == FAIL)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001348 return FAIL;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001349
Bram Moolenaar35c807d2022-01-27 16:36:29 +00001350 if (maptype != NULL && maptype[0].type_decl->tt_member != NULL
1351 && maptype[0].type_decl->tt_member != &t_any)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001352 // Check that map() didn't change the item types.
Bram Moolenaar35c807d2022-01-27 16:36:29 +00001353 generate_TYPECHECK(cctx, maptype[0].type_decl, -1, 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001354
1355 return OK;
1356}
1357
1358/*
1359 * Generate an ISN_LISTAPPEND instruction. Works like add().
1360 * Argument count is already checked.
1361 */
1362 int
1363generate_LISTAPPEND(cctx_T *cctx)
1364{
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001365 type_T *list_type;
1366 type_T *item_type;
1367 type_T *expected;
1368
1369 // Caller already checked that list_type is a list.
Bram Moolenaar81330182022-02-01 12:11:58 +00001370 // For checking the item type we use the declared type of the list and the
1371 // current type of the added item, adding a string to [1, 2] is OK.
1372 list_type = get_decl_type_on_stack(cctx, 1);
Bram Moolenaar078a4612022-01-04 15:17:03 +00001373 item_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001374 expected = list_type->tt_member;
1375 if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL)
1376 return FAIL;
1377
1378 if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
1379 return FAIL;
1380
Bram Moolenaar078a4612022-01-04 15:17:03 +00001381 --cctx->ctx_type_stack.ga_len; // drop the argument
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001382 return OK;
1383}
1384
1385/*
1386 * Generate an ISN_BLOBAPPEND instruction. Works like add().
1387 * Argument count is already checked.
1388 */
1389 int
1390generate_BLOBAPPEND(cctx_T *cctx)
1391{
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001392 type_T *item_type;
1393
1394 // Caller already checked that blob_type is a blob.
Bram Moolenaar078a4612022-01-04 15:17:03 +00001395 item_type = get_type_on_stack(cctx, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001396 if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
1397 return FAIL;
1398
1399 if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL)
1400 return FAIL;
1401
Bram Moolenaar078a4612022-01-04 15:17:03 +00001402 --cctx->ctx_type_stack.ga_len; // drop the argument
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001403 return OK;
1404}
1405
1406/*
1407 * Generate an ISN_DCALL or ISN_UCALL instruction.
1408 * Return FAIL if the number of arguments is wrong.
1409 */
1410 int
1411generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
1412{
1413 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001414 int regular_args = ufunc->uf_args.ga_len;
1415 int argcount = pushed_argcount;
1416
1417 RETURN_OK_IF_SKIP(cctx);
1418 if (argcount > regular_args && !has_varargs(ufunc))
1419 {
1420 semsg(_(e_too_many_arguments_for_function_str),
1421 printable_func_name(ufunc));
1422 return FAIL;
1423 }
1424 if (argcount < regular_args - ufunc->uf_def_args.ga_len)
1425 {
1426 semsg(_(e_not_enough_arguments_for_function_str),
1427 printable_func_name(ufunc));
1428 return FAIL;
1429 }
1430
1431 if (ufunc->uf_def_status != UF_NOT_COMPILED
1432 && ufunc->uf_def_status != UF_COMPILE_ERROR)
1433 {
1434 int i;
1435
1436 for (i = 0; i < argcount; ++i)
1437 {
1438 type_T *expected;
1439 type_T *actual;
1440
Bram Moolenaar078a4612022-01-04 15:17:03 +00001441 actual = get_type_on_stack(cctx, argcount - i - 1);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001442 if (actual == &t_special
1443 && i >= regular_args - ufunc->uf_def_args.ga_len)
1444 {
1445 // assume v:none used for default argument value
1446 continue;
1447 }
1448 if (i < regular_args)
1449 {
1450 if (ufunc->uf_arg_types == NULL)
1451 continue;
1452 expected = ufunc->uf_arg_types[i];
1453 }
1454 else if (ufunc->uf_va_type == NULL
1455 || ufunc->uf_va_type == &t_list_any)
1456 // possibly a lambda or "...: any"
1457 expected = &t_any;
1458 else
1459 expected = ufunc->uf_va_type->tt_member;
1460 if (need_type(actual, expected, -argcount + i, i + 1, cctx,
1461 TRUE, FALSE) == FAIL)
1462 {
1463 arg_type_mismatch(expected, actual, i + 1);
1464 return FAIL;
1465 }
1466 }
1467 if (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
1468 && compile_def_function(ufunc, ufunc->uf_ret_type == NULL,
1469 COMPILE_TYPE(ufunc), NULL) == FAIL)
1470 return FAIL;
1471 }
1472 if (ufunc->uf_def_status == UF_COMPILE_ERROR)
1473 {
1474 emsg_funcname(_(e_call_to_function_that_failed_to_compile_str),
1475 ufunc->uf_name);
1476 return FAIL;
1477 }
1478
1479 if ((isn = generate_instr(cctx,
1480 ufunc->uf_def_status != UF_NOT_COMPILED ? ISN_DCALL
1481 : ISN_UCALL)) == NULL)
1482 return FAIL;
1483 if (isn->isn_type == ISN_DCALL)
1484 {
1485 isn->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
1486 isn->isn_arg.dfunc.cdf_argcount = argcount;
1487 }
1488 else
1489 {
1490 // A user function may be deleted and redefined later, can't use the
1491 // ufunc pointer, need to look it up again at runtime.
1492 isn->isn_arg.ufunc.cuf_name = vim_strsave(ufunc->uf_name);
1493 isn->isn_arg.ufunc.cuf_argcount = argcount;
1494 }
1495
Bram Moolenaar078a4612022-01-04 15:17:03 +00001496 // drop the argument types
1497 cctx->ctx_type_stack.ga_len -= argcount;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001498
Bram Moolenaar078a4612022-01-04 15:17:03 +00001499 // add return type
1500 return push_type_stack(cctx, ufunc->uf_ret_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001501}
1502
1503/*
1504 * Generate an ISN_UCALL instruction when the function isn't defined yet.
1505 */
1506 int
1507generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
1508{
1509 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001510
1511 RETURN_OK_IF_SKIP(cctx);
1512 if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
1513 return FAIL;
1514 isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
1515 isn->isn_arg.ufunc.cuf_argcount = argcount;
1516
Bram Moolenaar078a4612022-01-04 15:17:03 +00001517 // drop the argument types
1518 cctx->ctx_type_stack.ga_len -= argcount;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001519
Bram Moolenaar078a4612022-01-04 15:17:03 +00001520 // add return value
1521 return push_type_stack(cctx, &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001522}
1523
1524/*
1525 * Generate an ISN_PCALL instruction.
1526 * "type" is the type of the FuncRef.
1527 */
1528 int
1529generate_PCALL(
1530 cctx_T *cctx,
1531 int argcount,
1532 char_u *name,
1533 type_T *type,
1534 int at_top)
1535{
1536 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001537 type_T *ret_type;
1538
1539 RETURN_OK_IF_SKIP(cctx);
1540
Bram Moolenaar59618fe2021-12-21 12:32:17 +00001541 if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001542 ret_type = &t_any;
1543 else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
1544 {
1545 if (type->tt_argcount != -1)
1546 {
1547 int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
1548
1549 if (argcount < type->tt_min_argcount - varargs)
1550 {
1551 semsg(_(e_not_enough_arguments_for_function_str), name);
1552 return FAIL;
1553 }
1554 if (!varargs && argcount > type->tt_argcount)
1555 {
1556 semsg(_(e_too_many_arguments_for_function_str), name);
1557 return FAIL;
1558 }
1559 if (type->tt_args != NULL)
1560 {
1561 int i;
1562
1563 for (i = 0; i < argcount; ++i)
1564 {
1565 int offset = -argcount + i - (at_top ? 0 : 1);
Bram Moolenaar078a4612022-01-04 15:17:03 +00001566 type_T *actual = get_type_on_stack(cctx, -1 - offset);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001567 type_T *expected;
1568
1569 if (varargs && i >= type->tt_argcount - 1)
1570 expected = type->tt_args[
1571 type->tt_argcount - 1]->tt_member;
1572 else if (i >= type->tt_min_argcount
1573 && actual == &t_special)
1574 expected = &t_any;
1575 else
1576 expected = type->tt_args[i];
1577 if (need_type(actual, expected, offset, i + 1,
1578 cctx, TRUE, FALSE) == FAIL)
1579 {
1580 arg_type_mismatch(expected, actual, i + 1);
1581 return FAIL;
1582 }
1583 }
1584 }
1585 }
1586 ret_type = type->tt_member;
1587 if (ret_type == &t_unknown)
1588 // return type not known yet, use a runtime check
1589 ret_type = &t_any;
1590 }
1591 else
1592 {
1593 semsg(_(e_not_callable_type_str), name);
1594 return FAIL;
1595 }
1596
1597 if ((isn = generate_instr(cctx, ISN_PCALL)) == NULL)
1598 return FAIL;
1599 isn->isn_arg.pfunc.cpf_top = at_top;
1600 isn->isn_arg.pfunc.cpf_argcount = argcount;
1601
Bram Moolenaar078a4612022-01-04 15:17:03 +00001602 // drop the arguments and the funcref/partial
1603 cctx->ctx_type_stack.ga_len -= argcount + 1;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001604
Bram Moolenaar078a4612022-01-04 15:17:03 +00001605 // push the return value
1606 push_type_stack(cctx, ret_type);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001607
1608 // If partial is above the arguments it must be cleared and replaced with
1609 // the return value.
1610 if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
1611 return FAIL;
1612
1613 return OK;
1614}
1615
1616/*
1617 * Generate an ISN_STRINGMEMBER instruction.
1618 */
1619 int
1620generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
1621{
1622 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001623 type_T *type;
1624
1625 RETURN_OK_IF_SKIP(cctx);
1626 if ((isn = generate_instr(cctx, ISN_STRINGMEMBER)) == NULL)
1627 return FAIL;
1628 isn->isn_arg.string = vim_strnsave(name, len);
1629
1630 // check for dict type
Bram Moolenaar078a4612022-01-04 15:17:03 +00001631 type = get_type_on_stack(cctx, 0);
Bram Moolenaar59618fe2021-12-21 12:32:17 +00001632 if (type->tt_type != VAR_DICT && type != &t_any && type != &t_unknown)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001633 {
1634 char *tofree;
1635
1636 semsg(_(e_expected_dictionary_for_using_key_str_but_got_str),
1637 name, type_name(type, &tofree));
1638 vim_free(tofree);
1639 return FAIL;
1640 }
1641 // change dict type to dict member type
1642 if (type->tt_type == VAR_DICT)
1643 {
Bram Moolenaar078a4612022-01-04 15:17:03 +00001644 type_T *ntype = type->tt_member == &t_unknown
1645 ? &t_any : type->tt_member;
1646 set_type_on_stack(cctx, ntype, 0);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001647 }
1648
1649 return OK;
1650}
1651
1652/*
1653 * Generate an ISN_ECHO instruction.
1654 */
1655 int
1656generate_ECHO(cctx_T *cctx, int with_white, int count)
1657{
1658 isn_T *isn;
1659
1660 RETURN_OK_IF_SKIP(cctx);
1661 if ((isn = generate_instr_drop(cctx, ISN_ECHO, count)) == NULL)
1662 return FAIL;
1663 isn->isn_arg.echo.echo_with_white = with_white;
1664 isn->isn_arg.echo.echo_count = count;
1665
1666 return OK;
1667}
1668
1669/*
1670 * Generate an ISN_EXECUTE/ISN_ECHOMSG/ISN_ECHOERR instruction.
1671 */
1672 int
1673generate_MULT_EXPR(cctx_T *cctx, isntype_T isn_type, int count)
1674{
1675 isn_T *isn;
1676
1677 if ((isn = generate_instr_drop(cctx, isn_type, count)) == NULL)
1678 return FAIL;
1679 isn->isn_arg.number = count;
1680
1681 return OK;
1682}
1683
1684/*
1685 * Generate an ISN_PUT instruction.
1686 */
1687 int
1688generate_PUT(cctx_T *cctx, int regname, linenr_T lnum)
1689{
1690 isn_T *isn;
1691
1692 RETURN_OK_IF_SKIP(cctx);
1693 if ((isn = generate_instr(cctx, ISN_PUT)) == NULL)
1694 return FAIL;
1695 isn->isn_arg.put.put_regname = regname;
1696 isn->isn_arg.put.put_lnum = lnum;
1697 return OK;
1698}
1699
1700/*
1701 * Generate an EXEC instruction that takes a string argument.
1702 * A copy is made of "line".
1703 */
1704 int
1705generate_EXEC_copy(cctx_T *cctx, isntype_T isntype, char_u *line)
1706{
1707 isn_T *isn;
1708
1709 RETURN_OK_IF_SKIP(cctx);
1710 if ((isn = generate_instr(cctx, isntype)) == NULL)
1711 return FAIL;
1712 isn->isn_arg.string = vim_strsave(line);
1713 return OK;
1714}
1715
1716/*
1717 * Generate an EXEC instruction that takes a string argument.
1718 * "str" must be allocated, it is consumed.
1719 */
1720 int
1721generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *str)
1722{
1723 isn_T *isn;
1724
1725 if (cctx->ctx_skip == SKIP_YES)
1726 {
1727 vim_free(str);
1728 return OK;
1729 }
1730 if ((isn = generate_instr(cctx, isntype)) == NULL)
1731 {
1732 vim_free(str);
1733 return FAIL;
1734 }
1735 isn->isn_arg.string = str;
1736 return OK;
1737}
1738
1739 int
1740generate_LEGACY_EVAL(cctx_T *cctx, char_u *line)
1741{
1742 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001743
1744 RETURN_OK_IF_SKIP(cctx);
1745 if ((isn = generate_instr(cctx, ISN_LEGACY_EVAL)) == NULL)
1746 return FAIL;
1747 isn->isn_arg.string = vim_strsave(line);
1748
Bram Moolenaar078a4612022-01-04 15:17:03 +00001749 return push_type_stack(cctx, &t_any);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001750}
1751
1752 int
1753generate_EXECCONCAT(cctx_T *cctx, int count)
1754{
1755 isn_T *isn;
1756
1757 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
1758 return FAIL;
1759 isn->isn_arg.number = count;
1760 return OK;
1761}
1762
1763/*
1764 * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
1765 */
1766 int
1767generate_RANGE(cctx_T *cctx, char_u *range)
1768{
1769 isn_T *isn;
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001770
1771 if ((isn = generate_instr(cctx, ISN_RANGE)) == NULL)
1772 return FAIL;
1773 isn->isn_arg.string = range;
1774
Bram Moolenaar078a4612022-01-04 15:17:03 +00001775 return push_type_stack(cctx, &t_number);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001776}
1777
1778 int
1779generate_UNPACK(cctx_T *cctx, int var_count, int semicolon)
1780{
1781 isn_T *isn;
1782
1783 RETURN_OK_IF_SKIP(cctx);
1784 if ((isn = generate_instr(cctx, ISN_UNPACK)) == NULL)
1785 return FAIL;
1786 isn->isn_arg.unpack.unp_count = var_count;
1787 isn->isn_arg.unpack.unp_semicolon = semicolon;
1788 return OK;
1789}
1790
1791/*
1792 * Generate an instruction for any command modifiers.
1793 */
1794 int
1795generate_cmdmods(cctx_T *cctx, cmdmod_T *cmod)
1796{
1797 isn_T *isn;
1798
1799 if (has_cmdmod(cmod, FALSE))
1800 {
1801 cctx->ctx_has_cmdmod = TRUE;
1802
1803 if ((isn = generate_instr(cctx, ISN_CMDMOD)) == NULL)
1804 return FAIL;
1805 isn->isn_arg.cmdmod.cf_cmdmod = ALLOC_ONE(cmdmod_T);
1806 if (isn->isn_arg.cmdmod.cf_cmdmod == NULL)
1807 return FAIL;
1808 mch_memmove(isn->isn_arg.cmdmod.cf_cmdmod, cmod, sizeof(cmdmod_T));
1809 // filter program now belongs to the instruction
1810 cmod->cmod_filter_regmatch.regprog = NULL;
1811 }
1812
1813 return OK;
1814}
1815
1816 int
1817generate_undo_cmdmods(cctx_T *cctx)
1818{
1819 if (cctx->ctx_has_cmdmod && generate_instr(cctx, ISN_CMDMOD_REV) == NULL)
1820 return FAIL;
1821 cctx->ctx_has_cmdmod = FALSE;
1822 return OK;
1823}
1824
1825/*
1826 * Generate a STORE instruction for "dest", not being "dest_local".
1827 * Return FAIL when out of memory.
1828 */
1829 int
1830generate_store_var(
1831 cctx_T *cctx,
1832 assign_dest_T dest,
1833 int opt_flags,
1834 int vimvaridx,
1835 int scriptvar_idx,
1836 int scriptvar_sid,
1837 type_T *type,
1838 char_u *name)
1839{
1840 switch (dest)
1841 {
1842 case dest_option:
1843 return generate_STOREOPT(cctx, ISN_STOREOPT,
1844 skip_option_env_lead(name), opt_flags);
1845 case dest_func_option:
1846 return generate_STOREOPT(cctx, ISN_STOREFUNCOPT,
1847 skip_option_env_lead(name), opt_flags);
1848 case dest_global:
1849 // include g: with the name, easier to execute that way
1850 return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL
1851 ? ISN_STOREG : ISN_STOREAUTO, 0, name);
1852 case dest_buffer:
1853 // include b: with the name, easier to execute that way
1854 return generate_STORE(cctx, ISN_STOREB, 0, name);
1855 case dest_window:
1856 // include w: with the name, easier to execute that way
1857 return generate_STORE(cctx, ISN_STOREW, 0, name);
1858 case dest_tab:
1859 // include t: with the name, easier to execute that way
1860 return generate_STORE(cctx, ISN_STORET, 0, name);
1861 case dest_env:
1862 return generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
1863 case dest_reg:
1864 return generate_STORE(cctx, ISN_STOREREG,
1865 name[1] == '@' ? '"' : name[1], NULL);
1866 case dest_vimvar:
1867 return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
1868 case dest_script:
1869 if (scriptvar_idx < 0)
1870 // "s:" may be included in the name.
1871 return generate_OLDSCRIPT(cctx, ISN_STORES, name,
1872 scriptvar_sid, type);
1873 return generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
1874 scriptvar_sid, scriptvar_idx, type);
1875 case dest_local:
1876 case dest_expr:
1877 // cannot happen
1878 break;
1879 }
1880 return FAIL;
1881}
1882
Bram Moolenaar38ecd972022-01-15 21:44:44 +00001883/*
1884 * Return TRUE when inside a "for" or "while" loop.
1885 */
1886 int
1887inside_loop_scope(cctx_T *cctx)
1888{
1889 scope_T *scope = cctx->ctx_scope;
1890
1891 for (;;)
1892 {
1893 if (scope == NULL)
1894 break;
1895 if (scope->se_type == FOR_SCOPE || scope->se_type == WHILE_SCOPE)
1896 return TRUE;
1897 scope = scope->se_outer;
1898 }
1899 return FALSE;
1900}
1901
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001902 int
Bram Moolenaar5cd64792021-12-25 18:23:24 +00001903generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl)
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001904{
1905 if (lhs->lhs_dest != dest_local)
1906 return generate_store_var(cctx, lhs->lhs_dest,
1907 lhs->lhs_opt_flags, lhs->lhs_vimvaridx,
1908 lhs->lhs_scriptvar_idx, lhs->lhs_scriptvar_sid,
1909 lhs->lhs_type, lhs->lhs_name);
1910
1911 if (lhs->lhs_lvar != NULL)
1912 {
1913 garray_T *instr = &cctx->ctx_instr;
1914 isn_T *isn = ((isn_T *)instr->ga_data) + instr->ga_len - 1;
1915
Bram Moolenaar5cd64792021-12-25 18:23:24 +00001916 // Optimization: turn "var = 123" from ISN_PUSHNR + ISN_STORE into
1917 // ISN_STORENR.
1918 // And "var = 0" does not need any instruction.
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001919 if (lhs->lhs_lvar->lv_from_outer == 0
1920 && instr->ga_len == instr_count + 1
1921 && isn->isn_type == ISN_PUSHNR)
1922 {
1923 varnumber_T val = isn->isn_arg.number;
1924 garray_T *stack = &cctx->ctx_type_stack;
1925
Bram Moolenaar38ecd972022-01-15 21:44:44 +00001926 if (val == 0 && is_decl && !inside_loop_scope(cctx))
Bram Moolenaar5cd64792021-12-25 18:23:24 +00001927 {
Bram Moolenaar38ecd972022-01-15 21:44:44 +00001928 // zero is the default value, no need to do anything
Bram Moolenaar5cd64792021-12-25 18:23:24 +00001929 --instr->ga_len;
1930 }
1931 else
1932 {
1933 isn->isn_type = ISN_STORENR;
1934 isn->isn_arg.storenr.stnr_idx = lhs->lhs_lvar->lv_idx;
1935 isn->isn_arg.storenr.stnr_val = val;
1936 }
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001937 if (stack->ga_len > 0)
1938 --stack->ga_len;
1939 }
1940 else if (lhs->lhs_lvar->lv_from_outer > 0)
1941 generate_STOREOUTER(cctx, lhs->lhs_lvar->lv_idx,
1942 lhs->lhs_lvar->lv_from_outer);
1943 else
1944 generate_STORE(cctx, ISN_STORE, lhs->lhs_lvar->lv_idx, NULL);
1945 }
1946 return OK;
1947}
1948
1949#if defined(FEAT_PROFILE) || defined(PROTO)
1950 void
1951may_generate_prof_end(cctx_T *cctx, int prof_lnum)
1952{
1953 if (cctx->ctx_compile_type == CT_PROFILE && prof_lnum >= 0)
1954 generate_instr(cctx, ISN_PROF_END);
1955}
1956#endif
1957
1958
1959/*
1960 * Delete an instruction, free what it contains.
1961 */
1962 void
1963delete_instr(isn_T *isn)
1964{
1965 switch (isn->isn_type)
1966 {
Bram Moolenaar06b77222022-01-25 15:51:56 +00001967 case ISN_AUTOLOAD:
Bram Moolenaardc7c3662021-12-20 15:04:29 +00001968 case ISN_DEF:
1969 case ISN_EXEC:
1970 case ISN_EXECRANGE:
1971 case ISN_EXEC_SPLIT:
1972 case ISN_LEGACY_EVAL:
1973 case ISN_LOADAUTO:
1974 case ISN_LOADB:
1975 case ISN_LOADENV:
1976 case ISN_LOADG:
1977 case ISN_LOADOPT:
1978 case ISN_LOADT:
1979 case ISN_LOADW:
1980 case ISN_LOCKUNLOCK:
1981 case ISN_PUSHEXC:
1982 case ISN_PUSHFUNC:
1983 case ISN_PUSHS:
1984 case ISN_RANGE:
1985 case ISN_STOREAUTO:
1986 case ISN_STOREB:
1987 case ISN_STOREENV:
1988 case ISN_STOREG:
1989 case ISN_STORET:
1990 case ISN_STOREW:
1991 case ISN_STRINGMEMBER:
1992 vim_free(isn->isn_arg.string);
1993 break;
1994
1995 case ISN_SUBSTITUTE:
1996 {
1997 int idx;
1998 isn_T *list = isn->isn_arg.subs.subs_instr;
1999
2000 vim_free(isn->isn_arg.subs.subs_cmd);
2001 for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
2002 delete_instr(list + idx);
2003 vim_free(list);
2004 }
2005 break;
2006
2007 case ISN_INSTR:
2008 {
2009 int idx;
2010 isn_T *list = isn->isn_arg.instr;
2011
2012 for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
2013 delete_instr(list + idx);
2014 vim_free(list);
2015 }
2016 break;
2017
2018 case ISN_LOADS:
2019 case ISN_STORES:
2020 vim_free(isn->isn_arg.loadstore.ls_name);
2021 break;
2022
2023 case ISN_UNLET:
2024 case ISN_UNLETENV:
2025 vim_free(isn->isn_arg.unlet.ul_name);
2026 break;
2027
2028 case ISN_STOREOPT:
2029 case ISN_STOREFUNCOPT:
2030 vim_free(isn->isn_arg.storeopt.so_name);
2031 break;
2032
2033 case ISN_PUSHBLOB: // push blob isn_arg.blob
2034 blob_unref(isn->isn_arg.blob);
2035 break;
2036
2037 case ISN_PUSHJOB:
2038#ifdef FEAT_JOB_CHANNEL
2039 job_unref(isn->isn_arg.job);
2040#endif
2041 break;
2042
2043 case ISN_PUSHCHANNEL:
2044#ifdef FEAT_JOB_CHANNEL
2045 channel_unref(isn->isn_arg.channel);
2046#endif
2047 break;
2048
2049 case ISN_UCALL:
2050 vim_free(isn->isn_arg.ufunc.cuf_name);
2051 break;
2052
2053 case ISN_FUNCREF:
2054 {
2055 if (isn->isn_arg.funcref.fr_func_name == NULL)
2056 {
2057 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
2058 + isn->isn_arg.funcref.fr_dfunc_idx;
2059 ufunc_T *ufunc = dfunc->df_ufunc;
2060
2061 if (ufunc != NULL && func_name_refcount(ufunc->uf_name))
2062 func_ptr_unref(ufunc);
2063 }
2064 else
2065 {
2066 char_u *name = isn->isn_arg.funcref.fr_func_name;
2067
2068 if (name != NULL)
2069 func_unref(name);
2070 vim_free(isn->isn_arg.funcref.fr_func_name);
2071 }
2072 }
2073 break;
2074
2075 case ISN_DCALL:
2076 {
2077 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
2078 + isn->isn_arg.dfunc.cdf_idx;
2079
2080 if (dfunc->df_ufunc != NULL
2081 && func_name_refcount(dfunc->df_ufunc->uf_name))
2082 func_ptr_unref(dfunc->df_ufunc);
2083 }
2084 break;
2085
2086 case ISN_NEWFUNC:
2087 {
2088 char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
Bram Moolenaaracc4b562022-01-24 13:54:45 +00002089 ufunc_T *ufunc = find_func_even_dead(lambda, FFED_IS_GLOBAL);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002090
2091 if (ufunc != NULL)
2092 {
2093 unlink_def_function(ufunc);
2094 func_ptr_unref(ufunc);
2095 }
2096
2097 vim_free(lambda);
2098 vim_free(isn->isn_arg.newfunc.nf_global);
2099 }
2100 break;
2101
2102 case ISN_CHECKTYPE:
2103 case ISN_SETTYPE:
2104 free_type(isn->isn_arg.type.ct_type);
2105 break;
2106
2107 case ISN_CMDMOD:
2108 vim_regfree(isn->isn_arg.cmdmod.cf_cmdmod
2109 ->cmod_filter_regmatch.regprog);
2110 vim_free(isn->isn_arg.cmdmod.cf_cmdmod);
2111 break;
2112
2113 case ISN_LOADSCRIPT:
2114 case ISN_STORESCRIPT:
2115 vim_free(isn->isn_arg.script.scriptref);
2116 break;
2117
2118 case ISN_TRY:
Bram Moolenaar0d807102021-12-21 09:42:09 +00002119 vim_free(isn->isn_arg.tryref.try_ref);
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002120 break;
2121
2122 case ISN_CEXPR_CORE:
2123 vim_free(isn->isn_arg.cexpr.cexpr_ref->cer_cmdline);
2124 vim_free(isn->isn_arg.cexpr.cexpr_ref);
2125 break;
2126
2127 case ISN_2BOOL:
2128 case ISN_2STRING:
2129 case ISN_2STRING_ANY:
2130 case ISN_ADDBLOB:
2131 case ISN_ADDLIST:
2132 case ISN_ANYINDEX:
2133 case ISN_ANYSLICE:
2134 case ISN_BCALL:
2135 case ISN_BLOBAPPEND:
2136 case ISN_BLOBINDEX:
2137 case ISN_BLOBSLICE:
2138 case ISN_CATCH:
2139 case ISN_CEXPR_AUCMD:
2140 case ISN_CHECKLEN:
2141 case ISN_CHECKNR:
2142 case ISN_CLEARDICT:
2143 case ISN_CMDMOD_REV:
2144 case ISN_COMPAREANY:
2145 case ISN_COMPAREBLOB:
2146 case ISN_COMPAREBOOL:
2147 case ISN_COMPAREDICT:
2148 case ISN_COMPAREFLOAT:
2149 case ISN_COMPAREFUNC:
2150 case ISN_COMPARELIST:
2151 case ISN_COMPARENR:
Bram Moolenaar7a222242022-03-01 19:23:24 +00002152 case ISN_COMPARENULL:
Bram Moolenaardc7c3662021-12-20 15:04:29 +00002153 case ISN_COMPARESPECIAL:
2154 case ISN_COMPARESTRING:
2155 case ISN_CONCAT:
2156 case ISN_COND2BOOL:
2157 case ISN_DEBUG:
2158 case ISN_DROP:
2159 case ISN_ECHO:
2160 case ISN_ECHOCONSOLE:
2161 case ISN_ECHOERR:
2162 case ISN_ECHOMSG:
2163 case ISN_ENDTRY:
2164 case ISN_EXECCONCAT:
2165 case ISN_EXECUTE:
2166 case ISN_FINALLY:
2167 case ISN_FINISH:
2168 case ISN_FOR:
2169 case ISN_GETITEM:
2170 case ISN_JUMP:
2171 case ISN_JUMP_IF_ARG_SET:
2172 case ISN_LISTAPPEND:
2173 case ISN_LISTINDEX:
2174 case ISN_LISTSLICE:
2175 case ISN_LOAD:
2176 case ISN_LOADBDICT:
2177 case ISN_LOADGDICT:
2178 case ISN_LOADOUTER:
2179 case ISN_LOADREG:
2180 case ISN_LOADTDICT:
2181 case ISN_LOADV:
2182 case ISN_LOADWDICT:
2183 case ISN_LOCKCONST:
2184 case ISN_MEMBER:
2185 case ISN_NEGATENR:
2186 case ISN_NEWDICT:
2187 case ISN_NEWLIST:
2188 case ISN_OPANY:
2189 case ISN_OPFLOAT:
2190 case ISN_OPNR:
2191 case ISN_PCALL:
2192 case ISN_PCALL_END:
2193 case ISN_PROF_END:
2194 case ISN_PROF_START:
2195 case ISN_PUSHBOOL:
2196 case ISN_PUSHF:
2197 case ISN_PUSHNR:
2198 case ISN_PUSHSPEC:
2199 case ISN_PUT:
2200 case ISN_REDIREND:
2201 case ISN_REDIRSTART:
2202 case ISN_RETURN:
2203 case ISN_RETURN_VOID:
2204 case ISN_SHUFFLE:
2205 case ISN_SLICE:
2206 case ISN_STORE:
2207 case ISN_STOREINDEX:
2208 case ISN_STORENR:
2209 case ISN_STOREOUTER:
2210 case ISN_STORERANGE:
2211 case ISN_STOREREG:
2212 case ISN_STOREV:
2213 case ISN_STRINDEX:
2214 case ISN_STRSLICE:
2215 case ISN_THROW:
2216 case ISN_TRYCONT:
2217 case ISN_UNLETINDEX:
2218 case ISN_UNLETRANGE:
2219 case ISN_UNPACK:
2220 case ISN_USEDICT:
2221 // nothing allocated
2222 break;
2223 }
2224}
2225
2226 void
2227clear_instr_ga(garray_T *gap)
2228{
2229 int idx;
2230
2231 for (idx = 0; idx < gap->ga_len; ++idx)
2232 delete_instr(((isn_T *)gap->ga_data) + idx);
2233 ga_clear(gap);
2234}
2235
2236
2237#endif // defined(FEAT_EVAL)