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

Sources/ucode/compiler.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt