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