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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt