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