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

Sources/ucode/compiler.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt