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, I_POP); 2973 2974 uc_vector_grow(p); 2975 2976 p->entries[p->count++] = 2977 uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type); 2978 2979 uc_compiler_parse_consume(compiler, TK_SCOL); 2980 } 2981 2982 static void 2983 uc_compiler_compile_return(uc_compiler_t *compiler) 2984 { 2985 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2986 2987 if (compiler->function->module) { 2988 uc_compiler_syntax_error(compiler, 0, "return must be inside function body"); 2989 2990 return; 2991 } 2992 2993 /* if we compiled an empty expression statement (`;`), load implicit null */ 2994 if (uc_compiler_compile_expstmt(compiler) == TK_NULL) 2995 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL); 2996 2997 /* otherwise overwrite the final I_POP instruction with I_RETURN */ 2998 else 2999 uc_chunk_pop(chunk); 3000 3001 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_RETURN); 3002 } 3003 3004 static void 3005 uc_compiler_compile_tplexp(uc_compiler_t *compiler) 3006 { 3007 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 3008 size_t off = chunk->count; 3009 3010 uc_compiler_compile_expression(compiler); 3011 3012 /* XXX: the lexer currently emits a superfluous trailing semicolon... */ 3013 uc_compiler_parse_match(compiler, TK_SCOL); 3014 3015 uc_compiler_parse_consume(compiler, TK_REXP); 3016 3017 if (chunk->count > off) 3018 uc_compiler_emit_insn(compiler, 0, I_PRINT); 3019 } 3020 3021 static void 3022 uc_compiler_compile_text(uc_compiler_t *compiler) 3023 { 3024 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 3025 uc_compiler_emit_insn(compiler, 0, I_PRINT); 3026 } 3027 3028 static uc_tokentype_t 3029 uc_compiler_compile_block(uc_compiler_t *compiler) 3030 { 3031 uc_tokentype_t last_statement_type = TK_NULL; 3032 3033 uc_compiler_enter_scope(compiler); 3034 3035 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 3036 !uc_compiler_parse_check(compiler, TK_EOF)) 3037 last_statement_type = uc_compiler_compile_declaration(compiler); 3038 3039 uc_compiler_parse_consume(compiler, TK_RBRACE); 3040 3041 uc_compiler_leave_scope(compiler); 3042 3043 return last_statement_type; 3044 } 3045 3046 static uc_tokentype_t 3047 uc_compiler_compile_expstmt(uc_compiler_t *compiler) 3048 { 3049 /* empty statement */ 3050 if (uc_compiler_parse_match(compiler, TK_SCOL)) 3051 return TK_NULL; 3052 3053 uc_compiler_compile_expression(compiler); 3054 3055 /* allow omitting final semicolon */ 3056 switch (compiler->parser->curr.type) { 3057 case TK_RBRACE: 3058 case TK_ELIF: 3059 case TK_ENDIF: 3060 case TK_ENDFOR: 3061 case TK_ENDWHILE: 3062 case TK_ENDFUNC: 3063 case TK_EOF: 3064 break; 3065 3066 case TK_ELSE: 3067 if (!uc_compiler_exprstack_is(compiler, F_ALTBLOCKMODE)) 3068 uc_compiler_parse_consume(compiler, TK_SCOL); 3069 3070 break; 3071 3072 default: 3073 uc_compiler_parse_consume(compiler, TK_SCOL); 3074 3075 break; 3076 } 3077 3078 uc_compiler_emit_insn(compiler, 0, I_POP); 3079 3080 return TK_SCOL; 3081 } 3082 3083 static uc_tokentype_t 3084 uc_compiler_compile_statement(uc_compiler_t *compiler) 3085 { 3086 uc_tokentype_t last_statement_type = compiler->parser->curr.type; 3087 uc_exprstack_t expr = { 3088 .token = compiler->parser->curr.type, 3089 .parent = compiler->exprstack 3090 }; 3091 3092 compiler->exprstack = &expr; 3093 3094 if (uc_compiler_parse_match(compiler, TK_IF)) 3095 uc_compiler_compile_if(compiler); 3096 else if (uc_compiler_parse_match(compiler, TK_WHILE)) 3097 uc_compiler_compile_while(compiler); 3098 else if (uc_compiler_parse_match(compiler, TK_FOR)) 3099 uc_compiler_compile_for(compiler); 3100 else if (uc_compiler_parse_match(compiler, TK_SWITCH)) 3101 uc_compiler_compile_switch(compiler); 3102 else if (uc_compiler_parse_match(compiler, TK_TRY)) 3103 uc_compiler_compile_try(compiler); 3104 else if (uc_compiler_parse_match(compiler, TK_FUNC)) 3105 uc_compiler_compile_funcdecl(compiler); 3106 else if (uc_compiler_parse_match(compiler, TK_BREAK)) 3107 uc_compiler_compile_control(compiler); 3108 else if (uc_compiler_parse_match(compiler, TK_CONTINUE)) 3109 uc_compiler_compile_control(compiler); 3110 else if (uc_compiler_parse_match(compiler, TK_RETURN)) 3111 uc_compiler_compile_return(compiler); 3112 else if (uc_compiler_parse_match(compiler, TK_TEXT)) 3113 uc_compiler_compile_text(compiler); 3114 else if (uc_compiler_parse_match(compiler, TK_LEXP)) 3115 uc_compiler_compile_tplexp(compiler); 3116 else if (uc_compiler_parse_match(compiler, TK_LBRACE)) 3117 last_statement_type = uc_compiler_compile_block(compiler); 3118 else 3119 last_statement_type = uc_compiler_compile_expstmt(compiler); 3120 3121 compiler->exprstack = expr.parent; 3122 3123 return last_statement_type; 3124 } 3125 3126 static void 3127 uc_compiler_export_add(uc_compiler_t *compiler, uc_value_t *name, ssize_t slot) 3128 { 3129 uc_source_t *source = uc_compiler_current_source(compiler); 3130 3131 if (!uc_source_export_add(source, name)) { 3132 if (name) 3133 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3134 "Duplicate export '%s' for module '%s'", ucv_string_get(name), source->filename); 3135 else 3136 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3137 "Duplicate default export for module '%s'", source->filename); 3138 } 3139 else { 3140 uc_vector_push(compiler->patchlist, slot); 3141 uc_compiler_inc_exportnum(compiler); 3142 } 3143 } 3144 3145 static void 3146 uc_compiler_compile_exportlist(uc_compiler_t *compiler) 3147 { 3148 uc_value_t *label, *name; 3149 bool constant; 3150 ssize_t slot; 3151 3152 /* parse export symbols */ 3153 do { 3154 uc_compiler_parse_consume(compiler, TK_LABEL); 3155 3156 label = ucv_get(compiler->parser->prev.uv); 3157 name = NULL; 3158 3159 slot = uc_compiler_resolve_local(compiler, label, &constant); 3160 3161 if (slot == -1) { 3162 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3163 "Attempt to export undeclared or non-local variable '%s'", 3164 ucv_string_get(label)); 3165 } 3166 3167 if (uc_compiler_keyword_match(compiler, "as")) { 3168 if (uc_compiler_parse_match(compiler, TK_LABEL) || uc_compiler_parse_match(compiler, TK_STRING)) { 3169 name = ucv_get(compiler->parser->prev.uv); 3170 } 3171 else if (!uc_compiler_parse_match(compiler, TK_DEFAULT)) { 3172 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3173 "Unexpected token\nExpecting Label, String or 'default'"); 3174 } 3175 } 3176 else { 3177 name = ucv_get(label); 3178 } 3179 3180 uc_compiler_export_add(compiler, name, slot); 3181 3182 ucv_put(label); 3183 ucv_put(name); 3184 3185 if (uc_compiler_parse_match(compiler, TK_RBRACE)) 3186 break; 3187 } 3188 while (uc_compiler_parse_match(compiler, TK_COMMA)); 3189 3190 uc_compiler_parse_consume(compiler, TK_SCOL); 3191 } 3192 3193 static void 3194 uc_compiler_compile_export(uc_compiler_t *compiler) 3195 { 3196 uc_locals_t *locals = &compiler->locals; 3197 size_t off = locals->count; 3198 uc_value_t *name; 3199 ssize_t slot; 3200 3201 if (!compiler->function->module || compiler->scope_depth) { 3202 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3203 "Exports may only appear at top level of a module"); 3204 3205 return; 3206 } 3207 3208 if (uc_compiler_parse_match(compiler, TK_LBRACE)) { 3209 uc_compiler_compile_exportlist(compiler); 3210 3211 return; 3212 } 3213 3214 if (uc_compiler_parse_match(compiler, TK_LOCAL)) 3215 uc_compiler_compile_declexpr(compiler, false); 3216 else if (uc_compiler_parse_match(compiler, TK_CONST)) 3217 uc_compiler_compile_declexpr(compiler, true); 3218 else if (uc_compiler_parse_match(compiler, TK_FUNC)) 3219 uc_compiler_compile_funcdecl(compiler); 3220 else if (uc_compiler_parse_match(compiler, TK_DEFAULT)) 3221 uc_compiler_compile_expression(compiler); 3222 else 3223 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3224 "Unexpected token\nExpecting 'let', 'const', 'function', 'default' or '{'"); 3225 3226 if (off == locals->count) { 3227 name = ucv_string_new("(module default export)"); 3228 slot = uc_compiler_declare_local(compiler, name, true); 3229 ucv_put(name); 3230 3231 if (slot != -1) 3232 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3233 "Duplicate default export statement"); 3234 else 3235 uc_compiler_export_add(compiler, NULL, compiler->locals.count - 1); 3236 } 3237 else { 3238 for (; off < locals->count; off++) 3239 uc_compiler_export_add(compiler, locals->entries[off].name, off); 3240 } 3241 3242 uc_compiler_parse_consume(compiler, TK_SCOL); 3243 } 3244 3245 static uc_program_t * 3246 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, uc_program_t *prog, char **errp); 3247 3248 static bool 3249 uc_compiler_compile_module_source(uc_compiler_t *compiler, uc_source_t *source, uc_value_t *imports, char **errp) 3250 { 3251 uc_parse_config_t config = { 3252 .raw_mode = true, 3253 .strict_declarations = true, 3254 .module_search_path = compiler->parser->lex.config->module_search_path 3255 }; 3256 3257 size_t i, load_idx = 0, n_imports = 0; 3258 bool loaded = false; 3259 uc_value_t *import; 3260 ssize_t slot; 3261 3262 uc_program_function_foreach(compiler->program, fn) { 3263 if (uc_program_function_source(fn) == source) { 3264 if (source->exports.offset == (size_t)-1) 3265 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3266 "Circular dependency"); 3267 3268 loaded = true; 3269 break; 3270 } 3271 } 3272 3273 if (!loaded) { 3274 load_idx = uc_program_function_id(compiler->program, 3275 uc_program_function_last(compiler->program)) + 1; 3276 3277 source->exports.offset = (size_t)-1; 3278 3279 if (!uc_compile_from_source(&config, source, compiler->program, errp)) 3280 return false; 3281 3282 source->exports.offset = uc_compiler_get_exportnum(compiler) - source->exports.count; 3283 uc_compiler_current_source(compiler)->exports.offset += source->exports.count; 3284 3285 /* emit load, call & pop instructions */ 3286 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_CLFN); 3287 uc_compiler_emit_u32(compiler, 0, load_idx); 3288 3289 uc_compiler_emit_insn(compiler, 0, I_CALL); 3290 uc_compiler_emit_u32(compiler, 0, 0); 3291 3292 uc_compiler_emit_insn(compiler, 0, I_POP); 3293 } 3294 3295 /* count imports, handle wildcard imports */ 3296 for (i = 0; i < ucv_array_length(imports); i++) { 3297 if (ucv_boolean_get(ucv_array_get(imports, i))) { 3298 if (source->exports.offset > 0xffff || source->exports.count > 0xffff) { 3299 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3300 "Too many module exports"); 3301 } 3302 3303 /* emit import instruction... */ 3304 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_IMPORT); 3305 uc_compiler_emit_u32(compiler, 0, source->exports.count | (0xffff << 16)); 3306 3307 /* ... followed by first module export offset ... */ 3308 uc_compiler_emit_u16(compiler, 0, source->exports.offset); 3309 3310 /* ... and constant indexes for all exported names */ 3311 for (load_idx = 0; load_idx < source->exports.count; load_idx++) { 3312 if (source->exports.entries[load_idx]) 3313 import = ucv_get(source->exports.entries[load_idx]); 3314 else 3315 import = ucv_string_new("default"); 3316 3317 uc_compiler_emit_constant_index(compiler, 0, import); 3318 ucv_put(import); 3319 } 3320 3321 } 3322 else { 3323 n_imports++; 3324 } 3325 } 3326 3327 /* 0xffff is reserved for wildcard import */ 3328 if (n_imports > 0xfffe) 3329 uc_compiler_syntax_error(compiler, 0, "Too many imports"); 3330 3331 /* emit non-wilcard import instructions */ 3332 for (i = 0; i < ucv_array_length(imports); i++) { 3333 import = ucv_array_get(imports, i); 3334 3335 if (!ucv_boolean_get(import)) { 3336 slot = uc_source_export_lookup(source, import); 3337 3338 if (slot == -1) { 3339 if (import) 3340 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3341 "Module %s does not export '%s'", source->filename, ucv_string_get(import)); 3342 else 3343 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3344 "Module %s has no default export", source->filename); 3345 } 3346 else if (slot > 0xffff) { 3347 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3348 "Too many module exports"); 3349 } 3350 else { 3351 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_IMPORT); 3352 uc_compiler_emit_u32(compiler, 0, 3353 (source->exports.offset + slot) | ((compiler->upvals.count - n_imports + i) << 16)); 3354 } 3355 } 3356 } 3357 3358 return true; 3359 } 3360 3361 static char * 3362 uc_compiler_canonicalize_path(const char *path, const char *runpath) 3363 { 3364 char *p, *resolved; 3365 3366 if (*path == '/') 3367 xasprintf(&p, "%s", path); 3368 else if (runpath && (p = strrchr(runpath, '/')) != NULL) 3369 xasprintf(&p, "%.*s/%s", (int)(p - runpath), runpath, path); 3370 else 3371 xasprintf(&p, "./%s", path); 3372 3373 resolved = realpath(p, NULL); 3374 3375 free(p); 3376 3377 return resolved; 3378 } 3379 3380 static char * 3381 uc_compiler_expand_module_path(const char *name, const char *runpath, const char *template) 3382 { 3383 int namelen, prefixlen; 3384 char *path, *p; 3385 3386 p = strchr(template, '*'); 3387 3388 if (!p) 3389 return NULL; 3390 3391 prefixlen = p - template; 3392 namelen = strlen(name); 3393 3394 xasprintf(&path, "%.*s%.*s%s", prefixlen, template, namelen, name, p + 1); 3395 3396 for (p = path + prefixlen; namelen > 0; namelen--, p++) 3397 if (*p == '.') 3398 *p = '/'; 3399 3400 p = uc_compiler_canonicalize_path(path, runpath); 3401 3402 free(path); 3403 3404 return p; 3405 } 3406 3407 static char * 3408 uc_compiler_resolve_module_path(uc_compiler_t *compiler, const char *name) 3409 { 3410 uc_search_path_t *search = &compiler->parser->lex.config->module_search_path; 3411 uc_source_t *source = uc_compiler_current_source(compiler); 3412 char *path = NULL; 3413 size_t i; 3414 3415 if (strchr(name, '/')) 3416 return uc_compiler_canonicalize_path(name, source->runpath); 3417 3418 for (i = 0; i < search->count && !path; i++) 3419 path = uc_compiler_expand_module_path(name, source->runpath, search->entries[i]); 3420 3421 return path; 3422 } 3423 3424 static uc_source_t * 3425 uc_compiler_acquire_source(uc_compiler_t *compiler, const char *path) 3426 { 3427 size_t i; 3428 3429 for (i = 0; i < compiler->program->sources.count; i++) 3430 if (!strcmp(compiler->program->sources.entries[i]->filename, path)) 3431 return uc_source_get(compiler->program->sources.entries[i]); 3432 3433 return uc_source_new_file(path); 3434 } 3435 3436 static bool 3437 uc_compiler_compile_dynload(uc_compiler_t *compiler, const char *name, uc_value_t *imports) 3438 { 3439 uc_value_t *modname = ucv_string_new(name); 3440 size_t i, n_imports; 3441 uc_value_t *import; 3442 3443 for (i = 0, n_imports = 0; i < ucv_array_length(imports); i++) { 3444 import = ucv_array_get(imports, i); 3445 3446 if (ucv_boolean_get(import)) { 3447 uc_compiler_emit_insn(compiler, 0, I_DYNLOAD); 3448 uc_compiler_emit_u32(compiler, 0, 0); 3449 uc_compiler_emit_constant_index(compiler, 0, modname); 3450 } 3451 else { 3452 n_imports++; 3453 } 3454 } 3455 3456 if (n_imports > 0) { 3457 uc_compiler_emit_insn(compiler, 0, I_DYNLOAD); 3458 uc_compiler_emit_u32(compiler, 0, n_imports | ((compiler->upvals.count - n_imports) << 16)); 3459 uc_compiler_emit_constant_index(compiler, 0, modname); 3460 3461 for (i = 0; i < ucv_array_length(imports); i++) { 3462 import = ucv_get(ucv_array_get(imports, i)); 3463 3464 if (!import) 3465 import = ucv_string_new("default"); 3466 3467 if (!ucv_boolean_get(import)) 3468 uc_compiler_emit_constant_index(compiler, 0, import); 3469 3470 ucv_put(import); 3471 } 3472 } 3473 3474 ucv_put(modname); 3475 3476 return true; 3477 } 3478 3479 static bool 3480 uc_compiler_is_dynlink_module(uc_compiler_t *compiler, const char *name, const char *path) 3481 { 3482 uc_search_path_t *dynlink_list = &compiler->parser->config->force_dynlink_list; 3483 size_t i; 3484 char *p; 3485 3486 for (i = 0; i < dynlink_list->count; i++) 3487 if (!strcmp(dynlink_list->entries[i], name)) 3488 return true; 3489 3490 if (!path) 3491 return false; 3492 3493 p = strrchr(path, '.'); 3494 3495 return (p && !strcmp(p, ".so")); 3496 } 3497 3498 static bool 3499 uc_compiler_compile_module(uc_compiler_t *compiler, const char *name, uc_value_t *imports) 3500 { 3501 uc_source_t *source; 3502 char *path, *err; 3503 bool res; 3504 3505 if (!name) 3506 return false; 3507 3508 path = uc_compiler_resolve_module_path(compiler, name); 3509 3510 if (uc_compiler_is_dynlink_module(compiler, name, path)) { 3511 res = uc_compiler_compile_dynload(compiler, name, imports); 3512 } 3513 else if (path) { 3514 source = uc_compiler_acquire_source(compiler, path); 3515 3516 if (source) { 3517 err = NULL; 3518 res = uc_compiler_compile_module_source(compiler, source, imports, &err); 3519 3520 if (!res) { 3521 uc_error_message_indent(&err); 3522 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3523 "Unable to compile module '%s':\n\n%s", source->filename, err); 3524 } 3525 3526 free(err); 3527 } 3528 else { 3529 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3530 "Unable to open module '%s': %s", 3531 path, strerror(errno)); 3532 3533 res = false; 3534 } 3535 3536 uc_source_put(source); 3537 } 3538 else { 3539 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3540 "Unable to resolve path for module '%s'", name); 3541 3542 return false; 3543 } 3544 3545 free(path); 3546 3547 return res; 3548 } 3549 3550 static void 3551 uc_compiler_import_add(uc_compiler_t *compiler, uc_value_t *name) 3552 { 3553 bool constant; 3554 ssize_t slot; 3555 3556 slot = uc_compiler_resolve_local(compiler, name, &constant); 3557 3558 if (slot != -1) { 3559 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3560 "Import name '%s' is already declared as local variable", 3561 ucv_string_get(name)); 3562 3563 return; 3564 } 3565 3566 slot = uc_compiler_resolve_upval(compiler, name, &constant); 3567 3568 if (slot != -1) { 3569 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3570 "Import name '%s' is already used", 3571 ucv_string_get(name)); 3572 3573 return; 3574 } 3575 3576 uc_compiler_add_upval(compiler, (2 << 14) + compiler->upvals.count, false, name, true); 3577 } 3578 3579 static void 3580 uc_compiler_compile_importlist(uc_compiler_t *compiler, uc_value_t *namelist) 3581 { 3582 uc_value_t *label, *name; 3583 3584 /* parse export symbols */ 3585 do { 3586 name = NULL; 3587 label = NULL; 3588 3589 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) { 3590 uc_compiler_keyword_consume(compiler, "as"); 3591 uc_compiler_parse_consume(compiler, TK_LABEL); 3592 3593 label = ucv_get(compiler->parser->prev.uv); 3594 } 3595 else if (uc_compiler_parse_match(compiler, TK_STRING)) { 3596 name = ucv_get(compiler->parser->prev.uv); 3597 3598 uc_compiler_keyword_consume(compiler, "as"); 3599 uc_compiler_parse_consume(compiler, TK_LABEL); 3600 3601 label = ucv_get(compiler->parser->prev.uv); 3602 } 3603 else if (uc_compiler_parse_match(compiler, TK_LABEL)) { 3604 name = ucv_get(compiler->parser->prev.uv); 3605 3606 if (uc_compiler_keyword_match(compiler, "as")) { 3607 uc_compiler_parse_consume(compiler, TK_LABEL); 3608 3609 label = ucv_get(compiler->parser->prev.uv); 3610 } 3611 else { 3612 label = ucv_get(name); 3613 } 3614 } 3615 else { 3616 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3617 "Unexpected token\nExpecting Label, String or 'default'"); 3618 } 3619 3620 uc_compiler_import_add(compiler, label); 3621 ucv_array_push(namelist, name); 3622 ucv_put(label); 3623 3624 if (uc_compiler_parse_match(compiler, TK_RBRACE)) 3625 return; 3626 } 3627 while (uc_compiler_parse_match(compiler, TK_COMMA)); 3628 3629 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3630 "Unexpected token\nExpecting 'as', ',' or '}'"); 3631 } 3632 3633 static void 3634 uc_compiler_compile_import(uc_compiler_t *compiler) 3635 { 3636 uc_value_t *namelist = ucv_array_new(NULL); 3637 3638 if (compiler->scope_depth) { 3639 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 3640 "Imports may only appear at top level"); 3641 3642 ucv_put(namelist); 3643 3644 return; 3645 } 3646 3647 /* import { ... } from */ 3648 if (uc_compiler_parse_match(compiler, TK_LBRACE)) { 3649 uc_compiler_compile_importlist(compiler, namelist); 3650 uc_compiler_keyword_consume(compiler, "from"); 3651 } 3652 3653 /* import * as name from */ 3654 else if (uc_compiler_parse_match(compiler, TK_MUL)) { 3655 uc_compiler_keyword_consume(compiler, "as"); 3656 uc_compiler_parse_consume(compiler, TK_LABEL); 3657 3658 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, true); 3659 uc_compiler_initialize_local(compiler); 3660 ucv_array_push(namelist, ucv_boolean_new(true)); 3661 3662 uc_compiler_keyword_consume(compiler, "from"); 3663 } 3664 3665 /* import defaultExport [, ... ] from */ 3666 else if (uc_compiler_parse_match(compiler, TK_LABEL)) { 3667 uc_compiler_import_add(compiler, compiler->parser->prev.uv); 3668 ucv_array_push(namelist, NULL); 3669 3670 /* import defaultExport, ... from */ 3671 if (uc_compiler_parse_match(compiler, TK_COMMA)) { 3672 /* import defaultExport, { ... } from */ 3673 if (uc_compiler_parse_match(compiler, TK_LBRACE)) { 3674 uc_compiler_compile_importlist(compiler, namelist); 3675 } 3676 3677 /* import defaultExport, * as name from */ 3678 else if (uc_compiler_parse_match(compiler, TK_MUL)) { 3679 uc_compiler_keyword_consume(compiler, "as"); 3680 uc_compiler_parse_consume(compiler, TK_LABEL); 3681 3682 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, true); 3683 uc_compiler_initialize_local(compiler); 3684 ucv_array_push(namelist, ucv_boolean_new(true)); 3685 } 3686 3687 /* error */ 3688 else { 3689 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 3690 "Unexpected token\nExpecting '{' or '*'"); 3691 } 3692 } 3693 3694 uc_compiler_keyword_consume(compiler, "from"); 3695 } 3696 3697 uc_compiler_parse_consume(compiler, TK_STRING); 3698 3699 uc_compiler_compile_module(compiler, ucv_string_get(compiler->parser->prev.uv), namelist); 3700 3701 uc_compiler_parse_consume(compiler, TK_SCOL); 3702 3703 ucv_put(namelist); 3704 } 3705 3706 static uc_tokentype_t 3707 uc_compiler_compile_declaration(uc_compiler_t *compiler) 3708 { 3709 uc_tokentype_t last_statement_type = compiler->parser->curr.type; 3710 3711 if (uc_compiler_parse_match(compiler, TK_LOCAL)) 3712 uc_compiler_compile_local(compiler); 3713 else if (uc_compiler_parse_match(compiler, TK_CONST)) 3714 uc_compiler_compile_const(compiler); 3715 else if (uc_compiler_parse_match(compiler, TK_EXPORT)) 3716 uc_compiler_compile_export(compiler); 3717 else if (uc_compiler_parse_match(compiler, TK_IMPORT)) 3718 uc_compiler_compile_import(compiler); 3719 else 3720 last_statement_type = uc_compiler_compile_statement(compiler); 3721 3722 if (compiler->parser->synchronizing) 3723 uc_compiler_parse_synchronize(compiler); 3724 3725 return last_statement_type; 3726 } 3727 3728 #endif /* NO_COMPILE */ 3729 3730 3731 static uc_program_t * 3732 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, uc_program_t *prog, char **errp) 3733 { 3734 #ifdef NO_COMPILE 3735 if (errp) 3736 xasprintf(errp, "Source code compilation not supported\n"); 3737 3738 return NULL; 3739 #else 3740 uc_patchlist_t exports = { .token = TK_EXPORT }; 3741 uc_exprstack_t expr = { .token = TK_EOF }; 3742 uc_parser_t parser = { .config = config }; 3743 uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr }; 3744 uc_tokentype_t last_statement_type = TK_NULL; 3745 uc_program_t *progptr; 3746 uc_function_t *fn; 3747 const char *name; 3748 3749 if (!prog) { 3750 progptr = uc_program_new(); 3751 name = "main"; 3752 } 3753 else { 3754 progptr = prog; 3755 name = "module"; 3756 } 3757 3758 uc_lexer_init(&parser.lex, config, source); 3759 uc_compiler_init(&compiler, name, source, 0, progptr, 3760 config && config->strict_declarations); 3761 3762 if (progptr == prog) { 3763 compiler.patchlist = &exports; 3764 compiler.function->module = true; 3765 } 3766 3767 uc_compiler_parse_advance(&compiler); 3768 3769 while (!uc_compiler_parse_match(&compiler, TK_EOF)) 3770 last_statement_type = uc_compiler_compile_declaration(&compiler); 3771 3772 if (!compiler.function->module && last_statement_type == TK_SCOL) { 3773 uc_chunk_pop(uc_compiler_current_chunk(&compiler)); 3774 uc_compiler_emit_insn(&compiler, 0, I_RETURN); 3775 last_statement_type = TK_RETURN; 3776 } 3777 3778 fn = uc_compiler_finish(&compiler, last_statement_type); 3779 3780 if (errp) { 3781 *errp = parser.error ? parser.error->buf : NULL; 3782 free(parser.error); 3783 } 3784 else { 3785 printbuf_free(parser.error); 3786 } 3787 3788 uc_lexer_free(&parser.lex); 3789 uc_vector_clear(&exports); 3790 3791 if (!fn) { 3792 if (progptr != prog) 3793 ucv_put(&progptr->header); 3794 3795 return NULL; 3796 } 3797 3798 return progptr; 3799 #endif 3800 } 3801 3802 static uc_program_t * 3803 uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp) 3804 { 3805 uc_program_t *prog; 3806 3807 prog = uc_program_load(source, errp); 3808 3809 if (prog && !uc_program_entry(prog)) { 3810 if (errp) 3811 xasprintf(errp, "Program file contains no entry function\n"); 3812 3813 ucv_put(&prog->header); 3814 } 3815 3816 return prog; 3817 } 3818 3819 uc_program_t * 3820 uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp) 3821 { 3822 uc_program_t *prog = NULL; 3823 3824 if (!config) 3825 config = &uc_default_parse_config; 3826 3827 switch (uc_source_type_test(source)) { 3828 case UC_SOURCE_TYPE_PLAIN: 3829 prog = uc_compile_from_source(config, source, NULL, errp); 3830 break; 3831 3832 case UC_SOURCE_TYPE_PRECOMPILED: 3833 prog = uc_compile_from_bytecode(config, source, errp); 3834 break; 3835 3836 default: 3837 if (errp) 3838 xasprintf(errp, "Unrecognized source type\n"); 3839 3840 break; 3841 } 3842 3843 return prog; 3844 } 3845
This page was automatically generated by LXR 0.3.1. • OpenWrt