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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt