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 slot = uc_compiler_resolve_funcstub(compiler, name); 1953 1954 if (slot > -1) { 1955 compiler->locals.entries[slot].funcstub = false; 1956 } 1957 else { 1958 slot = uc_compiler_declare_local(compiler, name, false); 1959 1960 if (slot == -1) 1961 uc_compiler_initialize_local(compiler); 1962 else if (compiler->locals.entries[slot].constant) 1963 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 1964 "Redeclaration of constant '%s'", 1965 ucv_string_get(name)); 1966 } 1967 } 1968 else if (require_name) { 1969 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting function name"); 1970 } 1971 1972 uc_compiler_init(&fncompiler, 1973 name ? ucv_string_get(name) : NULL, 1974 uc_compiler_current_source(compiler), 1975 compiler->parser->prev.pos, 1976 compiler->program, 1977 uc_compiler_is_strict(compiler)); 1978 1979 fncompiler.parent = compiler; 1980 fncompiler.parser = compiler->parser; 1981 fncompiler.exprstack = compiler->exprstack; 1982 fn = (uc_function_t *)fncompiler.function; 1983 1984 uc_compiler_parse_consume(&fncompiler, TK_LPAREN); 1985 1986 uc_compiler_enter_scope(&fncompiler); 1987 1988 /* compile argument specification */ 1989 while (true) { 1990 if (uc_compiler_parse_check(&fncompiler, TK_RPAREN)) 1991 break; 1992 1993 if (uc_compiler_parse_match(&fncompiler, TK_ELLIP)) 1994 fn->vararg = true; 1995 1996 if (uc_compiler_parse_match(&fncompiler, TK_LABEL)) { 1997 fn->nargs++; 1998 1999 uc_compiler_declare_local(&fncompiler, fncompiler.parser->prev.uv, false); 2000 uc_compiler_initialize_local(&fncompiler); 2001 2002 if (fn->vararg || 2003 !uc_compiler_parse_match(&fncompiler, TK_COMMA)) 2004 break; 2005 } 2006 else { 2007 uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos, 2008 "Expecting Label"); 2009 2010 return; 2011 } 2012 } 2013 2014 uc_compiler_parse_consume(&fncompiler, TK_RPAREN); 2015 2016 /* parse and compile function body */ 2017 if (uc_compiler_parse_match(&fncompiler, TK_COLON)) { 2018 last_statement_type = uc_compiler_compile_delimitted_block(&fncompiler, TK_ENDFUNC); 2019 uc_compiler_parse_consume(&fncompiler, TK_ENDFUNC); 2020 } 2021 else if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) { 2022 last_statement_type = uc_compiler_compile_delimitted_block(&fncompiler, TK_RBRACE); 2023 uc_compiler_parse_consume(&fncompiler, TK_RBRACE); 2024 } 2025 else { 2026 uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos, 2027 "Expecting '{' or ':' after function parameters"); 2028 } 2029 2030 /* emit load instruction for function value */ 2031 uc_compiler_emit_insn(compiler, pos, (type == TK_ARROW) ? I_ARFN : I_CLFN); 2032 load_off = uc_compiler_emit_u32(compiler, 0, 0); 2033 2034 /* encode upvalue information */ 2035 for (i = 0; i < fn->nupvals; i++) 2036 uc_compiler_emit_s32(compiler, 0, 2037 fncompiler.upvals.entries[i].local 2038 ? -(fncompiler.upvals.entries[i].index + 1) 2039 : fncompiler.upvals.entries[i].index); 2040 2041 /* finalize function compiler */ 2042 fn = uc_compiler_finish(&fncompiler, last_statement_type); 2043 2044 if (fn) 2045 uc_compiler_set_u32(compiler, load_off, 2046 uc_program_function_id(compiler->program, fn)); 2047 2048 /* if a local variable of the same name already existed, overwrite its value 2049 * with the compiled function here */ 2050 if (slot != -1) { 2051 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2052 uc_compiler_emit_u32(compiler, 0, slot); 2053 uc_compiler_emit_insn(compiler, 0, I_POP); 2054 } 2055 } 2056 2057 static void 2058 uc_compiler_compile_funcexpr(uc_compiler_t *compiler) 2059 { 2060 return uc_compiler_compile_funcexpr_common(compiler, false); 2061 } 2062 2063 static void 2064 uc_compiler_compile_funcdecl(uc_compiler_t *compiler) 2065 { 2066 return uc_compiler_compile_funcexpr_common(compiler, true); 2067 } 2068 2069 static void 2070 uc_compiler_compile_dot(uc_compiler_t *compiler) 2071 { 2072 bool optional_chaining = (compiler->parser->prev.type == TK_QDOT); 2073 2074 /* no regexp literal possible after property access */ 2075 compiler->parser->lex.no_regexp = true; 2076 2077 if (optional_chaining) 2078 uc_compiler_emit_jmpnt(compiler, compiler->parser->prev.pos, 2079 (1u << UC_ARRAY) | (1u << UC_OBJECT) | (1u << UC_RESOURCE), 0); 2080 2081 /* parse label lhs */ 2082 uc_compiler_parse_consume(compiler, TK_LABEL); 2083 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 2084 2085 /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */ 2086 if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL)) 2087 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QDOT : 0); 2088 2089 compiler->patchlist->depth = uc_compiler_current_chunk(compiler)->count; 2090 } 2091 2092 static void 2093 uc_compiler_compile_subscript(uc_compiler_t *compiler) 2094 { 2095 bool optional_chaining = (compiler->parser->prev.type == TK_QLBRACK); 2096 2097 if (optional_chaining) 2098 uc_compiler_emit_jmpnt(compiler, compiler->parser->prev.pos, 2099 (1u << UC_ARRAY) | (1u << UC_OBJECT) | (1u << UC_RESOURCE), 0); 2100 2101 /* compile lhs */ 2102 uc_compiler_compile_expression(compiler); 2103 2104 /* no regexp literal possible after computed property access */ 2105 compiler->parser->lex.no_regexp = true; 2106 uc_compiler_parse_consume(compiler, TK_RBRACK); 2107 2108 /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */ 2109 if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL)) 2110 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QLBRACK : 0); 2111 2112 compiler->patchlist->depth = uc_compiler_current_chunk(compiler)->count; 2113 } 2114 2115 static void 2116 uc_compiler_compile_ternary(uc_compiler_t *compiler) 2117 { 2118 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2119 size_t jmpz_off, jmp_off; 2120 2121 /* jump to false branch */ 2122 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2123 2124 /* compile true branch */ 2125 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2126 2127 /* jump after false branch */ 2128 jmp_off = uc_compiler_emit_jmp(compiler, 0); 2129 2130 uc_compiler_parse_consume(compiler, TK_COLON); 2131 2132 /* compile false branch */ 2133 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2134 uc_compiler_parse_precedence(compiler, P_TERNARY); 2135 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 2136 } 2137 2138 static void 2139 uc_compiler_compile_array(uc_compiler_t *compiler) 2140 { 2141 size_t hint_off, hint_count = 0, len = 0; 2142 2143 /* create empty array on stack */ 2144 uc_compiler_emit_insn(compiler, 0, I_NARR); 2145 hint_off = uc_compiler_emit_u32(compiler, 0, 0); 2146 2147 /* parse initializer values */ 2148 do { 2149 if (uc_compiler_parse_check(compiler, TK_RBRACK)) { 2150 break; 2151 } 2152 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) { 2153 /* push items on stack so far... */ 2154 if (len > 0) { 2155 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR); 2156 uc_compiler_emit_u32(compiler, 0, len); 2157 len = 0; 2158 } 2159 2160 /* compile spread value expression */ 2161 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2162 2163 /* emit merge operation */ 2164 uc_compiler_emit_insn(compiler, 0, I_MARR); 2165 } 2166 else { 2167 /* push items on stack so far... */ 2168 if (len >= 0xffffffff) { 2169 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR); 2170 uc_compiler_emit_u32(compiler, 0, len); 2171 len = 0; 2172 } 2173 2174 /* compile item value expression */ 2175 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2176 2177 hint_count++; 2178 len++; 2179 } 2180 } 2181 while (uc_compiler_parse_match(compiler, TK_COMMA)); 2182 2183 /* no regexp literal possible after array literal */ 2184 compiler->parser->lex.no_regexp = true; 2185 uc_compiler_parse_consume(compiler, TK_RBRACK); 2186 2187 /* push items on stack */ 2188 if (len > 0) { 2189 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR); 2190 uc_compiler_emit_u32(compiler, 0, len); 2191 } 2192 2193 /* set initial size hint */ 2194 uc_compiler_set_u32(compiler, hint_off, hint_count); 2195 } 2196 2197 static void 2198 uc_compiler_compile_object(uc_compiler_t *compiler) 2199 { 2200 size_t hint_off, hint_count = 0, len = 0; 2201 2202 /* create empty object on stack */ 2203 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_NOBJ); 2204 hint_off = uc_compiler_emit_u32(compiler, 0, 0); 2205 2206 /* parse initializer values */ 2207 do { 2208 /* End of object literal */ 2209 if (uc_compiler_parse_check(compiler, TK_RBRACE)) 2210 break; 2211 2212 /* Spread operator */ 2213 if (uc_compiler_parse_match(compiler, TK_ELLIP)) { 2214 /* set items on stack so far... */ 2215 if (len > 0) { 2216 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ); 2217 uc_compiler_emit_u32(compiler, 0, len); 2218 len = 0; 2219 } 2220 2221 /* compile spread value expression */ 2222 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2223 2224 /* emit merge operation */ 2225 uc_compiler_emit_insn(compiler, 0, I_MOBJ); 2226 2227 compiler->parser->lex.no_keyword = true; 2228 continue; 2229 } 2230 2231 /* Computed property name */ 2232 if (uc_compiler_parse_match(compiler, TK_LBRACK)) { 2233 /* parse property name expression */ 2234 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2235 2236 /* consume closing bracket and colon */ 2237 uc_compiler_parse_consume(compiler, TK_RBRACK); 2238 uc_compiler_parse_consume(compiler, TK_COLON); 2239 2240 /* parse value expression */ 2241 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2242 } 2243 2244 /* Property/value tuple or property shorthand */ 2245 else { 2246 /* parse key expression */ 2247 if (!uc_compiler_parse_match(compiler, TK_LABEL) && 2248 !uc_compiler_parse_match(compiler, TK_STRING)) 2249 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2250 "Expecting label"); 2251 2252 /* load label */ 2253 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, 2254 compiler->parser->prev.uv); 2255 2256 /* If the property name is a plain label followed by a comma or 2257 * closing curly brace, treat it as ES2015 property shorthand 2258 * notation... */ 2259 if (compiler->parser->prev.type == TK_LABEL && 2260 (uc_compiler_parse_check(compiler, TK_COMMA) || 2261 uc_compiler_parse_check(compiler, TK_RBRACE))) { 2262 /* disallow keywords in this case */ 2263 if (uc_lexer_is_keyword(compiler->parser->prev.uv)) 2264 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 2265 "Invalid identifier"); 2266 2267 uc_compiler_emit_variable_rw(compiler, 2268 compiler->parser->prev.uv, 0); 2269 } 2270 2271 /* ... otherwise treat it as ordinary `key: value` tuple */ 2272 else { 2273 uc_compiler_parse_consume(compiler, TK_COLON); 2274 2275 /* parse value expression */ 2276 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2277 } 2278 } 2279 2280 /* set items on stack so far... */ 2281 if (len >= 0xfffffffe) { 2282 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ); 2283 uc_compiler_emit_u32(compiler, 0, len); 2284 len = 0; 2285 } 2286 2287 hint_count += 2; 2288 len += 2; 2289 2290 compiler->parser->lex.no_keyword = true; 2291 } 2292 while (uc_compiler_parse_match(compiler, TK_COMMA)); 2293 2294 /* no regexp literal possible after object literal */ 2295 compiler->parser->lex.no_regexp = true; 2296 uc_compiler_parse_consume(compiler, TK_RBRACE); 2297 2298 /* set items on stack */ 2299 if (len > 0) { 2300 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ); 2301 uc_compiler_emit_u32(compiler, 0, len); 2302 } 2303 2304 /* set initial size hint */ 2305 uc_compiler_set_u32(compiler, hint_off, hint_count); 2306 } 2307 2308 2309 static void 2310 uc_compiler_declare_local_null(uc_compiler_t *compiler, size_t srcpos, uc_value_t *varname) 2311 { 2312 ssize_t existing_slot = uc_compiler_declare_local(compiler, varname, false); 2313 2314 uc_compiler_emit_insn(compiler, srcpos, I_LNULL); 2315 2316 if (existing_slot == -1) { 2317 uc_compiler_initialize_local(compiler); 2318 } 2319 else { 2320 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2321 uc_compiler_emit_u32(compiler, 0, existing_slot); 2322 uc_compiler_emit_insn(compiler, 0, I_POP); 2323 } 2324 } 2325 2326 static size_t 2327 uc_compiler_declare_internal(uc_compiler_t *compiler, size_t srcpos, const char *name) 2328 { 2329 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2330 uc_locals_t *locals = &compiler->locals; 2331 2332 uc_vector_push(locals, { 2333 .name = ucv_string_new(name), 2334 .depth = compiler->scope_depth, 2335 .captured = false, 2336 .from = chunk->count 2337 }); 2338 2339 return locals->count - 1; 2340 } 2341 2342 static void 2343 uc_compiler_compile_declexpr(uc_compiler_t *compiler, bool constant) 2344 { 2345 ssize_t slot; 2346 2347 do { 2348 /* parse variable name */ 2349 if (!uc_compiler_parse_match(compiler, TK_LABEL)) { 2350 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2351 "Expecting variable name"); 2352 2353 return; 2354 } 2355 2356 /* declare local variable */ 2357 slot = uc_compiler_declare_local(compiler, compiler->parser->prev.uv, constant); 2358 2359 /* if followed by '=', parse initializer expression */ 2360 if (uc_compiler_parse_match(compiler, TK_ASSIGN)) 2361 uc_compiler_parse_precedence(compiler, P_ASSIGN); 2362 /* otherwise, for writable variables, load implicit null */ 2363 else if (!constant) 2364 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL); 2365 /* for constant variables, a missing initializer is a syntax error */ 2366 else 2367 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 2368 "Expecting initializer expression"); 2369 2370 /* initialize local */ 2371 if (slot == -1) { 2372 uc_compiler_initialize_local(compiler); 2373 } 2374 /* if the variable was redeclared, overwrite it */ 2375 else { 2376 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2377 uc_compiler_emit_u32(compiler, 0, slot); 2378 uc_compiler_emit_insn(compiler, 0, I_POP); 2379 } 2380 } 2381 while (uc_compiler_parse_match(compiler, TK_COMMA)); 2382 } 2383 2384 static void 2385 uc_compiler_compile_local(uc_compiler_t *compiler) 2386 { 2387 uc_compiler_compile_declexpr(compiler, false); 2388 uc_compiler_parse_consume(compiler, TK_SCOL); 2389 } 2390 2391 static void 2392 uc_compiler_compile_const(uc_compiler_t *compiler) 2393 { 2394 uc_compiler_compile_declexpr(compiler, true); 2395 uc_compiler_parse_consume(compiler, TK_SCOL); 2396 } 2397 2398 static uc_tokentype_t 2399 uc_compiler_compile_altifblock(uc_compiler_t *compiler) 2400 { 2401 uc_compiler_enter_scope(compiler); 2402 2403 while (true) { 2404 switch (compiler->parser->curr.type) { 2405 case TK_ELIF: 2406 case TK_ELSE: 2407 case TK_ENDIF: 2408 case TK_EOF: 2409 uc_compiler_leave_scope(compiler); 2410 2411 return compiler->parser->curr.type; 2412 2413 default: 2414 uc_compiler_compile_declaration(compiler); 2415 break; 2416 } 2417 } 2418 2419 return 0; 2420 } 2421 2422 static void 2423 uc_compiler_compile_if(uc_compiler_t *compiler) 2424 { 2425 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2426 size_t jmpz_off, jmp_off, i; 2427 bool expect_endif = false; 2428 uc_jmplist_t elifs = { 0 }; 2429 uc_tokentype_t type; 2430 2431 /* parse & compile condition expression */ 2432 uc_compiler_parse_consume(compiler, TK_LPAREN); 2433 uc_compiler_compile_expression(compiler); 2434 uc_compiler_parse_consume(compiler, TK_RPAREN); 2435 2436 /* conditional jump to else/elif branch */ 2437 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2438 2439 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2440 compiler->exprstack->flags |= F_ALTBLOCKMODE; 2441 2442 while (true) { 2443 /* compile elsif or else branch */ 2444 type = uc_compiler_compile_altifblock(compiler); 2445 2446 /* we just compiled an elsif block */ 2447 if (!expect_endif && type == TK_ELIF) { 2448 /* emit jump to skip to the end */ 2449 uc_vector_push(&elifs, uc_compiler_emit_jmp(compiler, 0)); 2450 2451 /* point previous conditional jump to beginning of branch */ 2452 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2453 2454 /* parse & compile elsif condition */ 2455 uc_compiler_parse_advance(compiler); 2456 uc_compiler_parse_consume(compiler, TK_LPAREN); 2457 uc_compiler_compile_expression(compiler); 2458 uc_compiler_parse_consume(compiler, TK_RPAREN); 2459 uc_compiler_parse_consume(compiler, TK_COLON); 2460 2461 /* conditional jump to else/elif branch */ 2462 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2463 } 2464 else if (!expect_endif && type == TK_ELSE) { 2465 /* emit jump to skip to the end */ 2466 uc_vector_push(&elifs, uc_compiler_emit_jmp(compiler, 0)); 2467 2468 /* point previous conditional jump to beginning of branch */ 2469 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2470 jmpz_off = 0; 2471 2472 /* skip "else" keyword */ 2473 uc_compiler_parse_advance(compiler); 2474 2475 expect_endif = true; 2476 } 2477 else if (type == TK_ENDIF) { 2478 /* if no else clause, point previous conditional jump after block */ 2479 if (jmpz_off) 2480 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2481 2482 /* patch the elif branch jumps to point here after the else */ 2483 for (i = 0; i < elifs.count; i++) 2484 uc_compiler_set_jmpaddr(compiler, elifs.entries[i], 2485 chunk->count); 2486 2487 /* skip the "endif" keyword */ 2488 uc_compiler_parse_advance(compiler); 2489 break; 2490 } 2491 else { 2492 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2493 expect_endif 2494 ? "Expecting 'endif'" 2495 : "Expecting 'elif', 'else' or 'endif'"); 2496 2497 break; 2498 } 2499 } 2500 2501 uc_vector_clear(&elifs); 2502 } 2503 else { 2504 /* compile true branch */ 2505 uc_compiler_compile_statement(compiler); 2506 2507 /* ... when present, handle false branch */ 2508 if (uc_compiler_parse_match(compiler, TK_ELSE)) { 2509 /* jump to skip else branch */ 2510 jmp_off = uc_compiler_emit_jmp(compiler, 0); 2511 2512 /* set conditional jump address */ 2513 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2514 2515 /* compile false branch */ 2516 uc_compiler_compile_statement(compiler); 2517 2518 /* set else skip jump address */ 2519 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 2520 } 2521 /* ... otherwise point the conditional jump after the true branch */ 2522 else { 2523 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2524 } 2525 } 2526 } 2527 2528 static void 2529 uc_compiler_compile_while(uc_compiler_t *compiler) 2530 { 2531 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2532 uc_patchlist_t p = { .depth = compiler->scope_depth, .token = TK_WHILE }; 2533 size_t cond_off, jmpz_off, end_off; 2534 2535 p.parent = compiler->patchlist; 2536 compiler->patchlist = &p; 2537 2538 cond_off = chunk->count; 2539 2540 /* parse & compile loop condition */ 2541 uc_compiler_parse_consume(compiler, TK_LPAREN); 2542 uc_compiler_compile_expression(compiler); 2543 uc_compiler_parse_consume(compiler, TK_RPAREN); 2544 2545 /* conditional jump to end */ 2546 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2547 2548 /* compile loop body */ 2549 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2550 uc_compiler_enter_scope(compiler); 2551 2552 if (uc_compiler_compile_delimitted_block(compiler, TK_ENDWHILE) == TK_EOF) 2553 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2554 "Expecting 'endwhile'"); 2555 else 2556 uc_compiler_parse_advance(compiler); 2557 2558 uc_compiler_leave_scope(compiler); 2559 } 2560 else { 2561 uc_compiler_compile_statement(compiler); 2562 } 2563 2564 end_off = chunk->count; 2565 2566 /* jump back to condition */ 2567 uc_compiler_emit_jmp_dest(compiler, 0, cond_off); 2568 2569 /* set conditional jump target */ 2570 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2571 2572 /* patch up break/continue */ 2573 uc_compiler_backpatch(compiler, chunk->count, end_off); 2574 } 2575 2576 static void 2577 uc_compiler_compile_for_in(uc_compiler_t *compiler, bool local, uc_token_t *kvar, uc_token_t *vvar) 2578 { 2579 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2580 uc_patchlist_t p = { .depth = compiler->scope_depth + 1, .token = TK_FOR }; 2581 size_t skip_jmp, test_jmp, key_slot, val_slot; 2582 2583 p.parent = compiler->patchlist; 2584 compiler->patchlist = &p; 2585 2586 uc_compiler_enter_scope(compiler); 2587 2588 /* declare internal loop variables */ 2589 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2590 key_slot = uc_compiler_declare_internal(compiler, 0, "(for in key)"); 2591 2592 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2593 val_slot = uc_compiler_declare_internal(compiler, 0, "(for in value)"); 2594 2595 /* declare loop variables */ 2596 if (local) { 2597 uc_compiler_declare_local_null(compiler, kvar->pos, kvar->uv); 2598 2599 if (vvar) 2600 uc_compiler_declare_local_null(compiler, vvar->pos, vvar->uv); 2601 } 2602 2603 /* value to iterate */ 2604 uc_compiler_compile_expression(compiler); 2605 uc_compiler_parse_consume(compiler, TK_RPAREN); 2606 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2607 uc_compiler_emit_u32(compiler, 0, val_slot); 2608 2609 /* initial key value */ 2610 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2611 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2612 uc_compiler_emit_u32(compiler, 0, key_slot); 2613 2614 /* jump over variable read for first cycle */ 2615 skip_jmp = uc_compiler_emit_jmp(compiler, 0); 2616 2617 /* read value */ 2618 uc_compiler_emit_insn(compiler, 0, I_LLOC); 2619 uc_compiler_emit_u32(compiler, 0, val_slot); 2620 2621 /* read key */ 2622 uc_compiler_emit_insn(compiler, 0, I_LLOC); 2623 uc_compiler_emit_u32(compiler, 0, key_slot); 2624 2625 /* backpatch skip jump */ 2626 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); 2627 2628 /* load loop variable and get next key from object */ 2629 uc_compiler_emit_insn(compiler, 0, vvar ? I_NEXTKV : I_NEXTK); 2630 2631 /* set internal key variable */ 2632 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2633 uc_compiler_emit_u32(compiler, 0, key_slot); 2634 2635 /* test for != null */ 2636 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2637 uc_compiler_emit_insn(compiler, 0, I_NES); 2638 2639 /* jump after loop body if no next key */ 2640 test_jmp = uc_compiler_emit_jmpz(compiler, 0); 2641 2642 /* set key and value variables */ 2643 if (vvar) { 2644 uc_compiler_emit_variable_rw(compiler, vvar->uv, TK_ASSIGN); 2645 uc_compiler_emit_insn(compiler, 0, I_POP); 2646 } 2647 2648 /* set key variable */ 2649 uc_compiler_emit_variable_rw(compiler, kvar->uv, TK_ASSIGN); 2650 uc_compiler_emit_insn(compiler, 0, I_POP); 2651 2652 /* compile loop body */ 2653 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2654 uc_compiler_enter_scope(compiler); 2655 2656 if (uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR) == TK_EOF) 2657 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2658 "Expecting 'endfor'"); 2659 else 2660 uc_compiler_parse_advance(compiler); 2661 2662 uc_compiler_leave_scope(compiler); 2663 } 2664 else { 2665 uc_compiler_compile_statement(compiler); 2666 } 2667 2668 /* jump back to retrieve next key */ 2669 uc_compiler_emit_jmp_dest(compiler, 0, skip_jmp + 5); 2670 2671 /* back patch conditional jump */ 2672 uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count); 2673 2674 /* pop loop variables */ 2675 uc_compiler_emit_insn(compiler, 0, I_POP); 2676 2677 if (vvar) 2678 uc_compiler_emit_insn(compiler, 0, I_POP); 2679 2680 /* patch up break/continue */ 2681 uc_compiler_backpatch(compiler, chunk->count, skip_jmp + 5); 2682 2683 uc_compiler_leave_scope(compiler); 2684 } 2685 2686 static void 2687 uc_compiler_compile_for_count(uc_compiler_t *compiler, bool local, uc_token_t *var) 2688 { 2689 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2690 size_t test_off = 0, incr_off, skip_off, cond_off = 0; 2691 uc_patchlist_t p = { .depth = compiler->scope_depth + 1, .token = TK_FOR }; 2692 2693 p.parent = compiler->patchlist; 2694 compiler->patchlist = &p; 2695 2696 uc_compiler_enter_scope(compiler); 2697 2698 /* Initializer ---------------------------------------------------------- */ 2699 2700 /* If we parsed at least one label, try continue parsing as variable 2701 * expression... */ 2702 if (var) { 2703 /* We parsed a `local x` or `local x, y` expression, so (re)declare 2704 * last label as local initializer variable */ 2705 if (local) 2706 uc_compiler_declare_local_null(compiler, var->pos, var->uv); 2707 2708 uc_compiler_exprstack_push(compiler, TK_FOR, F_ASSIGNABLE); 2709 2710 uc_compiler_compile_labelexpr(compiler); 2711 uc_compiler_emit_insn(compiler, 0, I_POP); 2712 2713 /* If followed by a comma, continue parsing expression */ 2714 if (uc_compiler_parse_match(compiler, TK_COMMA)) { 2715 /* Is a continuation of a declaration list... */ 2716 if (local) { 2717 uc_compiler_compile_declexpr(compiler, false); 2718 } 2719 /* ... otherwise an unrelated expression */ 2720 else { 2721 uc_compiler_compile_expression(compiler); 2722 uc_compiler_emit_insn(compiler, 0, I_POP); 2723 } 2724 } 2725 2726 uc_compiler_exprstack_pop(compiler); 2727 } 2728 /* ... otherwise try parsing an entire expression (which might be absent) */ 2729 else if (!uc_compiler_parse_check(compiler, TK_SCOL)) { 2730 uc_compiler_compile_expression(compiler); 2731 uc_compiler_emit_insn(compiler, 0, I_POP); 2732 } 2733 2734 uc_compiler_parse_consume(compiler, TK_SCOL); 2735 2736 2737 /* Condition ------------------------------------------------------------ */ 2738 if (!uc_compiler_parse_check(compiler, TK_SCOL)) { 2739 cond_off = chunk->count; 2740 2741 uc_compiler_compile_expression(compiler); 2742 2743 test_off = uc_compiler_emit_jmpz(compiler, 0); 2744 } 2745 2746 uc_compiler_parse_consume(compiler, TK_SCOL); 2747 2748 /* jump over incrementer */ 2749 skip_off = uc_compiler_emit_jmp(compiler, 0); 2750 2751 2752 /* Incrementer ---------------------------------------------------------- */ 2753 incr_off = chunk->count; 2754 2755 if (!uc_compiler_parse_check(compiler, TK_RPAREN)) { 2756 uc_compiler_compile_expression(compiler); 2757 uc_compiler_emit_insn(compiler, 0, I_POP); 2758 } 2759 2760 uc_compiler_parse_consume(compiler, TK_RPAREN); 2761 2762 /* if we have a condition, jump back to it, else continue to the loop body */ 2763 if (cond_off) 2764 uc_compiler_emit_jmp_dest(compiler, 0, cond_off); 2765 2766 /* back patch skip address */ 2767 uc_compiler_set_jmpaddr(compiler, skip_off, chunk->count); 2768 2769 2770 /* Body ----------------------------------------------------------------- */ 2771 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2772 uc_compiler_enter_scope(compiler); 2773 2774 if (uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR) == TK_EOF) 2775 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2776 "Expecting 'endfor'"); 2777 else 2778 uc_compiler_parse_advance(compiler); 2779 2780 uc_compiler_leave_scope(compiler); 2781 } 2782 else { 2783 uc_compiler_compile_statement(compiler); 2784 } 2785 2786 /* jump back to incrementer */ 2787 uc_compiler_emit_jmp_dest(compiler, 0, incr_off); 2788 2789 /* back patch conditional jump */ 2790 if (test_off) 2791 uc_compiler_set_jmpaddr(compiler, test_off, chunk->count); 2792 2793 /* patch up break/continue */ 2794 uc_compiler_backpatch(compiler, chunk->count, incr_off); 2795 2796 uc_compiler_leave_scope(compiler); 2797 } 2798 2799 static void 2800 uc_compiler_compile_for(uc_compiler_t *compiler) 2801 { 2802 uc_token_t keyvar = { 0 }, valvar = { 0 }; 2803 bool local; 2804 2805 uc_compiler_parse_consume(compiler, TK_LPAREN); 2806 2807 /* check the next few tokens and see if we have either a 2808 * `let x in` / `let x, y` expression or an ordinary initializer 2809 * statement */ 2810 2811 local = uc_compiler_parse_match(compiler, TK_LOCAL); 2812 2813 if (uc_compiler_parse_match(compiler, TK_LABEL)) { 2814 keyvar = compiler->parser->prev; 2815 ucv_get(keyvar.uv); 2816 2817 if (uc_compiler_parse_match(compiler, TK_COMMA)) { 2818 uc_compiler_parse_consume(compiler, TK_LABEL); 2819 2820 valvar = compiler->parser->prev; 2821 ucv_get(valvar.uv); 2822 } 2823 2824 /* is a for-in loop */ 2825 if (uc_compiler_parse_match(compiler, TK_IN)) { 2826 uc_compiler_compile_for_in(compiler, local, &keyvar, 2827 valvar.type ? &valvar : NULL); 2828 2829 goto out; 2830 } 2831 } 2832 else if (local) { 2833 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2834 "Expecting label after 'local'"); 2835 2836 goto out; 2837 } 2838 2839 /* 2840 * The previous expression ruled out a for-in loop, so continue parsing 2841 * as counting for loop... 2842 */ 2843 uc_compiler_compile_for_count(compiler, local, 2844 valvar.uv ? &valvar : (keyvar.uv ? &keyvar : NULL)); 2845 2846 out: 2847 ucv_put(keyvar.uv); 2848 ucv_put(valvar.uv); 2849 } 2850 2851 static void 2852 uc_compiler_compile_switch(uc_compiler_t *compiler) 2853 { 2854 size_t i, test_jmp, skip_jmp, next_jmp = 0, value_slot, default_off = 0; 2855 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2856 uc_patchlist_t p = { .depth = compiler->scope_depth, .token = TK_SWITCH }; 2857 uc_locals_t *locals = &compiler->locals; 2858 uc_jmplist_t cases = { 0 }; 2859 2860 p.parent = compiler->patchlist; 2861 compiler->patchlist = &p; 2862 2863 uc_compiler_enter_scope(compiler); 2864 2865 /* parse and compile match value */ 2866 uc_compiler_parse_consume(compiler, TK_LPAREN); 2867 uc_compiler_compile_expression(compiler); 2868 uc_compiler_parse_consume(compiler, TK_RPAREN); 2869 uc_compiler_parse_consume(compiler, TK_LBRACE); 2870 2871 value_slot = uc_compiler_declare_internal(compiler, 0, "(switch value)"); 2872 2873 /* jump to branch tests */ 2874 test_jmp = uc_compiler_emit_jmp(compiler, 0); 2875 2876 /* parse and compile case matches */ 2877 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 2878 !uc_compiler_parse_check(compiler, TK_EOF)) { 2879 /* handle `default:` */ 2880 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) { 2881 if (default_off) { 2882 uc_vector_clear(&cases); 2883 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 2884 "more than one switch default case"); 2885 2886 break; 2887 } 2888 2889 uc_compiler_parse_consume(compiler, TK_COLON); 2890 2891 /* remember address of default branch */ 2892 default_off = chunk->count; 2893 2894 /* Store three values in case offset list: 2895 * 1) amount of local variables declared so far 2896 * 2) beginning of condition expression 2897 * 3) end of condition expression 2898 * For the `default` case, beginning and end offsets of the 2899 * condition expression are equal. 2900 */ 2901 uc_vector_extend(&cases, 3); 2902 cases.entries[cases.count++] = (locals->count - 1) - value_slot; 2903 cases.entries[cases.count++] = chunk->count; 2904 cases.entries[cases.count++] = chunk->count; 2905 } 2906 2907 /* handle `case …:` */ 2908 else if (uc_compiler_parse_match(compiler, TK_CASE)) { 2909 /* jump over `case …:` label expression */ 2910 skip_jmp = uc_compiler_emit_jmp(compiler, 0); 2911 2912 /* compile case value expression */ 2913 uc_compiler_compile_expression(compiler); 2914 uc_compiler_parse_consume(compiler, TK_COLON); 2915 2916 /* Store three values in case offset list: 2917 * 1) amount of local variables declared so far 2918 * 2) beginning of condition expression 2919 * 3) end of condition expression 2920 */ 2921 uc_vector_extend(&cases, 3); 2922 cases.entries[cases.count++] = (locals->count - 1) - value_slot; 2923 cases.entries[cases.count++] = skip_jmp + 5; 2924 cases.entries[cases.count++] = uc_compiler_emit_jmp(compiler, 0); 2925 2926 /* patch jump skipping over the case value */ 2927 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); 2928 } 2929 2930 /* handle interleaved statement */ 2931 else if (cases.count) { 2932 uc_compiler_compile_declaration(compiler); 2933 } 2934 2935 /* a statement or expression preceding any `default` or `case` is a 2936 * syntax error */ 2937 else { 2938 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2939 "Expecting 'case' or 'default'"); 2940 2941 break; 2942 } 2943 } 2944 2945 uc_compiler_parse_consume(compiler, TK_RBRACE); 2946 2947 /* evaluate case matches */ 2948 if (cases.count) { 2949 skip_jmp = uc_compiler_emit_jmp(compiler, 0); 2950 2951 uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count); 2952 2953 for (i = 0, default_off = cases.count; i < cases.count; i += 3) { 2954 /* remember and skip default case */ 2955 if (cases.entries[i + 1] == cases.entries[i + 2]) { 2956 default_off = i; 2957 continue; 2958 } 2959 2960 /* read switch match value */ 2961 uc_compiler_emit_insn(compiler, 0, I_LLOC); 2962 uc_compiler_emit_u32(compiler, 0, value_slot); 2963 2964 /* jump to case value expression code */ 2965 uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 1]); 2966 2967 /* patch final case value expression jump back here */ 2968 uc_compiler_set_jmpaddr(compiler, cases.entries[i + 2], chunk->count); 2969 2970 /* strict equal test */ 2971 uc_compiler_emit_insn(compiler, 0, I_EQS); 2972 2973 /* conditional jump to next match */ 2974 next_jmp = uc_compiler_emit_jmpz(compiler, 0); 2975 2976 /* fill local slots */ 2977 while (cases.entries[i + 0] > 0) { 2978 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2979 cases.entries[i + 0]--; 2980 } 2981 2982 /* jump to target code */ 2983 uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 2] + 5); 2984 2985 /* patch next jump */ 2986 uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count); 2987 } 2988 2989 /* handle default case (if any) */ 2990 if (default_off < cases.count) { 2991 /* fill local slots */ 2992 while (cases.entries[default_off + 0] > 0) { 2993 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2994 cases.entries[default_off + 0]--; 2995 } 2996 2997 /* jump to target */ 2998 uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[default_off + 2]); 2999 3000 /* do not patch final match failure jump later, we handle it here 3001 * in the default case */ 3002 next_jmp = 0; 3003 } 3004 3005 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); 3006 } 3007 else { 3008 uc_compiler_set_jmpaddr(compiler, test_jmp, test_jmp + 5); 3009 } 3010 3011 uc_vector_clear(&cases); 3012 3013 uc_compiler_leave_scope(compiler); 3014 3015 /* if no default case exists, patch last case match failure jump */ 3016 if (next_jmp) { 3017 /* There's pop instructions for all local variables including the 3018 * switch test value itself on the stack. Jump onto the last POP 3019 * instruction (-1) to get rid of the on-stack switch test value 3020 * but skip the POP instructions for all other scoped local variables 3021 * which never have been initialized. */ 3022 uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count - 1); 3023 } 3024 3025 uc_compiler_backpatch(compiler, chunk->count, 0); 3026 } 3027 3028 static void 3029 uc_compiler_compile_try(uc_compiler_t *compiler) 3030 { 3031 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 3032 size_t try_from = 0, try_to = 0, jmp_off = 0, ehvar_slot = 0; 3033 uc_ehranges_t *ranges = &chunk->ehranges; 3034 3035 try_from = chunk->count; 3036 ehvar_slot = compiler->locals.count; 3037 3038 /* Try block ------------------------------------------------------------ */ 3039 uc_compiler_enter_scope(compiler); 3040 3041 uc_compiler_parse_consume(compiler, TK_LBRACE); 3042 3043 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 3044 !uc_compiler_parse_check(compiler, TK_EOF)) 3045 uc_compiler_compile_declaration(compiler); 3046 3047 uc_compiler_parse_consume(compiler, TK_RBRACE); 3048 3049 uc_compiler_leave_scope(compiler); 3050 3051 /* jump beyond catch branch */ 3052 try_to = chunk->count; 3053 jmp_off = uc_compiler_emit_jmp(compiler, 0); 3054 3055 3056 /* Catch block ---------------------------------------------------------- */ 3057 if (try_to > try_from) { 3058 uc_vector_push(ranges, { 3059 .from = try_from, 3060 .to = try_to, 3061 .target = chunk->count, 3062 .slot = ehvar_slot 3063 }); 3064 } 3065 3066 uc_compiler_enter_scope(compiler); 3067 3068 uc_compiler_parse_consume(compiler, TK_CATCH); 3069 3070 /* have exception variable */ 3071 if (uc_compiler_parse_match(compiler, TK_LPAREN)) { 3072 uc_compiler_parse_consume(compiler, TK_LABEL); 3073 3074 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, false); 3075 uc_compiler_initialize_local(compiler); 3076 3077 uc_compiler_parse_consume(compiler, TK_RPAREN); 3078 } 3079 /* ... else pop exception object from stack */ 3080 else { 3081 uc_compiler_emit_insn(compiler, 0, I_POP); 3082 } 3083 3084 uc_compiler_parse_consume(compiler, TK_LBRACE); 3085 3086 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 3087 !uc_compiler_parse_check(compiler, TK_EOF)) 3088 uc_compiler_compile_declaration(compiler); 3089 3090 uc_compiler_parse_consume(compiler, TK_RBRACE); 3091 3092 uc_compiler_leave_scope(compiler); 3093 3094 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 3095 } 3096 3097 static void 3098 uc_compiler_compile_control(uc_compiler_t *compiler) 3099 { 3100 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 3101 uc_tokentype_t type = compiler->parser->prev.type; 3102 uc_patchlist_t *p = compiler->patchlist; 3103 uc_locals_t *locals = &compiler->locals; 3104 size_t i, pos = compiler->parser->prev.pos; 3105 3106 /* select applicable patchlist: for continue statements select the 3107 * first non-switch scope */ 3108 while (p) { 3109 if (type != TK_CONTINUE || p->token != TK_SWITCH) 3110 break; 3111 3112 p = p->parent; 3113 } 3114 3115 if (!p || p->token == TK_EXPORT) { 3116 uc_compiler_syntax_error(compiler, pos, 3117 (type == TK_BREAK) 3118 ? "break must be inside loop or switch" 3119 : "continue must be inside loop"); 3120 3121 return; 3122 } 3123 3124 /* pop locals in all scopes covered by the target patchlist */ 3125 for (i = locals->count; i > 0 && (size_t)locals->entries[i - 1].depth > p->depth; i--) 3126 uc_compiler_emit_insn(compiler, 0, 3127 locals->entries[i - 1].captured ? I_CUPV : I_POP); 3128 3129 uc_vector_push(p, 3130 uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type)); 3131 3132 uc_compiler_parse_consume(compiler, TK_SCOL); 3133 } 3134 3135 static void 3136 uc_compiler_compile_return(uc_compiler_t *compiler) 3137 { 3138 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 3139 3140 if (compiler->function->module) { 3141 uc_compiler_syntax_error(compiler, 0, "return must be inside function body"); 3142 3143 return; 3144 } 3145 3146 /* if we compiled an empty expression statement (`;`), load implicit null */ 3147 if (uc_compiler_compile_expstmt(compiler) == TK_NULL) 3148 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL); 3149 3150 /* otherwise overwrite the final I_POP instruction with I_RETURN */ 3151 else 3152 uc_chunk_pop(chunk); 3153 3154 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_RETURN); 3155 } 3156 3157 static void 3158 uc_compiler_compile_tplexp(uc_compiler_t *compiler) 3159 { 3160 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 3161 size_t off = chunk->count; 3162 3163 uc_compiler_compile_expression(compiler); 3164 3165 /* XXX: the lexer currently emits a superfluous trailing semicolon... */ 3166 uc_compiler_parse_match(compiler, TK_SCOL); 3167 3168 uc_compiler_parse_consume(compiler, TK_REXP); 3169 3170 if (chunk->count > off) 3171 uc_compiler_emit_insn(compiler, 0, I_PRINT); 3172 } 3173 3174 static void 3175 uc_compiler_compile_text(uc_compiler_t *compiler) 3176 { 3177 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 3178 uc_compiler_emit_insn(compiler, 0, I_PRINT); 3179 } 3180 3181 static uc_tokentype_t 3182 uc_compiler_compile_block(uc_compiler_t *compiler) 3183 { 3184 uc_tokentype_t last_statement_type = TK_NULL; 3185 3186 uc_compiler_enter_scope(compiler); 3187 3188 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 3189 !uc_compiler_parse_check(compiler, TK_EOF)) 3190 last_statement_type = uc_compiler_compile_declaration(compiler); 3191 3192 uc_compiler_parse_consume(compiler, TK_RBRACE); 3193 3194 uc_compiler_leave_scope(compiler); 3195 3196 return last_statement_type; 3197 } 3198 3199 static uc_tokentype_t 3200 uc_compiler_compile_expstmt(uc_compiler_t *compiler) 3201 { 3202 /* empty statement */ 3203 if (uc_compiler_parse_match(compiler, TK_SCOL)) 3204 return TK_NULL; 3205 3206 uc_compiler_compile_expression(compiler); 3207 3208 /* allow omitting final semicolon */ 3209 switch (compiler->parser->curr.type) { 3210 case TK_RBRACE: 3211 case TK_ELIF: 3212 case TK_ENDIF: 3213 case TK_ENDFOR: 3214 case TK_ENDWHILE: 3215 case TK_ENDFUNC: 3216 case TK_EOF: 3217 break; 3218 3219 case TK_ELSE: 3220 if (!uc_compiler_exprstack_is(compiler, F_ALTBLOCKMODE)) 3221 uc_compiler_parse_consume(compiler, TK_SCOL); 3222 3223 break; 3224 3225 default: 3226 uc_compiler_parse_consume(compiler, TK_SCOL); 3227 3228 break; 3229 } 3230 3231 uc_compiler_emit_insn(compiler, 0, I_POP); 3232 3233 return TK_SCOL; 3234 } 3235 3236 static uc_tokentype_t 3237 uc_compiler_compile_statement(uc_compiler_t *compiler) 3238 { 3239 uc_tokentype_t last_statement_type = compiler->parser->curr.type; 3240 uc_exprstack_t expr = { 3241 .token = compiler->parser->curr.type, 3242 .parent = compiler->exprstack 3243 }; 3244 3245 compiler->exprstack = &expr; 3246 3247 if (uc_compiler_parse_match(compiler, TK_IF)) 3248 uc_compiler_compile_if(compiler); 3249 else if (uc_compiler_parse_match(compiler, TK_WHILE)) 3250 uc_compiler_compile_while(compiler); 3251 else if (uc_compiler_parse_match(compiler, TK_FOR)) 3252 uc_compiler_compile_for(compiler); 3253 else if (uc_compiler_parse_match(compiler, TK_SWITCH)) 3254 uc_compiler_compile_switch(compiler); 3255 else if (uc_compiler_parse_match(compiler, TK_TRY)) 3256 uc_compiler_compile_try(compiler); 3257 else if (uc_compiler_parse_match(compiler, TK_FUNC)) 3258 uc_compiler_compile_funcdecl(compiler); 3259 else if (uc_compiler_parse_match(compiler, TK_BREAK)) 3260 uc_compiler_compile_control(compiler); 3261 else if (uc_compiler_parse_match(compiler, TK_CONTINUE)) 3262 uc_compiler_compile_control(compiler); 3263 else if (uc_compiler_parse_match(compiler, TK_RETURN)) 3264 uc_compiler_compile_return(compiler); 3265 else if (uc_compiler_parse_match(compiler, TK_TEXT)) 3266 uc_compiler_compile_text(compiler); 3267 else if (uc_compiler_parse_match(compiler, TK_LEXP)) 3268 uc_compiler_compile_tplexp(compiler); 3269 else if (uc_compiler_parse_match(compiler, TK_LBRACE)) 3270 last_statement_type = uc_compiler_compile_block(compiler); 3271 else 3272 last_statement_type = uc_compiler_compile_expstmt(compiler); 3273 3274 compiler->exprstack = expr.parent; 3275 3276 return last_statement_type; 3277 } 3278 3279 static void 3280 uc_compiler_export_add(uc_compiler_t *compiler, uc_value_t *name, ssize_t slot) 3281 { 3282 uc_source_t *source = uc_compiler_current_source(compiler); 3283 3284 uc_compiler_inc_exportnum(compiler); 3285 3286 if (!uc_source_export_add(source, name)) { 3287 if (name) 3288 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3289 "Duplicate export '%s' for module '%s'", ucv_string_get(name), source->filename); 3290 else 3291 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3292 "Duplicate default export for module '%s'", source->filename); 3293 } 3294 else { 3295 uc_vector_push(compiler->patchlist, slot); 3296 } 3297 } 3298 3299 static void 3300 uc_compiler_compile_exportlist(uc_compiler_t *compiler) 3301 { 3302 uc_value_t *label, *name; 3303 bool constant; 3304 ssize_t slot; 3305 3306 /* parse export symbols */ 3307 do { 3308 uc_compiler_parse_consume(compiler, TK_LABEL); 3309 3310 label = ucv_get(compiler->parser->prev.uv); 3311 name = NULL; 3312 3313 slot = uc_compiler_resolve_local(compiler, label, &constant); 3314 3315 if (slot == -1) { 3316 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3317 "Attempt to export undeclared or non-local variable '%s'", 3318 ucv_string_get(label)); 3319 } 3320 3321 if (uc_compiler_keyword_match(compiler, "as")) { 3322 if (uc_compiler_parse_match(compiler, TK_LABEL) || uc_compiler_parse_match(compiler, TK_STRING)) { 3323 name = ucv_get(compiler->parser->prev.uv); 3324 } 3325 else if (!uc_compiler_parse_match(compiler, TK_DEFAULT)) { 3326 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3327 "Unexpected token\nExpecting Label, String or 'default'"); 3328 } 3329 } 3330 else { 3331 name = ucv_get(label); 3332 } 3333 3334 uc_compiler_export_add(compiler, name, slot); 3335 3336 ucv_put(label); 3337 ucv_put(name); 3338 3339 if (uc_compiler_parse_match(compiler, TK_RBRACE)) 3340 break; 3341 } 3342 while (uc_compiler_parse_match(compiler, TK_COMMA)); 3343 3344 uc_compiler_parse_consume(compiler, TK_SCOL); 3345 } 3346 3347 static void 3348 uc_compiler_compile_export(uc_compiler_t *compiler) 3349 { 3350 uc_locals_t *locals = &compiler->locals; 3351 size_t off = locals->count; 3352 uc_value_t *name; 3353 ssize_t slot; 3354 3355 if (!compiler->function->module || compiler->scope_depth) { 3356 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3357 "Exports may only appear at top level of a module"); 3358 3359 return; 3360 } 3361 3362 if (uc_compiler_parse_match(compiler, TK_LBRACE)) { 3363 uc_compiler_compile_exportlist(compiler); 3364 3365 return; 3366 } 3367 3368 if (uc_compiler_parse_match(compiler, TK_LOCAL)) 3369 uc_compiler_compile_declexpr(compiler, false); 3370 else if (uc_compiler_parse_match(compiler, TK_CONST)) 3371 uc_compiler_compile_declexpr(compiler, true); 3372 else if (uc_compiler_parse_match(compiler, TK_FUNC)) { 3373 uc_compiler_compile_funcdecl(compiler); 3374 3375 for (; off < locals->count; off++) 3376 uc_compiler_export_add(compiler, locals->entries[off].name, off); 3377 3378 return; 3379 } 3380 else if (uc_compiler_parse_match(compiler, TK_DEFAULT)) 3381 uc_compiler_compile_expression(compiler); 3382 else 3383 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3384 "Unexpected token\nExpecting 'let', 'const', 'function', 'default' or '{'"); 3385 3386 if (off == locals->count) { 3387 name = ucv_string_new("(module default export)"); 3388 slot = uc_compiler_declare_local(compiler, name, true); 3389 ucv_put(name); 3390 3391 if (slot != -1) 3392 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3393 "Duplicate default export statement"); 3394 else 3395 uc_compiler_export_add(compiler, NULL, compiler->locals.count - 1); 3396 } 3397 else { 3398 for (; off < locals->count; off++) 3399 uc_compiler_export_add(compiler, locals->entries[off].name, off); 3400 } 3401 3402 uc_compiler_parse_consume(compiler, TK_SCOL); 3403 } 3404 3405 static uc_program_t * 3406 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, uc_program_t *prog, char **errp); 3407 3408 static bool 3409 uc_compiler_compile_dynload(uc_compiler_t *compiler, const char *name, uc_value_t *imports) 3410 { 3411 uc_value_t *modname = ucv_string_new(name); 3412 size_t i, n_imports; 3413 uc_value_t *import; 3414 3415 for (i = 0, n_imports = 0; i < ucv_array_length(imports); i++) { 3416 import = ucv_array_get(imports, i); 3417 3418 if (ucv_boolean_get(import)) { 3419 uc_compiler_emit_constant(compiler, 0, modname); 3420 uc_compiler_emit_insn(compiler, 0, I_DYNLOAD); 3421 uc_compiler_emit_u32(compiler, 0, 0); 3422 } 3423 else { 3424 n_imports++; 3425 } 3426 } 3427 3428 if (n_imports > 0) { 3429 uc_compiler_emit_constant(compiler, 0, modname); 3430 uc_compiler_emit_insn(compiler, 0, I_DYNLOAD); 3431 uc_compiler_emit_u32(compiler, 0, n_imports | ((compiler->upvals.count - n_imports) << 16)); 3432 3433 for (i = 0; i < ucv_array_length(imports); i++) { 3434 import = ucv_get(ucv_array_get(imports, i)); 3435 3436 if (!import) 3437 import = ucv_string_new("default"); 3438 3439 if (!ucv_boolean_get(import)) 3440 uc_compiler_emit_constant_index(compiler, 0, import); 3441 3442 ucv_put(import); 3443 } 3444 } 3445 3446 ucv_put(modname); 3447 3448 return true; 3449 } 3450 3451 static bool 3452 uc_compiler_compile_module_source(uc_compiler_t *compiler, const char *modname, uc_source_t *source, uc_value_t *imports, char **errp) 3453 { 3454 uc_parse_config_t config = { 3455 .raw_mode = true, 3456 .strict_declarations = true, 3457 .module_search_path = compiler->parser->lex.config->module_search_path 3458 }; 3459 3460 size_t i, load_idx = 0, n_imports = 0; 3461 bool loaded = false; 3462 uc_value_t *import; 3463 ssize_t slot; 3464 3465 uc_program_function_foreach(compiler->program, fn) { 3466 if (uc_program_function_source(fn) == source) { 3467 if (source->exports.offset == (size_t)-1) 3468 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3469 "Circular dependency"); 3470 3471 loaded = true; 3472 break; 3473 } 3474 } 3475 3476 if (!loaded) { 3477 /* We do not yet support linking precompiled modules at compile time, 3478 turn static import operation into dynamic load one. */ 3479 if (uc_source_type_test(source) == UC_SOURCE_TYPE_PRECOMPILED) 3480 return uc_compiler_compile_dynload(compiler, modname, imports); 3481 3482 load_idx = uc_program_function_id(compiler->program, 3483 uc_program_function_last(compiler->program)) + 1; 3484 3485 source->exports.offset = (size_t)-1; 3486 3487 if (!uc_compile_from_source(&config, source, compiler->program, errp)) 3488 return false; 3489 3490 source->exports.offset = uc_compiler_get_exportnum(compiler) - source->exports.count; 3491 uc_compiler_current_source(compiler)->exports.offset += source->exports.count; 3492 3493 /* emit load, call & pop instructions */ 3494 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_CLFN); 3495 uc_compiler_emit_u32(compiler, 0, load_idx); 3496 3497 uc_compiler_emit_insn(compiler, 0, I_CALL); 3498 uc_compiler_emit_u32(compiler, 0, 0); 3499 3500 uc_compiler_emit_insn(compiler, 0, I_POP); 3501 } 3502 3503 /* count imports, handle wildcard imports */ 3504 for (i = 0; i < ucv_array_length(imports); i++) { 3505 if (ucv_boolean_get(ucv_array_get(imports, i))) { 3506 if (source->exports.offset > 0xffff || source->exports.count > 0xffff) { 3507 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3508 "Too many module exports"); 3509 } 3510 3511 /* emit import instruction... */ 3512 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_IMPORT); 3513 uc_compiler_emit_u32(compiler, 0, source->exports.count | (0xffff << 16)); 3514 3515 /* ... followed by first module export offset ... */ 3516 uc_compiler_emit_u16(compiler, 0, source->exports.offset); 3517 3518 /* ... and constant indexes for all exported names */ 3519 for (load_idx = 0; load_idx < source->exports.count; load_idx++) { 3520 if (source->exports.entries[load_idx]) 3521 import = ucv_get(source->exports.entries[load_idx]); 3522 else 3523 import = ucv_string_new("default"); 3524 3525 uc_compiler_emit_constant_index(compiler, 0, import); 3526 ucv_put(import); 3527 } 3528 3529 } 3530 else { 3531 n_imports++; 3532 } 3533 } 3534 3535 /* 0xffff is reserved for wildcard import */ 3536 if (n_imports > 0xfffe) 3537 uc_compiler_syntax_error(compiler, 0, "Too many imports"); 3538 3539 /* emit non-wildcard import instructions */ 3540 for (i = 0; i < ucv_array_length(imports); i++) { 3541 import = ucv_array_get(imports, i); 3542 3543 if (!ucv_boolean_get(import)) { 3544 slot = uc_source_export_lookup(source, import); 3545 3546 if (slot == -1) { 3547 if (import) 3548 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3549 "Module %s does not export '%s'", source->filename, ucv_string_get(import)); 3550 else 3551 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3552 "Module %s has no default export", source->filename); 3553 } 3554 else if (slot > 0xffff) { 3555 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3556 "Too many module exports"); 3557 } 3558 else { 3559 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_IMPORT); 3560 uc_compiler_emit_u32(compiler, 0, 3561 (source->exports.offset + slot) | ((compiler->upvals.count - n_imports + i) << 16)); 3562 } 3563 } 3564 } 3565 3566 return true; 3567 } 3568 3569 static char * 3570 uc_compiler_canonicalize_path(const char *path, const char *runpath) 3571 { 3572 char *p, *resolved; 3573 const char *slash; 3574 3575 if (*path == '/') 3576 xasprintf(&p, "%s", path); 3577 else if (runpath && (slash = strrchr(runpath, '/')) != NULL) 3578 xasprintf(&p, "%.*s/%s", (int)(slash - runpath), runpath, path); 3579 else 3580 xasprintf(&p, "./%s", path); 3581 3582 resolved = realpath(p, NULL); 3583 3584 free(p); 3585 3586 return resolved; 3587 } 3588 3589 static char * 3590 uc_compiler_expand_module_path(const char *name, const char *runpath, const char *template) 3591 { 3592 int namelen, prefixlen; 3593 const char *asterix; 3594 char *path, *p; 3595 3596 asterix = strchr(template, '*'); 3597 3598 if (!asterix) 3599 return NULL; 3600 3601 prefixlen = asterix - template; 3602 namelen = strlen(name); 3603 3604 xasprintf(&path, "%.*s%.*s%s", prefixlen, template, namelen, name, asterix + 1); 3605 3606 for (p = path + prefixlen; namelen > 0; namelen--, p++) 3607 if (*p == '.') 3608 *p = '/'; 3609 3610 p = uc_compiler_canonicalize_path(path, runpath); 3611 3612 free(path); 3613 3614 return p; 3615 } 3616 3617 static char * 3618 uc_compiler_resolve_module_path(uc_compiler_t *compiler, const char *name) 3619 { 3620 uc_search_path_t *search = &compiler->parser->lex.config->module_search_path; 3621 uc_source_t *source = uc_compiler_current_source(compiler); 3622 char *path = NULL; 3623 size_t i; 3624 3625 if (strchr(name, '/')) 3626 return uc_compiler_canonicalize_path(name, source->runpath); 3627 3628 for (i = 0; i < search->count && !path; i++) 3629 path = uc_compiler_expand_module_path(name, source->runpath, search->entries[i]); 3630 3631 return path; 3632 } 3633 3634 static uc_source_t * 3635 uc_compiler_acquire_source(uc_compiler_t *compiler, const char *path) 3636 { 3637 size_t i; 3638 3639 for (i = 0; i < compiler->program->sources.count; i++) 3640 if (!strcmp(compiler->program->sources.entries[i]->filename, path)) 3641 return uc_source_get(compiler->program->sources.entries[i]); 3642 3643 return uc_source_new_file(path); 3644 } 3645 3646 static bool 3647 uc_compiler_is_dynlink_module(uc_compiler_t *compiler, const char *name, const char *path) 3648 { 3649 uc_search_path_t *dynlink_list = &compiler->parser->config->force_dynlink_list; 3650 const char *dot; 3651 size_t i; 3652 3653 for (i = 0; i < dynlink_list->count; i++) 3654 if (!strcmp(dynlink_list->entries[i], name)) 3655 return true; 3656 3657 if (!path) 3658 return false; 3659 3660 dot = strrchr(path, '.'); 3661 3662 return (dot && !strcmp(dot, ".so")); 3663 } 3664 3665 static bool 3666 uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t *imports) 3667 { 3668 uc_source_t *source; 3669 char *path, *err; 3670 bool res; 3671 3672 if (!name) 3673 return false; 3674 3675 path = uc_compiler_resolve_module_path(compiler, name); 3676 3677 if (uc_compiler_is_dynlink_module(compiler, name, path)) { 3678 res = uc_compiler_compile_dynload(compiler, name, imports); 3679 } 3680 else if (path) { 3681 source = uc_compiler_acquire_source(compiler, path); 3682 3683 if (source) { 3684 err = NULL; 3685 res = uc_compiler_compile_module_source(compiler, name, source, imports, &err); 3686 3687 if (!res) { 3688 uc_error_message_indent(&err); 3689 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3690 "Unable to compile module '%s':\n\n%s", source->filename, err); 3691 } 3692 3693 free(err); 3694 } 3695 else { 3696 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3697 "Unable to open module '%s': %s", 3698 path, strerror(errno)); 3699 3700 res = false; 3701 } 3702 3703 uc_source_put(source); 3704 } 3705 else { 3706 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3707 "Unable to resolve path for module '%s'", name); 3708 3709 return false; 3710 } 3711 3712 free(path); 3713 3714 return res; 3715 } 3716 3717 static void 3718 uc_compiler_import_add(uc_compiler_t *compiler, uc_value_t *name) 3719 { 3720 bool constant; 3721 ssize_t slot; 3722 3723 slot = uc_compiler_resolve_local(compiler, name, &constant); 3724 3725 if (slot != -1) { 3726 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3727 "Import name '%s' is already declared as local variable", 3728 ucv_string_get(name)); 3729 3730 return; 3731 } 3732 3733 slot = uc_compiler_resolve_upval(compiler, name, &constant); 3734 3735 if (slot != -1) { 3736 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3737 "Import name '%s' is already used", 3738 ucv_string_get(name)); 3739 3740 return; 3741 } 3742 3743 uc_compiler_add_upval(compiler, (2 << 14) + compiler->upvals.count, false, name, true); 3744 } 3745 3746 static void 3747 uc_compiler_compile_importlist(uc_compiler_t *compiler, uc_value_t *namelist) 3748 { 3749 uc_value_t *label, *name; 3750 3751 /* parse export symbols */ 3752 do { 3753 name = NULL; 3754 label = NULL; 3755 3756 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) { 3757 uc_compiler_keyword_consume(compiler, "as"); 3758 uc_compiler_parse_consume(compiler, TK_LABEL); 3759 3760 label = ucv_get(compiler->parser->prev.uv); 3761 } 3762 else if (uc_compiler_parse_match(compiler, TK_STRING)) { 3763 name = ucv_get(compiler->parser->prev.uv); 3764 3765 uc_compiler_keyword_consume(compiler, "as"); 3766 uc_compiler_parse_consume(compiler, TK_LABEL); 3767 3768 label = ucv_get(compiler->parser->prev.uv); 3769 } 3770 else if (uc_compiler_parse_match(compiler, TK_LABEL)) { 3771 name = ucv_get(compiler->parser->prev.uv); 3772 3773 if (uc_compiler_keyword_match(compiler, "as")) { 3774 uc_compiler_parse_consume(compiler, TK_LABEL); 3775 3776 label = ucv_get(compiler->parser->prev.uv); 3777 } 3778 else { 3779 label = ucv_get(name); 3780 } 3781 } 3782 else { 3783 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3784 "Unexpected token\nExpecting Label, String or 'default'"); 3785 } 3786 3787 uc_compiler_import_add(compiler, label); 3788 ucv_array_push(namelist, name); 3789 ucv_put(label); 3790 3791 if (uc_compiler_parse_match(compiler, TK_RBRACE)) 3792 return; 3793 } 3794 while (uc_compiler_parse_match(compiler, TK_COMMA)); 3795 3796 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3797 "Unexpected token\nExpecting 'as', ',' or '}'"); 3798 } 3799 3800 static void 3801 uc_compiler_compile_importcall(uc_compiler_t *compiler) 3802 { 3803 uc_compiler_parse_consume(compiler, TK_LPAREN); 3804 uc_compiler_parse_precedence(compiler, P_ASSIGN); 3805 uc_compiler_parse_consume(compiler, TK_RPAREN); 3806 3807 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_DYNLOAD); 3808 uc_compiler_emit_u32(compiler, 0, 0); 3809 } 3810 3811 static uc_tokentype_t 3812 uc_compiler_compile_import(uc_compiler_t *compiler) 3813 { 3814 uc_value_t *namelist; 3815 3816 /* import(...) */ 3817 if (uc_compiler_parse_check(compiler, TK_LPAREN)) { 3818 uc_compiler_parse_precedence_for_token(compiler, P_UNARY, 3819 &compiler->parser->prev); 3820 3821 uc_compiler_emit_insn(compiler, 0, I_POP); 3822 3823 return TK_SCOL; 3824 } 3825 3826 if (compiler->scope_depth) { 3827 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3828 "Imports may only appear at top level"); 3829 3830 return TK_IMPORT; 3831 } 3832 3833 namelist = ucv_array_new(NULL); 3834 3835 /* import { ... } from */ 3836 if (uc_compiler_parse_match(compiler, TK_LBRACE)) { 3837 uc_compiler_compile_importlist(compiler, namelist); 3838 uc_compiler_keyword_consume(compiler, "from"); 3839 } 3840 3841 /* import * as name from */ 3842 else if (uc_compiler_parse_match(compiler, TK_MUL)) { 3843 uc_compiler_keyword_consume(compiler, "as"); 3844 uc_compiler_parse_consume(compiler, TK_LABEL); 3845 3846 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, true); 3847 uc_compiler_initialize_local(compiler); 3848 ucv_array_push(namelist, ucv_boolean_new(true)); 3849 3850 uc_compiler_keyword_consume(compiler, "from"); 3851 } 3852 3853 /* import defaultExport [, ... ] from */ 3854 else if (uc_compiler_parse_match(compiler, TK_LABEL)) { 3855 uc_compiler_import_add(compiler, compiler->parser->prev.uv); 3856 ucv_array_push(namelist, NULL); 3857 3858 /* import defaultExport, ... from */ 3859 if (uc_compiler_parse_match(compiler, TK_COMMA)) { 3860 /* import defaultExport, { ... } from */ 3861 if (uc_compiler_parse_match(compiler, TK_LBRACE)) { 3862 uc_compiler_compile_importlist(compiler, namelist); 3863 } 3864 3865 /* import defaultExport, * as name from */ 3866 else if (uc_compiler_parse_match(compiler, TK_MUL)) { 3867 uc_compiler_keyword_consume(compiler, "as"); 3868 uc_compiler_parse_consume(compiler, TK_LABEL); 3869 3870 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, true); 3871 uc_compiler_initialize_local(compiler); 3872 ucv_array_push(namelist, ucv_boolean_new(true)); 3873 } 3874 3875 /* error */ 3876 else { 3877 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3878 "Unexpected token\nExpecting '{' or '*'"); 3879 } 3880 } 3881 3882 uc_compiler_keyword_consume(compiler, "from"); 3883 } 3884 3885 uc_compiler_parse_consume(compiler, TK_STRING); 3886 3887 uc_compiler_compile_module(compiler, ucv_string_get(compiler->parser->prev.uv), namelist); 3888 3889 uc_compiler_parse_consume(compiler, TK_SCOL); 3890 3891 ucv_put(namelist); 3892 3893 return TK_IMPORT; 3894 } 3895 3896 static uc_tokentype_t 3897 uc_compiler_compile_declaration(uc_compiler_t *compiler) 3898 { 3899 uc_tokentype_t last_statement_type = compiler->parser->curr.type; 3900 3901 if (uc_compiler_parse_match(compiler, TK_LOCAL)) 3902 uc_compiler_compile_local(compiler); 3903 else if (uc_compiler_parse_match(compiler, TK_CONST)) 3904 uc_compiler_compile_const(compiler); 3905 else if (uc_compiler_parse_match(compiler, TK_EXPORT)) 3906 uc_compiler_compile_export(compiler); 3907 else if (uc_compiler_parse_match(compiler, TK_IMPORT)) 3908 last_statement_type = uc_compiler_compile_import(compiler); 3909 else 3910 last_statement_type = uc_compiler_compile_statement(compiler); 3911 3912 if (compiler->parser->synchronizing) 3913 uc_compiler_parse_synchronize(compiler); 3914 3915 return last_statement_type; 3916 } 3917 3918 #endif /* NO_COMPILE */ 3919 3920 3921 static uc_program_t * 3922 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, uc_program_t *prog, char **errp) 3923 { 3924 #ifdef NO_COMPILE 3925 if (errp) 3926 xasprintf(errp, "Source code compilation not supported\n"); 3927 3928 return NULL; 3929 #else 3930 bool is_module = (prog != NULL) || (config && config->compile_module); 3931 uc_patchlist_t exports = { .token = TK_EXPORT }; 3932 uc_exprstack_t expr = { .token = TK_EOF }; 3933 uc_parser_t parser = { .config = config }; 3934 uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr }; 3935 uc_tokentype_t last_statement_type = TK_NULL; 3936 uc_program_t *progptr; 3937 uc_function_t *fn; 3938 const char *name; 3939 3940 if (!prog) { 3941 progptr = uc_program_new(); 3942 name = is_module ? "module" : "main"; 3943 } 3944 else { 3945 progptr = prog; 3946 name = "module"; 3947 } 3948 3949 uc_lexer_init(&parser.lex, config, source); 3950 uc_compiler_init(&compiler, name, source, 0, progptr, 3951 config && config->strict_declarations); 3952 3953 if (is_module) { 3954 compiler.patchlist = &exports; 3955 compiler.function->module = true; 3956 } 3957 3958 uc_compiler_parse_advance(&compiler); 3959 3960 while (!uc_compiler_parse_match(&compiler, TK_EOF)) 3961 last_statement_type = uc_compiler_compile_declaration(&compiler); 3962 3963 if (!compiler.function->module && last_statement_type == TK_SCOL) { 3964 uc_chunk_pop(uc_compiler_current_chunk(&compiler)); 3965 uc_compiler_emit_insn(&compiler, 0, I_RETURN); 3966 last_statement_type = TK_RETURN; 3967 } 3968 3969 fn = uc_compiler_finish(&compiler, last_statement_type); 3970 3971 if (errp) { 3972 *errp = parser.error ? parser.error->buf : NULL; 3973 free(parser.error); 3974 } 3975 else { 3976 printbuf_free(parser.error); 3977 } 3978 3979 uc_lexer_free(&parser.lex); 3980 uc_vector_clear(&exports); 3981 3982 if (!fn) { 3983 if (progptr != prog) 3984 ucv_put(&progptr->header); 3985 3986 return NULL; 3987 } 3988 3989 return progptr; 3990 #endif 3991 } 3992 3993 static uc_program_t * 3994 uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp) 3995 { 3996 uc_program_t *prog; 3997 3998 prog = uc_program_load(source, errp); 3999 4000 if (prog && !uc_program_entry(prog)) { 4001 if (errp) 4002 xasprintf(errp, "Program file contains no entry function\n"); 4003 4004 ucv_put(&prog->header); 4005 } 4006 4007 return prog; 4008 } 4009 4010 uc_program_t * 4011 uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp) 4012 { 4013 uc_program_t *prog = NULL; 4014 4015 if (!config) 4016 config = &uc_default_parse_config; 4017 4018 switch (uc_source_type_test(source)) { 4019 case UC_SOURCE_TYPE_PLAIN: 4020 prog = uc_compile_from_source(config, source, NULL, errp); 4021 break; 4022 4023 case UC_SOURCE_TYPE_PRECOMPILED: 4024 prog = uc_compile_from_bytecode(config, source, errp); 4025 break; 4026 4027 default: 4028 if (errp) 4029 xasprintf(errp, "Unrecognized source type\n"); 4030 4031 break; 4032 } 4033 4034 return prog; 4035 } 4036
This page was automatically generated by LXR 0.3.1. • OpenWrt