• 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_function(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_function, 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, 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, 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 compiler->program->source;
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_stringbuf_t *buf = compiler->parser->error;
173         size_t line = 0, byte = 0, len = 0;
174         va_list ap;
175         char *s;
176 
177         if (compiler->parser->synchronizing)
178                 return;
179 
180         compiler->parser->synchronizing = true;
181 
182         if (!buf)
183                 buf = compiler->parser->error = xprintbuf_new();
184 
185         if (!off)
186                 off = uc_program_function_srcpos(compiler->function,
187                         uc_compiler_current_chunk(compiler)->count);
188 
189         if (off) {
190                 byte = off;
191                 line = uc_source_get_line(uc_compiler_current_source(compiler), &byte);
192         }
193 
194         va_start(ap, fmt);
195         len = xvasprintf(&s, fmt, ap);
196         va_end(ap);
197 
198         ucv_stringbuf_append(buf, "Syntax error: ");
199         ucv_stringbuf_addstr(buf, s, len);
200         ucv_stringbuf_append(buf, "\n");
201 
202         free(s);
203 
204         if (line)
205                 ucv_stringbuf_printf(buf, "In line %zu, byte %zu:\n", line, byte);
206 
207         if (uc_error_context_format(buf, uc_compiler_current_source(compiler), NULL, off))
208                 ucv_stringbuf_append(buf, "\n\n");
209 }
210 
211 static size_t
212 uc_compiler_set_srcpos(uc_compiler_t *compiler, size_t srcpos)
213 {
214         size_t delta;
215 
216         /* ensure that lines counts are strictly increasing */
217         assert(srcpos == 0 || srcpos >= compiler->current_srcpos);
218 
219         delta = srcpos ? srcpos - compiler->current_srcpos : 0;
220         compiler->current_srcpos += delta;
221 
222         return delta;
223 }
224 
225 static void
226 uc_compiler_parse_advance(uc_compiler_t *compiler)
227 {
228         ucv_put(compiler->parser->prev.uv);
229         compiler->parser->prev = compiler->parser->curr;
230 
231         while (true) {
232                 compiler->parser->curr = *uc_lexer_next_token(&compiler->parser->lex);
233 
234                 if (compiler->parser->curr.type != TK_ERROR)
235                         break;
236 
237                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "%s",
238                         ucv_string_get(compiler->parser->curr.uv));
239 
240                 ucv_put(compiler->parser->curr.uv);
241                 compiler->parser->curr.uv = NULL;
242         }
243 }
244 
245 static void
246 uc_compiler_parse_consume(uc_compiler_t *compiler, uc_tokentype_t type)
247 {
248         if (compiler->parser->curr.type == type) {
249                 uc_compiler_parse_advance(compiler);
250 
251                 return;
252         }
253 
254         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
255                 "Unexpected token\nExpecting %s", uc_tokenname(type));
256 }
257 
258 static bool
259 uc_compiler_parse_check(uc_compiler_t *compiler, uc_tokentype_t type)
260 {
261         return (compiler->parser->curr.type == type);
262 }
263 
264 static bool
265 uc_compiler_parse_match(uc_compiler_t *compiler, uc_tokentype_t type)
266 {
267         if (!uc_compiler_parse_check(compiler, type))
268                 return false;
269 
270         uc_compiler_parse_advance(compiler);
271 
272         return true;
273 }
274 
275 static void
276 uc_compiler_parse_synchronize(uc_compiler_t *compiler)
277 {
278         compiler->parser->synchronizing = false;
279 
280         while (compiler->parser->curr.type != TK_EOF) {
281                 if (compiler->parser->prev.type == TK_SCOL)
282                         return;
283 
284                 switch (compiler->parser->curr.type) {
285                 case TK_IF:
286                 case TK_FOR:
287                 case TK_WHILE:
288                 case TK_SWITCH:
289                 case TK_FUNC:
290                 case TK_TRY:
291                 case TK_RETURN:
292                 case TK_BREAK:
293                 case TK_CONTINUE:
294                 case TK_LOCAL:
295                         return;
296 
297                 default:
298                         break;
299                 }
300 
301                 uc_compiler_parse_advance(compiler);
302         }
303 }
304 
305 static uc_parse_rule_t *
306 uc_compiler_parse_rule(uc_tokentype_t type)
307 {
308         return &uc_compiler_parse_rules[type];
309 }
310 
311 static bool
312 uc_compiler_parse_at_assignment_op(uc_compiler_t *compiler)
313 {
314         switch (compiler->parser->curr.type) {
315         case TK_ASBAND:
316         case TK_ASBXOR:
317         case TK_ASBOR:
318         case TK_ASLEFT:
319         case TK_ASRIGHT:
320         case TK_ASMUL:
321         case TK_ASDIV:
322         case TK_ASMOD:
323         case TK_ASADD:
324         case TK_ASSUB:
325         case TK_ASAND:
326         case TK_ASOR:
327         case TK_ASEXP:
328         case TK_ASNULLISH:
329         case TK_ASSIGN:
330                 return true;
331 
332         default:
333                 return false;
334         }
335 }
336 
337 static void
338 uc_compiler_parse_precedence(uc_compiler_t *compiler, uc_precedence_t precedence)
339 {
340         uc_parse_rule_t *rule;
341 
342         rule = uc_compiler_parse_rule(compiler->parser->curr.type);
343 
344         if (!rule->prefix) {
345                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting expression");
346                 uc_compiler_parse_advance(compiler);
347 
348                 return;
349         }
350 
351         uc_compiler_exprstack_push(compiler,
352                 compiler->parser->curr.type,
353                 (precedence <= P_ASSIGN) ? F_ASSIGNABLE : 0);
354 
355         /* allow reserved words as property names in object literals */
356         if (rule->prefix == uc_compiler_compile_object)
357                 compiler->parser->lex.no_keyword = true;
358 
359         /* unless a sub-expression follows, treat subsequent slash as division
360          * operator and not as beginning of regexp literal */
361         if (rule->prefix != uc_compiler_compile_paren &&
362             rule->prefix != uc_compiler_compile_unary &&
363             rule->prefix != uc_compiler_compile_array)
364                 compiler->parser->lex.no_regexp = true;
365 
366         uc_compiler_parse_advance(compiler);
367 
368         rule->prefix(compiler);
369 
370         while (precedence <= uc_compiler_parse_rule(compiler->parser->curr.type)->precedence) {
371                 compiler->exprstack->token = compiler->parser->curr.type;
372 
373                 rule = uc_compiler_parse_rule(compiler->exprstack->token);
374 
375                 if (!rule->infix) {
376                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting ';' or binary operator");
377                         uc_compiler_parse_advance(compiler);
378 
379                         return;
380                 }
381 
382                 /* allow reserved words in property accessors */
383                 if (rule->infix == uc_compiler_compile_dot)
384                         compiler->parser->lex.no_keyword = true;
385 
386                 uc_compiler_parse_advance(compiler);
387 
388                 rule->infix(compiler);
389         }
390 
391         if (uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) && uc_compiler_parse_at_assignment_op(compiler))
392                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, "Invalid left-hand side expression for assignment");
393 
394         uc_compiler_exprstack_pop(compiler);
395 }
396 
397 static size_t
398 uc_compiler_reladdr(uc_compiler_t *compiler, size_t from, size_t to)
399 {
400         ssize_t delta = to - from;
401 
402         if (delta < -0x7fffffff || delta > 0x7fffffff) {
403                 uc_compiler_syntax_error(compiler, 0, "Jump address too far");
404 
405                 return 0;
406         }
407 
408         return (size_t)(delta + 0x7fffffff);
409 }
410 
411 static size_t
412 uc_compiler_emit_insn(uc_compiler_t *compiler, size_t srcpos, uc_vm_insn_t insn)
413 {
414         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
415         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
416 
417         compiler->last_insn = uc_chunk_add(chunk, (uint8_t)insn, lineoff);
418 
419         return compiler->last_insn;
420 }
421 
422 static size_t
423 uc_compiler_emit_u8(uc_compiler_t *compiler, size_t srcpos, uint8_t n)
424 {
425         return uc_chunk_add(
426                 uc_compiler_current_chunk(compiler),
427                 n,
428                 uc_compiler_set_srcpos(compiler, srcpos));
429 }
430 
431 static size_t
432 uc_compiler_emit_u16(uc_compiler_t *compiler, size_t srcpos, uint16_t n)
433 {
434         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
435         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
436 
437         uc_chunk_add(chunk, n / 0x100, lineoff);
438         uc_chunk_add(chunk, n % 0x100, 0);
439 
440         return chunk->count - 2;
441 }
442 
443 static size_t
444 uc_compiler_emit_u32(uc_compiler_t *compiler, size_t srcpos, uint32_t n)
445 {
446         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
447         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
448 
449         uc_chunk_add(chunk, n / 0x1000000, lineoff);
450         uc_chunk_add(chunk, (n / 0x10000) % 0x100, 0);
451         uc_chunk_add(chunk, (n / 0x100) % 0x100, 0);
452         uc_chunk_add(chunk, n % 0x100, 0);
453 
454         return chunk->count - 4;
455 }
456 
457 static size_t
458 uc_compiler_emit_s32(uc_compiler_t *compiler, size_t srcpos, int32_t n)
459 {
460         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
461         size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos);
462         uint32_t v;
463 
464         if (n <= 0)
465                 v = n + 0x7fffffff;
466         else
467                 v = (uint32_t)n + 0x7fffffff;
468 
469         uc_chunk_add(chunk, v / 0x1000000, lineoff);
470         uc_chunk_add(chunk, (v / 0x10000) % 0x100, 0);
471         uc_chunk_add(chunk, (v / 0x100) % 0x100, 0);
472         uc_chunk_add(chunk, v % 0x100, 0);
473 
474         return chunk->count - 4;
475 }
476 
477 static uint32_t
478 uc_compiler_get_u32(uc_compiler_t *compiler, size_t off)
479 {
480         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
481 
482         return chunk->entries[off + 0] * 0x1000000 +
483                chunk->entries[off + 1] * 0x10000 +
484                chunk->entries[off + 2] * 0x100 +
485                chunk->entries[off + 3];
486 }
487 
488 static void
489 uc_compiler_set_u32(uc_compiler_t *compiler, size_t off, uint32_t n)
490 {
491         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
492 
493         chunk->entries[off + 0] = n / 0x1000000;
494         chunk->entries[off + 1] = (n / 0x10000) % 0x100;
495         chunk->entries[off + 2] = (n / 0x100) % 0x100;
496         chunk->entries[off + 3] = n % 0x100;
497 }
498 
499 static size_t
500 uc_compiler_emit_constant(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
501 {
502         size_t cidx = uc_program_add_constant(compiler->program, val);
503 
504         uc_compiler_emit_insn(compiler, srcpos, I_LOAD);
505         uc_compiler_emit_u32(compiler, 0, cidx);
506 
507         return cidx;
508 }
509 
510 static size_t
511 uc_compiler_emit_regexp(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val)
512 {
513         size_t cidx = uc_program_add_constant(compiler->program, val);
514 
515         uc_compiler_emit_insn(compiler, srcpos, I_LREXP);
516         uc_compiler_emit_u32(compiler, 0, cidx);
517 
518         return cidx;
519 }
520 
521 static size_t
522 uc_compiler_emit_jmp(uc_compiler_t *compiler, size_t srcpos)
523 {
524         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
525 
526         uc_compiler_emit_insn(compiler, srcpos, I_JMP);
527         uc_compiler_emit_u32(compiler, 0, 0);
528 
529         return chunk->count - 5;
530 }
531 
532 static size_t
533 uc_compiler_emit_jmpz(uc_compiler_t *compiler, size_t srcpos)
534 {
535         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
536 
537         uc_compiler_emit_insn(compiler, srcpos, I_JMPZ);
538         uc_compiler_emit_u32(compiler, 0, 0);
539 
540         return chunk->count - 5;
541 }
542 
543 static size_t
544 uc_compiler_emit_jmp_dest(uc_compiler_t *compiler, size_t srcpos, uint32_t dest)
545 {
546         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
547 
548         uc_compiler_emit_insn(compiler, srcpos, I_JMP);
549         uc_compiler_emit_u32(compiler, 0, uc_compiler_reladdr(compiler, chunk->count - 1, dest));
550 
551         return chunk->count - 5;
552 }
553 
554 static ssize_t
555 uc_compiler_get_jmpaddr(uc_compiler_t *compiler, size_t off)
556 {
557         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
558 
559         assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ);
560         assert(off + 4 < chunk->count);
561 
562         return (
563                 chunk->entries[off + 1] * 0x1000000UL +
564                 chunk->entries[off + 2] * 0x10000UL +
565                 chunk->entries[off + 3] * 0x100UL +
566                 chunk->entries[off + 4]
567         ) - 0x7fffffff;
568 }
569 
570 static void
571 uc_compiler_set_jmpaddr(uc_compiler_t *compiler, size_t off, uint32_t dest)
572 {
573         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
574         size_t addr = uc_compiler_reladdr(compiler, off, dest);
575 
576         assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ);
577         assert(off + 4 < chunk->count);
578 
579         chunk->entries[off + 1] = addr / 0x1000000;
580         chunk->entries[off + 2] = (addr / 0x10000) % 0x100;
581         chunk->entries[off + 3] = (addr / 0x100) % 0x100;
582         chunk->entries[off + 4] = addr % 0x100;
583 }
584 
585 static uc_function_t *
586 uc_compiler_finish(uc_compiler_t *compiler)
587 {
588         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
589         uc_locals_t *locals = &compiler->locals;
590         uc_upvals_t *upvals = &compiler->upvals;
591         size_t i;
592 
593         uc_compiler_emit_insn(compiler, 0, I_LNULL);
594         uc_compiler_emit_insn(compiler, 0, I_RETURN);
595 
596         for (i = 0; i < locals->count; i++) {
597                 uc_chunk_debug_add_variable(chunk,
598                         locals->entries[i].from,
599                         chunk->count,
600                         i,
601                         false,
602                         locals->entries[i].name);
603 
604                 ucv_put(locals->entries[i].name);
605         }
606 
607         for (i = 0; i < upvals->count; i++) {
608                 uc_chunk_debug_add_variable(chunk,
609                         0,
610                         chunk->count,
611                         i,
612                         true,
613                         upvals->entries[i].name);
614 
615                 ucv_put(upvals->entries[i].name);
616         }
617 
618         uc_vector_clear(locals);
619         uc_vector_clear(upvals);
620 
621         if (compiler->parser->error) {
622                 uc_program_function_free(compiler->function);
623 
624                 return NULL;
625         }
626 
627         return compiler->function;
628 }
629 
630 static void
631 uc_compiler_enter_scope(uc_compiler_t *compiler)
632 {
633         compiler->scope_depth++;
634 }
635 
636 static void
637 uc_compiler_leave_scope(uc_compiler_t *compiler)
638 {
639         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
640         uc_locals_t *locals = &compiler->locals;
641 
642         compiler->scope_depth--;
643 
644         while (locals->count > 0 && locals->entries[locals->count - 1].depth > (ssize_t)compiler->scope_depth) {
645                 locals->count--;
646 
647                 uc_chunk_debug_add_variable(chunk,
648                         locals->entries[locals->count].from,
649                         chunk->count,
650                         locals->count,
651                         false,
652                         locals->entries[locals->count].name);
653 
654                 ucv_put(locals->entries[locals->count].name);
655                 locals->entries[locals->count].name = NULL;
656 
657                 uc_compiler_emit_insn(compiler, 0,
658                         locals->entries[locals->count].captured ? I_CUPV : I_POP);
659         }
660 }
661 
662 static bool
663 uc_compiler_is_strict(uc_compiler_t *compiler)
664 {
665         uc_function_t *fn = (uc_function_t *)compiler->function;
666 
667         return fn->strict;
668 }
669 
670 static ssize_t
671 uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool constant)
672 {
673         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
674         uc_locals_t *locals = &compiler->locals;
675         const char *str1, *str2;
676         size_t i, len1, len2;
677 
678         if (locals->count >= 0x00FFFFFF) {
679                 uc_compiler_syntax_error(compiler, 0, "Too many local variables");
680 
681                 return -1;
682         }
683 
684         str1 = ucv_string_get(name);
685         len1 = ucv_string_length(name);
686 
687         for (i = locals->count; i > 0; i--) {
688                 if (locals->entries[i - 1].depth != -1 && locals->entries[i - 1].depth < (ssize_t)compiler->scope_depth)
689                         break;
690 
691                 str2 = ucv_string_get(locals->entries[i - 1].name);
692                 len2 = ucv_string_length(locals->entries[i - 1].name);
693 
694                 if (len1 == len2 && !strcmp(str1, str2)) {
695                         if (uc_compiler_is_strict(compiler)) {
696                                 uc_compiler_syntax_error(compiler, 0, "Variable '%s' redeclared", str2);
697 
698                                 return -1;
699                         }
700 
701                         return i - 1;
702                 }
703         }
704 
705         uc_vector_grow(locals);
706 
707         locals->entries[locals->count].name = ucv_get(name);
708         locals->entries[locals->count].depth = -1;
709         locals->entries[locals->count].captured = false;
710         locals->entries[locals->count].from = chunk->count;
711         locals->entries[locals->count].constant = constant;
712         locals->count++;
713 
714         return -1;
715 }
716 
717 static ssize_t
718 uc_compiler_initialize_local(uc_compiler_t *compiler)
719 {
720         uc_locals_t *locals = &compiler->locals;
721 
722         locals->entries[locals->count - 1].depth = compiler->scope_depth;
723 
724         return locals->count - 1;
725 }
726 
727 static ssize_t
728 uc_compiler_resolve_local(uc_compiler_t *compiler, uc_value_t *name, bool *constant)
729 {
730         uc_locals_t *locals = &compiler->locals;
731         const char *str1, *str2;
732         size_t i, len1, len2;
733 
734         str1 = ucv_string_get(name);
735         len1 = ucv_string_length(name);
736 
737         for (i = locals->count; i > 0; i--) {
738                 str2 = ucv_string_get(locals->entries[i - 1].name);
739                 len2 = ucv_string_length(locals->entries[i - 1].name);
740 
741                 if (len1 != len2 || strcmp(str1, str2))
742                         continue;
743 
744                 if (locals->entries[i - 1].depth == -1) {
745                         uc_compiler_syntax_error(compiler, 0,
746                                 "Can't access lexical declaration '%s' before initialization", str2);
747 
748                         return -1;
749                 }
750 
751                 *constant = locals->entries[i - 1].constant;
752 
753                 return i - 1;
754         }
755 
756         return -1;
757 }
758 
759 static ssize_t
760 uc_compiler_add_upval(uc_compiler_t *compiler, size_t idx, bool local, uc_value_t *name, bool constant)
761 {
762         uc_function_t *function = (uc_function_t *)compiler->function;
763         uc_upvals_t *upvals = &compiler->upvals;
764         uc_upval_t *uv;
765         size_t i;
766 
767         for (i = 0, uv = upvals->entries; i < upvals->count; i++, uv = upvals->entries + i)
768                 if (uv->index == idx && uv->local == local)
769                         return i;
770 
771         /* XXX: encoding... */
772         if (upvals->count >= (2 << 14)) {
773                 uc_compiler_syntax_error(compiler, 0, "Too many upvalues");
774 
775                 return -1;
776         }
777 
778         uc_vector_grow(upvals);
779 
780         upvals->entries[upvals->count].local = local;
781         upvals->entries[upvals->count].index = idx;
782         upvals->entries[upvals->count].name  = ucv_get(name);
783         upvals->entries[upvals->count].constant = constant;
784 
785         function->nupvals++;
786 
787         return upvals->count++;
788 }
789 
790 static ssize_t
791 uc_compiler_resolve_upval(uc_compiler_t *compiler, uc_value_t *name, bool *constant)
792 {
793         ssize_t idx;
794 
795         if (!compiler->parent)
796                 return -1;
797 
798         idx = uc_compiler_resolve_local(compiler->parent, name, constant);
799 
800         if (idx > -1) {
801                 compiler->parent->locals.entries[idx].captured = true;
802 
803                 return uc_compiler_add_upval(compiler, idx, true, name, *constant);
804         }
805 
806         idx = uc_compiler_resolve_upval(compiler->parent, name, constant);
807 
808         if (idx > -1)
809                 return uc_compiler_add_upval(compiler, idx, false, name, *constant);
810 
811         return -1;
812 }
813 
814 static void
815 uc_compiler_backpatch(uc_compiler_t *compiler, size_t break_addr, size_t next_addr)
816 {
817         uc_patchlist_t *pl = compiler->patchlist;
818         uc_patchlist_t *pp = pl->parent;
819         volatile ssize_t jmpaddr;
820         size_t i;
821 
822         for (i = 0; i < pl->count; i++) {
823                 jmpaddr = uc_compiler_get_jmpaddr(compiler, pl->entries[i]);
824 
825                 switch (jmpaddr) {
826                 case TK_BREAK:
827                         /* if we have a break addr, patch instruction */
828                         if (break_addr) {
829                                 uc_compiler_set_jmpaddr(compiler, pl->entries[i], break_addr);
830                                 continue;
831                         }
832 
833                         break;
834 
835                 case TK_CONTINUE:
836                         /* if we have a continue addr, patch instruction */
837                         if (next_addr) {
838                                 uc_compiler_set_jmpaddr(compiler, pl->entries[i], next_addr);
839                                 continue;
840                         }
841 
842                         break;
843                 }
844 
845                 /* propagate unhandled patch instructions to parent patch list */
846                 if (pp) {
847                         uc_vector_grow(pp);
848                         pp->entries[pp->count++] = pl->entries[i];
849                 }
850         }
851 
852         free(pl->entries);
853 
854         compiler->patchlist = pl->parent;
855 }
856 
857 static void
858 uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool is_postfix)
859 {
860         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
861         uc_value_t *varname = NULL;
862         uc_vm_insn_t type;
863         uint32_t cidx = 0;
864         int insn;
865 
866         /* determine kind of emitted load instruction and operand value (if any) */
867         type = chunk->entries ? chunk->entries[compiler->last_insn] : 0;
868 
869         if (type == I_LVAR || type == I_LLOC || type == I_LUPV) {
870                 cidx = uc_compiler_get_u32(compiler, compiler->last_insn + 1);
871 
872                 if (type == I_LLOC && compiler->locals.entries[cidx].constant)
873                         varname = compiler->locals.entries[cidx].name;
874                 else if (type == I_LUPV && compiler->upvals.entries[cidx].constant)
875                         varname = compiler->upvals.entries[cidx].name;
876 
877                 if (varname)
878                         uc_compiler_syntax_error(compiler, 0,
879                                 "Invalid increment/decrement of constant '%s'",
880                                 ucv_string_get(varname));
881 
882                 uc_chunk_pop(chunk);
883                 uc_chunk_pop(chunk);
884                 uc_chunk_pop(chunk);
885                 uc_chunk_pop(chunk);
886                 uc_chunk_pop(chunk);
887         }
888 
889         /* if we're mutating an object or array field, pop the last lval instruction
890          * to leave object + last field name value on stack */
891         else if (type == I_LVAL && !uc_compiler_exprstack_is(compiler, F_OPTCHAINING)) {
892                 uc_chunk_pop(chunk);
893         }
894         else {
895                 uc_compiler_syntax_error(compiler, 0, "Invalid increment/decrement operand");
896 
897                 return;
898         }
899 
900         insn = (toktype == TK_INC) ? I_PLUS : I_MINUS;
901 
902         /* add / substract 1 */
903         uc_compiler_emit_insn(compiler, 0, I_LOAD8);
904         uc_compiler_emit_u8(compiler, 0, 1);
905 
906         /* depending on variable type, emit corresponding increment instruction */
907         switch (type) {
908         case I_LVAR:
909                 uc_compiler_emit_insn(compiler, 0, I_UVAR);
910                 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
911                 break;
912 
913         case I_LLOC:
914                 uc_compiler_emit_insn(compiler, 0, I_ULOC);
915                 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
916                 break;
917 
918         case I_LUPV:
919                 uc_compiler_emit_insn(compiler, 0, I_UUPV);
920                 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx);
921                 break;
922 
923         case I_LVAL:
924                 uc_compiler_emit_insn(compiler, 0, I_UVAL);
925                 uc_compiler_emit_u8(compiler, 0, insn);
926                 break;
927 
928         default:
929                 break;
930         }
931 
932         /* for post increment or decrement, add/substract 1 to yield final value */
933         if (is_postfix) {
934                 uc_compiler_emit_insn(compiler, 0, I_LOAD8);
935                 uc_compiler_emit_u8(compiler, 0, 1);
936 
937                 uc_compiler_emit_insn(compiler, 0, (toktype == TK_INC) ? I_SUB : I_ADD);
938         }
939 }
940 
941 
942 static void
943 uc_compiler_compile_unary(uc_compiler_t *compiler)
944 {
945         uc_tokentype_t type = compiler->parser->prev.type;
946 
947         uc_compiler_parse_precedence(compiler, P_UNARY);
948 
949         switch (type) {
950         case TK_SUB:
951                 uc_compiler_emit_insn(compiler, 0, I_MINUS);
952                 break;
953 
954         case TK_ADD:
955                 uc_compiler_emit_insn(compiler, 0, I_PLUS);
956                 break;
957 
958         case TK_NOT:
959                 uc_compiler_emit_insn(compiler, 0, I_NOT);
960                 break;
961 
962         case TK_COMPL:
963                 uc_compiler_emit_insn(compiler, 0, I_COMPL);
964                 break;
965 
966         case TK_INC:
967         case TK_DEC:
968                 uc_compiler_emit_inc_dec(compiler, type, false);
969                 break;
970 
971         default:
972                 return;
973         }
974 }
975 
976 static void
977 uc_compiler_compile_binary(uc_compiler_t *compiler)
978 {
979         uc_tokentype_t type = compiler->parser->prev.type;
980 
981         uc_compiler_parse_precedence(compiler, uc_compiler_parse_rule(type)->precedence + 1);
982         uc_compiler_emit_insn(compiler, 0, I_BOR + (type - TK_BOR));
983 }
984 
985 static void
986 uc_compiler_compile_delete(uc_compiler_t *compiler)
987 {
988         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
989         uc_vm_insn_t type;
990 
991         uc_compiler_parse_precedence(compiler, P_UNARY);
992 
993         type = chunk->entries[compiler->last_insn];
994 
995         if (type != I_LVAL)
996                 uc_compiler_syntax_error(compiler, 0,
997                         "expecting a property access expression");
998 
999         chunk->entries[compiler->last_insn] = I_DELETE;
1000 }
1001 
1002 static uc_vm_insn_t
1003 uc_compiler_emit_variable_rw(uc_compiler_t *compiler, uc_value_t *varname, uc_tokentype_t type)
1004 {
1005         uc_vm_insn_t insn;
1006         uint32_t sub_insn;
1007         bool constant;
1008         ssize_t idx;
1009 
1010         switch (type) {
1011         case TK_ASADD:     sub_insn = I_ADD;     break;
1012         case TK_ASSUB:     sub_insn = I_SUB;     break;
1013         case TK_ASMUL:     sub_insn = I_MUL;     break;
1014         case TK_ASDIV:     sub_insn = I_DIV;     break;
1015         case TK_ASMOD:     sub_insn = I_MOD;     break;
1016         case TK_ASBAND:    sub_insn = I_BAND;    break;
1017         case TK_ASBXOR:    sub_insn = I_BXOR;    break;
1018         case TK_ASBOR:     sub_insn = I_BOR;     break;
1019         case TK_ASLEFT:    sub_insn = I_LSHIFT;  break;
1020         case TK_ASRIGHT:   sub_insn = I_RSHIFT;  break;
1021         case TK_ASAND:     sub_insn = I_LTRUE;   break;
1022         case TK_ASOR:      sub_insn = I_LFALSE;  break;
1023         case TK_ASEXP:     sub_insn = I_EXP;     break;
1024         case TK_ASNULLISH: sub_insn = I_LNULL;   break;
1025         default:           sub_insn = 0;         break;
1026         }
1027 
1028         if (!varname) {
1029                 if (sub_insn != 0)
1030                         insn = I_UVAL;
1031                 else if (type == TK_QDOT || type == TK_QLBRACK)
1032                         insn = I_QLVAL;
1033                 else if (type != 0)
1034                         insn = I_SVAL;
1035                 else
1036                         insn = I_LVAL;
1037 
1038                 if ((insn == I_UVAL || insn == I_SVAL) && uc_compiler_exprstack_is(compiler, F_OPTCHAINING))
1039                         uc_compiler_syntax_error(compiler, 0,
1040                                 "Invalid left-hand side expression for assignment");
1041 
1042                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1043 
1044                 if (sub_insn)
1045                         uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, sub_insn);
1046         }
1047         else if ((idx = uc_compiler_resolve_local(compiler, varname, &constant)) > -1) {
1048                 insn = sub_insn ? I_ULOC : (type ? I_SLOC : I_LLOC);
1049 
1050                 if (insn != I_LLOC && constant)
1051                         uc_compiler_syntax_error(compiler, 0,
1052                                 "Invalid assignment to constant '%s'", ucv_string_get(varname));
1053 
1054                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1055                 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos,
1056                         ((sub_insn & 0xff) << 24) | idx);
1057         }
1058         else if ((idx = uc_compiler_resolve_upval(compiler, varname, &constant)) > -1) {
1059                 insn = sub_insn ? I_UUPV : (type ? I_SUPV : I_LUPV);
1060 
1061                 if (insn != I_LUPV && constant)
1062                         uc_compiler_syntax_error(compiler, 0,
1063                                 "Invalid assignment to constant '%s'", ucv_string_get(varname));
1064 
1065                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1066                 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos,
1067                         ((sub_insn & 0xff) << 24) | idx);
1068         }
1069         else {
1070                 idx = uc_program_add_constant(compiler->program, varname);
1071                 insn = sub_insn ? I_UVAR : (type ? I_SVAR : I_LVAR);
1072 
1073                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn);
1074                 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos,
1075                         ((sub_insn & 0xff) << 24) | idx);
1076         }
1077 
1078         return insn;
1079 }
1080 
1081 static void
1082 uc_compiler_compile_expression(uc_compiler_t *compiler)
1083 {
1084         uc_compiler_parse_precedence(compiler, P_COMMA);
1085 }
1086 
1087 static bool
1088 uc_compiler_compile_assignment(uc_compiler_t *compiler, uc_value_t *var)
1089 {
1090         uc_tokentype_t type = compiler->parser->curr.type;
1091 
1092         if (uc_compiler_parse_at_assignment_op(compiler)) {
1093                 uc_compiler_parse_advance(compiler);
1094                 uc_compiler_parse_precedence(compiler, P_ASSIGN);
1095                 uc_compiler_emit_variable_rw(compiler, var, type);
1096 
1097                 return true;
1098         }
1099 
1100         return false;
1101 }
1102 
1103 static bool
1104 uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool restarg)
1105 {
1106         bool array = (ucv_type(args) == UC_ARRAY);
1107         uc_compiler_t fncompiler = { 0 };
1108         size_t i, pos, load_off;
1109         uc_function_t *fn;
1110         ssize_t slot;
1111 
1112         if (!uc_compiler_parse_match(compiler, TK_ARROW))
1113                 return false;
1114 
1115         pos = compiler->parser->prev.pos;
1116 
1117         uc_compiler_init(&fncompiler, NULL, compiler->parser->prev.pos,
1118                 compiler->program,
1119                 uc_compiler_is_strict(compiler));
1120 
1121         fncompiler.parent = compiler;
1122         fncompiler.parser = compiler->parser;
1123         fncompiler.exprstack = compiler->exprstack;
1124 
1125         fn = (uc_function_t *)fncompiler.function;
1126         fn->arrow = true;
1127         fn->vararg = args ? restarg : false;
1128         fn->nargs = array ? ucv_array_length(args) : !!args;
1129 
1130         uc_compiler_enter_scope(&fncompiler);
1131 
1132         /* declare local variables for arguments */
1133         for (i = 0; i < fn->nargs; i++) {
1134                 slot = uc_compiler_declare_local(&fncompiler,
1135                         array ? ucv_array_get(args, i) : args, false);
1136 
1137                 if (slot != -1)
1138                         uc_compiler_syntax_error(&fncompiler, pos,
1139                                 "Duplicate argument names are not allowed in this context");
1140 
1141                 uc_compiler_initialize_local(&fncompiler);
1142         }
1143 
1144         /* parse and compile body */
1145         if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) {
1146                 while (!uc_compiler_parse_check(&fncompiler, TK_RBRACE) &&
1147                        !uc_compiler_parse_check(&fncompiler, TK_EOF))
1148                         uc_compiler_compile_declaration(&fncompiler);
1149 
1150                 uc_compiler_parse_consume(&fncompiler, TK_RBRACE);
1151 
1152                 /* overwrite last pop result with return */
1153                 if (fn->chunk.count) {
1154                         uc_chunk_pop(&fn->chunk);
1155                         uc_compiler_emit_insn(&fncompiler, 0, I_RETURN);
1156                 }
1157         }
1158         else {
1159                 uc_compiler_parse_precedence(&fncompiler, P_ASSIGN);
1160                 uc_compiler_emit_insn(&fncompiler, 0, I_RETURN);
1161         }
1162 
1163         /* emit load instruction for function value */
1164         uc_compiler_emit_insn(compiler, pos, I_ARFN);
1165         load_off = uc_compiler_emit_u32(compiler, 0, 0);
1166 
1167         /* encode upvalue information */
1168         for (i = 0; i < fn->nupvals; i++)
1169                 uc_compiler_emit_s32(compiler, 0,
1170                         fncompiler.upvals.entries[i].local
1171                                 ? -(fncompiler.upvals.entries[i].index + 1)
1172                                 : fncompiler.upvals.entries[i].index);
1173 
1174         /* finalize function compiler */
1175         fn = uc_compiler_finish(&fncompiler);
1176 
1177         if (fn)
1178                 uc_compiler_set_u32(compiler, load_off,
1179                         uc_program_function_id(compiler->program, fn));
1180 
1181         return true;
1182 }
1183 
1184 static uc_tokentype_t
1185 uc_compiler_compile_var_or_arrowfn(uc_compiler_t *compiler, uc_value_t *name)
1186 {
1187         uc_tokentype_t rv;
1188 
1189         if (uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) && uc_compiler_compile_assignment(compiler, name)) {
1190                 rv = TK_ASSIGN;
1191         }
1192         else if (uc_compiler_compile_arrowfn(compiler, name, false)) {
1193                 rv = TK_ARROW;
1194         }
1195         else {
1196                 uc_compiler_emit_variable_rw(compiler, name, 0);
1197                 rv = TK_LABEL;
1198         }
1199 
1200         return rv;
1201 }
1202 
1203 static void
1204 uc_compiler_compile_paren(uc_compiler_t *compiler)
1205 {
1206         uc_value_t *varnames = NULL, *varname;
1207         bool maybe_arrowfn = false;
1208         bool restarg = false;
1209 
1210         /* First try to parse a complete parameter expression and remember the
1211          * consumed label tokens as we go. */
1212         while (true) {
1213                 if (uc_compiler_parse_check(compiler, TK_LABEL)) {
1214                         if (!varnames)
1215                                 varnames = ucv_array_new(NULL);
1216 
1217                         ucv_array_push(varnames, ucv_get(compiler->parser->curr.uv));
1218 
1219                         /* A subsequent slash cannot be a regular expression literal */
1220                         compiler->parser->lex.no_regexp = true;
1221                         uc_compiler_parse_advance(compiler);
1222                 }
1223                 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
1224                         uc_compiler_parse_consume(compiler, TK_LABEL);
1225 
1226                         if (!varnames)
1227                                 varnames = ucv_array_new(NULL);
1228 
1229                         ucv_array_push(varnames, ucv_get(compiler->parser->prev.uv));
1230 
1231                         /* A subsequent slash cannot be a regular expression literal */
1232                         compiler->parser->lex.no_regexp = true;
1233                         uc_compiler_parse_consume(compiler, TK_RPAREN);
1234 
1235                         maybe_arrowfn = true;
1236                         restarg = true;
1237 
1238                         break;
1239                 }
1240                 else if (uc_compiler_parse_check(compiler, TK_COMMA)) {
1241                         /* Reject consecutive commas */
1242                         if (compiler->parser->prev.type == TK_COMMA)
1243                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
1244                                         "Expecting expression");
1245 
1246                         uc_compiler_parse_advance(compiler);
1247 
1248                         continue;
1249                 }
1250                 else {
1251                         maybe_arrowfn = uc_compiler_parse_check(compiler, TK_RPAREN);
1252 
1253                         if (maybe_arrowfn) {
1254                                 /* A subsequent slash cannot be a regular expression literal */
1255                                 compiler->parser->lex.no_regexp = true;
1256                                 uc_compiler_parse_advance(compiler);
1257                         }
1258 
1259                         /* If we encouter a dot, treat potential subsequent keyword as label */
1260                         if (uc_compiler_parse_check(compiler, TK_DOT) ||
1261                             uc_compiler_parse_check(compiler, TK_QDOT))
1262                                 compiler->parser->lex.no_keyword = true;
1263 
1264                         break;
1265                 }
1266         }
1267 
1268         /* The lhs we parsed so far is elligible for an arrow function arg list,
1269          * try to continue compiling into arrow function... */
1270         if (maybe_arrowfn) {
1271                 /* If we can parse the remainder as arrow function, we're done */
1272                 if (uc_compiler_compile_arrowfn(compiler, varnames, restarg))
1273                         goto out;
1274 
1275                 /* ... otherwise disallow the `...` spread operator and empty
1276                  * parenthesized expressions */
1277                 if (restarg || !varnames) {
1278                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1279                                 "Expecting '=>' after parameter list");
1280 
1281                         goto out;
1282                 }
1283         }
1284 
1285         /* If we reach this, the expression we parsed so far cannot be a parameter
1286          * list for an arrow function and we might have consumed one or multiple
1287          * consecutive labels. */
1288         if (varnames) {
1289                 /* Get last variable name */
1290                 varname = ucv_array_get(varnames,
1291                         ucv_array_length(varnames) - 1);
1292 
1293                 /* If we consumed the right paren, the expression is complete and we
1294                  * only need to emit a variable read operation for the last parsed
1295                  * label since previous read operations are shadowed by subsequent ones
1296                  * in comma expressions and since pure variable reads are without
1297                  * side effects. */
1298                 if (maybe_arrowfn) {
1299                         uc_compiler_emit_variable_rw(compiler, varname, 0);
1300 
1301                         goto out;
1302                 }
1303 
1304                 /* ... otherwise if the last token was a label, try continue parsing as
1305                  * assignment or arrow function expression and if that fails, as
1306                  * relational one */
1307                 if (compiler->parser->prev.type == TK_LABEL) {
1308                         uc_compiler_exprstack_push(compiler, TK_LABEL, F_ASSIGNABLE);
1309 
1310                         if (uc_compiler_compile_var_or_arrowfn(compiler, varname) == TK_LABEL) {
1311                                 /* parse operand and rhs */
1312                                 while (P_TERNARY <= uc_compiler_parse_rule(compiler->parser->curr.type)->precedence) {
1313                                         uc_compiler_parse_advance(compiler);
1314                                         uc_compiler_parse_rule(compiler->parser->prev.type)->infix(compiler);
1315                                 }
1316                         }
1317 
1318                         /* If we're not at the end of the expression, we require a comma.
1319                          * Also pop intermediate result in this case. */
1320                         if (!uc_compiler_parse_check(compiler, TK_RPAREN)) {
1321                                 uc_compiler_emit_insn(compiler, 0, I_POP);
1322                                 uc_compiler_parse_consume(compiler, TK_COMMA);
1323                         }
1324 
1325                         uc_compiler_exprstack_pop(compiler);
1326                 }
1327         }
1328 
1329         /* When we reach this point, all already complete expression possibilities
1330          * have been eliminated and we either need to compile the next, non-label
1331          * expression or reached the closing paren. If neither applies, we have a
1332          * syntax error. */
1333         if (!uc_compiler_parse_check(compiler, TK_RPAREN))
1334                 uc_compiler_compile_expression(compiler);
1335 
1336         /* A subsequent slash cannot be a regular expression literal */
1337         compiler->parser->lex.no_regexp = true;
1338 
1339         /* At this point we expect the end of the parenthesized expression, anything
1340          * else is a syntax error */
1341         uc_compiler_parse_consume(compiler, TK_RPAREN);
1342 
1343 out:
1344         ucv_put(varnames);
1345 }
1346 
1347 static void
1348 uc_compiler_compile_call(uc_compiler_t *compiler)
1349 {
1350         bool optional_chaining = (compiler->parser->prev.type == TK_QLPAREN);
1351         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1352         uc_jmplist_t spreads = { 0 };
1353         uc_vm_insn_t type;
1354         size_t i, nargs = 0;
1355 
1356         /* flag optional chaining usage in current expression */
1357         compiler->exprstack->flags |= optional_chaining ? F_OPTCHAINING : 0;
1358 
1359         /* determine the kind of the lhs */
1360         type = chunk->entries[compiler->last_insn];
1361 
1362         /* if lhs is a dot or bracket expression, pop the LVAL instruction */
1363         if (type == I_LVAL || type == I_QLVAL)
1364                 uc_chunk_pop(chunk);
1365 
1366         /* compile arguments */
1367         if (!uc_compiler_parse_check(compiler, TK_RPAREN)) {
1368                 do {
1369                         /* if this is a spread arg, remember the argument index */
1370                         if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
1371                                 uc_vector_grow(&spreads);
1372                                 spreads.entries[spreads.count++] = nargs;
1373                         }
1374 
1375                         /* compile argument expression */
1376                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1377                         nargs++;
1378                 }
1379                 while (uc_compiler_parse_match(compiler, TK_COMMA));
1380         }
1381 
1382         /* after a function call expression, no regexp literal can follow */
1383         compiler->parser->lex.no_regexp = true;
1384         uc_compiler_parse_consume(compiler, TK_RPAREN);
1385 
1386         /* if lhs is a dot or bracket expression, emit a method call */
1387         if (type == I_LVAL || type == I_QLVAL)
1388                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, optional_chaining ? I_QMCALL : I_MCALL);
1389         /* else ordinary call */
1390         else
1391                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, optional_chaining ? I_QCALL : I_CALL);
1392 
1393         if (nargs > 0xffff || spreads.count > 0xffff)
1394                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1395                         "Too many function call arguments");
1396 
1397         /* encode ordinary (low 16 bit) and spread argument (high 16 bit) count */
1398         uc_compiler_emit_u32(compiler, 0, ((spreads.count & 0xffff) << 16) | nargs);
1399 
1400         /* encode spread arg positions */
1401         for (i = 0; i < spreads.count; i++)
1402                 uc_compiler_emit_u16(compiler, 0, nargs - spreads.entries[i] - 1);
1403 
1404         uc_vector_clear(&spreads);
1405 }
1406 
1407 static void
1408 uc_compiler_compile_post_inc(uc_compiler_t *compiler)
1409 {
1410         uc_compiler_emit_inc_dec(compiler, compiler->parser->prev.type, true);
1411 }
1412 
1413 static bool
1414 uc_compiler_is_use_strict_pragma(uc_compiler_t *compiler)
1415 {
1416         uc_value_t *v;
1417 
1418         if (uc_compiler_current_chunk(compiler)->count > 0)
1419                 return false;
1420 
1421         if (compiler->parser->lex.block != STATEMENTS)
1422                 return false;
1423 
1424         v = compiler->parser->prev.uv;
1425 
1426         return (strcmp(ucv_string_get(v), "use strict") == 0);
1427 }
1428 
1429 static void
1430 uc_compiler_compile_constant(uc_compiler_t *compiler)
1431 {
1432         uc_function_t *fn;
1433         uint64_t u;
1434 
1435         switch (compiler->parser->prev.type) {
1436         case TK_THIS:
1437                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LTHIS);
1438                 break;
1439 
1440         case TK_NULL:
1441                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
1442                 break;
1443 
1444         case TK_TRUE:
1445                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LTRUE);
1446                 break;
1447 
1448         case TK_FALSE:
1449                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LFALSE);
1450                 break;
1451 
1452         case TK_STRING:
1453                 if (uc_compiler_is_use_strict_pragma(compiler)) {
1454                         fn = (uc_function_t *)compiler->function;
1455                         fn->strict = true;
1456                 }
1457 
1458                 /* fall through */
1459 
1460         case TK_DOUBLE:
1461                 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1462                 break;
1463 
1464         case TK_REGEXP:
1465                 uc_compiler_emit_regexp(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1466                 break;
1467 
1468         case TK_NUMBER:
1469                 u = ucv_uint64_get(compiler->parser->prev.uv);
1470                 assert(errno == 0);
1471 
1472                 if (u <= 0xff) {
1473                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD8);
1474                         uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, u);
1475                 }
1476                 else if (u <= 0xffff) {
1477                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD16);
1478                         uc_compiler_emit_u16(compiler, compiler->parser->prev.pos, u);
1479                 }
1480                 else if (u <= 0xffffffff) {
1481                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD32);
1482                         uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, u);
1483                 }
1484                 else {
1485                         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1486                 }
1487 
1488                 break;
1489 
1490         default:
1491                 break;
1492         }
1493 }
1494 
1495 static void
1496 uc_compiler_compile_template(uc_compiler_t *compiler)
1497 {
1498         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1499 
1500         while (true) {
1501                 if (uc_compiler_parse_match(compiler, TK_TEMPLATE)) {
1502                         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1503                         uc_compiler_emit_insn(compiler, 0, I_ADD);
1504                 }
1505                 else if (uc_compiler_parse_match(compiler, TK_PLACEH)) {
1506                         uc_compiler_compile_expression(compiler);
1507                         uc_compiler_emit_insn(compiler, 0, I_ADD);
1508                         uc_compiler_parse_consume(compiler, TK_RBRACE);
1509                 }
1510                 else {
1511                         break;
1512                 }
1513         }
1514 }
1515 
1516 static void
1517 uc_compiler_compile_comma(uc_compiler_t *compiler)
1518 {
1519         uc_compiler_emit_insn(compiler, 0, I_POP);
1520         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1521 }
1522 
1523 static void
1524 uc_compiler_compile_labelexpr(uc_compiler_t *compiler)
1525 {
1526         uc_value_t *label = ucv_get(compiler->parser->prev.uv);
1527 
1528         uc_compiler_compile_var_or_arrowfn(compiler, label);
1529         ucv_put(label);
1530 }
1531 
1532 static bool
1533 uc_compiler_compile_delimitted_block(uc_compiler_t *compiler, uc_tokentype_t endtype)
1534 {
1535         while (!uc_compiler_parse_check(compiler, endtype) &&
1536                !uc_compiler_parse_check(compiler, TK_EOF))
1537                 uc_compiler_compile_declaration(compiler);
1538 
1539         return uc_compiler_parse_check(compiler, endtype);
1540 }
1541 
1542 static void
1543 uc_compiler_compile_function(uc_compiler_t *compiler)
1544 {
1545         uc_compiler_t fncompiler = { 0 };
1546         uc_value_t *name = NULL;
1547         ssize_t slot = -1, pos;
1548         uc_tokentype_t type;
1549         size_t i, load_off;
1550         uc_function_t *fn;
1551 
1552         pos = compiler->parser->prev.pos;
1553         type = compiler->parser->prev.type;
1554 
1555         if (uc_compiler_parse_match(compiler, TK_LABEL)) {
1556                 name = compiler->parser->prev.uv;
1557 
1558                 /* Named functions are syntactic sugar for local variable declaration
1559                  * with function value assignment. If a name token was encountered,
1560                  * initialize a local variable for it... */
1561                 slot = uc_compiler_declare_local(compiler, name, false);
1562 
1563                 if (slot == -1)
1564                         uc_compiler_initialize_local(compiler);
1565         }
1566 
1567         uc_compiler_init(&fncompiler,
1568                 name ? ucv_string_get(name) : NULL, compiler->parser->prev.pos,
1569                 compiler->program,
1570                 uc_compiler_is_strict(compiler));
1571 
1572         fncompiler.parent = compiler;
1573         fncompiler.parser = compiler->parser;
1574         fncompiler.exprstack = compiler->exprstack;
1575         fn = (uc_function_t *)fncompiler.function;
1576 
1577         uc_compiler_parse_consume(&fncompiler, TK_LPAREN);
1578 
1579         uc_compiler_enter_scope(&fncompiler);
1580 
1581         /* compile argument specification */
1582         while (true) {
1583                 if (uc_compiler_parse_check(&fncompiler, TK_RPAREN))
1584                         break;
1585 
1586                 if (uc_compiler_parse_match(&fncompiler, TK_ELLIP))
1587                         fn->vararg = true;
1588 
1589                 if (uc_compiler_parse_match(&fncompiler, TK_LABEL)) {
1590                         fn->nargs++;
1591 
1592                         uc_compiler_declare_local(&fncompiler, fncompiler.parser->prev.uv, false);
1593                         uc_compiler_initialize_local(&fncompiler);
1594 
1595                         if (fn->vararg ||
1596                             !uc_compiler_parse_match(&fncompiler, TK_COMMA))
1597                                 break;
1598                 }
1599                 else {
1600                         uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos,
1601                                 "Expecting Label");
1602 
1603                         return;
1604                 }
1605         }
1606 
1607         uc_compiler_parse_consume(&fncompiler, TK_RPAREN);
1608 
1609         /* parse and compile function body */
1610         if (uc_compiler_parse_match(&fncompiler, TK_COLON)) {
1611                 uc_compiler_compile_delimitted_block(&fncompiler, TK_ENDFUNC);
1612                 uc_compiler_parse_consume(&fncompiler, TK_ENDFUNC);
1613         }
1614         else if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) {
1615                 uc_compiler_compile_delimitted_block(&fncompiler, TK_RBRACE);
1616                 uc_compiler_parse_consume(&fncompiler, TK_RBRACE);
1617         }
1618         else {
1619                 uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos,
1620                         "Expecting '{' or ':' after function parameters");
1621         }
1622 
1623         /* emit load instruction for function value */
1624         uc_compiler_emit_insn(compiler, pos, (type == TK_ARROW) ? I_ARFN : I_CLFN);
1625         load_off = uc_compiler_emit_u32(compiler, 0, 0);
1626 
1627         /* encode upvalue information */
1628         for (i = 0; i < fn->nupvals; i++)
1629                 uc_compiler_emit_s32(compiler, 0,
1630                         fncompiler.upvals.entries[i].local
1631                                 ? -(fncompiler.upvals.entries[i].index + 1)
1632                                 : fncompiler.upvals.entries[i].index);
1633 
1634         /* finalize function compiler */
1635         fn = uc_compiler_finish(&fncompiler);
1636 
1637         if (fn)
1638                 uc_compiler_set_u32(compiler, load_off,
1639                         uc_program_function_id(compiler->program, fn));
1640 
1641         /* if a local variable of the same name already existed, overwrite its value
1642          * with the compiled function here */
1643         if (slot != -1) {
1644                 uc_compiler_emit_insn(compiler, 0, I_SLOC);
1645                 uc_compiler_emit_u32(compiler, 0, slot);
1646                 uc_compiler_emit_insn(compiler, 0, I_POP);
1647         }
1648 }
1649 
1650 static void
1651 uc_compiler_compile_and(uc_compiler_t *compiler)
1652 {
1653         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1654         size_t jmpz_off;
1655 
1656         uc_compiler_emit_insn(compiler, 0, I_COPY);
1657         uc_compiler_emit_u8(compiler, 0, 0);
1658         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1659         uc_compiler_emit_insn(compiler, 0, I_POP);
1660         uc_compiler_parse_precedence(compiler, P_AND);
1661         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1662 }
1663 
1664 static void
1665 uc_compiler_compile_or(uc_compiler_t *compiler)
1666 {
1667         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1668         size_t jmpz_off, jmp_off;
1669 
1670         uc_compiler_emit_insn(compiler, 0, I_COPY);
1671         uc_compiler_emit_u8(compiler, 0, 0);
1672         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1673         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1674         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1675         uc_compiler_emit_insn(compiler, 0, I_POP);
1676         uc_compiler_parse_precedence(compiler, P_OR);
1677         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1678 }
1679 
1680 static void
1681 uc_compiler_compile_nullish(uc_compiler_t *compiler)
1682 {
1683         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1684         size_t jmpz_off, jmp_off;
1685 
1686         uc_compiler_emit_insn(compiler, 0, I_COPY);
1687         uc_compiler_emit_u8(compiler, 0, 0);
1688         uc_compiler_emit_insn(compiler, 0, I_LNULL);
1689         uc_compiler_emit_insn(compiler, 0, I_NES);
1690         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1691         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1692         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1693         uc_compiler_emit_insn(compiler, 0, I_POP);
1694         uc_compiler_parse_precedence(compiler, P_OR);
1695         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1696 }
1697 
1698 static void
1699 uc_compiler_compile_dot(uc_compiler_t *compiler)
1700 {
1701         bool optional_chaining = (compiler->parser->prev.type == TK_QDOT);
1702 
1703         /* flag optional chaining usage in current expression */
1704         compiler->exprstack->flags |= optional_chaining ? F_OPTCHAINING : 0;
1705 
1706         /* no regexp literal possible after property access */
1707         compiler->parser->lex.no_regexp = true;
1708 
1709         /* parse label lhs */
1710         uc_compiler_parse_consume(compiler, TK_LABEL);
1711         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
1712 
1713         /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */
1714         if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL))
1715                 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QDOT : 0);
1716 }
1717 
1718 static void
1719 uc_compiler_compile_subscript(uc_compiler_t *compiler)
1720 {
1721         bool optional_chaining = (compiler->parser->prev.type == TK_QLBRACK);
1722 
1723         /* flag optional chaining usage in current expression */
1724         compiler->exprstack->flags |= optional_chaining ? F_OPTCHAINING : 0;
1725 
1726         /* compile lhs */
1727         uc_compiler_compile_expression(compiler);
1728 
1729         /* no regexp literal possible after computed property access */
1730         compiler->parser->lex.no_regexp = true;
1731         uc_compiler_parse_consume(compiler, TK_RBRACK);
1732 
1733         /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */
1734         if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL))
1735                 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QLBRACK : 0);
1736 }
1737 
1738 static void
1739 uc_compiler_compile_ternary(uc_compiler_t *compiler)
1740 {
1741         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1742         size_t jmpz_off, jmp_off;
1743 
1744         /* jump to false branch */
1745         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
1746 
1747         /* compile true branch */
1748         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1749 
1750         /* jump after false branch */
1751         jmp_off = uc_compiler_emit_jmp(compiler, 0);
1752 
1753         uc_compiler_parse_consume(compiler, TK_COLON);
1754 
1755         /* compile false branch */
1756         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
1757         uc_compiler_parse_precedence(compiler, P_TERNARY);
1758         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
1759 }
1760 
1761 static void
1762 uc_compiler_compile_array(uc_compiler_t *compiler)
1763 {
1764         size_t hint_off, hint_count = 0, len = 0;
1765 
1766         /* create empty array on stack */
1767         uc_compiler_emit_insn(compiler, 0, I_NARR);
1768         hint_off = uc_compiler_emit_u32(compiler, 0, 0);
1769 
1770         /* parse initializer values */
1771         do {
1772                 if (uc_compiler_parse_check(compiler, TK_RBRACK)) {
1773                         break;
1774                 }
1775                 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
1776                         /* push items on stack so far... */
1777                         if (len > 0) {
1778                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR);
1779                                 uc_compiler_emit_u32(compiler, 0, len);
1780                                 len = 0;
1781                         }
1782 
1783                         /* compile spread value expression */
1784                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1785 
1786                         /* emit merge operation */
1787                         uc_compiler_emit_insn(compiler, 0, I_MARR);
1788                 }
1789                 else {
1790                         /* push items on stack so far... */
1791                         if (len >= 0xffffffff) {
1792                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR);
1793                                 uc_compiler_emit_u32(compiler, 0, len);
1794                                 len = 0;
1795                         }
1796 
1797                         /* compile item value expression */
1798                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1799 
1800                         hint_count++;
1801                         len++;
1802                 }
1803         }
1804         while (uc_compiler_parse_match(compiler, TK_COMMA));
1805 
1806         /* no regexp literal possible after array literal */
1807         compiler->parser->lex.no_regexp = true;
1808         uc_compiler_parse_consume(compiler, TK_RBRACK);
1809 
1810         /* push items on stack */
1811         if (len > 0) {
1812                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR);
1813                 uc_compiler_emit_u32(compiler, 0, len);
1814         }
1815 
1816         /* set initial size hint */
1817         uc_compiler_set_u32(compiler, hint_off, hint_count);
1818 }
1819 
1820 static void
1821 uc_compiler_compile_object(uc_compiler_t *compiler)
1822 {
1823         size_t hint_off, hint_count = 0, len = 0;
1824 
1825         /* create empty object on stack */
1826         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_NOBJ);
1827         hint_off = uc_compiler_emit_u32(compiler, 0, 0);
1828 
1829         /* parse initializer values */
1830         do {
1831                 /* End of object literal */
1832                 if (uc_compiler_parse_check(compiler, TK_RBRACE))
1833                         break;
1834 
1835                 /* Spread operator */
1836                 if (uc_compiler_parse_match(compiler, TK_ELLIP)) {
1837                         /* set items on stack so far... */
1838                         if (len > 0) {
1839                                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
1840                                 uc_compiler_emit_u32(compiler, 0, len);
1841                                 len = 0;
1842                         }
1843 
1844                         /* compile spread value expression */
1845                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1846 
1847                         /* emit merge operation */
1848                         uc_compiler_emit_insn(compiler, 0, I_MOBJ);
1849 
1850                         continue;
1851                 }
1852 
1853                 /* Computed property name */
1854                 if (uc_compiler_parse_match(compiler, TK_LBRACK)) {
1855                         /* parse property name expression */
1856                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1857 
1858                         /* cosume closing bracket and colon */
1859                         uc_compiler_parse_consume(compiler, TK_RBRACK);
1860                         uc_compiler_parse_consume(compiler, TK_COLON);
1861 
1862                         /* parse value expression */
1863                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1864                 }
1865 
1866                 /* Property/value tuple or property shorthand */
1867                 else {
1868                         /* parse key expression */
1869                         if (!uc_compiler_parse_match(compiler, TK_LABEL) &&
1870                             !uc_compiler_parse_match(compiler, TK_STRING))
1871                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
1872                                         "Expecting label");
1873 
1874                         /* load label */
1875                         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos,
1876                                 compiler->parser->prev.uv);
1877 
1878                         /* If the property name is a plain label followed by a comma or
1879                          * closing curly brace, treat it as ES2015 property shorthand
1880                          * notation... */
1881                         if (compiler->parser->prev.type == TK_LABEL &&
1882                             (uc_compiler_parse_check(compiler, TK_COMMA) ||
1883                              uc_compiler_parse_check(compiler, TK_RBRACE))) {
1884                                 /* disallow keywords in this case */
1885                                 if (uc_lexer_is_keyword(compiler->parser->prev.uv))
1886                                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1887                                                 "Invalid identifier");
1888 
1889                                 uc_compiler_emit_variable_rw(compiler,
1890                                         compiler->parser->prev.uv, 0);
1891                         }
1892 
1893                         /* ... otherwise treat it as ordinary `key: value` tuple */
1894                         else {
1895                                 uc_compiler_parse_consume(compiler, TK_COLON);
1896 
1897                                 /* parse value expression */
1898                                 uc_compiler_parse_precedence(compiler, P_ASSIGN);
1899                         }
1900                 }
1901 
1902                 /* set items on stack so far... */
1903                 if (len >= 0xfffffffe) {
1904                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
1905                         uc_compiler_emit_u32(compiler, 0, len);
1906                         len = 0;
1907                 }
1908 
1909                 hint_count += 2;
1910                 len += 2;
1911 
1912                 compiler->parser->lex.no_keyword = true;
1913         }
1914         while (uc_compiler_parse_match(compiler, TK_COMMA));
1915 
1916         /* no regexp literal possible after object literal */
1917         compiler->parser->lex.no_regexp = true;
1918         uc_compiler_parse_consume(compiler, TK_RBRACE);
1919 
1920         /* set items on stack */
1921         if (len > 0) {
1922                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ);
1923                 uc_compiler_emit_u32(compiler, 0, len);
1924         }
1925 
1926         /* set initial size hint */
1927         uc_compiler_set_u32(compiler, hint_off, hint_count);
1928 }
1929 
1930 
1931 static void
1932 uc_compiler_declare_local_null(uc_compiler_t *compiler, size_t srcpos, uc_value_t *varname)
1933 {
1934         ssize_t existing_slot = uc_compiler_declare_local(compiler, varname, false);
1935 
1936         uc_compiler_emit_insn(compiler, srcpos, I_LNULL);
1937 
1938         if (existing_slot == -1) {
1939                 uc_compiler_initialize_local(compiler);
1940         }
1941         else {
1942                 uc_compiler_emit_insn(compiler, 0, I_SLOC);
1943                 uc_compiler_emit_u32(compiler, 0, existing_slot);
1944                 uc_compiler_emit_insn(compiler, 0, I_POP);
1945         }
1946 }
1947 
1948 static size_t
1949 uc_compiler_declare_internal(uc_compiler_t *compiler, size_t srcpos, const char *name)
1950 {
1951         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
1952         uc_locals_t *locals = &compiler->locals;
1953 
1954         uc_vector_grow(locals);
1955 
1956         locals->entries[locals->count].name = ucv_string_new(name);
1957         locals->entries[locals->count].depth = compiler->scope_depth;
1958         locals->entries[locals->count].captured = false;
1959         locals->entries[locals->count].from = chunk->count;
1960 
1961         return locals->count++;
1962 }
1963 
1964 static void
1965 uc_compiler_compile_declexpr(uc_compiler_t *compiler, bool constant)
1966 {
1967         ssize_t slot;
1968 
1969         do {
1970                 /* parse variable name */
1971                 if (!uc_compiler_parse_match(compiler, TK_LABEL)) {
1972                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
1973                                 "Expecting variable name");
1974 
1975                         return;
1976                 }
1977 
1978                 /* declare local variable */
1979                 slot = uc_compiler_declare_local(compiler, compiler->parser->prev.uv, constant);
1980 
1981                 /* if followed by '=', parse initializer expression */
1982                 if (uc_compiler_parse_match(compiler, TK_ASSIGN))
1983                         uc_compiler_parse_precedence(compiler, P_ASSIGN);
1984                 /* otherwise, for writable variables, load implicit null */
1985                 else if (!constant)
1986                         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
1987                 /* for constant variables, a missing initializer is a syntax error */
1988                 else
1989                         uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
1990                                 "Expecting initializer expression");
1991 
1992                 /* initialize local */
1993                 if (slot == -1) {
1994                         uc_compiler_initialize_local(compiler);
1995                 }
1996                 /* if the variable was redeclared, overwrite it */
1997                 else {
1998                         uc_compiler_emit_insn(compiler, 0, I_SLOC);
1999                         uc_compiler_emit_u32(compiler, 0, slot);
2000                         uc_compiler_emit_insn(compiler, 0, I_POP);
2001                 }
2002         }
2003         while (uc_compiler_parse_match(compiler, TK_COMMA));
2004 }
2005 
2006 static void
2007 uc_compiler_compile_local(uc_compiler_t *compiler)
2008 {
2009         uc_compiler_compile_declexpr(compiler, false);
2010         uc_compiler_parse_consume(compiler, TK_SCOL);
2011 }
2012 
2013 static void
2014 uc_compiler_compile_const(uc_compiler_t *compiler)
2015 {
2016         uc_compiler_compile_declexpr(compiler, true);
2017         uc_compiler_parse_consume(compiler, TK_SCOL);
2018 }
2019 
2020 static uc_tokentype_t
2021 uc_compiler_compile_altifblock(uc_compiler_t *compiler)
2022 {
2023         uc_compiler_enter_scope(compiler);
2024 
2025         while (true) {
2026                 switch (compiler->parser->curr.type) {
2027                 case TK_ELIF:
2028                 case TK_ELSE:
2029                 case TK_ENDIF:
2030                 case TK_EOF:
2031                         uc_compiler_leave_scope(compiler);
2032 
2033                         return compiler->parser->curr.type;
2034 
2035                 default:
2036                         uc_compiler_compile_declaration(compiler);
2037                         break;
2038                 }
2039         }
2040 
2041         return 0;
2042 }
2043 
2044 static void
2045 uc_compiler_compile_if(uc_compiler_t *compiler)
2046 {
2047         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2048         size_t jmpz_off, jmp_off, i;
2049         bool expect_endif = false;
2050         uc_jmplist_t elifs = { 0 };
2051         uc_tokentype_t type;
2052 
2053         /* parse & compile condition expression */
2054         uc_compiler_parse_consume(compiler, TK_LPAREN);
2055         uc_compiler_compile_expression(compiler);
2056         uc_compiler_parse_consume(compiler, TK_RPAREN);
2057 
2058         /* conditional jump to else/elif branch */
2059         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2060 
2061         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2062                 compiler->exprstack->flags |= F_ALTBLOCKMODE;
2063 
2064                 while (true) {
2065                         /* compile elsif or else branch */
2066                         type = uc_compiler_compile_altifblock(compiler);
2067 
2068                         /* we just compiled an elsif block */
2069                         if (!expect_endif && type == TK_ELIF) {
2070                                 /* emit jump to skip to the end */
2071                                 uc_vector_grow(&elifs);
2072                                 elifs.entries[elifs.count++] = uc_compiler_emit_jmp(compiler, 0);
2073 
2074                                 /* point previous conditional jump to beginning of branch */
2075                                 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2076 
2077                                 /* parse & compile elsif condition */
2078                                 uc_compiler_parse_advance(compiler);
2079                                 uc_compiler_parse_consume(compiler, TK_LPAREN);
2080                                 uc_compiler_compile_expression(compiler);
2081                                 uc_compiler_parse_consume(compiler, TK_RPAREN);
2082                                 uc_compiler_parse_consume(compiler, TK_COLON);
2083 
2084                                 /* conditional jump to else/elif branch */
2085                                 jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2086                         }
2087                         else if (!expect_endif && type == TK_ELSE) {
2088                                 /* emit jump to skip to the end */
2089                                 uc_vector_grow(&elifs);
2090                                 elifs.entries[elifs.count++] = uc_compiler_emit_jmp(compiler, 0);
2091 
2092                                 /* point previous conditional jump to beginning of branch */
2093                                 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2094                                 jmpz_off = 0;
2095 
2096                                 /* skip "else" keyword */
2097                                 uc_compiler_parse_advance(compiler);
2098 
2099                                 expect_endif = true;
2100                         }
2101                         else if (type == TK_ENDIF) {
2102                                 /* if no else clause, point previous conditional jump after block */
2103                                 if (jmpz_off)
2104                                         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2105 
2106                                 /* patch the elif branch jumps to point here after the else */
2107                                 for (i = 0; i < elifs.count; i++)
2108                                         uc_compiler_set_jmpaddr(compiler, elifs.entries[i],
2109                                                 chunk->count);
2110 
2111                                 /* skip the "endif" keyword */
2112                                 uc_compiler_parse_advance(compiler);
2113                                 break;
2114                         }
2115                         else {
2116                                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2117                                         expect_endif
2118                                                 ? "Expecting 'endif'"
2119                                                 : "Expecting 'elif', 'else' or 'endif'");
2120 
2121                                 break;
2122                         }
2123                 }
2124 
2125                 uc_vector_clear(&elifs);
2126         }
2127         else {
2128                 /* compile true branch */
2129                 uc_compiler_compile_statement(compiler);
2130 
2131                 /* ... when present, handle false branch */
2132                 if (uc_compiler_parse_match(compiler, TK_ELSE)) {
2133                         /* jump to skip else branch */
2134                         jmp_off = uc_compiler_emit_jmp(compiler, 0);
2135 
2136                         /* set conditional jump address */
2137                         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2138 
2139                         /* compile false branch */
2140                         uc_compiler_compile_statement(compiler);
2141 
2142                         /* set else skip jump address */
2143                         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
2144                 }
2145                 /* ... otherwise point the conditional jump after the true branch */
2146                 else {
2147                         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2148                 }
2149         }
2150 }
2151 
2152 static void
2153 uc_compiler_compile_while(uc_compiler_t *compiler)
2154 {
2155         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2156         uc_patchlist_t p = { .depth = compiler->scope_depth };
2157         size_t cond_off, jmpz_off, end_off;
2158 
2159         p.parent = compiler->patchlist;
2160         compiler->patchlist = &p;
2161 
2162         cond_off = chunk->count;
2163 
2164         /* parse & compile loop condition */
2165         uc_compiler_parse_consume(compiler, TK_LPAREN);
2166         uc_compiler_compile_expression(compiler);
2167         uc_compiler_parse_consume(compiler, TK_RPAREN);
2168 
2169         /* conditional jump to end */
2170         jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
2171 
2172         /* compile loop body */
2173         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2174                 uc_compiler_enter_scope(compiler);
2175 
2176                 if (!uc_compiler_compile_delimitted_block(compiler, TK_ENDWHILE))
2177                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2178                                 "Expecting 'endwhile'");
2179                 else
2180                         uc_compiler_parse_advance(compiler);
2181 
2182                 uc_compiler_leave_scope(compiler);
2183         }
2184         else {
2185                 uc_compiler_compile_statement(compiler);
2186         }
2187 
2188         end_off = chunk->count;
2189 
2190         /* jump back to condition */
2191         uc_compiler_emit_jmp_dest(compiler, 0, cond_off);
2192 
2193         /* set conditional jump target */
2194         uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
2195 
2196         /* patch up break/continue */
2197         uc_compiler_backpatch(compiler, chunk->count, end_off);
2198 }
2199 
2200 static void
2201 uc_compiler_compile_for_in(uc_compiler_t *compiler, bool local, uc_token_t *kvar, uc_token_t *vvar)
2202 {
2203         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2204         uc_patchlist_t p = { .depth = compiler->scope_depth + 1 };
2205         size_t skip_jmp, test_jmp, key_slot, val_slot;
2206 
2207         p.parent = compiler->patchlist;
2208         compiler->patchlist = &p;
2209 
2210         uc_compiler_enter_scope(compiler);
2211 
2212         /* declare internal loop variables */
2213         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2214         key_slot = uc_compiler_declare_internal(compiler, 0, "(for in key)");
2215 
2216         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2217         val_slot = uc_compiler_declare_internal(compiler, 0, "(for in value)");
2218 
2219         /* declare loop variables */
2220         if (local) {
2221                 uc_compiler_declare_local_null(compiler, kvar->pos, kvar->uv);
2222 
2223                 if (vvar)
2224                         uc_compiler_declare_local_null(compiler, vvar->pos, vvar->uv);
2225         }
2226 
2227         /* value to iterate */
2228         uc_compiler_compile_expression(compiler);
2229         uc_compiler_parse_consume(compiler, TK_RPAREN);
2230         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2231         uc_compiler_emit_u32(compiler, 0, val_slot);
2232 
2233         /* initial key value */
2234         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2235         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2236         uc_compiler_emit_u32(compiler, 0, key_slot);
2237 
2238         /* jump over variable read for first cycle */
2239         skip_jmp = uc_compiler_emit_jmp(compiler, 0);
2240 
2241         /* read value */
2242         uc_compiler_emit_insn(compiler, 0, I_LLOC);
2243         uc_compiler_emit_u32(compiler, 0, val_slot);
2244 
2245         /* read key */
2246         uc_compiler_emit_insn(compiler, 0, I_LLOC);
2247         uc_compiler_emit_u32(compiler, 0, key_slot);
2248 
2249         /* backpatch skip jump */
2250         uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count);
2251 
2252         /* load loop variable and get next key from object */
2253         uc_compiler_emit_insn(compiler, 0, vvar ? I_NEXTKV : I_NEXTK);
2254 
2255         /* set internal key variable */
2256         uc_compiler_emit_insn(compiler, 0, I_SLOC);
2257         uc_compiler_emit_u32(compiler, 0, key_slot);
2258 
2259         /* test for != null */
2260         uc_compiler_emit_insn(compiler, 0, I_LNULL);
2261         uc_compiler_emit_insn(compiler, 0, I_NES);
2262 
2263         /* jump after loop body if no next key */
2264         test_jmp = uc_compiler_emit_jmpz(compiler, 0);
2265 
2266         /* set key and value variables */
2267         if (vvar) {
2268                 uc_compiler_emit_variable_rw(compiler, vvar->uv, TK_ASSIGN);
2269                 uc_compiler_emit_insn(compiler, 0, I_POP);
2270         }
2271 
2272         /* set key variable */
2273         uc_compiler_emit_variable_rw(compiler, kvar->uv, TK_ASSIGN);
2274         uc_compiler_emit_insn(compiler, 0, I_POP);
2275 
2276         /* compile loop body */
2277         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2278                 uc_compiler_enter_scope(compiler);
2279 
2280                 if (!uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR))
2281                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2282                                 "Expecting 'endfor'");
2283                 else
2284                         uc_compiler_parse_advance(compiler);
2285 
2286                 uc_compiler_leave_scope(compiler);
2287         }
2288         else {
2289                 uc_compiler_compile_statement(compiler);
2290         }
2291 
2292         /* jump back to retrieve next key */
2293         uc_compiler_emit_jmp_dest(compiler, 0, skip_jmp + 5);
2294 
2295         /* back patch conditional jump */
2296         uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count);
2297 
2298         /* pop loop variables */
2299         uc_compiler_emit_insn(compiler, 0, I_POP);
2300 
2301         if (vvar)
2302                 uc_compiler_emit_insn(compiler, 0, I_POP);
2303 
2304         /* patch up break/continue */
2305         uc_compiler_backpatch(compiler, chunk->count, skip_jmp + 5);
2306 
2307         uc_compiler_leave_scope(compiler);
2308 }
2309 
2310 static void
2311 uc_compiler_compile_for_count(uc_compiler_t *compiler, bool local, uc_token_t *var)
2312 {
2313         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2314         size_t test_off = 0, incr_off, skip_off, cond_off = 0;
2315         uc_patchlist_t p = { .depth = compiler->scope_depth + 1 };
2316 
2317         p.parent = compiler->patchlist;
2318         compiler->patchlist = &p;
2319 
2320         uc_compiler_enter_scope(compiler);
2321 
2322         /* Initializer ---------------------------------------------------------- */
2323 
2324         /* If we parsed at least one label, try continue parsing as variable
2325          * expression... */
2326         if (var) {
2327                 /* We parsed a `local x` or `local x, y` expression, so (re)declare
2328                  * last label as local initializer variable */
2329                 if (local)
2330                         uc_compiler_declare_local_null(compiler, var->pos, var->uv);
2331 
2332                 uc_compiler_exprstack_push(compiler, TK_FOR, F_ASSIGNABLE);
2333 
2334                 uc_compiler_compile_labelexpr(compiler);
2335                 uc_compiler_emit_insn(compiler, 0, I_POP);
2336 
2337                 /* If followed by a comma, continue parsing expression */
2338                 if (uc_compiler_parse_match(compiler, TK_COMMA)) {
2339                         /* Is a continuation of a declaration list... */
2340                         if (local) {
2341                                 uc_compiler_compile_declexpr(compiler, false);
2342                         }
2343                         /* ... otherwise an unrelated expression */
2344                         else {
2345                                 uc_compiler_compile_expression(compiler);
2346                                 uc_compiler_emit_insn(compiler, 0, I_POP);
2347                         }
2348                 }
2349 
2350                 uc_compiler_exprstack_pop(compiler);
2351         }
2352         /* ... otherwise try parsing an entire expression (which might be absent) */
2353         else if (!uc_compiler_parse_check(compiler, TK_SCOL)) {
2354                 uc_compiler_compile_expression(compiler);
2355                 uc_compiler_emit_insn(compiler, 0, I_POP);
2356         }
2357 
2358         uc_compiler_parse_consume(compiler, TK_SCOL);
2359 
2360 
2361         /* Condition ------------------------------------------------------------ */
2362         if (!uc_compiler_parse_check(compiler, TK_SCOL)) {
2363                 cond_off = chunk->count;
2364 
2365                 uc_compiler_compile_expression(compiler);
2366 
2367                 test_off = uc_compiler_emit_jmpz(compiler, 0);
2368         }
2369 
2370         uc_compiler_parse_consume(compiler, TK_SCOL);
2371 
2372         /* jump over incrementer */
2373         skip_off = uc_compiler_emit_jmp(compiler, 0);
2374 
2375 
2376         /* Incrementer ---------------------------------------------------------- */
2377         incr_off = chunk->count;
2378 
2379         if (!uc_compiler_parse_check(compiler, TK_RPAREN)) {
2380                 uc_compiler_compile_expression(compiler);
2381                 uc_compiler_emit_insn(compiler, 0, I_POP);
2382         }
2383 
2384         uc_compiler_parse_consume(compiler, TK_RPAREN);
2385 
2386         /* if we have a condition, jump back to it, else continue to the loop body */
2387         if (cond_off)
2388                 uc_compiler_emit_jmp_dest(compiler, 0, cond_off);
2389 
2390         /* back patch skip address */
2391         uc_compiler_set_jmpaddr(compiler, skip_off, chunk->count);
2392 
2393 
2394         /* Body ----------------------------------------------------------------- */
2395         if (uc_compiler_parse_match(compiler, TK_COLON)) {
2396                 uc_compiler_enter_scope(compiler);
2397 
2398                 if (!uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR))
2399                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2400                                 "Expecting 'endfor'");
2401                 else
2402                         uc_compiler_parse_advance(compiler);
2403 
2404                 uc_compiler_leave_scope(compiler);
2405         }
2406         else {
2407                 uc_compiler_compile_statement(compiler);
2408         }
2409 
2410         /* jump back to incrementer */
2411         uc_compiler_emit_jmp_dest(compiler, 0, incr_off);
2412 
2413         /* back patch conditional jump */
2414         if (test_off)
2415                 uc_compiler_set_jmpaddr(compiler, test_off, chunk->count);
2416 
2417         /* patch up break/continue */
2418         uc_compiler_backpatch(compiler, chunk->count, incr_off);
2419 
2420         uc_compiler_leave_scope(compiler);
2421 }
2422 
2423 static void
2424 uc_compiler_compile_for(uc_compiler_t *compiler)
2425 {
2426         uc_token_t keyvar = { 0 }, valvar = { 0 };
2427         bool local;
2428 
2429         uc_compiler_parse_consume(compiler, TK_LPAREN);
2430 
2431         /* check the next few tokens and see if we have either a
2432          * `let x in` / `let x, y` expression or an ordinary initializer
2433          * statement */
2434 
2435         local = uc_compiler_parse_match(compiler, TK_LOCAL);
2436 
2437         if (uc_compiler_parse_match(compiler, TK_LABEL)) {
2438                 keyvar = compiler->parser->prev;
2439                 ucv_get(keyvar.uv);
2440 
2441                 if (uc_compiler_parse_match(compiler, TK_COMMA)) {
2442                         uc_compiler_parse_consume(compiler, TK_LABEL);
2443 
2444                         valvar = compiler->parser->prev;
2445                         ucv_get(valvar.uv);
2446                 }
2447 
2448                 /* is a for-in loop */
2449                 if (uc_compiler_parse_match(compiler, TK_IN)) {
2450                         uc_compiler_compile_for_in(compiler, local, &keyvar,
2451                                 valvar.type ? &valvar : NULL);
2452 
2453                         goto out;
2454                 }
2455         }
2456         else if (local) {
2457                 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2458                         "Expecting label after 'local'");
2459 
2460                 goto out;
2461         }
2462 
2463         /*
2464          * The previous expression ruled out a for-in loop, so continue parsing
2465          * as counting for loop...
2466          */
2467         uc_compiler_compile_for_count(compiler, local,
2468                 valvar.uv ? &valvar : (keyvar.uv ? &keyvar : NULL));
2469 
2470 out:
2471         ucv_put(keyvar.uv);
2472         ucv_put(valvar.uv);
2473 }
2474 
2475 static void
2476 uc_compiler_compile_switch(uc_compiler_t *compiler)
2477 {
2478         size_t i, test_jmp, skip_jmp, next_jmp, value_slot, default_off = 0;
2479         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2480         uc_patchlist_t p = { .depth = compiler->scope_depth };
2481         uc_locals_t *locals = &compiler->locals;
2482         uc_jmplist_t cases = { 0 };
2483 
2484         p.parent = compiler->patchlist;
2485         compiler->patchlist = &p;
2486 
2487         uc_compiler_enter_scope(compiler);
2488 
2489         /* parse and compile match value */
2490         uc_compiler_parse_consume(compiler, TK_LPAREN);
2491         uc_compiler_compile_expression(compiler);
2492         uc_compiler_parse_consume(compiler, TK_RPAREN);
2493         uc_compiler_parse_consume(compiler, TK_LBRACE);
2494 
2495         value_slot = uc_compiler_declare_internal(compiler, 0, "(switch value)");
2496 
2497         /* jump to branch tests */
2498         test_jmp = uc_compiler_emit_jmp(compiler, 0);
2499 
2500         /* parse and compile case matches */
2501         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
2502                !uc_compiler_parse_check(compiler, TK_EOF)) {
2503                 /* handle `default:` */
2504                 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) {
2505                         if (default_off) {
2506                                 uc_vector_clear(&cases);
2507                                 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos,
2508                                         "more than one switch default case");
2509 
2510                                 break;
2511                         }
2512 
2513                         uc_compiler_parse_consume(compiler, TK_COLON);
2514 
2515                         /* remember address of default branch */
2516                         default_off = chunk->count;
2517 
2518                         /* Store three values in case offset list:
2519                          *  1) amount of local variables declared so far
2520                          *  2) beginning of condition expression
2521                          *  3) end of condition expression
2522                          * For the `default` case, beginning and end offsets of the
2523                          * condition expression are equal.
2524                          */
2525                         uc_vector_grow(&cases);
2526                         cases.entries[cases.count++] = (locals->count - 1) - value_slot;
2527 
2528                         uc_vector_grow(&cases);
2529                         cases.entries[cases.count++] = chunk->count;
2530 
2531                         uc_vector_grow(&cases);
2532                         cases.entries[cases.count++] = chunk->count;
2533                 }
2534 
2535                 /* handle `case …:` */
2536                 else if (uc_compiler_parse_match(compiler, TK_CASE)) {
2537                         /* jump over `case …:` label expression */
2538                         skip_jmp = uc_compiler_emit_jmp(compiler, 0);
2539 
2540                         /* compile case value expression */
2541                         uc_compiler_compile_expression(compiler);
2542                         uc_compiler_parse_consume(compiler, TK_COLON);
2543 
2544                         /* Store three values in case offset list:
2545                          *  1) amount of local variables declared so far
2546                          *  2) beginning of condition expression
2547                          *  3) end of condition expression
2548                          */
2549                         uc_vector_grow(&cases);
2550                         cases.entries[cases.count++] = (locals->count - 1) - value_slot;
2551 
2552                         uc_vector_grow(&cases);
2553                         cases.entries[cases.count++] = skip_jmp + 5;
2554 
2555                         uc_vector_grow(&cases);
2556                         cases.entries[cases.count++] = uc_compiler_emit_jmp(compiler, 0);
2557 
2558                         /* patch jump skipping over the case value */
2559                         uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count);
2560                 }
2561 
2562                 /* handle interleaved statement */
2563                 else if (cases.count) {
2564                         uc_compiler_compile_declaration(compiler);
2565                 }
2566 
2567                 /* a statement or expression preceeding any `default` or `case` is a
2568                  * syntax error */
2569                 else {
2570                         uc_compiler_syntax_error(compiler, compiler->parser->curr.pos,
2571                                 "Expecting 'case' or 'default'");
2572 
2573                         break;
2574                 }
2575         }
2576 
2577         uc_compiler_parse_consume(compiler, TK_RBRACE);
2578 
2579         /* evaluate case matches */
2580         if (cases.count) {
2581                 skip_jmp = uc_compiler_emit_jmp(compiler, 0);
2582 
2583                 uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count);
2584 
2585                 for (i = 0, default_off = cases.count; i < cases.count; i += 3) {
2586                         /* remember and skip default case */
2587                         if (cases.entries[i + 1] == cases.entries[i + 2]) {
2588                                 default_off = i;
2589                                 continue;
2590                         }
2591 
2592                         /* read switch match value */
2593                         uc_compiler_emit_insn(compiler, 0, I_LLOC);
2594                         uc_compiler_emit_u32(compiler, 0, value_slot);
2595 
2596                         /* jump to case value expression code */
2597                         uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 1]);
2598 
2599                         /* patch final case value expression jump back here */
2600                         uc_compiler_set_jmpaddr(compiler, cases.entries[i + 2], chunk->count);
2601 
2602                         /* strict equal test */
2603                         uc_compiler_emit_insn(compiler, 0, I_EQS);
2604 
2605                         /* conditional jump to next match */
2606                         next_jmp = uc_compiler_emit_jmpz(compiler, 0);
2607 
2608                         /* fill local slots */
2609                         while (cases.entries[i + 0] > 0) {
2610                                 uc_compiler_emit_insn(compiler, 0, I_LNULL);
2611                                 cases.entries[i + 0]--;
2612                         }
2613 
2614                         /* jump to target code */
2615                         uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 2] + 5);
2616 
2617                         /* patch next jump */
2618                         uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count);
2619                 }
2620 
2621                 /* handle default case (if any) */
2622                 if (default_off < cases.count) {
2623                         /* fill local slots */
2624                         while (cases.entries[default_off + 0] > 0) {
2625                                 uc_compiler_emit_insn(compiler, 0, I_LNULL);
2626                                 cases.entries[default_off + 0]--;
2627                         }
2628 
2629                         /* jump to target */
2630                         uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[default_off + 2]);
2631                 }
2632 
2633                 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count);
2634         }
2635         else {
2636                 uc_compiler_set_jmpaddr(compiler, test_jmp, test_jmp + 5);
2637         }
2638 
2639         uc_vector_clear(&cases);
2640 
2641         uc_compiler_leave_scope(compiler);
2642 
2643         uc_compiler_backpatch(compiler, chunk->count, 0);
2644 }
2645 
2646 static void
2647 uc_compiler_compile_try(uc_compiler_t *compiler)
2648 {
2649         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2650         size_t try_from = 0, try_to = 0, jmp_off = 0, ehvar_slot = 0;
2651         uc_ehranges_t *ranges = &chunk->ehranges;
2652 
2653         try_from = chunk->count;
2654         ehvar_slot = compiler->locals.count;
2655 
2656         /* Try block ------------------------------------------------------------ */
2657         uc_compiler_enter_scope(compiler);
2658 
2659         uc_compiler_parse_consume(compiler, TK_LBRACE);
2660 
2661         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
2662                !uc_compiler_parse_check(compiler, TK_EOF))
2663                 uc_compiler_compile_declaration(compiler);
2664 
2665         uc_compiler_parse_consume(compiler, TK_RBRACE);
2666 
2667         uc_compiler_leave_scope(compiler);
2668 
2669         /* jump beyond catch branch */
2670         try_to = chunk->count;
2671         jmp_off = uc_compiler_emit_jmp(compiler, 0);
2672 
2673 
2674         /* Catch block ---------------------------------------------------------- */
2675         if (try_to > try_from) {
2676                 uc_vector_grow(ranges);
2677 
2678                 ranges->entries[ranges->count].from   = try_from;
2679                 ranges->entries[ranges->count].to     = try_to;
2680                 ranges->entries[ranges->count].target = chunk->count;
2681                 ranges->entries[ranges->count].slot   = ehvar_slot;
2682                 ranges->count++;
2683         }
2684 
2685         uc_compiler_enter_scope(compiler);
2686 
2687         uc_compiler_parse_consume(compiler, TK_CATCH);
2688 
2689         /* have exception variable */
2690         if (uc_compiler_parse_match(compiler, TK_LPAREN)) {
2691                 uc_compiler_parse_consume(compiler, TK_LABEL);
2692 
2693                 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, false);
2694                 uc_compiler_initialize_local(compiler);
2695 
2696                 uc_compiler_parse_consume(compiler, TK_RPAREN);
2697         }
2698         /* ... else pop exception object from stack */
2699         else {
2700                 uc_compiler_emit_insn(compiler, 0, I_POP);
2701         }
2702 
2703         uc_compiler_parse_consume(compiler, TK_LBRACE);
2704 
2705         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
2706                !uc_compiler_parse_check(compiler, TK_EOF))
2707                 uc_compiler_compile_declaration(compiler);
2708 
2709         uc_compiler_parse_consume(compiler, TK_RBRACE);
2710 
2711         uc_compiler_leave_scope(compiler);
2712 
2713         uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count);
2714 }
2715 
2716 static void
2717 uc_compiler_compile_control(uc_compiler_t *compiler)
2718 {
2719         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2720         uc_tokentype_t type = compiler->parser->prev.type;
2721         uc_patchlist_t *p = compiler->patchlist;
2722         uc_locals_t *locals = &compiler->locals;
2723         size_t i, pos = compiler->parser->prev.pos;
2724 
2725         if (!p) {
2726                 uc_compiler_syntax_error(compiler, pos,
2727                         (type == TK_BREAK)
2728                                 ? "break must be inside loop or switch"
2729                                 : "continue must be inside loop");
2730 
2731                 return;
2732         }
2733 
2734         /* pop locals in scope up to this point */
2735         for (i = locals->count; i > 0 && (size_t)locals->entries[i - 1].depth > p->depth; i--)
2736                 uc_compiler_emit_insn(compiler, 0, I_POP);
2737 
2738         uc_vector_grow(p);
2739 
2740         p->entries[p->count++] =
2741                 uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type);
2742 
2743         uc_compiler_parse_consume(compiler, TK_SCOL);
2744 }
2745 
2746 static void
2747 uc_compiler_compile_return(uc_compiler_t *compiler)
2748 {
2749         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2750         size_t off = chunk->count;
2751 
2752         uc_compiler_compile_expstmt(compiler);
2753 
2754         /* if we compiled an empty expression statement (`;`), load implicit null */
2755         if (chunk->count == off)
2756                 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL);
2757         /* otherwise overwrite the final I_POP instruction with I_RETURN */
2758         else
2759                 uc_chunk_pop(chunk);
2760 
2761         uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_RETURN);
2762 }
2763 
2764 static void
2765 uc_compiler_compile_tplexp(uc_compiler_t *compiler)
2766 {
2767         uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
2768         size_t off = chunk->count;
2769 
2770         uc_compiler_compile_expression(compiler);
2771 
2772         /* XXX: the lexer currently emits a superfluous trailing semicolon... */
2773         uc_compiler_parse_match(compiler, TK_SCOL);
2774 
2775         uc_compiler_parse_consume(compiler, TK_REXP);
2776 
2777         if (chunk->count > off)
2778                 uc_compiler_emit_insn(compiler, 0, I_PRINT);
2779 }
2780 
2781 static void
2782 uc_compiler_compile_text(uc_compiler_t *compiler)
2783 {
2784         uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv);
2785         uc_compiler_emit_insn(compiler, 0, I_PRINT);
2786 }
2787 
2788 static void
2789 uc_compiler_compile_block(uc_compiler_t *compiler)
2790 {
2791         uc_compiler_enter_scope(compiler);
2792 
2793         while (!uc_compiler_parse_check(compiler, TK_RBRACE) &&
2794                !uc_compiler_parse_check(compiler, TK_EOF))
2795                 uc_compiler_compile_declaration(compiler);
2796 
2797         uc_compiler_parse_consume(compiler, TK_RBRACE);
2798 
2799         uc_compiler_leave_scope(compiler);
2800 }
2801 
2802 static void
2803 uc_compiler_compile_expstmt(uc_compiler_t *compiler)
2804 {
2805         /* empty statement */
2806         if (uc_compiler_parse_match(compiler, TK_SCOL))
2807                 return;
2808 
2809         uc_compiler_compile_expression(compiler);
2810 
2811         /* allow omitting final semicolon */
2812         switch (compiler->parser->curr.type) {
2813         case TK_RBRACE:
2814         case TK_ELIF:
2815         case TK_ENDIF:
2816         case TK_ENDFOR:
2817         case TK_ENDWHILE:
2818         case TK_ENDFUNC:
2819         case TK_EOF:
2820                 break;
2821 
2822         case TK_ELSE:
2823                 if (!uc_compiler_exprstack_is(compiler, F_ALTBLOCKMODE))
2824                         uc_compiler_parse_consume(compiler, TK_SCOL);
2825 
2826                 break;
2827 
2828         default:
2829                 uc_compiler_parse_consume(compiler, TK_SCOL);
2830 
2831                 break;
2832         }
2833 
2834         uc_compiler_emit_insn(compiler, 0, I_POP);
2835 }
2836 
2837 static void
2838 uc_compiler_compile_statement(uc_compiler_t *compiler)
2839 {
2840         uc_exprstack_t expr = {
2841                 .token = compiler->parser->curr.type,
2842                 .parent = compiler->exprstack
2843         };
2844 
2845         compiler->exprstack = &expr;
2846 
2847         if (uc_compiler_parse_match(compiler, TK_IF))
2848                 uc_compiler_compile_if(compiler);
2849         else if (uc_compiler_parse_match(compiler, TK_WHILE))
2850                 uc_compiler_compile_while(compiler);
2851         else if (uc_compiler_parse_match(compiler, TK_FOR))
2852                 uc_compiler_compile_for(compiler);
2853         else if (uc_compiler_parse_match(compiler, TK_SWITCH))
2854                 uc_compiler_compile_switch(compiler);
2855         else if (uc_compiler_parse_match(compiler, TK_TRY))
2856                 uc_compiler_compile_try(compiler);
2857         else if (uc_compiler_parse_match(compiler, TK_FUNC))
2858                 uc_compiler_compile_function(compiler);
2859         else if (uc_compiler_parse_match(compiler, TK_BREAK))
2860                 uc_compiler_compile_control(compiler);
2861         else if (uc_compiler_parse_match(compiler, TK_CONTINUE))
2862                 uc_compiler_compile_control(compiler);
2863         else if (uc_compiler_parse_match(compiler, TK_RETURN))
2864                 uc_compiler_compile_return(compiler);
2865         else if (uc_compiler_parse_match(compiler, TK_TEXT))
2866                 uc_compiler_compile_text(compiler);
2867         else if (uc_compiler_parse_match(compiler, TK_LEXP))
2868                 uc_compiler_compile_tplexp(compiler);
2869         else if (uc_compiler_parse_match(compiler, TK_LBRACE))
2870                 uc_compiler_compile_block(compiler);
2871         else
2872                 uc_compiler_compile_expstmt(compiler);
2873 
2874         compiler->exprstack = expr.parent;
2875 }
2876 
2877 static void
2878 uc_compiler_compile_declaration(uc_compiler_t *compiler)
2879 {
2880 
2881         if (uc_compiler_parse_match(compiler, TK_LOCAL))
2882                 uc_compiler_compile_local(compiler);
2883         else if (uc_compiler_parse_match(compiler, TK_CONST))
2884                 uc_compiler_compile_const(compiler);
2885         else
2886                 uc_compiler_compile_statement(compiler);
2887 
2888         if (compiler->parser->synchronizing)
2889                 uc_compiler_parse_synchronize(compiler);
2890 }
2891 
2892 #endif /* NO_COMPILE */
2893 
2894 
2895 static uc_program_t *
2896 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **errp)
2897 {
2898 #ifdef NO_COMPILE
2899         if (errp)
2900                 xasprintf(errp, "Source code compilation not supported\n");
2901 
2902         return NULL;
2903 #else
2904         uc_exprstack_t expr = { .token = TK_EOF };
2905         uc_parser_t parser = { .config = config };
2906         uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr };
2907         uc_program_t *prog;
2908         uc_function_t *fn;
2909 
2910         prog = uc_program_new(source);
2911 
2912         uc_lexer_init(&parser.lex, config, source);
2913         uc_compiler_init(&compiler, "main", 0, prog,
2914                 config && config->strict_declarations);
2915 
2916         uc_compiler_parse_advance(&compiler);
2917 
2918         while (!uc_compiler_parse_match(&compiler, TK_EOF))
2919                 uc_compiler_compile_declaration(&compiler);
2920 
2921         fn = uc_compiler_finish(&compiler);
2922 
2923         if (errp) {
2924                 *errp = parser.error ? parser.error->buf : NULL;
2925                 free(parser.error);
2926         }
2927         else {
2928                 printbuf_free(parser.error);
2929         }
2930 
2931         uc_lexer_free(&parser.lex);
2932 
2933         if (!fn) {
2934                 ucv_put(&prog->header);
2935 
2936                 return NULL;
2937         }
2938 
2939         return prog;
2940 #endif
2941 }
2942 
2943 static uc_program_t *
2944 uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp)
2945 {
2946         uc_program_t *prog;
2947 
2948         prog = uc_program_load(source, errp);
2949 
2950         if (prog && !uc_program_entry(prog)) {
2951                 if (errp)
2952                         xasprintf(errp, "Program file contains no entry function\n");
2953 
2954                 ucv_put(&prog->header);
2955         }
2956 
2957         return prog;
2958 }
2959 
2960 uc_program_t *
2961 uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp)
2962 {
2963         uc_program_t *prog = NULL;
2964 
2965         switch (uc_source_type_test(source)) {
2966         case UC_SOURCE_TYPE_PLAIN:
2967                 prog = uc_compile_from_source(config, source, errp);
2968                 break;
2969 
2970         case UC_SOURCE_TYPE_PRECOMPILED:
2971                 prog = uc_compile_from_bytecode(config, source, errp);
2972                 break;
2973 
2974         default:
2975                 if (errp)
2976                         xasprintf(errp, "Unrecognized source type\n");
2977 
2978                 break;
2979         }
2980 
2981         return prog;
2982 }
2983 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt