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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt