• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/compiler.c

  1 /*
  2  * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io>
  3  *
  4  * Permission to use, copy, modify, and/or distribute this software for any
  5  * purpose with or without fee is hereby granted, provided that the above
  6  * copyright notice and this permission notice appear in all copies.
  7  *
  8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15  */
 16 
 17 #include <assert.h>
 18 #include <errno.h>
 19 
 20 #include "ucode/compiler.h"
 21 #include "ucode/chunk.h"
 22 #include "ucode/vm.h" /* I_* */
 23 #include "ucode/source.h"
 24 #include "ucode/program.h"
 25 #include "ucode/lib.h" /* uc_error_context_format() */
 26 
 27 #ifndef NO_COMPILE
 28 
 29 static void uc_compiler_compile_unary(uc_compiler_t *compiler);
 30 static void uc_compiler_compile_binary(uc_compiler_t *compiler);
 31 static void uc_compiler_compile_delete(uc_compiler_t *compiler);
 32 static void uc_compiler_compile_importcall(uc_compiler_t *compiler);
 33 static void uc_compiler_compile_paren(uc_compiler_t *compiler);
 34 static void uc_compiler_compile_call(uc_compiler_t *compiler);
 35 static void uc_compiler_compile_post_inc(uc_compiler_t *compiler);
 36 static void uc_compiler_compile_constant(uc_compiler_t *compiler);
 37 static void uc_compiler_compile_template(uc_compiler_t *compiler);
 38 static void uc_compiler_compile_comma(uc_compiler_t *compiler);
 39 static void uc_compiler_compile_labelexpr(uc_compiler_t *compiler);
 40 static void uc_compiler_compile_funcexpr(uc_compiler_t *compiler);
 41 static void uc_compiler_compile_and(uc_compiler_t *compiler);
 42 static void uc_compiler_compile_or(uc_compiler_t *compiler);
 43 static void uc_compiler_compile_nullish(uc_compiler_t *compiler);
 44 static void uc_compiler_compile_dot(uc_compiler_t *compiler);
 45 static void uc_compiler_compile_subscript(uc_compiler_t *compiler);
 46 static void uc_compiler_compile_ternary(uc_compiler_t *compiler);
 47 static void uc_compiler_compile_array(uc_compiler_t *compiler);
 48 static void uc_compiler_compile_object(uc_compiler_t *compiler);
 49 
 50 static uc_tokentype_t uc_compiler_compile_declaration(uc_compiler_t *compiler);
 51 static uc_tokentype_t uc_compiler_compile_statement(uc_compiler_t *compiler);
 52 static uc_tokentype_t uc_compiler_compile_expstmt(uc_compiler_t *compiler);
 53 
 54 static uc_parse_rule_t
 55 uc_compiler_parse_rules[TK_ERROR + 1] = {
 56         [TK_LPAREN]             = { uc_compiler_compile_paren, uc_compiler_compile_call, P_CALL },
 57         [TK_QLPAREN]    = { NULL, uc_compiler_compile_call, P_CALL },
 58         [TK_SUB]                = { uc_compiler_compile_unary, uc_compiler_compile_binary, P_ADD },
 59         [TK_ADD]                = { uc_compiler_compile_unary, uc_compiler_compile_binary, P_ADD },
 60         [TK_COMPL]              = { uc_compiler_compile_unary, NULL, P_UNARY },
 61         [TK_NOT]                = { uc_compiler_compile_unary, NULL, P_UNARY },
 62         [TK_DELETE]             = { uc_compiler_compile_delete, NULL, P_UNARY },
 63         [TK_IMPORT]             = { uc_compiler_compile_importcall, NULL, P_UNARY },
 64         [TK_INC]                = { uc_compiler_compile_unary, uc_compiler_compile_post_inc, P_INC },
 65         [TK_DEC]                = { uc_compiler_compile_unary, uc_compiler_compile_post_inc, P_INC },
 66         [TK_DIV]                = { NULL, uc_compiler_compile_binary, P_MUL },
 67         [TK_MUL]                = { NULL, uc_compiler_compile_binary, P_MUL },
 68         [TK_MOD]                = { NULL, uc_compiler_compile_binary, P_MUL },
 69         [TK_EXP]                = { NULL, uc_compiler_compile_binary, P_EXP },
 70         [TK_NUMBER]             = { uc_compiler_compile_constant, NULL, P_NONE },
 71         [TK_DOUBLE]             = { uc_compiler_compile_constant, NULL, P_NONE },
 72         [TK_STRING]             = { uc_compiler_compile_constant, NULL, P_NONE },
 73         [TK_TRUE]               = { uc_compiler_compile_constant, NULL, P_NONE },
 74         [TK_FALSE]              = { uc_compiler_compile_constant, NULL, P_NONE },
 75         [TK_NULL]               = { uc_compiler_compile_constant, NULL, P_NONE },
 76         [TK_THIS]               = { uc_compiler_compile_constant, NULL, P_NONE },
 77         [TK_REGEXP]             = { uc_compiler_compile_constant, NULL, P_NONE },
 78         [TK_TEMPLATE]   = { uc_compiler_compile_template, NULL, P_NONE },
 79         [TK_COMMA]              = { NULL, uc_compiler_compile_comma, P_COMMA },
 80         [TK_LABEL]              = { uc_compiler_compile_labelexpr, NULL, P_NONE },
 81         [TK_FUNC]               = { uc_compiler_compile_funcexpr, NULL, P_NONE },
 82         [TK_AND]                = { NULL, uc_compiler_compile_and, P_AND },
 83         [TK_OR]                 = { NULL, uc_compiler_compile_or, P_OR },
 84         [TK_NULLISH]    = { NULL, uc_compiler_compile_nullish, P_OR },
 85         [TK_BOR]                = { NULL, uc_compiler_compile_binary, P_BOR },
 86         [TK_BXOR]               = { NULL, uc_compiler_compile_binary, P_BXOR },
 87         [TK_BAND]               = { NULL, uc_compiler_compile_binary, P_BAND },
 88         [TK_EQ]                 = { NULL, uc_compiler_compile_binary, P_EQUAL },
 89         [TK_EQS]                = { NULL, uc_compiler_compile_binary, P_EQUAL },
 90         [TK_NE]                 = { NULL, uc_compiler_compile_binary, P_EQUAL },
 91         [TK_NES]                = { NULL, uc_compiler_compile_binary, P_EQUAL },
 92         [TK_LT]                 = { NULL, uc_compiler_compile_binary, P_COMPARE },
 93         [TK_LE]                 = { NULL, uc_compiler_compile_binary, P_COMPARE },
 94         [TK_GT]                 = { NULL, uc_compiler_compile_binary, P_COMPARE },
 95         [TK_GE]                 = { NULL, uc_compiler_compile_binary, P_COMPARE },
 96         [TK_IN]                 = { NULL, uc_compiler_compile_binary, P_COMPARE },
 97         [TK_LSHIFT]             = { NULL, uc_compiler_compile_binary, P_SHIFT },
 98         [TK_RSHIFT]             = { NULL, uc_compiler_compile_binary, P_SHIFT },
 99         [TK_DOT]                = { NULL, uc_compiler_compile_dot, P_CALL },
100         [TK_QDOT]               = { NULL, uc_compiler_compile_dot, P_CALL },
101         [TK_LBRACK]             = { uc_compiler_compile_array, uc_compiler_compile_subscript, P_CALL },
102         [TK_QLBRACK]    = { NULL, uc_compiler_compile_subscript, P_CALL },
103         [TK_QMARK]              = { NULL, uc_compiler_compile_ternary, P_TERNARY },
104         [TK_LBRACE]             = { uc_compiler_compile_object, NULL, P_NONE },
105 };
106 
107 static ssize_t
108 uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool constant);
109 
110 static ssize_t
111 uc_compiler_initialize_local(uc_compiler_t *compiler);
112 
113 static bool
114 uc_compiler_exprstack_is(uc_compiler_t *compiler, uc_exprflag_t flag)
115 {
116         uc_exprstack_t *expr;
117 
118         for (expr = compiler->exprstack; expr; expr = expr->parent)
119                 if (expr->flags & flag)
120                         return true;
121 
122         return false;
123 }
124 
125 static void
126 uc_compiler_init(uc_compiler_t *compiler, const char *name, uc_source_t *source, size_t srcpos, uc_program_t *program, bool strict)
127 {
128         uc_value_t *varname = ucv_string_new("(callee)");
129         uc_function_t *fn;
130 
131         compiler->scope_depth = 0;
132 
133         compiler->program = program;
134         compiler->function = uc_program_function_new(program, name, source, srcpos);
135 
136         compiler->locals.count = 0;
137         compiler->locals.entries = NULL;
138 
139         compiler->upvals.count = 0;
140         compiler->upvals.entries = NULL;
141 
142         compiler->patchlist = NULL;
143 
144         compiler->parent = NULL;
145 
146         compiler->current_srcpos = srcpos;
147 
148         fn = (uc_function_t *)compiler->function;
149         fn->strict = strict;
150 
151         /* reserve stack slot 0 */
152         uc_compiler_declare_local(compiler, varname, false);
153         uc_compiler_initialize_local(compiler);
154         ucv_put(varname);
155 }
156 
157 static uc_chunk_t *
158 uc_compiler_current_chunk(uc_compiler_t *compiler)
159 {
160         uc_function_t *fn = (uc_function_t *)compiler->function;
161 
162         return &fn->chunk;
163 }
164 
165 static uc_source_t *
166 uc_compiler_current_source(uc_compiler_t *compiler)
167 {
168         return uc_program_function_source(compiler->function);
169 }
170 
171 __attribute__((format(printf, 3, 0))) static void
172 uc_compiler_syntax_error(uc_compiler_t *compiler, size_t off, const char *fmt, ...)
173 {
174         uc_source_t *source = uc_compiler_current_source(compiler);
175         uc_stringbuf_t *buf = compiler->parser->error;
176         size_t line = 0, byte = 0, len = 0;
177         va_list ap;
178         char *s;
179 
180         if (compiler->parser->synchronizing)
181                 return;
182 
183         compiler->parser->synchronizing = true;
184 
185         if (!buf)
186                 buf = compiler->parser->error = xprintbuf_new();
187 
188         if (!off)
189                 off = uc_program_function_srcpos(compiler->function,
190                         uc_compiler_current_chunk(compiler)->count);
191 
192         byte = off;
193         line = uc_source_get_line(source, &byte);
194 
195         va_start(ap, fmt);
196         len = xvasprintf(&s, fmt, ap);
197         va_end(ap);
198 
199         ucv_stringbuf_append(buf, "Syntax error: ");
200         ucv_stringbuf_addstr(buf, s, len);
201         ucv_stringbuf_append(buf, "\n");
202 
203         free(s);
204 
205         if (line) {
206                 ucv_stringbuf_append(buf, "In ");
207 
208                 if (compiler->program->sources.count > 1) {
209                         len = strlen(source->filename);
210 
211                         if (len > 48)
212                                 ucv_stringbuf_printf(buf, "...%s", source->filename + len - 45);
213                         else
214                                 ucv_stringbuf_addstr(buf, source->filename, len);
215 
216                         ucv_stringbuf_append(buf, ", ");
217                 }
218 
219                 ucv_stringbuf_printf(buf, "line %zu, byte %zu:\n", line, byte);
220         }
221 
222         if (uc_error_context_format(buf, source, NULL, off))
223                 ucv_stringbuf_append(buf, "\n\n");
224 }
225 
226 static size_t
227 uc_compiler_set_srcpos(uc_compiler_t *compiler, size_t srcpos)
228 {
229         size_t delta;
230 
231         /* ensure that lines counts are strictly increasing */
232         assert(srcpos == 0 || srcpos >= compiler->current_srcpos);
233 
234         delta = srcpos ? srcpos - compiler->current_srcpos : 0;
235         compiler->current_srcpos += delta;
236 
237         return delta;
238 }
239 
240 static void
241 uc_compiler_parse_advance(uc_compiler_t *compiler)
242 {
243         ucv_put(compiler->parser->prev.uv);
244         compiler->parser->prev = compiler->parser->curr;
245 
246         while (true) {
247                 uc_token_t *tok = uc_lexer_next_token(&compiler->parser->lex);
248 
249                 if (tok->type == TK_COMMENT || tok->type == TK_LSTM) {
250                         ucv_put(tok->uv);
251                         continue;
252                 }
253                 else if (tok->type == TK_RSTM) {
254                         tok->type = TK_SCOL;
255                 }
256 
257                 compiler->parser->curr = *tok;
258 
259                 if (compiler->parser->curr.type != TK_ERROR)
260                         break;
261 
262                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "%s",
263                         ucv_string_get(compiler->parser->curr.uv));
264 
265                 ucv_put(compiler->parser->curr.uv);
266                 compiler->parser->curr.uv = NULL;
267         }
268 }
269 
270 static void
271 uc_compiler_parse_consume(uc_compiler_t *compiler, uc_tokentype_t type)
272 {
273         if (compiler->parser->curr.type == type) {
274                 uc_compiler_parse_advance(compiler);
275 
276                 return;
277         }
278 
279         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
280                 "Unexpected token\nExpecting %s", uc_tokenname(type));
281 }
282 
283 static bool
284 uc_compiler_parse_check(uc_compiler_t *compiler, uc_tokentype_t type)
285 {
286         return (compiler->parser->curr.type == type);
287 }
288 
289 static bool
290 uc_compiler_parse_match(uc_compiler_t *compiler, uc_tokentype_t type)
291 {
292         if (!uc_compiler_parse_check(compiler, type))
293                 return false;
294 
295         uc_compiler_parse_advance(compiler);
296 
297         return true;
298 }
299 
300 static bool
301 uc_compiler_keyword_check(uc_compiler_t *compiler, const char *keyword)
302 {
303         size_t keywordlen = strlen(keyword);
304 
305         return (compiler->parser->curr.type == TK_LABEL &&
306                 ucv_string_length(compiler->parser->curr.uv) == keywordlen &&
307                 strcmp(ucv_string_get(compiler->parser->curr.uv), keyword) == 0);
308 }
309 
310 static bool
311 uc_compiler_keyword_match(uc_compiler_t *compiler, const char *keyword)
312 {
313         if (!uc_compiler_keyword_check(compiler, keyword))
314                 return false;
315 
316         uc_compiler_parse_advance(compiler);
317 
318         return true;
319 }
320 
321 static void
322 uc_compiler_keyword_consume(uc_compiler_t *compiler, const char *keyword)
323 {
324         if (uc_compiler_keyword_check(compiler, keyword)) {
325                 uc_compiler_parse_advance(compiler);
326 
327                 return;
328         }
329 
330         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
331                 "Unexpected token\nExpecting '%s'", keyword);
332 }
333 
334 static void
335 uc_compiler_parse_synchronize(uc_compiler_t *compiler)
336 {
337         compiler->parser->synchronizing = false;
338 
339         while (compiler->parser->curr.type != TK_EOF) {
340                 if (compiler->parser->prev.type == TK_SCOL)
341                         return;
342 
343                 switch (compiler->parser->curr.type) {
344                 case TK_IF:
345                 case TK_FOR:
346                 case TK_WHILE:
347                 case TK_SWITCH:
348                 case TK_FUNC:
349                 case TK_TRY:
350                 case TK_RETURN:
351                 case TK_BREAK:
352                 case TK_CONTINUE:
353                 case TK_LOCAL:
354                         return;
355 
356                 default:
357                         break;
358                 }
359 
360                 uc_compiler_parse_advance(compiler);
361         }
362 }
363 
364 static uc_parse_rule_t *
365 uc_compiler_parse_rule(uc_tokentype_t type)
366 {
367         return &uc_compiler_parse_rules[type];
368 }
369 
370 static bool
371 uc_compiler_parse_at_assignment_op(uc_compiler_t *compiler)
372 {
373         switch (compiler->parser->curr.type) {
374         case TK_ASBAND:
375         case TK_ASBXOR:
376         case TK_ASBOR:
377         case TK_ASLEFT:
378         case TK_ASRIGHT:
379         case TK_ASMUL:
380         case TK_ASDIV:
381         case TK_ASMOD:
382         case TK_ASADD:
383         case TK_ASSUB:
384         case TK_ASAND:
385         case TK_ASOR:
386         case TK_ASEXP:
387         case TK_ASNULLISH:
388         case TK_ASSIGN:
389                 return true;
390 
391         default:
392                 return false;
393         }
394 }
395 
396 static void
397 uc_compiler_backpatch(uc_compiler_t *compiler, size_t break_addr, size_t next_addr);
398 
399 static void
400 uc_compiler_parse_precedence_for_token(uc_compiler_t *compiler, uc_precedence_t precedence, uc_token_t *token)
401 {
402         uc_parse_rule_t *rule;
403 
404         rule = uc_compiler_parse_rule(token->type);
405 
406         if (!rule->prefix) {
407                 uc_compiler_syntax_error(compiler, token->pos, "Expecting expression");
408 
409                 return;
410         }
411 
412         uc_compiler_exprstack_push(compiler, token->type,
413                 (precedence <= P_ASSIGN) ? F_ASSIGNABLE : 0);
414 
415         compiler->patchlist = &(uc_patchlist_t){
416                 .parent = compiler->patchlist,
417                 .token = TK_EXP,
418         };
419 
420         rule->prefix(compiler);
421 
422         while (precedence <= uc_compiler_parse_rule(compiler->parser->curr.type)->precedence) {
423                 compiler->exprstack->token = compiler->parser->curr.type;
424 
425                 rule = uc_compiler_parse_rule(compiler->exprstack->token);
426 
427                 if (!rule->infix) {
428                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting ';' or binary operator");
429                         uc_compiler_parse_advance(compiler);
430 
431                         return;
432                 }
433 
434                 /* allow reserved words in property accessors */
435                 if (rule->infix == uc_compiler_compile_dot)
436                         compiler->parser->lex.no_keyword = true;
437 
438                 uc_compiler_parse_advance(compiler);
439 
440                 rule->infix(compiler);
441         }
442 
443         uc_compiler_backpatch(compiler, compiler->patchlist->depth, 0);
444 
445         uc_compiler_exprstack_pop(compiler);
446 }
447 
448 static void
449 uc_compiler_parse_precedence(uc_compiler_t *compiler, uc_precedence_t precedence)
450 {
451         uc_token_t token = compiler->parser->curr;
452         uc_parse_rule_t *rule = uc_compiler_parse_rule(token.type);
453 
454         /* allow reserved words as property names in object literals */
455         if (rule->prefix == uc_compiler_compile_object)
456                 compiler->parser->lex.no_keyword = true;
457 
458         /* unless a sub-expression follows, treat subsequent slash as division
459          * operator and not as beginning of regexp literal */
460         if (rule->prefix != uc_compiler_compile_paren &&
461             rule->prefix != uc_compiler_compile_unary &&
462             rule->prefix != uc_compiler_compile_array)
463                 compiler->parser->lex.no_regexp = true;
464 
465         uc_compiler_parse_advance(compiler);
466         uc_compiler_parse_precedence_for_token(compiler, precedence, &token);
467 }
468 
469 static size_t
470 uc_compiler_reladdr32(uc_compiler_t *compiler, size_t from, size_t to)
471 {
472         ssize_t delta = to - from;
473 
474         if (delta < -0x7fffffff || delta > 0x7fffffff) {
475                 uc_compiler_syntax_error(compiler, 0, "Jump address too far");
476 
477                 return 0;
478         }
479 
480         return (size_t)(delta + 0x7fffffff);
481 }
482 
483 static size_t
484 uc_compiler_reladdr16(uc_compiler_t *compiler, size_t from, size_t to)
485 {
486         ssize_t delta = to - from;
487 
488         if (delta < -0x7fff || delta > 0x7fff) {
489                 uc_compiler_syntax_error(compiler, 0, "Jump address too far");
490 
491                 return 0;
492         }
493 
494         return (size_t)(delta + 0x7fff);
495 }
496 
497 static size_t
498 uc_compiler_emit_insn(uc_compiler_t *compiler, size_t srcpos, uc_vm_insn_t insn)
499 {
500         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
501         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
502 
503         compiler->last_insn = uc_chunk_add(chunk, (uint8_t)insn, lineoff);
504 
505         return compiler->last_insn;
506 }
507 
508 static size_t
509 uc_compiler_emit_u8(uc_compiler_t *compiler, size_t srcpos, uint8_t n)
510 {
511         return uc_chunk_add(
512                 uc_compiler_current_chunk(compiler),
513                 n,
514                 uc_compiler_set_srcpos(compiler, srcpos));
515 }
516 
517 static size_t
518 uc_compiler_emit_u16(uc_compiler_t *compiler, size_t srcpos, uint16_t n)
519 {
520         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
521         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
522 
523         uc_chunk_add(chunk, n / 0x100, lineoff);
524         uc_chunk_add(chunk, n % 0x100, 0);
525 
526         return chunk->count - 2;
527 }
528 
529 static size_t
530 uc_compiler_emit_u32(uc_compiler_t *compiler, size_t srcpos, uint32_t n)
531 {
532         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
533         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
534 
535         uc_chunk_add(chunk, n / 0x1000000, lineoff);
536         uc_chunk_add(chunk, (n / 0x10000) % 0x100, 0);
537         uc_chunk_add(chunk, (n / 0x100) % 0x100, 0);
538         uc_chunk_add(chunk, n % 0x100, 0);
539 
540         return chunk->count - 4;
541 }
542 
543 static size_t
544 uc_compiler_emit_s32(uc_compiler_t *compiler, size_t srcpos, int32_t n)
545 {
546         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
547         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
548         uint32_t v;
549 
550         if (n <= 0)
551                 v = n + 0x7fffffff;
552         else
553                 v = (uint32_t)n + 0x7fffffff;
554 
555         uc_chunk_add(chunk, v / 0x1000000, lineoff);
556         uc_chunk_add(chunk, (v / 0x10000) % 0x100, 0);
557         uc_chunk_add(chunk, (v / 0x100) % 0x100, 0);
558         uc_chunk_add(chunk, v % 0x100, 0);
559 
560         return chunk->count - 4;
561 }
562 
563 static uint32_t
564 uc_compiler_get_u32(uc_compiler_t *compiler, size_t off)
565 {
566         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
567 
568         return chunk->entries[off + 0] * 0x1000000 +
569                chunk->entries[off + 1] * 0x10000 +
570                chunk->entries[off + 2] * 0x100 +
571                chunk->entries[off + 3];
572 }
573 
574 static void
575 uc_compiler_set_u32(uc_compiler_t *compiler, size_t off, uint32_t n)
576 {
577         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
578 
579         chunk->entries[off + 0] = n / 0x1000000;
580         chunk->entries[off + 1] = (n / 0x10000) % 0x100;
581         chunk->entries[off + 2] = (n / 0x100) % 0x100;
582         chunk->entries[off + 3] = n % 0x100;
583 }
584 
585 static size_t
586 uc_compiler_emit_constant_index(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
587 {
588         size_t cidx = uc_program_add_constant(compiler->program, val);
589 
590         uc_compiler_emit_u32(compiler, srcpos, cidx);
591 
592         return cidx;
593 }
594 
595 static size_t
596 uc_compiler_emit_constant(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
597 {
598         size_t cidx;
599 
600         uc_compiler_emit_insn(compiler, srcpos, I_LOAD);
601 
602         cidx = uc_compiler_emit_constant_index(compiler, srcpos, val);
603 
604         return cidx;
605 }
606 
607 static size_t
608 uc_compiler_emit_regexp(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
609 {
610         size_t cidx = uc_program_add_constant(compiler->program, val);
611 
612         uc_compiler_emit_insn(compiler, srcpos, I_LREXP);
613         uc_compiler_emit_u32(compiler, 0, cidx);
614 
615         return cidx;
616 }
617 
618 static size_t
619 uc_compiler_emit_jmp(uc_compiler_t *compiler, size_t srcpos)
620 {
621         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
622 
623         uc_compiler_emit_insn(compiler, srcpos, I_JMP);
624         uc_compiler_emit_u32(compiler, 0, 0);
625 
626         return chunk->count - 5;
627 }
628 
629 static size_t
630 uc_compiler_emit_jmpz(uc_compiler_t *compiler, size_t srcpos)
631 {
632         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
633 
634         uc_compiler_emit_insn(compiler, srcpos, I_JMPZ);
635         uc_compiler_emit_u32(compiler, 0, 0);
636 
637         return chunk->count - 5;
638 }
639 
640 static size_t
641 uc_compiler_emit_jmp_dest(uc_compiler_t *compiler, size_t srcpos, uint32_t dest)
642 {
643         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
644 
645         uc_compiler_emit_insn(compiler, srcpos, I_JMP);
646         uc_compiler_emit_u32(compiler, 0, uc_compiler_reladdr32(compiler, chunk->count - 1, dest));
647 
648         return chunk->count - 5;
649 }
650 
651 static size_t
652 uc_compiler_emit_jmpnt(uc_compiler_t *compiler, size_t srcpos, uint16_t types, uint8_t depth)
653 {
654         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
655 
656         uc_vector_push(compiler->patchlist,
657                 uc_compiler_emit_insn(compiler, srcpos, I_JMPNT));
658 
659         uc_compiler_emit_u32(compiler, 0,
660                 uc_compiler_reladdr16(compiler, 0, TK_BREAK)
661                         | ((types & 0x1fff) << 16)
662                         | ((depth & 0x7) << 29));
663 
664         return chunk->count - 5;
665 }
666 
667 static size_t
668 uc_compiler_emit_copy(uc_compiler_t *compiler, size_t srcpos, uint8_t depth)
669 {
670         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
671 
672         uc_compiler_emit_insn(compiler, srcpos, I_COPY);
673         uc_compiler_emit_u8(compiler, 0, depth);
674 
675         return chunk->count - 2;
676 }
677 
678 static ssize_t
679 uc_compiler_get_jmpaddr(uc_compiler_t *compiler, size_t off)
680 {
681         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
682         size_t width = (chunk->entries[off] == I_JMPNT) ? 2 : 4;
683 
684         assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ || chunk->entries[off] == I_JMPNT);
685         assert(off + 4 < chunk->count);
686 
687         if (width == 2)
688                 return (
689                         chunk->entries[off + 3] * 0x100UL +
690                         chunk->entries[off + 4]
691                 ) - 0x7fff;
692         else
693                 return (
694                         chunk->entries[off + 1] * 0x1000000UL +
695                         chunk->entries[off + 2] * 0x10000UL +
696                         chunk->entries[off + 3] * 0x100UL +
697                         chunk->entries[off + 4]
698                 ) - 0x7fffffff;
699 }
700 
701 static void
702 uc_compiler_set_jmpaddr(uc_compiler_t *compiler, size_t off, uint32_t dest)
703 {
704         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
705         size_t width = (chunk->entries[off] == I_JMPNT) ? 2 : 4;
706         size_t addr;
707 
708         assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ || chunk->entries[off] == I_JMPNT);
709         assert(off + 4 < chunk->count);
710 
711         if (width == 2) {
712                 addr = uc_compiler_reladdr16(compiler, off, dest);
713                 chunk->entries[off + 3] = addr / 0x100;
714                 chunk->entries[off + 4] = addr % 0x100;
715         }
716         else {
717                 addr = uc_compiler_reladdr32(compiler, off, dest);
718                 chunk->entries[off + 1] = addr / 0x1000000;
719                 chunk->entries[off + 2] = (addr / 0x10000) % 0x100;
720                 chunk->entries[off + 3] = (addr / 0x100) % 0x100;
721                 chunk->entries[off + 4] = addr % 0x100;
722         }
723 }
724 
725 static void
726 uc_compiler_inc_exportnum(uc_compiler_t *compiler)
727 {
728         uc_source_t *root = uc_program_function_source(uc_program_entry(compiler->program));
729         uint64_t u;
730 
731         if (root->exports.count == 0) {
732                 uc_vector_push(&root->exports, ucv_uint64_new(1));
733         }
734         else {
735                 u = ucv_uint64_get(root->exports.entries[0]);
736 
737                 ucv_put(root->exports.entries[0]);
738 
739                 root->exports.entries[0] = ucv_uint64_new(u + 1);
740         }
741 }
742 
743 static size_t
744 uc_compiler_get_exportnum(uc_compiler_t *compiler)
745 {
746         uc_source_t *root = uc_program_function_source(uc_program_entry(compiler->program));
747 
748         return root->exports.count ? ucv_uint64_get(root->exports.entries[0]) : 0;
749 }
750 
751 static void
752 uc_compiler_emit_exports(uc_compiler_t *compiler) {
753         size_t i;
754 
755         if (!compiler->patchlist || compiler->patchlist->token != TK_EXPORT)
756                 return;
757 
758         for (i = 0; i < compiler->patchlist->count; i++) {
759                 uc_compiler_emit_insn(compiler, 0, I_EXPORT);
760                 uc_compiler_emit_u32(compiler, 0, compiler->patchlist->entries[i]);
761         }
762 }
763 
764 static uc_function_t *
765 uc_compiler_finish(uc_compiler_t *compiler, uc_tokentype_t last_statement_type)
766 {
767         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
768         uc_locals_t *locals = &compiler->locals;
769         uc_upvals_t *upvals = &compiler->upvals;
770         size_t i;
771 
772         if (compiler->function->module)
773                 uc_compiler_emit_exports(compiler);
774 
775         uc_compiler_emit_insn(compiler, 0, I_LNULL);
776         uc_compiler_emit_insn(compiler, 0, I_RETURN);
777 
778         for (i = 0; i < locals->count; i++) {
779                 uc_chunk_debug_add_variable(chunk,
780                         locals->entries[i].from,
781                         chunk->count,
782                         i,
783                         false,
784                         locals->entries[i].name);
785 
786                 ucv_put(locals->entries[i].name);
787         }
788 
789         for (i = 0; i < upvals->count; i++) {
790                 uc_chunk_debug_add_variable(chunk,
791                         0,
792                         chunk->count,
793                         i,
794                         true,
795                         upvals->entries[i].name);
796 
797                 ucv_put(upvals->entries[i].name);
798         }
799 
800         uc_vector_clear(locals);
801         uc_vector_clear(upvals);
802 
803         if (compiler->parser->error) {
804                 uc_program_function_free(compiler->function);
805 
806                 return NULL;
807         }
808 
809         return compiler->function;
810 }
811 
812 static void
813 uc_compiler_enter_scope(uc_compiler_t *compiler)
814 {
815         compiler->scope_depth++;
816 }
817 
818 static void
819 uc_compiler_leave_scope(uc_compiler_t *compiler)
820 {
821         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
822         uc_locals_t *locals = &compiler->locals;
823 
824         compiler->scope_depth--;
825 
826         while (locals->count > 0 && locals->entries[locals->count - 1].depth > (ssize_t)compiler->scope_depth) {
827                 locals->count--;
828 
829                 uc_chunk_debug_add_variable(chunk,
830                         locals->entries[locals->count].from,
831                         chunk->count,
832                         locals->count,
833                         false,
834                         locals->entries[locals->count].name);
835 
836                 ucv_put(locals->entries[locals->count].name);
837                 locals->entries[locals->count].name = NULL;
838 
839                 uc_compiler_emit_insn(compiler, 0,
840                         locals->entries[locals->count].captured ? I_CUPV : I_POP);
841         }
842 }
843 
844 static bool
845 uc_compiler_is_strict(uc_compiler_t *compiler)
846 {
847         uc_function_t *fn = (uc_function_t *)compiler->function;
848 
849         return fn->strict;
850 }
851 
852 static ssize_t
853 uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool constant)
854 {
855         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
856         uc_locals_t *locals = &compiler->locals;
857         const char *str1, *str2;
858         size_t i, len1, len2;
859 
860         if (locals->count >= 0x00FFFFFF) {
861                 uc_compiler_syntax_error(compiler, 0, "Too many local variables");
862 
863                 return -1;
864         }
865 
866         str1 = ucv_string_get(name);
867         len1 = ucv_string_length(name);
868 
869         for (i = locals->count; i > 0; i--) {
870                 if (locals->entries[i - 1].depth != -1 && locals->entries[i - 1].depth < (ssize_t)compiler->scope_depth)
871                         break;
872 
873                 str2 = ucv_string_get(locals->entries[i - 1].name);
874                 len2 = ucv_string_length(locals->entries[i - 1].name);
875 
876                 if (len1 == len2 && !strcmp(str1, str2)) {
877                         if (locals->entries[i - 1].funcstub) {
878                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
879                                         "Variable '%s' redeclared", str2);
880 
881                                 return -1;
882                         }
883 
884                         if (uc_compiler_is_strict(compiler)) {
885                                 uc_compiler_syntax_error(compiler, 0, "Variable '%s' redeclared", str2);
886 
887                                 return -1;
888                         }
889 
890                         return i - 1;
891                 }
892         }
893 
894         uc_vector_push(locals, {
895                 .name = ucv_get(name),
896                 .depth = -1,
897                 .captured = false,
898                 .from = chunk->count,
899                 .constant = constant
900         });
901 
902         return -1;
903 }
904 
905 static ssize_t
906 uc_compiler_initialize_local(uc_compiler_t *compiler)
907 {
908         uc_locals_t *locals = &compiler->locals;
909 
910         locals->entries[locals->count - 1].depth = compiler->scope_depth;
911 
912         return locals->count - 1;
913 }
914 
915 static ssize_t
916 uc_compiler_resolve_local(uc_compiler_t *compiler, uc_value_t *name, bool *constant)
917 {
918         uc_locals_t *locals = &compiler->locals;
919         const char *str1, *str2;
920         size_t i, len1, len2;
921 
922         str1 = ucv_string_get(name);
923         len1 = ucv_string_length(name);
924 
925         for (i = locals->count; i > 0; i--) {
926                 str2 = ucv_string_get(locals->entries[i - 1].name);
927                 len2 = ucv_string_length(locals->entries[i - 1].name);
928 
929                 if (len1 != len2 || strcmp(str1, str2))
930                         continue;
931 
932                 if (locals->entries[i - 1].depth == -1) {
933                         uc_compiler_syntax_error(compiler, 0,
934                                 "Can't access lexical declaration '%s' before initialization", str2);
935 
936                         return -1;
937                 }
938 
939                 *constant = locals->entries[i - 1].constant;
940 
941                 return i - 1;
942         }
943 
944         return -1;
945 }
946 
947 static ssize_t
948 uc_compiler_resolve_funcstub(uc_compiler_t *compiler, uc_value_t *name)
949 {
950         uc_locals_t *locals = &compiler->locals;
951         const char *str1, *str2;
952         size_t i, len1, len2;
953 
954         str1 = ucv_string_get(name);
955         len1 = ucv_string_length(name);
956 
957         for (i = locals->count; i > 0; i--) {
958                 if (locals->entries[i - 1].depth != -1 &&
959                     locals->entries[i - 1].depth < (ssize_t)compiler->scope_depth)
960                         break;
961 
962                 str2 = ucv_string_get(locals->entries[i - 1].name);
963                 len2 = ucv_string_length(locals->entries[i - 1].name);
964 
965                 if (len1 == len2 && !strcmp(str1, str2))
966                         return locals->entries[i - 1].funcstub ? (ssize_t)(i - 1) : -1;
967         }
968 
969         return -1;
970 }
971 
972 static ssize_t
973 uc_compiler_add_upval(uc_compiler_t *compiler, size_t idx, bool local, uc_value_t *name, bool constant)
974 {
975         uc_function_t *function = (uc_function_t *)compiler->function;
976         uc_upvals_t *upvals = &compiler->upvals;
977         uc_upval_t *uv;
978         size_t i;
979 
980         for (i = 0, uv = upvals->entries; i < upvals->count; i++, uv = upvals->entries + i)
981                 if (uv->index == idx && uv->local == local)
982                         return i;
983 
984         /* XXX: encoding... */
985         if (upvals->count >= (2 << 14)) {
986                 uc_compiler_syntax_error(compiler, 0, "Too many upvalues");
987 
988                 return -1;
989         }
990 
991         uc_vector_push(upvals, {
992                 .local = local,
993                 .index = idx,
994                 .name  = ucv_get(name),
995                 .constant = constant
996         });
997 
998         function->nupvals++;
999 
1000         return upvals->count - 1;
1001 }
1002 
1003 static ssize_t
1004 uc_compiler_resolve_upval(uc_compiler_t *compiler, uc_value_t *name, bool *constant)
1005 {
1006         uc_upvals_t *upvals = &compiler->upvals;
1007         uc_upval_t *uv;
1008         ssize_t idx;
1009         size_t i;
1010 
1011         if (!compiler->parent) {
1012                 for (i = 0, uv = upvals->entries; i < upvals->count; i++, uv = upvals->entries + i) {
1013                         if (ucv_is_equal(uv->name, name) && uv->local == false) {
1014                                 *constant = uv->constant;
1015 
1016                                 return i;
1017                         }
1018                 }
1019 
1020                 return -1;
1021         }
1022 
1023         idx = uc_compiler_resolve_local(compiler->parent, name, constant);
1024 
1025         if (idx > -1) {
1026                 compiler->parent->locals.entries[idx].captured = true;
1027 
1028                 return uc_compiler_add_upval(compiler, idx, true, name, *constant);
1029         }
1030 
1031         idx = uc_compiler_resolve_upval(compiler->parent, name, constant);
1032 
1033         if (idx > -1)
1034                 return uc_compiler_add_upval(compiler, idx, false, name, *constant);
1035 
1036         return -1;
1037 }
1038 
1039 static void
1040 uc_compiler_backpatch(uc_compiler_t *compiler, size_t break_addr, size_t next_addr)
1041 {
1042         uc_patchlist_t *pl = compiler->patchlist;
1043         volatile ssize_t jmpaddr;
1044         size_t i;
1045 
1046         for (i = 0; i < pl->count; i++) {
1047                 jmpaddr = uc_compiler_get_jmpaddr(compiler, pl->entries[i]);
1048 
1049                 switch (jmpaddr) {
1050                 case TK_BREAK:
1051                         /* if we have a break addr, patch instruction */
1052                         if (break_addr) {
1053                                 uc_compiler_set_jmpaddr(compiler, pl->entries[i], break_addr);
1054                                 continue;
1055                         }
1056 
1057                         break;
1058 
1059                 case TK_CONTINUE:
1060                         /* if we have a continue addr, patch instruction */
1061                         if (next_addr) {
1062                                 uc_compiler_set_jmpaddr(compiler, pl->entries[i], next_addr);
1063                                 continue;
1064                         }
1065 
1066                         break;
1067                 }
1068 
1069                 /* there should be no unhandled instructions */
1070                 assert(0);
1071         }
1072 
1073         free(pl->entries);
1074 
1075         compiler->patchlist = pl->parent;
1076 }
1077 
1078 static bool
1079 uc_compiler_check_assignment_lhs(uc_compiler_t *compiler)
1080 {
1081         return (
1082                 compiler->patchlist == NULL ||
1083                 compiler->patchlist->count == 0 ||
1084                 compiler->patchlist->token != TK_EXP
1085         );
1086 }
1087 
1088 static void
1089 uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool is_postfix)
1090 {
1091         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1092         uc_value_t *varname = NULL;
1093         uc_vm_insn_t type;
1094         uint32_t cidx = 0;
1095         int insn;
1096 
1097         /* determine kind of emitted load instruction and operand value (if any) */
1098         type = chunk->entries ? chunk->entries[compiler->last_insn] : 0;
1099 
1100         if (type == I_LVAR || type == I_LLOC || type == I_LUPV) {
1101                 cidx = uc_compiler_get_u32(compiler, compiler->last_insn + 1);
1102 
1103                 if (type == I_LLOC && compiler->locals.entries[cidx].constant)
1104                         varname = compiler->locals.entries[cidx].name;
1105                 else if (type == I_LUPV && compiler->upvals.entries[cidx].constant)
1106                         varname = compiler->upvals.entries[cidx].name;
1107 
1108                 if (varname)
1109                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1110                                 "Invalid increment/decrement of constant '%s'",
1111                                 ucv_string_get(varname));
1112 
1113                 uc_chunk_pop(chunk);
1114                 uc_chunk_pop(chunk);
1115                 uc_chunk_pop(chunk);
1116                 uc_chunk_pop(chunk);
1117                 uc_chunk_pop(chunk);
1118         }
1119 
1120         /* if we're mutating an object or array field, pop the last lval instruction
1121          * to leave object + last field name value on stack */
1122         else if (type == I_LVAL) {
1123                 if (!uc_compiler_check_assignment_lhs(compiler)) {
1124                         uc_compiler_syntax_error(compiler, 0,
1125                                 "Invalid left-hand side expression for increment/decrement");
1126 
1127                         return;
1128                 }
1129 
1130                 uc_chunk_pop(chunk);
1131         }
1132         else {
1133                 uc_compiler_syntax_error(compiler, 0, "Invalid increment/decrement operand");
1134 
1135                 return;
1136         }
1137 
1138         insn = (toktype == TK_INC) ? I_PLUS : I_MINUS;
1139 
1140         /* add / subtract 1 */
1141         uc_compiler_emit_insn(compiler, 0, I_LOAD8);
1142         uc_compiler_emit_u8(compiler, 0, 1);
1143 
1144         /* depending on variable type, emit corresponding increment instruction */
1145         switch (type) {
1146         case I_LVAR:
1147                 uc_compiler_emit_insn(compiler, 0, I_UVAR);
1148                 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
1149                 break;
1150 
1151         case I_LLOC:
1152                 uc_compiler_emit_insn(compiler, 0, I_ULOC);
1153                 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
1154                 break;
1155 
1156         case I_LUPV:
1157                 uc_compiler_emit_insn(compiler, 0, I_UUPV);
1158                 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
1159                 break;
1160 
1161         case I_LVAL:
1162                 uc_compiler_emit_insn(compiler, 0, I_UVAL);
1163                 uc_compiler_emit_u8(compiler, 0, insn);
1164                 break;
1165 
1166         default:
1167                 break;
1168         }
1169 
1170         /* for post increment or decrement, add/subtract 1 to yield final value */
1171         if (is_postfix) {
1172                 uc_compiler_emit_insn(compiler, 0, I_LOAD8);
1173                 uc_compiler_emit_u8(compiler, 0, 1);
1174 
1175                 uc_compiler_emit_insn(compiler, 0, (toktype == TK_INC) ? I_SUB : I_ADD);
1176         }
1177 }
1178 
1179 
1180 static void
1181 uc_compiler_compile_unary(uc_compiler_t *compiler)
1182 {
1183         uc_tokentype_t type = compiler->parser->prev.type;
1184 
1185         uc_compiler_parse_precedence(compiler, P_UNARY);
1186 
1187         switch (type) {
1188         case TK_SUB:
1189                 uc_compiler_emit_insn(compiler, 0, I_MINUS);
1190                 break;
1191 
1192         case TK_ADD:
1193                 uc_compiler_emit_insn(compiler, 0, I_PLUS);
1194                 break;
1195 
1196         case TK_NOT:
1197                 uc_compiler_emit_insn(compiler, 0, I_NOT);
1198                 break;
1199 
1200         case TK_COMPL:
1201                 uc_compiler_emit_insn(compiler, 0, I_COMPL);
1202                 break;
1203 
1204         case TK_INC:
1205         case TK_DEC:
1206                 uc_compiler_emit_inc_dec(compiler, type, false);
1207                 break;
1208 
1209         default:
1210                 return;
1211         }
1212 }
1213 
1214 static void
1215 uc_compiler_compile_binary(uc_compiler_t *compiler)
1216 {
1217         uc_tokentype_t type = compiler->parser->prev.type;
1218 
1219         uc_compiler_parse_precedence(compiler, uc_compiler_parse_rule(type)->precedence + 1);
1220         uc_compiler_emit_insn(compiler, 0, I_BOR + (type - TK_BOR));
1221 }
1222 
1223 static void
1224 uc_compiler_compile_delete(uc_compiler_t *compiler)
1225 {
1226         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1227         uc_vm_insn_t type;
1228 
1229         uc_compiler_parse_precedence(compiler, P_UNARY);
1230 
1231         type = chunk->entries[compiler->last_insn];
1232 
1233         if (type != I_LVAL)
1234                 uc_compiler_syntax_error(compiler, 0,
1235                         "expecting a property access expression");
1236 
1237         chunk->entries[compiler->last_insn] = I_DELETE;
1238 }
1239 
1240 static uc_vm_insn_t
1241 uc_compiler_emit_variable_rw(uc_compiler_t *compiler, uc_value_t *varname, uc_tokentype_t type)
1242 {
1243         uc_vm_insn_t insn;
1244         uint32_t sub_insn;
1245         bool constant;
1246         ssize_t idx;
1247 
1248         switch (type) {
1249         case TK_ASADD:     sub_insn = I_ADD;     break;
1250         case TK_ASSUB:     sub_insn = I_SUB;     break;
1251         case TK_ASMUL:     sub_insn = I_MUL;     break;
1252         case TK_ASDIV:     sub_insn = I_DIV;     break;
1253         case TK_ASMOD:     sub_insn = I_MOD;     break;
1254         case TK_ASBAND:    sub_insn = I_BAND;    break;
1255         case TK_ASBXOR:    sub_insn = I_BXOR;    break;
1256         case TK_ASBOR:     sub_insn = I_BOR;     break;
1257         case TK_ASLEFT:    sub_insn = I_LSHIFT;  break;
1258         case TK_ASRIGHT:   sub_insn = I_RSHIFT;  break;
1259         case TK_ASEXP:     sub_insn = I_EXP;     break;
1260         default:           sub_insn = 0;         break;
1261         }
1262 
1263         if (!varname) {
1264                 if (sub_insn != 0)
1265                         insn = I_UVAL;
1266                 else if (type != 0 && type != TK_QDOT && type != TK_QLBRACK)
1267                         insn = I_SVAL;
1268                 else
1269                         insn = I_LVAL;
1270 
1271                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1272 
1273                 if (sub_insn)
1274                         uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, sub_insn);
1275         }
1276         else if ((idx = uc_compiler_resolve_local(compiler, varname, &constant)) > -1) {
1277                 insn = sub_insn ? I_ULOC : (type ? I_SLOC : I_LLOC);
1278 
1279                 if (insn != I_LLOC && constant)
1280                         uc_compiler_syntax_error(compiler, 0,
1281                                 "Invalid assignment to constant '%s'", ucv_string_get(varname));
1282 
1283                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1284                 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos,
1285                         ((sub_insn & 0xff) << 24) | idx);
1286         }
1287         else if ((idx = uc_compiler_resolve_upval(compiler, varname, &constant)) > -1) {
1288                 insn = sub_insn ? I_UUPV : (type ? I_SUPV : I_LUPV);
1289 
1290                 if (insn != I_LUPV && constant)
1291                         uc_compiler_syntax_error(compiler, 0,
1292                                 "Invalid assignment to constant '%s'", ucv_string_get(varname));
1293 
1294                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1295                 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos,
1296                         ((sub_insn & 0xff) << 24) | idx);
1297         }
1298         else {
1299                 idx = uc_program_add_constant(compiler->program, varname);
1300                 insn = sub_insn ? I_UVAR : (type ? I_SVAR : I_LVAR);
1301 
1302                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1303                 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos,
1304                         ((sub_insn & 0xff) << 24) | idx);
1305         }
1306 
1307         return insn;
1308 }
1309 
1310 static void
1311 uc_compiler_emit_variable_copy(uc_compiler_t *compiler, uc_value_t *var)
1312 {
1313         if (!var) {
1314                 uc_compiler_emit_copy(compiler, 0, 1);
1315                 uc_compiler_emit_copy(compiler, 0, 1);
1316         }
1317 
1318         uc_compiler_emit_variable_rw(compiler, var, 0);
1319 }
1320 
1321 static void
1322 uc_compiler_compile_and(uc_compiler_t *compiler)
1323 {
1324         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1325         size_t jmpz_off;
1326 
1327         uc_compiler_emit_copy(compiler, 0, 0);
1328         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1329         uc_compiler_emit_insn(compiler, 0, I_POP);
1330         uc_compiler_parse_precedence(compiler, P_AND);
1331         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1332 }
1333 
1334 static void
1335 uc_compiler_compile_and_assignment(uc_compiler_t *compiler, uc_value_t *var)
1336 {
1337         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1338         size_t jmpz_off;
1339 
1340         uc_compiler_emit_variable_copy(compiler, var);
1341         uc_compiler_emit_copy(compiler, 0, 0);
1342         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1343         uc_compiler_emit_insn(compiler, 0, I_POP);
1344         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1345         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1346         uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN);
1347 }
1348 
1349 static void
1350 uc_compiler_compile_or(uc_compiler_t *compiler)
1351 {
1352         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1353         size_t jmpz_off, jmp_off;
1354 
1355         uc_compiler_emit_copy(compiler, 0, 0);
1356         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1357         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1358         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1359         uc_compiler_emit_insn(compiler, 0, I_POP);
1360         uc_compiler_parse_precedence(compiler, P_OR);
1361         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1362 }
1363 
1364 static void
1365 uc_compiler_compile_or_assignment(uc_compiler_t *compiler, uc_value_t *var)
1366 {
1367         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1368         size_t jmpz_off, jmp_off;
1369 
1370         uc_compiler_emit_variable_copy(compiler, var);
1371         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1372         uc_compiler_emit_variable_rw(compiler, var, 0);
1373         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1374         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1375         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1376         uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN);
1377         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1378 }
1379 
1380 static void
1381 uc_compiler_compile_nullish(uc_compiler_t *compiler)
1382 {
1383         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1384         size_t jmpz_off, jmp_off;
1385 
1386         uc_compiler_emit_copy(compiler, 0, 0);
1387         uc_compiler_emit_insn(compiler, 0, I_LNULL);
1388         uc_compiler_emit_insn(compiler, 0, I_NES);
1389         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1390         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1391         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1392         uc_compiler_emit_insn(compiler, 0, I_POP);
1393         uc_compiler_parse_precedence(compiler, P_OR);
1394         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1395 }
1396 
1397 static void
1398 uc_compiler_compile_nullish_assignment(uc_compiler_t *compiler, uc_value_t *var)
1399 {
1400         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1401         size_t jmpz_off, jmp_off;
1402 
1403         uc_compiler_emit_variable_copy(compiler, var);
1404         uc_compiler_emit_insn(compiler, 0, I_LNULL);
1405         uc_compiler_emit_insn(compiler, 0, I_NES);
1406         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1407         uc_compiler_emit_variable_rw(compiler, var, 0);
1408         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1409         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1410         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1411         uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN);
1412         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1413 }
1414 
1415 static void
1416 uc_compiler_compile_expression(uc_compiler_t *compiler)
1417 {
1418         uc_compiler_parse_precedence(compiler, P_COMMA);
1419 }
1420 
1421 static bool
1422 uc_compiler_compile_assignment(uc_compiler_t *compiler, uc_value_t *var)
1423 {
1424         uc_tokentype_t type = compiler->parser->curr.type;
1425 
1426         if (!uc_compiler_parse_at_assignment_op(compiler))
1427                 return false;
1428 
1429         if (!uc_compiler_check_assignment_lhs(compiler)) {
1430                 uc_compiler_syntax_error(compiler, 0,
1431                         "Invalid left-hand side expression for assignment");
1432 
1433                 return false;
1434         }
1435 
1436         switch (type)
1437         {
1438         case TK_ASNULLISH:
1439                 uc_compiler_parse_advance(compiler);
1440                 uc_compiler_compile_nullish_assignment(compiler, var);
1441                 break;
1442 
1443         case TK_ASOR:
1444                 uc_compiler_parse_advance(compiler);
1445                 uc_compiler_compile_or_assignment(compiler, var);
1446                 break;
1447 
1448         case TK_ASAND:
1449                 uc_compiler_parse_advance(compiler);
1450                 uc_compiler_compile_and_assignment(compiler, var);
1451                 break;
1452 
1453         default:
1454                 uc_compiler_parse_advance(compiler);
1455                 uc_compiler_parse_precedence(compiler, P_ASSIGN);
1456                 uc_compiler_emit_variable_rw(compiler, var, type);
1457                 break;
1458         }
1459 
1460         return true;
1461 }
1462 
1463 static bool
1464 uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool restarg)
1465 {
1466         uc_tokentype_t last_statement_type = TK_NULL;
1467         bool array = (ucv_type(args) == UC_ARRAY);
1468         uc_compiler_t fncompiler = { 0 };
1469         size_t i, pos, load_off;
1470         uc_function_t *fn;
1471         ssize_t slot;
1472 
1473         if (!uc_compiler_parse_match(compiler, TK_ARROW))
1474                 return false;
1475 
1476         pos = compiler->parser->prev.pos;
1477 
1478         uc_compiler_init(&fncompiler, NULL, uc_compiler_current_source(compiler),
1479                 compiler->parser->prev.pos,
1480                 compiler->program,
1481                 uc_compiler_is_strict(compiler));
1482 
1483         fncompiler.parent = compiler;
1484         fncompiler.parser = compiler->parser;
1485         fncompiler.exprstack = compiler->exprstack;
1486 
1487         fn = (uc_function_t *)fncompiler.function;
1488         fn->arrow = true;
1489         fn->vararg = args ? restarg : false;
1490         fn->nargs = array ? ucv_array_length(args) : !!args;
1491 
1492         uc_compiler_enter_scope(&fncompiler);
1493 
1494         /* declare local variables for arguments */
1495         for (i = 0; i < fn->nargs; i++) {
1496                 slot = uc_compiler_declare_local(&fncompiler,
1497                         array ? ucv_array_get(args, i) : args, false);
1498 
1499                 if (slot != -1)
1500                         uc_compiler_syntax_error(&fncompiler, pos,
1501                                 "Duplicate argument names are not allowed in this context");
1502 
1503                 uc_compiler_initialize_local(&fncompiler);
1504         }
1505 
1506         /* parse and compile body */
1507         if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) {
1508                 while (!uc_compiler_parse_check(&fncompiler, TK_RBRACE) &&
1509                        !uc_compiler_parse_check(&fncompiler, TK_EOF))
1510                         uc_compiler_compile_declaration(&fncompiler);
1511 
1512                 uc_compiler_parse_consume(&fncompiler, TK_RBRACE);
1513 
1514                 /* emit final return */
1515                 if (last_statement_type != TK_RETURN) {
1516                         uc_compiler_emit_insn(&fncompiler, 0, I_LNULL);
1517                         uc_compiler_emit_insn(&fncompiler, 0, I_RETURN);
1518                 }
1519         }
1520         else {
1521                 uc_compiler_parse_precedence(&fncompiler, P_ASSIGN);
1522                 uc_compiler_emit_insn(&fncompiler, 0, I_RETURN);
1523         }
1524 
1525         /* emit load instruction for function value */
1526         uc_compiler_emit_insn(compiler, pos, I_ARFN);
1527         load_off = uc_compiler_emit_u32(compiler, 0, 0);
1528 
1529         /* encode upvalue information */
1530         for (i = 0; i < fn->nupvals; i++)
1531                 uc_compiler_emit_s32(compiler, 0,
1532                         fncompiler.upvals.entries[i].local
1533                                 ? -(fncompiler.upvals.entries[i].index + 1)
1534                                 : fncompiler.upvals.entries[i].index);
1535 
1536         /* finalize function compiler */
1537         fn = uc_compiler_finish(&fncompiler, TK_RETURN);
1538 
1539         if (fn)
1540                 uc_compiler_set_u32(compiler, load_off,
1541                         uc_program_function_id(compiler->program, fn));
1542 
1543         return true;
1544 }
1545 
1546 static uc_tokentype_t
1547 uc_compiler_compile_var_or_arrowfn(uc_compiler_t *compiler, uc_value_t *name)
1548 {
1549         uc_tokentype_t rv;
1550 
1551         if (uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) && uc_compiler_compile_assignment(compiler, name)) {
1552                 rv = TK_ASSIGN;
1553         }
1554         else if (uc_compiler_compile_arrowfn(compiler, name, false)) {
1555                 rv = TK_ARROW;
1556         }
1557         else {
1558                 uc_compiler_emit_variable_rw(compiler, name, 0);
1559                 rv = TK_LABEL;
1560         }
1561 
1562         return rv;
1563 }
1564 
1565 static void
1566 uc_compiler_compile_paren(uc_compiler_t *compiler)
1567 {
1568         uc_value_t *varnames = NULL, *varname;
1569         bool maybe_arrowfn = false;
1570         bool restarg = false;
1571 
1572         /* First try to parse a complete parameter expression and remember the
1573          * consumed label tokens as we go. */
1574         while (true) {
1575                 if (uc_compiler_parse_check(compiler, TK_LABEL)) {
1576                         if (!varnames)
1577                                 varnames = ucv_array_new(NULL);
1578 
1579                         ucv_array_push(varnames, ucv_get(compiler->parser->curr.uv));
1580 
1581                         /* A subsequent slash cannot be a regular expression literal */
1582                         compiler->parser->lex.no_regexp = true;
1583                         uc_compiler_parse_advance(compiler);
1584                 }
1585                 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
1586                         uc_compiler_parse_consume(compiler, TK_LABEL);
1587 
1588                         if (!varnames)
1589                                 varnames = ucv_array_new(NULL);
1590 
1591                         ucv_array_push(varnames, ucv_get(compiler->parser->prev.uv));
1592 
1593                         /* A subsequent slash cannot be a regular expression literal */
1594                         compiler->parser->lex.no_regexp = true;
1595                         uc_compiler_parse_consume(compiler, TK_RPAREN);
1596 
1597                         maybe_arrowfn = true;
1598                         restarg = true;
1599 
1600                         break;
1601                 }
1602                 else if (uc_compiler_parse_check(compiler, TK_COMMA)) {
1603                         /* Reject consecutive commas */
1604                         if (compiler->parser->prev.type == TK_COMMA)
1605                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
1606                                         "Expecting expression");
1607 
1608                         uc_compiler_parse_advance(compiler);
1609 
1610                         continue;
1611                 }
1612                 else {
1613                         maybe_arrowfn = uc_compiler_parse_check(compiler, TK_RPAREN);
1614 
1615                         if (maybe_arrowfn) {
1616                                 /* A subsequent slash cannot be a regular expression literal */
1617                                 compiler->parser->lex.no_regexp = true;
1618                                 uc_compiler_parse_advance(compiler);
1619                         }
1620 
1621                         /* If we encounter a dot, treat potential subsequent keyword as label */
1622                         if (uc_compiler_parse_check(compiler, TK_DOT) ||
1623                             uc_compiler_parse_check(compiler, TK_QDOT))
1624                                 compiler->parser->lex.no_keyword = true;
1625 
1626                         break;
1627                 }
1628         }
1629 
1630         /* The lhs we parsed so far is eligible for an arrow function arg list,
1631          * try to continue compiling into arrow function... */
1632         if (maybe_arrowfn) {
1633                 /* If we can parse the remainder as arrow function, we're done */
1634                 if (uc_compiler_compile_arrowfn(compiler, varnames, restarg))
1635                         goto out;
1636 
1637                 /* ... otherwise disallow the `...` spread operator and empty
1638                  * parenthesized expressions */
1639                 if (restarg || !varnames) {
1640                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1641                                 "Expecting '=>' after parameter list");
1642 
1643                         goto out;
1644                 }
1645         }
1646 
1647         /* If we reach this, the expression we parsed so far cannot be a parameter
1648          * list for an arrow function and we might have consumed one or multiple
1649          * consecutive labels. */
1650         if (varnames) {
1651                 /* Get last variable name */
1652                 varname = ucv_array_get(varnames,
1653                         ucv_array_length(varnames) - 1);
1654 
1655                 /* If we consumed the right paren, the expression is complete and we
1656                  * only need to emit a variable read operation for the last parsed
1657                  * label since previous read operations are shadowed by subsequent ones
1658                  * in comma expressions and since pure variable reads are without
1659                  * side effects. */
1660                 if (maybe_arrowfn) {
1661                         uc_compiler_emit_variable_rw(compiler, varname, 0);
1662 
1663                         goto out;
1664                 }
1665 
1666                 /* ... otherwise if the last token was a label, try continue parsing as
1667                  * assignment or arrow function expression and if that fails, as
1668                  * relational one */
1669                 if (compiler->parser->prev.type == TK_LABEL) {
1670                         uc_compiler_exprstack_push(compiler, TK_LABEL, F_ASSIGNABLE);
1671 
1672                         if (uc_compiler_compile_var_or_arrowfn(compiler, varname) == TK_LABEL) {
1673                                 /* parse operand and rhs */
1674                                 while (P_TERNARY <= uc_compiler_parse_rule(compiler->parser->curr.type)->precedence) {
1675                                         uc_compiler_parse_advance(compiler);
1676                                         uc_compiler_parse_rule(compiler->parser->prev.type)->infix(compiler);
1677                                 }
1678                         }
1679 
1680                         /* If we're not at the end of the expression, we require a comma.
1681                          * Also pop intermediate result in this case. */
1682                         if (!uc_compiler_parse_check(compiler, TK_RPAREN)) {
1683                                 uc_compiler_emit_insn(compiler, 0, I_POP);
1684                                 uc_compiler_parse_consume(compiler, TK_COMMA);
1685                         }
1686 
1687                         uc_compiler_exprstack_pop(compiler);
1688                 }
1689         }
1690 
1691         /* When we reach this point, all already complete expression possibilities
1692          * have been eliminated and we either need to compile the next, non-label
1693          * expression or reached the closing paren. If neither applies, we have a
1694          * syntax error. */
1695         if (!uc_compiler_parse_check(compiler, TK_RPAREN))
1696                 uc_compiler_compile_expression(compiler);
1697 
1698         /* A subsequent slash cannot be a regular expression literal */
1699         compiler->parser->lex.no_regexp = true;
1700 
1701         /* At this point we expect the end of the parenthesized expression, anything
1702          * else is a syntax error */
1703         uc_compiler_parse_consume(compiler, TK_RPAREN);
1704 
1705 out:
1706         ucv_put(varnames);
1707 }
1708 
1709 static void
1710 uc_compiler_compile_call(uc_compiler_t *compiler)
1711 {
1712         bool optional_chaining = (compiler->parser->prev.type == TK_QLPAREN);
1713         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1714         uc_jmplist_t spreads = { 0 };
1715         uc_vm_insn_t type;
1716         size_t i, nargs = 0;
1717         bool mcall;
1718 
1719         /* determine the kind of the lhs */
1720         type = chunk->entries[compiler->last_insn];
1721         mcall = (type == I_LVAL);
1722 
1723         if (mcall) {
1724                 uc_chunk_pop(chunk);
1725                 uc_compiler_emit_insn(compiler, 0, I_PVAL);
1726         }
1727 
1728         if (optional_chaining)
1729                 uc_compiler_emit_jmpnt(compiler, compiler->parser->prev.pos,
1730                         (1u << UC_CFUNCTION) | (1u << UC_CLOSURE), mcall);
1731 
1732         /* compile arguments */
1733         if (!uc_compiler_parse_check(compiler, TK_RPAREN)) {
1734                 do {
1735                         /* if this is a spread arg, remember the argument index */
1736                         if (uc_compiler_parse_match(compiler, TK_ELLIP))
1737                                 uc_vector_push(&spreads, nargs);
1738 
1739                         /* compile argument expression */
1740                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1741                         nargs++;
1742                 }
1743                 while (uc_compiler_parse_match(compiler, TK_COMMA));
1744         }
1745 
1746         /* after a function call expression, no regexp literal can follow */
1747         compiler->parser->lex.no_regexp = true;
1748         uc_compiler_parse_consume(compiler, TK_RPAREN);
1749 
1750         /* if lhs is a dot or bracket expression, emit a method call */
1751         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_CALL);
1752 
1753         if (nargs > 0xffff || spreads.count > 0x7fff)
1754                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1755                         "Too many function call arguments");
1756 
1757         /* encode ordinary (bits 0..15) and spread argument (bits 16..30) count
1758            as well as method call indication (bit 31) */
1759         uc_compiler_emit_u32(compiler, 0,
1760                 (mcall ? 0x80000000 : 0) | ((spreads.count & 0x7fff) << 16) | nargs);
1761 
1762         /* encode spread arg positions */
1763         for (i = 0; i < spreads.count; i++)
1764                 uc_compiler_emit_u16(compiler, 0, nargs - spreads.entries[i] - 1);
1765 
1766         uc_vector_clear(&spreads);
1767 
1768         compiler->patchlist->depth = uc_compiler_current_chunk(compiler)->count;
1769 }
1770 
1771 static void
1772 uc_compiler_compile_post_inc(uc_compiler_t *compiler)
1773 {
1774         uc_compiler_emit_inc_dec(compiler, compiler->parser->prev.type, true);
1775 }
1776 
1777 static bool
1778 uc_compiler_is_use_strict_pragma(uc_compiler_t *compiler)
1779 {
1780         uc_value_t *v;
1781 
1782         if (uc_compiler_current_chunk(compiler)->count > 0)
1783                 return false;
1784 
1785         if (compiler->parser->lex.block != STATEMENTS)
1786                 return false;
1787 
1788         v = compiler->parser->prev.uv;
1789 
1790         return (strcmp(ucv_string_get(v), "use strict") == 0);
1791 }
1792 
1793 static void
1794 uc_compiler_compile_constant(uc_compiler_t *compiler)
1795 {
1796         uc_function_t *fn;
1797         uint64_t u;
1798 
1799         switch (compiler->parser->prev.type) {
1800         case TK_THIS:
1801                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LTHIS);
1802                 break;
1803 
1804         case TK_NULL:
1805                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
1806                 break;
1807 
1808         case TK_TRUE:
1809                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LTRUE);
1810                 break;
1811 
1812         case TK_FALSE:
1813                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LFALSE);
1814                 break;
1815 
1816         case TK_STRING:
1817                 if (uc_compiler_is_use_strict_pragma(compiler)) {
1818                         fn = (uc_function_t *)compiler->function;
1819                         fn->strict = true;
1820                 }
1821 
1822                 /* fall through */
1823 
1824         case TK_DOUBLE:
1825                 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1826                 break;
1827 
1828         case TK_REGEXP:
1829                 uc_compiler_emit_regexp(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1830                 break;
1831 
1832         case TK_NUMBER:
1833                 u = ucv_uint64_get(compiler->parser->prev.uv);
1834                 assert(errno == 0);
1835 
1836                 if (u <= 0xff) {
1837                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD8);
1838                         uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, u);
1839                 }
1840                 else if (u <= 0xffff) {
1841                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD16);
1842                         uc_compiler_emit_u16(compiler, compiler->parser->prev.pos, u);
1843                 }
1844                 else if (u <= 0xffffffff) {
1845                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD32);
1846                         uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, u);
1847                 }
1848                 else {
1849                         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1850                 }
1851 
1852                 break;
1853 
1854         default:
1855                 break;
1856         }
1857 }
1858 
1859 static void
1860 uc_compiler_compile_template(uc_compiler_t *compiler)
1861 {
1862         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1863 
1864         while (true) {
1865                 if (uc_compiler_parse_match(compiler, TK_TEMPLATE)) {
1866                         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1867                         uc_compiler_emit_insn(compiler, 0, I_ADD);
1868                 }
1869                 else if (uc_compiler_parse_match(compiler, TK_PLACEH)) {
1870                         uc_compiler_compile_expression(compiler);
1871                         uc_compiler_emit_insn(compiler, 0, I_ADD);
1872                         uc_compiler_parse_consume(compiler, TK_RBRACE);
1873                 }
1874                 else {
1875                         break;
1876                 }
1877         }
1878 }
1879 
1880 static void
1881 uc_compiler_compile_comma(uc_compiler_t *compiler)
1882 {
1883         uc_compiler_emit_insn(compiler, 0, I_POP);
1884         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1885 }
1886 
1887 static void
1888 uc_compiler_compile_labelexpr(uc_compiler_t *compiler)
1889 {
1890         uc_value_t *label = ucv_get(compiler->parser->prev.uv);
1891 
1892         uc_compiler_compile_var_or_arrowfn(compiler, label);
1893         ucv_put(label);
1894 }
1895 
1896 static uc_tokentype_t
1897 uc_compiler_compile_delimitted_block(uc_compiler_t *compiler, uc_tokentype_t endtype)
1898 {
1899         uc_tokentype_t last_statement_type = TK_NULL;
1900 
1901         while (!uc_compiler_parse_check(compiler, endtype) &&
1902                !uc_compiler_parse_check(compiler, TK_EOF))
1903                 last_statement_type = uc_compiler_compile_declaration(compiler);
1904 
1905         return uc_compiler_parse_check(compiler, endtype) ? last_statement_type : TK_EOF;
1906 }
1907 
1908 static void
1909 uc_compiler_compile_funcexpr_common(uc_compiler_t *compiler, bool require_name)
1910 {
1911         uc_tokentype_t last_statement_type = TK_NULL;
1912         uc_compiler_t fncompiler = { 0 };
1913         uc_value_t *name = NULL;
1914         ssize_t slot = -1, pos;
1915         uc_tokentype_t type;
1916         size_t i, load_off;
1917         uc_function_t *fn;
1918 
1919         pos = compiler->parser->prev.pos;
1920         type = compiler->parser->prev.type;
1921 
1922         if (uc_compiler_parse_match(compiler, TK_LABEL)) {
1923                 name = compiler->parser->prev.uv;
1924 
1925                 if (require_name && uc_compiler_parse_check(compiler, TK_SCOL)) {
1926                         slot = uc_compiler_resolve_funcstub(compiler, name);
1927 
1928                         if (slot > -1) {
1929                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1930                                         "Function '%s' redeclared", ucv_string_get(name));
1931 
1932                                 return;
1933                         }
1934 
1935                         slot = uc_compiler_declare_local(compiler, name, true);
1936 
1937                         if (slot > -1) {
1938                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1939                                         "Variable '%s' redeclared", ucv_string_get(name));
1940 
1941                                 return;
1942                         }
1943 
1944                         compiler->locals.entries[compiler->locals.count - 1].funcstub = true;
1945                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
1946                         uc_compiler_initialize_local(compiler);
1947                         uc_compiler_parse_consume(compiler, TK_SCOL);
1948 
1949                         return;
1950                 }
1951 
1952                 /* A function declaration binds its name in the enclosing scope. A named
1953                  * function expression must not: its name is only visible inside its own
1954                  * body (for self-reference), and declaring it in the enclosing scope
1955                  * would both leak it and shift the local slots, corrupting the
1956                  * initialisation state of a `let`/`const` the expression initialises. */
1957                 if (require_name) {
1958                         slot = uc_compiler_resolve_funcstub(compiler, name);
1959 
1960                         if (slot > -1) {
1961                                 compiler->locals.entries[slot].funcstub = false;
1962                         }
1963                         else {
1964                                 slot = uc_compiler_declare_local(compiler, name, false);
1965 
1966                                 if (slot == -1)
1967                                         uc_compiler_initialize_local(compiler);
1968                                 else if (compiler->locals.entries[slot].constant)
1969                                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1970                                                 "Redeclaration of constant '%s'",
1971                                                 ucv_string_get(name));
1972                         }
1973                 }
1974         }
1975         else if (require_name) {
1976                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting function name");
1977         }
1978 
1979         uc_compiler_init(&fncompiler,
1980                 name ? ucv_string_get(name) : NULL,
1981                 uc_compiler_current_source(compiler),
1982                 compiler->parser->prev.pos,
1983                 compiler->program,
1984                 uc_compiler_is_strict(compiler));
1985 
1986         /* Bind a named function expression's name to its own callee slot so the
1987          * body can reference itself for recursion, without touching the enclosing
1988          * scope. Declarations keep the name in the enclosing scope (handled above). */
1989         if (name && !require_name) {
1990                 ucv_put(fncompiler.locals.entries[0].name);
1991                 fncompiler.locals.entries[0].name = ucv_get(name);
1992         }
1993 
1994         fncompiler.parent = compiler;
1995         fncompiler.parser = compiler->parser;
1996         fncompiler.exprstack = compiler->exprstack;
1997         fn = (uc_function_t *)fncompiler.function;
1998 
1999         uc_compiler_parse_consume(&fncompiler, TK_LPAREN);
2000 
2001         uc_compiler_enter_scope(&fncompiler);
2002 
2003         /* compile argument specification */
2004         while (true) {
2005                 if (uc_compiler_parse_check(&fncompiler, TK_RPAREN))
2006                         break;
2007 
2008                 if (uc_compiler_parse_match(&fncompiler, TK_ELLIP))
2009                         fn->vararg = true;
2010 
2011                 if (uc_compiler_parse_match(&fncompiler, TK_LABEL)) {
2012                         fn->nargs++;
2013 
2014                         uc_compiler_declare_local(&fncompiler, fncompiler.parser->prev.uv, false);
2015                         uc_compiler_initialize_local(&fncompiler);
2016 
2017                         if (fn->vararg ||
2018                             !uc_compiler_parse_match(&fncompiler, TK_COMMA))
2019                                 break;
2020                 }
2021                 else {
2022                         uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos,
2023                                 "Expecting Label");
2024 
2025                         return;
2026                 }
2027         }
2028 
2029         uc_compiler_parse_consume(&fncompiler, TK_RPAREN);
2030 
2031         /* parse and compile function body */
2032         if (uc_compiler_parse_match(&fncompiler, TK_COLON)) {
2033                 last_statement_type = uc_compiler_compile_delimitted_block(&fncompiler, TK_ENDFUNC);
2034                 uc_compiler_parse_consume(&fncompiler, TK_ENDFUNC);
2035         }
2036         else if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) {
2037                 last_statement_type = uc_compiler_compile_delimitted_block(&fncompiler, TK_RBRACE);
2038                 uc_compiler_parse_consume(&fncompiler, TK_RBRACE);
2039         }
2040         else {
2041                 uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos,
2042                         "Expecting '{' or ':' after function parameters");
2043         }
2044 
2045         /* emit load instruction for function value */
2046         uc_compiler_emit_insn(compiler, pos, (type == TK_ARROW) ? I_ARFN : I_CLFN);
2047         load_off = uc_compiler_emit_u32(compiler, 0, 0);
2048 
2049         /* encode upvalue information */
2050         for (i = 0; i < fn->nupvals; i++)
2051                 uc_compiler_emit_s32(compiler, 0,
2052                         fncompiler.upvals.entries[i].local
2053                                 ? -(fncompiler.upvals.entries[i].index + 1)
2054                                 : fncompiler.upvals.entries[i].index);
2055 
2056         /* finalize function compiler */
2057         fn = uc_compiler_finish(&fncompiler, last_statement_type);
2058 
2059         if (fn)
2060                 uc_compiler_set_u32(compiler, load_off,
2061                         uc_program_function_id(compiler->program, fn));
2062 
2063         /* if a local variable of the same name already existed, overwrite its value
2064          * with the compiled function here */
2065         if (slot != -1) {
2066                 uc_compiler_emit_insn(compiler, 0, I_SLOC);
2067                 uc_compiler_emit_u32(compiler, 0, slot);
2068                 uc_compiler_emit_insn(compiler, 0, I_POP);
2069         }
2070 }
2071 
2072 static void
2073 uc_compiler_compile_funcexpr(uc_compiler_t *compiler)
2074 {
2075         return uc_compiler_compile_funcexpr_common(compiler, false);
2076 }
2077 
2078 static void
2079 uc_compiler_compile_funcdecl(uc_compiler_t *compiler)
2080 {
2081         return uc_compiler_compile_funcexpr_common(compiler, true);
2082 }
2083 
2084 static void
2085 uc_compiler_compile_dot(uc_compiler_t *compiler)
2086 {
2087         bool optional_chaining = (compiler->parser->prev.type == TK_QDOT);
2088 
2089         /* no regexp literal possible after property access */
2090         compiler->parser->lex.no_regexp = true;
2091 
2092         if (optional_chaining)
2093                 uc_compiler_emit_jmpnt(compiler, compiler->parser->prev.pos,
2094                         (1u << UC_ARRAY) | (1u << UC_OBJECT) | (1u << UC_RESOURCE), 0);
2095 
2096         /* parse label lhs */
2097         uc_compiler_parse_consume(compiler, TK_LABEL);
2098         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
2099 
2100         /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */
2101         if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL))
2102                 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QDOT : 0);
2103 
2104         compiler->patchlist->depth = uc_compiler_current_chunk(compiler)->count;
2105 }
2106 
2107 static void
2108 uc_compiler_compile_subscript(uc_compiler_t *compiler)
2109 {
2110         bool optional_chaining = (compiler->parser->prev.type == TK_QLBRACK);
2111 
2112         if (optional_chaining)
2113                 uc_compiler_emit_jmpnt(compiler, compiler->parser->prev.pos,
2114                         (1u << UC_ARRAY) | (1u << UC_OBJECT) | (1u << UC_RESOURCE), 0);
2115 
2116         /* compile lhs */
2117         uc_compiler_compile_expression(compiler);
2118 
2119         /* no regexp literal possible after computed property access */
2120         compiler->parser->lex.no_regexp = true;
2121         uc_compiler_parse_consume(compiler, TK_RBRACK);
2122 
2123         /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */
2124         if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL))
2125                 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QLBRACK : 0);
2126 
2127         compiler->patchlist->depth = uc_compiler_current_chunk(compiler)->count;
2128 }
2129 
2130 static void
2131 uc_compiler_compile_ternary(uc_compiler_t *compiler)
2132 {
2133         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2134         size_t jmpz_off, jmp_off;
2135 
2136         /* jump to false branch */
2137         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2138 
2139         /* compile true branch */
2140         uc_compiler_parse_precedence(compiler, P_ASSIGN);
2141 
2142         /* jump after false branch */
2143         jmp_off = uc_compiler_emit_jmp(compiler, 0);
2144 
2145         uc_compiler_parse_consume(compiler, TK_COLON);
2146 
2147         /* compile false branch */
2148         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2149         uc_compiler_parse_precedence(compiler, P_TERNARY);
2150         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
2151 }
2152 
2153 static void
2154 uc_compiler_compile_array(uc_compiler_t *compiler)
2155 {
2156         size_t hint_off, hint_count = 0, len = 0;
2157 
2158         /* create empty array on stack */
2159         uc_compiler_emit_insn(compiler, 0, I_NARR);
2160         hint_off = uc_compiler_emit_u32(compiler, 0, 0);
2161 
2162         /* parse initializer values */
2163         do {
2164                 if (uc_compiler_parse_check(compiler, TK_RBRACK)) {
2165                         break;
2166                 }
2167                 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
2168                         /* push items on stack so far... */
2169                         if (len > 0) {
2170                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR);
2171                                 uc_compiler_emit_u32(compiler, 0, len);
2172                                 len = 0;
2173                         }
2174 
2175                         /* compile spread value expression */
2176                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
2177 
2178                         /* emit merge operation */
2179                         uc_compiler_emit_insn(compiler, 0, I_MARR);
2180                 }
2181                 else {
2182                         /* push items on stack so far... */
2183                         if (len >= 0xffffffff) {
2184                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR);
2185                                 uc_compiler_emit_u32(compiler, 0, len);
2186                                 len = 0;
2187                         }
2188 
2189                         /* compile item value expression */
2190                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
2191 
2192                         hint_count++;
2193                         len++;
2194                 }
2195         }
2196         while (uc_compiler_parse_match(compiler, TK_COMMA));
2197 
2198         /* no regexp literal possible after array literal */
2199         compiler->parser->lex.no_regexp = true;
2200         uc_compiler_parse_consume(compiler, TK_RBRACK);
2201 
2202         /* push items on stack */
2203         if (len > 0) {
2204                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR);
2205                 uc_compiler_emit_u32(compiler, 0, len);
2206         }
2207 
2208         /* set initial size hint */
2209         uc_compiler_set_u32(compiler, hint_off, hint_count);
2210 }
2211 
2212 static void
2213 uc_compiler_compile_method(uc_compiler_t *compiler, uc_value_t *method_name)
2214 {
2215         uc_compiler_t fncompiler = { 0 };
2216         uc_function_t *fn;
2217         size_t i, load_off;
2218 
2219         uc_compiler_init(&fncompiler, method_name ? ucv_string_get(method_name) : NULL,
2220                          uc_compiler_current_source(compiler),
2221                          compiler->parser->prev.pos,
2222                          compiler->program,
2223                          uc_compiler_is_strict(compiler));
2224 
2225         fncompiler.parent = compiler;
2226         fncompiler.parser = compiler->parser;
2227         fncompiler.exprstack = compiler->exprstack;
2228 
2229         fn = (uc_function_t *)fncompiler.function;
2230 
2231         /* parse parameters - '(' is already consumed, expect parameters or ')' */
2232         uc_compiler_enter_scope(&fncompiler);
2233 
2234         while (true) {
2235                 if (uc_compiler_parse_check(&fncompiler, TK_RPAREN))
2236                         break;
2237 
2238                 if (uc_compiler_parse_match(&fncompiler, TK_ELLIP))
2239                         fn->vararg = true;
2240 
2241                 uc_compiler_parse_consume(&fncompiler, TK_LABEL);
2242                 fn->nargs++;
2243 
2244                 uc_compiler_declare_local(&fncompiler,
2245                         fncompiler.parser->prev.uv, false);
2246                 uc_compiler_initialize_local(&fncompiler);
2247 
2248                 if (fn->vararg ||
2249                     !uc_compiler_parse_match(&fncompiler, TK_COMMA))
2250                         break;
2251         }
2252 
2253         uc_compiler_parse_consume(&fncompiler, TK_RPAREN);
2254 
2255         /* parse function body - must be a block */
2256         uc_compiler_parse_consume(&fncompiler, TK_LBRACE);
2257 
2258         while (!uc_compiler_parse_check(&fncompiler, TK_RBRACE) &&
2259                !uc_compiler_parse_check(&fncompiler, TK_EOF))
2260                 uc_compiler_compile_declaration(&fncompiler);
2261 
2262         uc_compiler_parse_consume(&fncompiler, TK_RBRACE);
2263 
2264         /* emit load instruction for method */
2265         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_CLFN);
2266         load_off = uc_compiler_emit_u32(compiler, 0, 0);
2267 
2268         /* encode upvalue information */
2269         for (i = 0; i < fn->nupvals; i++)
2270                 uc_compiler_emit_s32(compiler, 0,
2271                         fncompiler.upvals.entries[i].local
2272                                 ? -(fncompiler.upvals.entries[i].index + 1)
2273                                 : fncompiler.upvals.entries[i].index);
2274 
2275         /* finalize function compiler */
2276         fn = uc_compiler_finish(&fncompiler, TK_RETURN);
2277 
2278         if (fn)
2279                 uc_compiler_set_u32(compiler, load_off,
2280                         uc_program_function_id(compiler->program, fn));
2281 }
2282 
2283 
2284 static void
2285 uc_compiler_compile_object(uc_compiler_t *compiler)
2286 {
2287         size_t hint_off, hint_count = 0, len = 0;
2288 
2289         /* create empty object on stack */
2290         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_NOBJ);
2291         hint_off = uc_compiler_emit_u32(compiler, 0, 0);
2292 
2293         /* parse initializer values */
2294         do {
2295                 /* End of object literal */
2296                 if (uc_compiler_parse_check(compiler, TK_RBRACE))
2297                         break;
2298 
2299                 /* Spread operator */
2300                 if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
2301                         /* set items on stack so far... */
2302                         if (len > 0) {
2303                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
2304                                 uc_compiler_emit_u32(compiler, 0, len);
2305                                 len = 0;
2306                         }
2307 
2308                         /* compile spread value expression */
2309                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
2310 
2311                         /* emit merge operation */
2312                         uc_compiler_emit_insn(compiler, 0, I_MOBJ);
2313 
2314                         compiler->parser->lex.no_keyword = true;
2315                         continue;
2316                 }
2317 
2318                 /* Computed property/method name */
2319                 if (uc_compiler_parse_match(compiler, TK_LBRACK)) {
2320                         /* parse property name expression */
2321                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
2322 
2323                         /* consume closing bracket */
2324                         uc_compiler_parse_consume(compiler, TK_RBRACK);
2325 
2326                         /* Check if this is a computed method: [expr]() { ... } */
2327                         if (uc_compiler_parse_match(compiler, TK_LPAREN)) {
2328                                 /* compile method - key is already on stack from [expr] */
2329                                 uc_compiler_compile_method(compiler, NULL);
2330                         }
2331                         else {
2332                                 /* regular computed property: [expr]: value */
2333                                 uc_compiler_parse_consume(compiler, TK_COLON);
2334                                 uc_compiler_parse_precedence(compiler, P_ASSIGN);
2335                         }
2336                 }
2337 
2338                 /* Property/method declaration or property shorthand */
2339                 else {
2340                         /* parse key expression */
2341                         uc_tokentype_t key_type = compiler->parser->curr.type;
2342                         if (!uc_compiler_parse_match(compiler, TK_LABEL) &&
2343                             !uc_compiler_parse_match(compiler, TK_STRING))
2344                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2345                                         "Expecting label");
2346 
2347                         /* hold a reference to the key: matching TK_LPAREN below advances
2348                          * the parser, which releases the underlying prev.uv token value */
2349                         uc_value_t *key = ucv_get(compiler->parser->prev.uv);
2350 
2351                         /* load label */
2352                         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos,
2353                                 key);
2354 
2355                         /* Check if this is a shorthand method: foo() { ... } */
2356                         if (uc_compiler_parse_match(compiler, TK_LPAREN)) {
2357                                 /* disallow keywords as method names */
2358                                 if (uc_lexer_is_keyword(key))
2359                                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
2360                                                 "Invalid identifier");
2361 
2362                                 uc_compiler_compile_method(compiler, key);
2363                         }
2364                         /* Check if this is property shorthand: foo */
2365                         else if (key_type == TK_LABEL &&
2366                                  (uc_compiler_parse_check(compiler, TK_COMMA) ||
2367                                   uc_compiler_parse_check(compiler, TK_RBRACE))) {
2368                                 /* disallow keywords in this case */
2369                                 if (uc_lexer_is_keyword(key))
2370                                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
2371                                                 "Invalid identifier");
2372 
2373                                 uc_compiler_emit_variable_rw(compiler, key, 0);
2374                         }
2375                         /* ... otherwise treat it as ordinary `key: value` tuple */
2376                         else {
2377                                 uc_compiler_parse_consume(compiler, TK_COLON);
2378 
2379                                 /* parse value expression */
2380                                 uc_compiler_parse_precedence(compiler, P_ASSIGN);
2381                         }
2382 
2383                         ucv_put(key);
2384                 }
2385 
2386                 /* set items on stack so far... */
2387                 if (len >= 0xfffffffe) {
2388                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
2389                         uc_compiler_emit_u32(compiler, 0, len);
2390                         len = 0;
2391                 }
2392 
2393                 hint_count += 2;
2394                 len += 2;
2395 
2396                 compiler->parser->lex.no_keyword = true;
2397         }
2398         while (uc_compiler_parse_match(compiler, TK_COMMA));
2399 
2400         /* no regexp literal possible after object literal */
2401         compiler->parser->lex.no_regexp = true;
2402         uc_compiler_parse_consume(compiler, TK_RBRACE);
2403 
2404         /* set items on stack */
2405         if (len > 0) {
2406                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
2407                 uc_compiler_emit_u32(compiler, 0, len);
2408         }
2409 
2410         /* set initial size hint */
2411         uc_compiler_set_u32(compiler, hint_off, hint_count);
2412 }
2413 
2414 
2415 static void
2416 uc_compiler_declare_local_null(uc_compiler_t *compiler, size_t srcpos, uc_value_t *varname)
2417 {
2418         ssize_t existing_slot = uc_compiler_declare_local(compiler, varname, false);
2419 
2420         uc_compiler_emit_insn(compiler, srcpos, I_LNULL);
2421 
2422         if (existing_slot == -1) {
2423                 uc_compiler_initialize_local(compiler);
2424         }
2425         else {
2426                 uc_compiler_emit_insn(compiler, 0, I_SLOC);
2427                 uc_compiler_emit_u32(compiler, 0, existing_slot);
2428                 uc_compiler_emit_insn(compiler, 0, I_POP);
2429         }
2430 }
2431 
2432 static size_t
2433 uc_compiler_declare_internal(uc_compiler_t *compiler, size_t srcpos, const char *name)
2434 {
2435         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2436         uc_locals_t *locals = &compiler->locals;
2437 
2438         uc_vector_push(locals, {
2439                 .name = ucv_string_new(name),
2440                 .depth = compiler->scope_depth,
2441                 .captured = false,
2442                 .from = chunk->count
2443         });
2444 
2445         return locals->count - 1;
2446 }
2447 
2448 static void
2449 uc_compiler_compile_declexpr(uc_compiler_t *compiler, bool constant)
2450 {
2451         ssize_t slot;
2452 
2453         do {
2454                 /* parse variable name */
2455                 if (!uc_compiler_parse_match(compiler, TK_LABEL)) {
2456                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2457                                 "Expecting variable name");
2458 
2459                         return;
2460                 }
2461 
2462                 /* declare local variable */
2463                 slot = uc_compiler_declare_local(compiler, compiler->parser->prev.uv, constant);
2464 
2465                 /* if followed by '=', parse initializer expression */
2466                 if (uc_compiler_parse_match(compiler, TK_ASSIGN))
2467                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
2468                 /* otherwise, for writable variables, load implicit null */
2469                 else if (!constant)
2470                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
2471                 /* for constant variables, a missing initializer is a syntax error */
2472                 else
2473                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
2474                                 "Expecting initializer expression");
2475 
2476                 /* initialize local */
2477                 if (slot == -1) {
2478                         uc_compiler_initialize_local(compiler);
2479                 }
2480                 /* if the variable was redeclared, overwrite it */
2481                 else {
2482                         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2483                         uc_compiler_emit_u32(compiler, 0, slot);
2484                         uc_compiler_emit_insn(compiler, 0, I_POP);
2485                 }
2486         }
2487         while (uc_compiler_parse_match(compiler, TK_COMMA));
2488 }
2489 
2490 static void
2491 uc_compiler_compile_local(uc_compiler_t *compiler)
2492 {
2493         uc_compiler_compile_declexpr(compiler, false);
2494         uc_compiler_parse_consume(compiler, TK_SCOL);
2495 }
2496 
2497 static void
2498 uc_compiler_compile_const(uc_compiler_t *compiler)
2499 {
2500         uc_compiler_compile_declexpr(compiler, true);
2501         uc_compiler_parse_consume(compiler, TK_SCOL);
2502 }
2503 
2504 static uc_tokentype_t
2505 uc_compiler_compile_altifblock(uc_compiler_t *compiler)
2506 {
2507         uc_compiler_enter_scope(compiler);
2508 
2509         while (true) {
2510                 switch (compiler->parser->curr.type) {
2511                 case TK_ELIF:
2512                 case TK_ELSE:
2513                 case TK_ENDIF:
2514                 case TK_EOF:
2515                         uc_compiler_leave_scope(compiler);
2516 
2517                         return compiler->parser->curr.type;
2518 
2519                 default:
2520                         uc_compiler_compile_declaration(compiler);
2521                         break;
2522                 }
2523         }
2524 
2525         return 0;
2526 }
2527 
2528 static void
2529 uc_compiler_compile_if(uc_compiler_t *compiler)
2530 {
2531         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2532         size_t jmpz_off, jmp_off, i;
2533         bool expect_endif = false;
2534         uc_jmplist_t elifs = { 0 };
2535         uc_tokentype_t type;
2536 
2537         /* parse & compile condition expression */
2538         uc_compiler_parse_consume(compiler, TK_LPAREN);
2539         uc_compiler_compile_expression(compiler);
2540         uc_compiler_parse_consume(compiler, TK_RPAREN);
2541 
2542         /* conditional jump to else/elif branch */
2543         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2544 
2545         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2546                 compiler->exprstack->flags |= F_ALTBLOCKMODE;
2547 
2548                 while (true) {
2549                         /* compile elsif or else branch */
2550                         type = uc_compiler_compile_altifblock(compiler);
2551 
2552                         /* we just compiled an elsif block */
2553                         if (!expect_endif && type == TK_ELIF) {
2554                                 /* emit jump to skip to the end */
2555                                 uc_vector_push(&elifs, uc_compiler_emit_jmp(compiler, 0));
2556 
2557                                 /* point previous conditional jump to beginning of branch */
2558                                 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2559 
2560                                 /* parse & compile elsif condition */
2561                                 uc_compiler_parse_advance(compiler);
2562                                 uc_compiler_parse_consume(compiler, TK_LPAREN);
2563                                 uc_compiler_compile_expression(compiler);
2564                                 uc_compiler_parse_consume(compiler, TK_RPAREN);
2565                                 uc_compiler_parse_consume(compiler, TK_COLON);
2566 
2567                                 /* conditional jump to else/elif branch */
2568                                 jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2569                         }
2570                         else if (!expect_endif && type == TK_ELSE) {
2571                                 /* emit jump to skip to the end */
2572                                 uc_vector_push(&elifs, uc_compiler_emit_jmp(compiler, 0));
2573 
2574                                 /* point previous conditional jump to beginning of branch */
2575                                 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2576                                 jmpz_off = 0;
2577 
2578                                 /* skip "else" keyword */
2579                                 uc_compiler_parse_advance(compiler);
2580 
2581                                 expect_endif = true;
2582                         }
2583                         else if (type == TK_ENDIF) {
2584                                 /* if no else clause, point previous conditional jump after block */
2585                                 if (jmpz_off)
2586                                         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2587 
2588                                 /* patch the elif branch jumps to point here after the else */
2589                                 for (i = 0; i < elifs.count; i++)
2590                                         uc_compiler_set_jmpaddr(compiler, elifs.entries[i],
2591                                                 chunk->count);
2592 
2593                                 /* skip the "endif" keyword */
2594                                 uc_compiler_parse_advance(compiler);
2595                                 break;
2596                         }
2597                         else {
2598                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2599                                         expect_endif
2600                                                 ? "Expecting 'endif'"
2601                                                 : "Expecting 'elif', 'else' or 'endif'");
2602 
2603                                 break;
2604                         }
2605                 }
2606 
2607                 uc_vector_clear(&elifs);
2608         }
2609         else {
2610                 /* compile true branch */
2611                 uc_compiler_compile_statement(compiler);
2612 
2613                 /* ... when present, handle false branch */
2614                 if (uc_compiler_parse_match(compiler, TK_ELSE)) {
2615                         /* jump to skip else branch */
2616                         jmp_off = uc_compiler_emit_jmp(compiler, 0);
2617 
2618                         /* set conditional jump address */
2619                         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2620 
2621                         /* compile false branch */
2622                         uc_compiler_compile_statement(compiler);
2623 
2624                         /* set else skip jump address */
2625                         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
2626                 }
2627                 /* ... otherwise point the conditional jump after the true branch */
2628                 else {
2629                         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2630                 }
2631         }
2632 }
2633 
2634 static void
2635 uc_compiler_compile_while(uc_compiler_t *compiler)
2636 {
2637         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2638         uc_patchlist_t p = { .depth = compiler->scope_depth, .token = TK_WHILE };
2639         size_t cond_off, jmpz_off, end_off;
2640 
2641         p.parent = compiler->patchlist;
2642         compiler->patchlist = &p;
2643 
2644         cond_off = chunk->count;
2645 
2646         /* parse & compile loop condition */
2647         uc_compiler_parse_consume(compiler, TK_LPAREN);
2648         uc_compiler_compile_expression(compiler);
2649         uc_compiler_parse_consume(compiler, TK_RPAREN);
2650 
2651         /* conditional jump to end */
2652         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2653 
2654         /* compile loop body */
2655         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2656                 uc_compiler_enter_scope(compiler);
2657 
2658                 if (uc_compiler_compile_delimitted_block(compiler, TK_ENDWHILE) == TK_EOF)
2659                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2660                                 "Expecting 'endwhile'");
2661                 else
2662                         uc_compiler_parse_advance(compiler);
2663 
2664                 uc_compiler_leave_scope(compiler);
2665         }
2666         else {
2667                 uc_compiler_compile_statement(compiler);
2668         }
2669 
2670         end_off = chunk->count;
2671 
2672         /* jump back to condition */
2673         uc_compiler_emit_jmp_dest(compiler, 0, cond_off);
2674 
2675         /* set conditional jump target */
2676         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2677 
2678         /* patch up break/continue */
2679         uc_compiler_backpatch(compiler, chunk->count, end_off);
2680 }
2681 
2682 static void
2683 uc_compiler_compile_for_in(uc_compiler_t *compiler, bool local, uc_token_t *kvar, uc_token_t *vvar)
2684 {
2685         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2686         uc_patchlist_t p = { .depth = compiler->scope_depth + 1, .token = TK_FOR };
2687         size_t skip_jmp, test_jmp, key_slot, val_slot;
2688 
2689         p.parent = compiler->patchlist;
2690         compiler->patchlist = &p;
2691 
2692         uc_compiler_enter_scope(compiler);
2693 
2694         /* declare internal loop variables */
2695         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2696         key_slot = uc_compiler_declare_internal(compiler, 0, "(for in key)");
2697 
2698         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2699         val_slot = uc_compiler_declare_internal(compiler, 0, "(for in value)");
2700 
2701         /* declare loop variables */
2702         if (local) {
2703                 uc_compiler_declare_local_null(compiler, kvar->pos, kvar->uv);
2704 
2705                 if (vvar)
2706                         uc_compiler_declare_local_null(compiler, vvar->pos, vvar->uv);
2707         }
2708 
2709         /* value to iterate */
2710         uc_compiler_compile_expression(compiler);
2711         uc_compiler_parse_consume(compiler, TK_RPAREN);
2712         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2713         uc_compiler_emit_u32(compiler, 0, val_slot);
2714 
2715         /* initial key value */
2716         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2717         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2718         uc_compiler_emit_u32(compiler, 0, key_slot);
2719 
2720         /* jump over variable read for first cycle */
2721         skip_jmp = uc_compiler_emit_jmp(compiler, 0);
2722 
2723         /* read value */
2724         uc_compiler_emit_insn(compiler, 0, I_LLOC);
2725         uc_compiler_emit_u32(compiler, 0, val_slot);
2726 
2727         /* read key */
2728         uc_compiler_emit_insn(compiler, 0, I_LLOC);
2729         uc_compiler_emit_u32(compiler, 0, key_slot);
2730 
2731         /* backpatch skip jump */
2732         uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count);
2733 
2734         /* load loop variable and get next key from object */
2735         uc_compiler_emit_insn(compiler, 0, vvar ? I_NEXTKV : I_NEXTK);
2736 
2737         /* set internal key variable */
2738         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2739         uc_compiler_emit_u32(compiler, 0, key_slot);
2740 
2741         /* test for != null */
2742         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2743         uc_compiler_emit_insn(compiler, 0, I_NES);
2744 
2745         /* jump after loop body if no next key */
2746         test_jmp = uc_compiler_emit_jmpz(compiler, 0);
2747 
2748         /* set key and value variables */
2749         if (vvar) {
2750                 uc_compiler_emit_variable_rw(compiler, vvar->uv, TK_ASSIGN);
2751                 uc_compiler_emit_insn(compiler, 0, I_POP);
2752         }
2753 
2754         /* set key variable */
2755         uc_compiler_emit_variable_rw(compiler, kvar->uv, TK_ASSIGN);
2756         uc_compiler_emit_insn(compiler, 0, I_POP);
2757 
2758         /* compile loop body */
2759         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2760                 uc_compiler_enter_scope(compiler);
2761 
2762                 if (uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR) == TK_EOF)
2763                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2764                                 "Expecting 'endfor'");
2765                 else
2766                         uc_compiler_parse_advance(compiler);
2767 
2768                 uc_compiler_leave_scope(compiler);
2769         }
2770         else {
2771                 uc_compiler_compile_statement(compiler);
2772         }
2773 
2774         /* jump back to retrieve next key */
2775         uc_compiler_emit_jmp_dest(compiler, 0, skip_jmp + 5);
2776 
2777         /* back patch conditional jump */
2778         uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count);
2779 
2780         /* pop loop variables */
2781         uc_compiler_emit_insn(compiler, 0, I_POP);
2782 
2783         if (vvar)
2784                 uc_compiler_emit_insn(compiler, 0, I_POP);
2785 
2786         /* patch up break/continue */
2787         uc_compiler_backpatch(compiler, chunk->count, skip_jmp + 5);
2788 
2789         uc_compiler_leave_scope(compiler);
2790 }
2791 
2792 static void
2793 uc_compiler_compile_for_count(uc_compiler_t *compiler, bool local, uc_token_t *predecl, uc_token_t *var)
2794 {
2795         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2796         size_t test_off = 0, incr_off, skip_off, cond_off = 0;
2797         uc_patchlist_t p = { .depth = compiler->scope_depth + 1, .token = TK_FOR };
2798 
2799         p.parent = compiler->patchlist;
2800         compiler->patchlist = &p;
2801 
2802         uc_compiler_enter_scope(compiler);
2803 
2804         /* Initializer ---------------------------------------------------------- */
2805 
2806         /* A leading declaration without initializer, e.g. the `x` in
2807          * `for (let x, y = 0; ...)`, was consumed while disambiguating for-in */
2808         if (predecl && local)
2809                 uc_compiler_declare_local_null(compiler, predecl->pos, predecl->uv);
2810 
2811         /* If we parsed at least one label, try continue parsing as variable
2812          * expression... */
2813         if (var) {
2814                 /* We parsed a `local x` or `local x, y` expression, so (re)declare
2815                  * last label as local initializer variable */
2816                 if (local)
2817                         uc_compiler_declare_local_null(compiler, var->pos, var->uv);
2818 
2819                 uc_compiler_exprstack_push(compiler, TK_FOR, F_ASSIGNABLE);
2820 
2821                 uc_compiler_compile_labelexpr(compiler);
2822                 uc_compiler_emit_insn(compiler, 0, I_POP);
2823 
2824                 /* If followed by a comma, continue parsing expression */
2825                 if (uc_compiler_parse_match(compiler, TK_COMMA)) {
2826                         /* Is a continuation of a declaration list... */
2827                         if (local) {
2828                                 uc_compiler_compile_declexpr(compiler, false);
2829                         }
2830                         /* ... otherwise an unrelated expression */
2831                         else {
2832                                 uc_compiler_compile_expression(compiler);
2833                                 uc_compiler_emit_insn(compiler, 0, I_POP);
2834                         }
2835                 }
2836 
2837                 uc_compiler_exprstack_pop(compiler);
2838         }
2839         /* ... otherwise try parsing an entire expression (which might be absent) */
2840         else if (!uc_compiler_parse_check(compiler, TK_SCOL)) {
2841                 uc_compiler_compile_expression(compiler);
2842                 uc_compiler_emit_insn(compiler, 0, I_POP);
2843         }
2844 
2845         uc_compiler_parse_consume(compiler, TK_SCOL);
2846 
2847 
2848         /* Condition ------------------------------------------------------------ */
2849         if (!uc_compiler_parse_check(compiler, TK_SCOL)) {
2850                 cond_off = chunk->count;
2851 
2852                 uc_compiler_compile_expression(compiler);
2853 
2854                 test_off = uc_compiler_emit_jmpz(compiler, 0);
2855         }
2856 
2857         uc_compiler_parse_consume(compiler, TK_SCOL);
2858 
2859         /* jump over incrementer */
2860         skip_off = uc_compiler_emit_jmp(compiler, 0);
2861 
2862 
2863         /* Incrementer ---------------------------------------------------------- */
2864         incr_off = chunk->count;
2865 
2866         if (!uc_compiler_parse_check(compiler, TK_RPAREN)) {
2867                 uc_compiler_compile_expression(compiler);
2868                 uc_compiler_emit_insn(compiler, 0, I_POP);
2869         }
2870 
2871         uc_compiler_parse_consume(compiler, TK_RPAREN);
2872 
2873         /* if we have a condition, jump back to it, else continue to the loop body */
2874         if (cond_off)
2875                 uc_compiler_emit_jmp_dest(compiler, 0, cond_off);
2876 
2877         /* back patch skip address */
2878         uc_compiler_set_jmpaddr(compiler, skip_off, chunk->count);
2879 
2880 
2881         /* Body ----------------------------------------------------------------- */
2882         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2883                 uc_compiler_enter_scope(compiler);
2884 
2885                 if (uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR) == TK_EOF)
2886                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2887                                 "Expecting 'endfor'");
2888                 else
2889                         uc_compiler_parse_advance(compiler);
2890 
2891                 uc_compiler_leave_scope(compiler);
2892         }
2893         else {
2894                 uc_compiler_compile_statement(compiler);
2895         }
2896 
2897         /* jump back to incrementer */
2898         uc_compiler_emit_jmp_dest(compiler, 0, incr_off);
2899 
2900         /* back patch conditional jump */
2901         if (test_off)
2902                 uc_compiler_set_jmpaddr(compiler, test_off, chunk->count);
2903 
2904         /* patch up break/continue */
2905         uc_compiler_backpatch(compiler, chunk->count, incr_off);
2906 
2907         uc_compiler_leave_scope(compiler);
2908 }
2909 
2910 static void
2911 uc_compiler_compile_for(uc_compiler_t *compiler)
2912 {
2913         uc_token_t keyvar = { 0 }, valvar = { 0 };
2914         bool local;
2915 
2916         uc_compiler_parse_consume(compiler, TK_LPAREN);
2917 
2918         /* check the next few tokens and see if we have either a
2919          * `let x in` / `let x, y` expression or an ordinary initializer
2920          * statement */
2921 
2922         local = uc_compiler_parse_match(compiler, TK_LOCAL);
2923 
2924         if (uc_compiler_parse_match(compiler, TK_LABEL)) {
2925                 keyvar = compiler->parser->prev;
2926                 ucv_get(keyvar.uv);
2927 
2928                 if (uc_compiler_parse_match(compiler, TK_COMMA)) {
2929                         uc_compiler_parse_consume(compiler, TK_LABEL);
2930 
2931                         valvar = compiler->parser->prev;
2932                         ucv_get(valvar.uv);
2933                 }
2934 
2935                 /* is a for-in loop */
2936                 if (uc_compiler_parse_match(compiler, TK_IN)) {
2937                         uc_compiler_compile_for_in(compiler, local, &keyvar,
2938                                 valvar.type ? &valvar : NULL);
2939 
2940                         goto out;
2941                 }
2942         }
2943         else if (local) {
2944                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2945                         "Expecting label after 'local'");
2946 
2947                 goto out;
2948         }
2949 
2950         /*
2951          * The previous expression ruled out a for-in loop, so continue parsing
2952          * as counting for loop...
2953          */
2954         if (valvar.uv)
2955                 uc_compiler_compile_for_count(compiler, local,
2956                         keyvar.uv ? &keyvar : NULL, &valvar);
2957         else
2958                 uc_compiler_compile_for_count(compiler, local,
2959                         NULL, keyvar.uv ? &keyvar : NULL);
2960 
2961 out:
2962         ucv_put(keyvar.uv);
2963         ucv_put(valvar.uv);
2964 }
2965 
2966 static void
2967 uc_compiler_compile_switch(uc_compiler_t *compiler)
2968 {
2969         size_t i, test_jmp, skip_jmp, next_jmp = 0, value_slot, default_off = 0;
2970         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2971         uc_patchlist_t p = { .depth = compiler->scope_depth, .token = TK_SWITCH };
2972         uc_locals_t *locals = &compiler->locals;
2973         uc_jmplist_t cases = { 0 };
2974 
2975         p.parent = compiler->patchlist;
2976         compiler->patchlist = &p;
2977 
2978         uc_compiler_enter_scope(compiler);
2979 
2980         /* parse and compile match value */
2981         uc_compiler_parse_consume(compiler, TK_LPAREN);
2982         uc_compiler_compile_expression(compiler);
2983         uc_compiler_parse_consume(compiler, TK_RPAREN);
2984         uc_compiler_parse_consume(compiler, TK_LBRACE);
2985 
2986         value_slot = uc_compiler_declare_internal(compiler, 0, "(switch value)");
2987 
2988         /* jump to branch tests */
2989         test_jmp = uc_compiler_emit_jmp(compiler, 0);
2990 
2991         /* parse and compile case matches */
2992         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
2993                !uc_compiler_parse_check(compiler, TK_EOF)) {
2994                 /* handle `default:` */
2995                 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) {
2996                         if (default_off) {
2997                                 uc_vector_clear(&cases);
2998                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
2999                                         "more than one switch default case");
3000 
3001                                 break;
3002                         }
3003 
3004                         uc_compiler_parse_consume(compiler, TK_COLON);
3005 
3006                         /* remember address of default branch */
3007                         default_off = chunk->count;
3008 
3009                         /* Store three values in case offset list:
3010                          *  1) amount of local variables declared so far
3011                          *  2) beginning of condition expression
3012                          *  3) end of condition expression
3013                          * For the `default` case, beginning and end offsets of the
3014                          * condition expression are equal.
3015                          */
3016                         uc_vector_extend(&cases, 3);
3017                         cases.entries[cases.count++] = (locals->count - 1) - value_slot;
3018                         cases.entries[cases.count++] = chunk->count;
3019                         cases.entries[cases.count++] = chunk->count;
3020                 }
3021 
3022                 /* handle `case …:` */
3023                 else if (uc_compiler_parse_match(compiler, TK_CASE)) {
3024                         /* jump over `case …:` label expression */
3025                         skip_jmp = uc_compiler_emit_jmp(compiler, 0);
3026 
3027                         /* compile case value expression */
3028                         uc_compiler_compile_expression(compiler);
3029                         uc_compiler_parse_consume(compiler, TK_COLON);
3030 
3031                         /* Store three values in case offset list:
3032                          *  1) amount of local variables declared so far
3033                          *  2) beginning of condition expression
3034                          *  3) end of condition expression
3035                          */
3036                         uc_vector_extend(&cases, 3);
3037                         cases.entries[cases.count++] = (locals->count - 1) - value_slot;
3038                         cases.entries[cases.count++] = skip_jmp + 5;
3039                         cases.entries[cases.count++] = uc_compiler_emit_jmp(compiler, 0);
3040 
3041                         /* patch jump skipping over the case value */
3042                         uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count);
3043                 }
3044 
3045                 /* handle interleaved statement */
3046                 else if (cases.count) {
3047                         uc_compiler_compile_declaration(compiler);
3048                 }
3049 
3050                 /* a statement or expression preceding any `default` or `case` is a
3051                  * syntax error */
3052                 else {
3053                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3054                                 "Expecting 'case' or 'default'");
3055 
3056                         break;
3057                 }
3058         }
3059 
3060         uc_compiler_parse_consume(compiler, TK_RBRACE);
3061 
3062         /* evaluate case matches */
3063         if (cases.count) {
3064                 skip_jmp = uc_compiler_emit_jmp(compiler, 0);
3065 
3066                 uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count);
3067 
3068                 for (i = 0, default_off = cases.count; i < cases.count; i += 3) {
3069                         /* remember and skip default case */
3070                         if (cases.entries[i + 1] == cases.entries[i + 2]) {
3071                                 default_off = i;
3072                                 continue;
3073                         }
3074 
3075                         /* read switch match value */
3076                         uc_compiler_emit_insn(compiler, 0, I_LLOC);
3077                         uc_compiler_emit_u32(compiler, 0, value_slot);
3078 
3079                         /* jump to case value expression code */
3080                         uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 1]);
3081 
3082                         /* patch final case value expression jump back here */
3083                         uc_compiler_set_jmpaddr(compiler, cases.entries[i + 2], chunk->count);
3084 
3085                         /* strict equal test */
3086                         uc_compiler_emit_insn(compiler, 0, I_EQS);
3087 
3088                         /* conditional jump to next match */
3089                         next_jmp = uc_compiler_emit_jmpz(compiler, 0);
3090 
3091                         /* fill local slots */
3092                         while (cases.entries[i + 0] > 0) {
3093                                 uc_compiler_emit_insn(compiler, 0, I_LNULL);
3094                                 cases.entries[i + 0]--;
3095                         }
3096 
3097                         /* jump to target code */
3098                         uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 2] + 5);
3099 
3100                         /* patch next jump */
3101                         uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count);
3102                 }
3103 
3104                 /* handle default case (if any) */
3105                 if (default_off < cases.count) {
3106                         /* fill local slots */
3107                         while (cases.entries[default_off + 0] > 0) {
3108                                 uc_compiler_emit_insn(compiler, 0, I_LNULL);
3109                                 cases.entries[default_off + 0]--;
3110                         }
3111 
3112                         /* jump to target */
3113                         uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[default_off + 2]);
3114 
3115                         /* do not patch final match failure jump later, we handle it here
3116                          * in the default case */
3117                         next_jmp = 0;
3118                 }
3119 
3120                 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count);
3121         }
3122         else {
3123                 uc_compiler_set_jmpaddr(compiler, test_jmp, test_jmp + 5);
3124         }
3125 
3126         uc_vector_clear(&cases);
3127 
3128         uc_compiler_leave_scope(compiler);
3129 
3130         /* if no default case exists, patch last case match failure jump */
3131         if (next_jmp) {
3132                 /* There's pop instructions for all local variables including the
3133                  * switch test value itself on the stack. Jump onto the last POP
3134                  * instruction (-1) to get rid of the on-stack switch test value
3135                  * but skip the POP instructions for all other scoped local variables
3136                  * which never have been initialized. */
3137                 uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count - 1);
3138         }
3139 
3140         uc_compiler_backpatch(compiler, chunk->count, 0);
3141 }
3142 
3143 static void
3144 uc_compiler_compile_try(uc_compiler_t *compiler)
3145 {
3146         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
3147         size_t try_from = 0, try_to = 0, jmp_off = 0, ehvar_slot = 0;
3148         uc_ehranges_t *ranges = &chunk->ehranges;
3149 
3150         try_from = chunk->count;
3151         ehvar_slot = compiler->locals.count;
3152 
3153         /* Try block ------------------------------------------------------------ */
3154         uc_compiler_enter_scope(compiler);
3155 
3156         uc_compiler_parse_consume(compiler, TK_LBRACE);
3157 
3158         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
3159                !uc_compiler_parse_check(compiler, TK_EOF))
3160                 uc_compiler_compile_declaration(compiler);
3161 
3162         uc_compiler_parse_consume(compiler, TK_RBRACE);
3163 
3164         uc_compiler_leave_scope(compiler);
3165 
3166         /* jump beyond catch branch */
3167         try_to = chunk->count;
3168         jmp_off = uc_compiler_emit_jmp(compiler, 0);
3169 
3170 
3171         /* Catch block ---------------------------------------------------------- */
3172         if (try_to > try_from) {
3173                 uc_vector_push(ranges, {
3174                         .from   = try_from,
3175                         .to     = try_to,
3176                         .target = chunk->count,
3177                         .slot   = ehvar_slot
3178                 });
3179         }
3180 
3181         uc_compiler_enter_scope(compiler);
3182 
3183         uc_compiler_parse_consume(compiler, TK_CATCH);
3184 
3185         /* have exception variable */
3186         if (uc_compiler_parse_match(compiler, TK_LPAREN)) {
3187                 uc_compiler_parse_consume(compiler, TK_LABEL);
3188 
3189                 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, false);
3190                 uc_compiler_initialize_local(compiler);
3191 
3192                 uc_compiler_parse_consume(compiler, TK_RPAREN);
3193         }
3194         /* ... else pop exception object from stack */
3195         else {
3196                 uc_compiler_emit_insn(compiler, 0, I_POP);
3197         }
3198 
3199         uc_compiler_parse_consume(compiler, TK_LBRACE);
3200 
3201         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
3202                !uc_compiler_parse_check(compiler, TK_EOF))
3203                 uc_compiler_compile_declaration(compiler);
3204 
3205         uc_compiler_parse_consume(compiler, TK_RBRACE);
3206 
3207         uc_compiler_leave_scope(compiler);
3208 
3209         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
3210 }
3211 
3212 static void
3213 uc_compiler_compile_control(uc_compiler_t *compiler)
3214 {
3215         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
3216         uc_tokentype_t type = compiler->parser->prev.type;
3217         uc_patchlist_t *p = compiler->patchlist;
3218         uc_locals_t *locals = &compiler->locals;
3219         size_t i, pos = compiler->parser->prev.pos;
3220 
3221         /* select applicable patchlist: for continue statements select the
3222          * first non-switch scope */
3223         while (p) {
3224                 if (type != TK_CONTINUE || p->token != TK_SWITCH)
3225                         break;
3226 
3227                 p = p->parent;
3228         }
3229 
3230         if (!p || p->token == TK_EXPORT) {
3231                 uc_compiler_syntax_error(compiler, pos,
3232                         (type == TK_BREAK)
3233                                 ? "break must be inside loop or switch"
3234                                 : "continue must be inside loop");
3235 
3236                 return;
3237         }
3238 
3239         /* pop locals in all scopes covered by the target patchlist */
3240         for (i = locals->count; i > 0 && (size_t)locals->entries[i - 1].depth > p->depth; i--)
3241                 uc_compiler_emit_insn(compiler, 0,
3242                         locals->entries[i - 1].captured ? I_CUPV : I_POP);
3243 
3244         uc_vector_push(p,
3245                 uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type));
3246 
3247         uc_compiler_parse_consume(compiler, TK_SCOL);
3248 }
3249 
3250 static void
3251 uc_compiler_compile_return(uc_compiler_t *compiler)
3252 {
3253         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
3254 
3255         if (compiler->function->module) {
3256                 uc_compiler_syntax_error(compiler, 0, "return must be inside function body");
3257 
3258                 return;
3259         }
3260 
3261         /* if we compiled an empty expression statement (`;`), load implicit null */
3262         if (uc_compiler_compile_expstmt(compiler) == TK_NULL)
3263                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
3264 
3265         /* otherwise overwrite the final I_POP instruction with I_RETURN */
3266         else
3267                 uc_chunk_pop(chunk);
3268 
3269         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_RETURN);
3270 }
3271 
3272 static void
3273 uc_compiler_compile_tplexp(uc_compiler_t *compiler)
3274 {
3275         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
3276         size_t off = chunk->count;
3277 
3278         uc_compiler_compile_expression(compiler);
3279 
3280         /* XXX: the lexer currently emits a superfluous trailing semicolon... */
3281         uc_compiler_parse_match(compiler, TK_SCOL);
3282 
3283         uc_compiler_parse_consume(compiler, TK_REXP);
3284 
3285         if (chunk->count > off)
3286                 uc_compiler_emit_insn(compiler, 0, I_PRINT);
3287 }
3288 
3289 static void
3290 uc_compiler_compile_text(uc_compiler_t *compiler)
3291 {
3292         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
3293         uc_compiler_emit_insn(compiler, 0, I_PRINT);
3294 }
3295 
3296 static uc_tokentype_t
3297 uc_compiler_compile_block(uc_compiler_t *compiler)
3298 {
3299         uc_tokentype_t last_statement_type = TK_NULL;
3300 
3301         uc_compiler_enter_scope(compiler);
3302 
3303         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
3304                !uc_compiler_parse_check(compiler, TK_EOF))
3305                 last_statement_type = uc_compiler_compile_declaration(compiler);
3306 
3307         uc_compiler_parse_consume(compiler, TK_RBRACE);
3308 
3309         uc_compiler_leave_scope(compiler);
3310 
3311         return last_statement_type;
3312 }
3313 
3314 static uc_tokentype_t
3315 uc_compiler_compile_expstmt(uc_compiler_t *compiler)
3316 {
3317         /* empty statement */
3318         if (uc_compiler_parse_match(compiler, TK_SCOL))
3319                 return TK_NULL;
3320 
3321         uc_compiler_compile_expression(compiler);
3322 
3323         /* allow omitting final semicolon */
3324         switch (compiler->parser->curr.type) {
3325         case TK_RBRACE:
3326         case TK_ELIF:
3327         case TK_ENDIF:
3328         case TK_ENDFOR:
3329         case TK_ENDWHILE:
3330         case TK_ENDFUNC:
3331         case TK_EOF:
3332                 break;
3333 
3334         case TK_ELSE:
3335                 if (!uc_compiler_exprstack_is(compiler, F_ALTBLOCKMODE))
3336                         uc_compiler_parse_consume(compiler, TK_SCOL);
3337 
3338                 break;
3339 
3340         default:
3341                 uc_compiler_parse_consume(compiler, TK_SCOL);
3342 
3343                 break;
3344         }
3345 
3346         uc_compiler_emit_insn(compiler, 0, I_POP);
3347 
3348         return TK_SCOL;
3349 }
3350 
3351 static uc_tokentype_t
3352 uc_compiler_compile_statement(uc_compiler_t *compiler)
3353 {
3354         uc_tokentype_t last_statement_type = compiler->parser->curr.type;
3355         uc_exprstack_t expr = {
3356                 .token = compiler->parser->curr.type,
3357                 .parent = compiler->exprstack
3358         };
3359 
3360         compiler->exprstack = &expr;
3361 
3362         if (uc_compiler_parse_match(compiler, TK_IF))
3363                 uc_compiler_compile_if(compiler);
3364         else if (uc_compiler_parse_match(compiler, TK_WHILE))
3365                 uc_compiler_compile_while(compiler);
3366         else if (uc_compiler_parse_match(compiler, TK_FOR))
3367                 uc_compiler_compile_for(compiler);
3368         else if (uc_compiler_parse_match(compiler, TK_SWITCH))
3369                 uc_compiler_compile_switch(compiler);
3370         else if (uc_compiler_parse_match(compiler, TK_TRY))
3371                 uc_compiler_compile_try(compiler);
3372         else if (uc_compiler_parse_match(compiler, TK_FUNC))
3373                 uc_compiler_compile_funcdecl(compiler);
3374         else if (uc_compiler_parse_match(compiler, TK_BREAK))
3375                 uc_compiler_compile_control(compiler);
3376         else if (uc_compiler_parse_match(compiler, TK_CONTINUE))
3377                 uc_compiler_compile_control(compiler);
3378         else if (uc_compiler_parse_match(compiler, TK_RETURN))
3379                 uc_compiler_compile_return(compiler);
3380         else if (uc_compiler_parse_match(compiler, TK_TEXT))
3381                 uc_compiler_compile_text(compiler);
3382         else if (uc_compiler_parse_match(compiler, TK_LEXP))
3383                 uc_compiler_compile_tplexp(compiler);
3384         else if (uc_compiler_parse_match(compiler, TK_LBRACE))
3385                 last_statement_type = uc_compiler_compile_block(compiler);
3386         else
3387                 last_statement_type = uc_compiler_compile_expstmt(compiler);
3388 
3389         compiler->exprstack = expr.parent;
3390 
3391         return last_statement_type;
3392 }
3393 
3394 static void
3395 uc_compiler_export_add(uc_compiler_t *compiler, uc_value_t *name, ssize_t slot)
3396 {
3397         uc_source_t *source = uc_compiler_current_source(compiler);
3398 
3399         uc_compiler_inc_exportnum(compiler);
3400 
3401         if (!uc_source_export_add(source, name)) {
3402                 if (name)
3403                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3404                                 "Duplicate export '%s' for module '%s'", ucv_string_get(name), source->filename);
3405                 else
3406                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3407                                 "Duplicate default export for module '%s'", source->filename);
3408         }
3409         else {
3410                 uc_vector_push(compiler->patchlist, slot);
3411         }
3412 }
3413 
3414 static void
3415 uc_compiler_compile_exportlist(uc_compiler_t *compiler)
3416 {
3417         uc_value_t *label, *name;
3418         bool constant;
3419         ssize_t slot;
3420 
3421         /* parse export symbols */
3422         do {
3423                 uc_compiler_parse_consume(compiler, TK_LABEL);
3424 
3425                 label = ucv_get(compiler->parser->prev.uv);
3426                 name = NULL;
3427 
3428                 slot = uc_compiler_resolve_local(compiler, label, &constant);
3429 
3430                 if (slot == -1) {
3431                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3432                                 "Attempt to export undeclared or non-local variable '%s'",
3433                                 ucv_string_get(label));
3434                 }
3435 
3436                 if (uc_compiler_keyword_match(compiler, "as")) {
3437                         if (uc_compiler_parse_match(compiler, TK_LABEL) || uc_compiler_parse_match(compiler, TK_STRING)) {
3438                                 name = ucv_get(compiler->parser->prev.uv);
3439                         }
3440                         else if (!uc_compiler_parse_match(compiler, TK_DEFAULT)) {
3441                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3442                                         "Unexpected token\nExpecting Label, String or 'default'");
3443                         }
3444                 }
3445                 else {
3446                         name = ucv_get(label);
3447                 }
3448 
3449                 uc_compiler_export_add(compiler, name, slot);
3450 
3451                 ucv_put(label);
3452                 ucv_put(name);
3453 
3454                 if (uc_compiler_parse_match(compiler, TK_RBRACE))
3455                         break;
3456         }
3457         while (uc_compiler_parse_match(compiler, TK_COMMA));
3458 
3459         uc_compiler_parse_consume(compiler, TK_SCOL);
3460 }
3461 
3462 static void
3463 uc_compiler_compile_export(uc_compiler_t *compiler)
3464 {
3465         uc_locals_t *locals = &compiler->locals;
3466         size_t off = locals->count;
3467         uc_value_t *name;
3468         ssize_t slot;
3469 
3470         if (!compiler->function->module || compiler->scope_depth) {
3471                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3472                         "Exports may only appear at top level of a module");
3473 
3474                 return;
3475         }
3476 
3477         if (uc_compiler_parse_match(compiler, TK_LBRACE)) {
3478                 uc_compiler_compile_exportlist(compiler);
3479 
3480                 return;
3481         }
3482 
3483         if (uc_compiler_parse_match(compiler, TK_LOCAL))
3484                 uc_compiler_compile_declexpr(compiler, false);
3485         else if (uc_compiler_parse_match(compiler, TK_CONST))
3486                 uc_compiler_compile_declexpr(compiler, true);
3487         else if (uc_compiler_parse_match(compiler, TK_FUNC)) {
3488                 uc_compiler_compile_funcdecl(compiler);
3489 
3490                 for (; off < locals->count; off++)
3491                         uc_compiler_export_add(compiler, locals->entries[off].name, off);
3492 
3493                 return;
3494         }
3495         else if (uc_compiler_parse_match(compiler, TK_DEFAULT))
3496                 uc_compiler_compile_expression(compiler);
3497         else
3498                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3499                         "Unexpected token\nExpecting 'let', 'const', 'function', 'default' or '{'");
3500 
3501         if (off == locals->count) {
3502                 name = ucv_string_new("(module default export)");
3503                 slot = uc_compiler_declare_local(compiler, name, true);
3504                 ucv_put(name);
3505 
3506                 if (slot != -1)
3507                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3508                                 "Duplicate default export statement");
3509                 else
3510                         uc_compiler_export_add(compiler, NULL, compiler->locals.count - 1);
3511         }
3512         else {
3513                 for (; off < locals->count; off++)
3514                         uc_compiler_export_add(compiler, locals->entries[off].name, off);
3515         }
3516 
3517         uc_compiler_parse_consume(compiler, TK_SCOL);
3518 }
3519 
3520 static uc_program_t *
3521 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, uc_program_t *prog, char **errp);
3522 
3523 static bool
3524 uc_compiler_compile_dynload(uc_compiler_t *compiler, const char *name, uc_value_t *imports)
3525 {
3526         uc_value_t *modname = ucv_string_new(name);
3527         size_t i, n_imports;
3528         uc_value_t *import;
3529 
3530         for (i = 0, n_imports = 0; i < ucv_array_length(imports); i++) {
3531                 import = ucv_array_get(imports, i);
3532 
3533                 if (ucv_boolean_get(import)) {
3534                         uc_compiler_emit_constant(compiler, 0, modname);
3535                         uc_compiler_emit_insn(compiler, 0, I_DYNLOAD);
3536                         uc_compiler_emit_u32(compiler, 0, 0);
3537                 }
3538                 else {
3539                         n_imports++;
3540                 }
3541         }
3542 
3543         if (n_imports > 0) {
3544                 uc_compiler_emit_constant(compiler, 0, modname);
3545                 uc_compiler_emit_insn(compiler, 0, I_DYNLOAD);
3546                 uc_compiler_emit_u32(compiler, 0, n_imports | ((compiler->upvals.count - n_imports) << 16));
3547 
3548                 for (i = 0; i < ucv_array_length(imports); i++) {
3549                         import = ucv_get(ucv_array_get(imports, i));
3550 
3551                         if (!import)
3552                                 import = ucv_string_new("default");
3553 
3554                         if (!ucv_boolean_get(import))
3555                                 uc_compiler_emit_constant_index(compiler, 0, import);
3556 
3557                         ucv_put(import);
3558                 }
3559         }
3560 
3561         ucv_put(modname);
3562 
3563         return true;
3564 }
3565 
3566 static bool
3567 uc_compiler_compile_module_source(uc_compiler_t *compiler, const char *modname, uc_source_t *source, uc_value_t *imports, char **errp)
3568 {
3569         uc_parse_config_t config = {
3570                 .raw_mode = true,
3571                 .strict_declarations = true,
3572                 .module_search_path = compiler->parser->lex.config->module_search_path
3573         };
3574 
3575         size_t i, load_idx = 0, n_imports = 0;
3576         bool loaded = false;
3577         uc_value_t *import;
3578         ssize_t slot;
3579 
3580         uc_program_function_foreach(compiler->program, fn) {
3581                 if (uc_program_function_source(fn) == source) {
3582                         loaded = true;
3583                         break;
3584                 }
3585         }
3586 
3587         /* An offset of -1 marks a source whose compilation was entered but not yet
3588          * completed. Re-entering it is either a circular dependency (its function is
3589          * still present) or a module whose earlier compilation failed and freed its
3590          * function. Recompiling in either case recurses without bound across a large
3591          * import graph, so report the cycle and propagate the failure instead. */
3592         if (source->exports.offset == (size_t)-1) {
3593                 if (loaded)
3594                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3595                                 "Circular dependency");
3596                 else if (errp)
3597                         xasprintf(errp, "Module previously failed to compile\n");
3598 
3599                 return false;
3600         }
3601 
3602         if (!loaded) {
3603                 /* We do not yet support linking precompiled modules at compile time,
3604                    turn static import operation into dynamic load one. */
3605                 if (uc_source_type_test(source) == UC_SOURCE_TYPE_PRECOMPILED)
3606                         return uc_compiler_compile_dynload(compiler, modname, imports);
3607 
3608                 load_idx = uc_program_function_id(compiler->program,
3609                         uc_program_function_last(compiler->program)) + 1;
3610 
3611                 source->exports.offset = (size_t)-1;
3612 
3613                 if (!uc_compile_from_source(&config, source, compiler->program, errp))
3614                         return false;
3615 
3616                 source->exports.offset = uc_compiler_get_exportnum(compiler) - source->exports.count;
3617                 uc_compiler_current_source(compiler)->exports.offset += source->exports.count;
3618 
3619                 /* emit load, call & pop instructions */
3620                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_CLFN);
3621                 uc_compiler_emit_u32(compiler, 0, load_idx);
3622 
3623                 uc_compiler_emit_insn(compiler, 0, I_CALL);
3624                 uc_compiler_emit_u32(compiler, 0, 0);
3625 
3626                 uc_compiler_emit_insn(compiler, 0, I_POP);
3627         }
3628 
3629         /* count imports, handle wildcard imports */
3630         for (i = 0; i < ucv_array_length(imports); i++) {
3631                 if (ucv_boolean_get(ucv_array_get(imports, i))) {
3632                         if (source->exports.offset > 0xffff || source->exports.count > 0xffff) {
3633                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3634                                         "Too many module exports");
3635                         }
3636 
3637                         /* emit import instruction... */
3638                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_IMPORT);
3639                         uc_compiler_emit_u32(compiler, 0, source->exports.count | (0xffff << 16));
3640 
3641                         /* ... followed by first module export offset ... */
3642                         uc_compiler_emit_u16(compiler, 0, source->exports.offset);
3643 
3644                         /* ... and constant indexes for all exported names */
3645                         for (load_idx = 0; load_idx < source->exports.count; load_idx++) {
3646                                 if (source->exports.entries[load_idx])
3647                                         import = ucv_get(source->exports.entries[load_idx]);
3648                                 else
3649                                         import = ucv_string_new("default");
3650 
3651                                 uc_compiler_emit_constant_index(compiler, 0, import);
3652                                 ucv_put(import);
3653                         }
3654 
3655                 }
3656                 else {
3657                         n_imports++;
3658                 }
3659         }
3660 
3661         /* 0xffff is reserved for wildcard import */
3662         if (n_imports > 0xfffe)
3663                 uc_compiler_syntax_error(compiler, 0, "Too many imports");
3664 
3665         /* emit non-wildcard import instructions */
3666         for (i = 0; i < ucv_array_length(imports); i++) {
3667                 import = ucv_array_get(imports, i);
3668 
3669                 if (!ucv_boolean_get(import)) {
3670                         slot = uc_source_export_lookup(source, import);
3671 
3672                         if (slot == -1) {
3673                                 if (import)
3674                                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3675                                                 "Module %s does not export '%s'", source->filename, ucv_string_get(import));
3676                                 else
3677                                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3678                                                 "Module %s has no default export", source->filename);
3679                         }
3680                         else if (slot > 0xffff) {
3681                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3682                                         "Too many module exports");
3683                         }
3684                         else {
3685                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_IMPORT);
3686                                 uc_compiler_emit_u32(compiler, 0,
3687                                         (source->exports.offset + slot) | ((compiler->upvals.count - n_imports + i) << 16));
3688                         }
3689                 }
3690         }
3691 
3692         return true;
3693 }
3694 
3695 static char *
3696 uc_compiler_canonicalize_path(const char *path, const char *runpath)
3697 {
3698         char *p, *resolved;
3699         const char *slash;
3700 
3701         if (*path == '/')
3702                 xasprintf(&p, "%s", path);
3703         else if (runpath && (slash = strrchr(runpath, '/')) != NULL)
3704                 xasprintf(&p, "%.*s/%s", (int)(slash - runpath), runpath, path);
3705         else
3706                 xasprintf(&p, "./%s", path);
3707 
3708         resolved = realpath(p, NULL);
3709 
3710         free(p);
3711 
3712         return resolved;
3713 }
3714 
3715 static char *
3716 uc_compiler_expand_module_path(const char *name, const char *runpath, const char *template)
3717 {
3718         int namelen, prefixlen;
3719         const char *asterix;
3720         char *path, *p;
3721 
3722         asterix = strchr(template, '*');
3723 
3724         if (!asterix)
3725                 return NULL;
3726 
3727         prefixlen = asterix - template;
3728         namelen = strlen(name);
3729 
3730         xasprintf(&path, "%.*s%.*s%s", prefixlen, template, namelen, name, asterix + 1);
3731 
3732         for (p = path + prefixlen; namelen > 0; namelen--, p++)
3733                 if (*p == '.')
3734                         *p = '/';
3735 
3736         p = uc_compiler_canonicalize_path(path, runpath);
3737 
3738         free(path);
3739 
3740         return p;
3741 }
3742 
3743 static char *
3744 uc_compiler_resolve_module_path(uc_compiler_t *compiler, const char *name)
3745 {
3746         uc_search_path_t *search = &compiler->parser->lex.config->module_search_path;
3747         uc_source_t *source = uc_compiler_current_source(compiler);
3748         char *path = NULL;
3749         size_t i;
3750 
3751         if (strchr(name, '/'))
3752                 return uc_compiler_canonicalize_path(name, source->runpath);
3753 
3754         for (i = 0; i < search->count && !path; i++)
3755                 path = uc_compiler_expand_module_path(name, source->runpath, search->entries[i]);
3756 
3757         return path;
3758 }
3759 
3760 static uc_source_t *
3761 uc_compiler_acquire_source(uc_compiler_t *compiler, const char *path)
3762 {
3763         size_t i;
3764 
3765         for (i = 0; i < compiler->program->sources.count; i++)
3766                 if (!strcmp(compiler->program->sources.entries[i]->filename, path))
3767                         return uc_source_get(compiler->program->sources.entries[i]);
3768 
3769         return uc_source_new_file(path);
3770 }
3771 
3772 static bool
3773 uc_compiler_is_dynlink_module(uc_compiler_t *compiler, const char *name, const char *path)
3774 {
3775         uc_search_path_t *dynlink_list = &compiler->parser->config->force_dynlink_list;
3776         const char *dot;
3777         size_t i;
3778 
3779         for (i = 0; i < dynlink_list->count; i++)
3780                 if (!strcmp(dynlink_list->entries[i], name))
3781                         return true;
3782 
3783         if (!path)
3784                 return false;
3785 
3786         dot = strrchr(path, '.');
3787 
3788         return (dot && !strcmp(dot, ".so"));
3789 }
3790 
3791 static bool
3792 uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t *imports)
3793 {
3794         uc_source_t *source;
3795         char *path, *err;
3796         bool res;
3797 
3798         if (!name)
3799                 return false;
3800 
3801         path = uc_compiler_resolve_module_path(compiler, name);
3802 
3803         if (uc_compiler_is_dynlink_module(compiler, name, path)) {
3804                 res = uc_compiler_compile_dynload(compiler, name, imports);
3805         }
3806         else if (path) {
3807                 source = uc_compiler_acquire_source(compiler, path);
3808 
3809                 if (source) {
3810                         err = NULL;
3811                         res = uc_compiler_compile_module_source(compiler, name, source, imports, &err);
3812 
3813                         if (!res) {
3814                                 uc_error_message_indent(&err);
3815                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3816                                         "Unable to compile module '%s':\n\n%s", source->filename, err);
3817                         }
3818 
3819                         free(err);
3820                 }
3821                 else {
3822                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3823                                 "Unable to open module '%s': %s",
3824                                 path, strerror(errno));
3825 
3826                         res = false;
3827                 }
3828 
3829                 uc_source_put(source);
3830         }
3831         else {
3832                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3833                         "Unable to resolve path for module '%s'", name);
3834 
3835                 return false;
3836         }
3837 
3838         free(path);
3839 
3840         return res;
3841 }
3842 
3843 static void
3844 uc_compiler_import_add(uc_compiler_t *compiler, uc_value_t *name)
3845 {
3846         bool constant;
3847         ssize_t slot;
3848 
3849         slot = uc_compiler_resolve_local(compiler, name, &constant);
3850 
3851         if (slot != -1) {
3852                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3853                         "Import name '%s' is already declared as local variable",
3854                         ucv_string_get(name));
3855 
3856                 return;
3857         }
3858 
3859         slot = uc_compiler_resolve_upval(compiler, name, &constant);
3860 
3861         if (slot != -1) {
3862                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3863                         "Import name '%s' is already used",
3864                         ucv_string_get(name));
3865 
3866                 return;
3867         }
3868 
3869         uc_compiler_add_upval(compiler, (2 << 14) + compiler->upvals.count, false, name, true);
3870 }
3871 
3872 static void
3873 uc_compiler_compile_importlist(uc_compiler_t *compiler, uc_value_t *namelist)
3874 {
3875         uc_value_t *label, *name;
3876 
3877         /* parse export symbols */
3878         do {
3879                 name = NULL;
3880                 label = NULL;
3881 
3882                 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) {
3883                         uc_compiler_keyword_consume(compiler, "as");
3884                         uc_compiler_parse_consume(compiler, TK_LABEL);
3885 
3886                         label = ucv_get(compiler->parser->prev.uv);
3887                 }
3888                 else if (uc_compiler_parse_match(compiler, TK_STRING)) {
3889                         name = ucv_get(compiler->parser->prev.uv);
3890 
3891                         uc_compiler_keyword_consume(compiler, "as");
3892                         uc_compiler_parse_consume(compiler, TK_LABEL);
3893 
3894                         label = ucv_get(compiler->parser->prev.uv);
3895                 }
3896                 else if (uc_compiler_parse_match(compiler, TK_LABEL)) {
3897                         name = ucv_get(compiler->parser->prev.uv);
3898 
3899                         if (uc_compiler_keyword_match(compiler, "as")) {
3900                                 uc_compiler_parse_consume(compiler, TK_LABEL);
3901 
3902                                 label = ucv_get(compiler->parser->prev.uv);
3903                         }
3904                         else {
3905                                 label = ucv_get(name);
3906                         }
3907                 }
3908                 else {
3909                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3910                                 "Unexpected token\nExpecting Label, String or 'default'");
3911                 }
3912 
3913                 uc_compiler_import_add(compiler, label);
3914                 ucv_array_push(namelist, name);
3915                 ucv_put(label);
3916 
3917                 if (uc_compiler_parse_match(compiler, TK_RBRACE))
3918                         return;
3919         }
3920         while (uc_compiler_parse_match(compiler, TK_COMMA));
3921 
3922         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
3923                 "Unexpected token\nExpecting 'as', ',' or '}'");
3924 }
3925 
3926 static void
3927 uc_compiler_compile_importcall(uc_compiler_t *compiler)
3928 {
3929         uc_compiler_parse_consume(compiler, TK_LPAREN);
3930         uc_compiler_parse_precedence(compiler, P_ASSIGN);
3931         uc_compiler_parse_consume(compiler, TK_RPAREN);
3932 
3933         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_DYNLOAD);
3934         uc_compiler_emit_u32(compiler, 0, 0);
3935 }
3936 
3937 static uc_tokentype_t
3938 uc_compiler_compile_import(uc_compiler_t *compiler)
3939 {
3940         uc_value_t *namelist;
3941 
3942         /* import(...) */
3943         if (uc_compiler_parse_check(compiler, TK_LPAREN)) {
3944                 uc_compiler_parse_precedence_for_token(compiler, P_UNARY,
3945                                                        &compiler->parser->prev);
3946 
3947                 uc_compiler_emit_insn(compiler, 0, I_POP);
3948 
3949                 return TK_SCOL;
3950         }
3951 
3952         if (compiler->scope_depth) {
3953                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
3954                         "Imports may only appear at top level");
3955 
3956                 return TK_IMPORT;
3957         }
3958 
3959         namelist = ucv_array_new(NULL);
3960 
3961         /* import { ... } from */
3962         if (uc_compiler_parse_match(compiler, TK_LBRACE)) {
3963                 uc_compiler_compile_importlist(compiler, namelist);
3964                 uc_compiler_keyword_consume(compiler, "from");
3965         }
3966 
3967         /* import * as name from */
3968         else if (uc_compiler_parse_match(compiler, TK_MUL)) {
3969                 uc_compiler_keyword_consume(compiler, "as");
3970                 uc_compiler_parse_consume(compiler, TK_LABEL);
3971 
3972                 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, true);
3973                 uc_compiler_initialize_local(compiler);
3974                 ucv_array_push(namelist, ucv_boolean_new(true));
3975 
3976                 uc_compiler_keyword_consume(compiler, "from");
3977         }
3978 
3979         /* import defaultExport [, ... ] from */
3980         else if (uc_compiler_parse_match(compiler, TK_LABEL)) {
3981                 uc_compiler_import_add(compiler, compiler->parser->prev.uv);
3982                 ucv_array_push(namelist, NULL);
3983 
3984                 /* import defaultExport, ... from */
3985                 if (uc_compiler_parse_match(compiler, TK_COMMA)) {
3986                         /* import defaultExport, { ... } from */
3987                         if (uc_compiler_parse_match(compiler, TK_LBRACE)) {
3988                                 uc_compiler_compile_importlist(compiler, namelist);
3989                         }
3990 
3991                         /* import defaultExport, * as name from */
3992                         else if (uc_compiler_parse_match(compiler, TK_MUL)) {
3993                                 uc_compiler_keyword_consume(compiler, "as");
3994                                 uc_compiler_parse_consume(compiler, TK_LABEL);
3995 
3996                                 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, true);
3997                                 uc_compiler_initialize_local(compiler);
3998                                 ucv_array_push(namelist, ucv_boolean_new(true));
3999                         }
4000 
4001                         /* error */
4002                         else {
4003                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
4004                                         "Unexpected token\nExpecting '{' or '*'");
4005                         }
4006                 }
4007 
4008                 uc_compiler_keyword_consume(compiler, "from");
4009         }
4010 
4011         uc_compiler_parse_consume(compiler, TK_STRING);
4012 
4013         uc_compiler_compile_module(compiler, ucv_string_get(compiler->parser->prev.uv), namelist);
4014 
4015         uc_compiler_parse_consume(compiler, TK_SCOL);
4016 
4017         ucv_put(namelist);
4018 
4019         return TK_IMPORT;
4020 }
4021 
4022 static uc_tokentype_t
4023 uc_compiler_compile_declaration(uc_compiler_t *compiler)
4024 {
4025         uc_tokentype_t last_statement_type = compiler->parser->curr.type;
4026 
4027         if (uc_compiler_parse_match(compiler, TK_LOCAL))
4028                 uc_compiler_compile_local(compiler);
4029         else if (uc_compiler_parse_match(compiler, TK_CONST))
4030                 uc_compiler_compile_const(compiler);
4031         else if (uc_compiler_parse_match(compiler, TK_EXPORT))
4032                 uc_compiler_compile_export(compiler);
4033         else if (uc_compiler_parse_match(compiler, TK_IMPORT))
4034                 last_statement_type = uc_compiler_compile_import(compiler);
4035         else
4036                 last_statement_type = uc_compiler_compile_statement(compiler);
4037 
4038         if (compiler->parser->synchronizing)
4039                 uc_compiler_parse_synchronize(compiler);
4040 
4041         return last_statement_type;
4042 }
4043 
4044 #endif /* NO_COMPILE */
4045 
4046 
4047 static uc_program_t *
4048 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, uc_program_t *prog, char **errp)
4049 {
4050 #ifdef NO_COMPILE
4051         if (errp)
4052                 xasprintf(errp, "Source code compilation not supported\n");
4053 
4054         return NULL;
4055 #else
4056         bool is_module = (prog != NULL) || (config && config->compile_module);
4057         uc_patchlist_t exports = { .token = TK_EXPORT };
4058         uc_exprstack_t expr = { .token = TK_EOF };
4059         uc_parser_t parser = { .config = config };
4060         uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr };
4061         uc_tokentype_t last_statement_type = TK_NULL;
4062         uc_program_t *progptr;
4063         uc_function_t *fn;
4064         const char *name;
4065 
4066         if (!prog) {
4067                 progptr = uc_program_new();
4068                 name = is_module ? "module" : "main";
4069         }
4070         else {
4071                 progptr = prog;
4072                 name = "module";
4073         }
4074 
4075         uc_lexer_init(&parser.lex, config, source);
4076         uc_compiler_init(&compiler, name, source, 0, progptr,
4077                 config && config->strict_declarations);
4078 
4079         if (is_module) {
4080                 compiler.patchlist = &exports;
4081                 compiler.function->module = true;
4082         }
4083 
4084         uc_compiler_parse_advance(&compiler);
4085 
4086         while (!uc_compiler_parse_match(&compiler, TK_EOF))
4087                 last_statement_type = uc_compiler_compile_declaration(&compiler);
4088 
4089         if (!compiler.function->module && last_statement_type == TK_SCOL) {
4090                 uc_chunk_pop(uc_compiler_current_chunk(&compiler));
4091                 uc_compiler_emit_insn(&compiler, 0, I_RETURN);
4092                 last_statement_type = TK_RETURN;
4093         }
4094 
4095         fn = uc_compiler_finish(&compiler, last_statement_type);
4096 
4097         if (errp) {
4098                 *errp = parser.error ? parser.error->buf : NULL;
4099                 free(parser.error);
4100         }
4101         else {
4102                 printbuf_free(parser.error);
4103         }
4104 
4105         uc_lexer_free(&parser.lex);
4106         uc_vector_clear(&exports);
4107 
4108         if (!fn) {
4109                 if (progptr != prog)
4110                         ucv_put(&progptr->header);
4111 
4112                 return NULL;
4113         }
4114 
4115         return progptr;
4116 #endif
4117 }
4118 
4119 static uc_program_t *
4120 uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp)
4121 {
4122         uc_program_t *prog;
4123 
4124         prog = uc_program_load(source, errp);
4125 
4126         if (prog && !uc_program_entry(prog)) {
4127                 if (errp)
4128                         xasprintf(errp, "Program file contains no entry function\n");
4129 
4130                 ucv_put(&prog->header);
4131         }
4132 
4133         return prog;
4134 }
4135 
4136 uc_program_t *
4137 uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
4138 {
4139         uc_program_t *prog = NULL;
4140 
4141         if (!config)
4142                 config = &uc_default_parse_config;
4143 
4144         switch (uc_source_type_test(source)) {
4145         case UC_SOURCE_TYPE_PLAIN:
4146                 prog = uc_compile_from_source(config, source, NULL, errp);
4147                 break;
4148 
4149         case UC_SOURCE_TYPE_PRECOMPILED:
4150                 prog = uc_compile_from_bytecode(config, source, errp);
4151                 break;
4152 
4153         default:
4154                 if (errp)
4155                         xasprintf(errp, "Unrecognized source type\n");
4156 
4157                 break;
4158         }
4159 
4160         return prog;
4161 }
4162 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt