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