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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt