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