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