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