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_function(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 void uc_compiler_compile_declaration(uc_compiler_t *compiler); 50 static void uc_compiler_compile_statement(uc_compiler_t *compiler); 51 static void 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_function, 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, 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, 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 compiler->program->source; 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_stringbuf_t *buf = compiler->parser->error; 173 size_t line = 0, byte = 0, len = 0; 174 va_list ap; 175 char *s; 176 177 if (compiler->parser->synchronizing) 178 return; 179 180 compiler->parser->synchronizing = true; 181 182 if (!buf) 183 buf = compiler->parser->error = xprintbuf_new(); 184 185 if (!off) 186 off = uc_program_function_srcpos(compiler->function, 187 uc_compiler_current_chunk(compiler)->count); 188 189 if (off) { 190 byte = off; 191 line = uc_source_get_line(uc_compiler_current_source(compiler), &byte); 192 } 193 194 va_start(ap, fmt); 195 len = xvasprintf(&s, fmt, ap); 196 va_end(ap); 197 198 ucv_stringbuf_append(buf, "Syntax error: "); 199 ucv_stringbuf_addstr(buf, s, len); 200 ucv_stringbuf_append(buf, "\n"); 201 202 free(s); 203 204 if (line) 205 ucv_stringbuf_printf(buf, "In line %zu, byte %zu:\n", line, byte); 206 207 if (uc_error_context_format(buf, uc_compiler_current_source(compiler), NULL, off)) 208 ucv_stringbuf_append(buf, "\n\n"); 209 } 210 211 static size_t 212 uc_compiler_set_srcpos(uc_compiler_t *compiler, size_t srcpos) 213 { 214 size_t delta; 215 216 /* ensure that lines counts are strictly increasing */ 217 assert(srcpos == 0 || srcpos >= compiler->current_srcpos); 218 219 delta = srcpos ? srcpos - compiler->current_srcpos : 0; 220 compiler->current_srcpos += delta; 221 222 return delta; 223 } 224 225 static void 226 uc_compiler_parse_advance(uc_compiler_t *compiler) 227 { 228 ucv_put(compiler->parser->prev.uv); 229 compiler->parser->prev = compiler->parser->curr; 230 231 while (true) { 232 compiler->parser->curr = *uc_lexer_next_token(&compiler->parser->lex); 233 234 if (compiler->parser->curr.type != TK_ERROR) 235 break; 236 237 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "%s", 238 ucv_string_get(compiler->parser->curr.uv)); 239 240 ucv_put(compiler->parser->curr.uv); 241 compiler->parser->curr.uv = NULL; 242 } 243 } 244 245 static void 246 uc_compiler_parse_consume(uc_compiler_t *compiler, uc_tokentype_t type) 247 { 248 if (compiler->parser->curr.type == type) { 249 uc_compiler_parse_advance(compiler); 250 251 return; 252 } 253 254 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 255 "Unexpected token\nExpecting %s", uc_tokenname(type)); 256 } 257 258 static bool 259 uc_compiler_parse_check(uc_compiler_t *compiler, uc_tokentype_t type) 260 { 261 return (compiler->parser->curr.type == type); 262 } 263 264 static bool 265 uc_compiler_parse_match(uc_compiler_t *compiler, uc_tokentype_t type) 266 { 267 if (!uc_compiler_parse_check(compiler, type)) 268 return false; 269 270 uc_compiler_parse_advance(compiler); 271 272 return true; 273 } 274 275 static void 276 uc_compiler_parse_synchronize(uc_compiler_t *compiler) 277 { 278 compiler->parser->synchronizing = false; 279 280 while (compiler->parser->curr.type != TK_EOF) { 281 if (compiler->parser->prev.type == TK_SCOL) 282 return; 283 284 switch (compiler->parser->curr.type) { 285 case TK_IF: 286 case TK_FOR: 287 case TK_WHILE: 288 case TK_SWITCH: 289 case TK_FUNC: 290 case TK_TRY: 291 case TK_RETURN: 292 case TK_BREAK: 293 case TK_CONTINUE: 294 case TK_LOCAL: 295 return; 296 297 default: 298 break; 299 } 300 301 uc_compiler_parse_advance(compiler); 302 } 303 } 304 305 static uc_parse_rule_t * 306 uc_compiler_parse_rule(uc_tokentype_t type) 307 { 308 return &uc_compiler_parse_rules[type]; 309 } 310 311 static bool 312 uc_compiler_parse_at_assignment_op(uc_compiler_t *compiler) 313 { 314 switch (compiler->parser->curr.type) { 315 case TK_ASBAND: 316 case TK_ASBXOR: 317 case TK_ASBOR: 318 case TK_ASLEFT: 319 case TK_ASRIGHT: 320 case TK_ASMUL: 321 case TK_ASDIV: 322 case TK_ASMOD: 323 case TK_ASADD: 324 case TK_ASSUB: 325 case TK_ASAND: 326 case TK_ASOR: 327 case TK_ASEXP: 328 case TK_ASNULLISH: 329 case TK_ASSIGN: 330 return true; 331 332 default: 333 return false; 334 } 335 } 336 337 static void 338 uc_compiler_parse_precedence(uc_compiler_t *compiler, uc_precedence_t precedence) 339 { 340 uc_parse_rule_t *rule; 341 342 rule = uc_compiler_parse_rule(compiler->parser->curr.type); 343 344 if (!rule->prefix) { 345 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting expression"); 346 uc_compiler_parse_advance(compiler); 347 348 return; 349 } 350 351 uc_compiler_exprstack_push(compiler, 352 compiler->parser->curr.type, 353 (precedence <= P_ASSIGN) ? F_ASSIGNABLE : 0); 354 355 /* allow reserved words as property names in object literals */ 356 if (rule->prefix == uc_compiler_compile_object) 357 compiler->parser->lex.no_keyword = true; 358 359 /* unless a sub-expression follows, treat subsequent slash as division 360 * operator and not as beginning of regexp literal */ 361 if (rule->prefix != uc_compiler_compile_paren && 362 rule->prefix != uc_compiler_compile_unary && 363 rule->prefix != uc_compiler_compile_array) 364 compiler->parser->lex.no_regexp = true; 365 366 uc_compiler_parse_advance(compiler); 367 368 rule->prefix(compiler); 369 370 while (precedence <= uc_compiler_parse_rule(compiler->parser->curr.type)->precedence) { 371 compiler->exprstack->token = compiler->parser->curr.type; 372 373 rule = uc_compiler_parse_rule(compiler->exprstack->token); 374 375 if (!rule->infix) { 376 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, "Expecting ';' or binary operator"); 377 uc_compiler_parse_advance(compiler); 378 379 return; 380 } 381 382 /* allow reserved words in property accessors */ 383 if (rule->infix == uc_compiler_compile_dot) 384 compiler->parser->lex.no_keyword = true; 385 386 uc_compiler_parse_advance(compiler); 387 388 rule->infix(compiler); 389 } 390 391 if (uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) && uc_compiler_parse_at_assignment_op(compiler)) 392 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, "Invalid left-hand side expression for assignment"); 393 394 uc_compiler_exprstack_pop(compiler); 395 } 396 397 static size_t 398 uc_compiler_reladdr(uc_compiler_t *compiler, size_t from, size_t to) 399 { 400 ssize_t delta = to - from; 401 402 if (delta < -0x7fffffff || delta > 0x7fffffff) { 403 uc_compiler_syntax_error(compiler, 0, "Jump address too far"); 404 405 return 0; 406 } 407 408 return (size_t)(delta + 0x7fffffff); 409 } 410 411 static size_t 412 uc_compiler_emit_insn(uc_compiler_t *compiler, size_t srcpos, uc_vm_insn_t insn) 413 { 414 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 415 size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); 416 417 compiler->last_insn = uc_chunk_add(chunk, (uint8_t)insn, lineoff); 418 419 return compiler->last_insn; 420 } 421 422 static size_t 423 uc_compiler_emit_u8(uc_compiler_t *compiler, size_t srcpos, uint8_t n) 424 { 425 return uc_chunk_add( 426 uc_compiler_current_chunk(compiler), 427 n, 428 uc_compiler_set_srcpos(compiler, srcpos)); 429 } 430 431 static size_t 432 uc_compiler_emit_u16(uc_compiler_t *compiler, size_t srcpos, uint16_t n) 433 { 434 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 435 size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); 436 437 uc_chunk_add(chunk, n / 0x100, lineoff); 438 uc_chunk_add(chunk, n % 0x100, 0); 439 440 return chunk->count - 2; 441 } 442 443 static size_t 444 uc_compiler_emit_u32(uc_compiler_t *compiler, size_t srcpos, uint32_t n) 445 { 446 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 447 size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); 448 449 uc_chunk_add(chunk, n / 0x1000000, lineoff); 450 uc_chunk_add(chunk, (n / 0x10000) % 0x100, 0); 451 uc_chunk_add(chunk, (n / 0x100) % 0x100, 0); 452 uc_chunk_add(chunk, n % 0x100, 0); 453 454 return chunk->count - 4; 455 } 456 457 static size_t 458 uc_compiler_emit_s32(uc_compiler_t *compiler, size_t srcpos, int32_t n) 459 { 460 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 461 size_t lineoff = uc_compiler_set_srcpos(compiler, srcpos); 462 uint32_t v; 463 464 if (n <= 0) 465 v = n + 0x7fffffff; 466 else 467 v = (uint32_t)n + 0x7fffffff; 468 469 uc_chunk_add(chunk, v / 0x1000000, lineoff); 470 uc_chunk_add(chunk, (v / 0x10000) % 0x100, 0); 471 uc_chunk_add(chunk, (v / 0x100) % 0x100, 0); 472 uc_chunk_add(chunk, v % 0x100, 0); 473 474 return chunk->count - 4; 475 } 476 477 static uint32_t 478 uc_compiler_get_u32(uc_compiler_t *compiler, size_t off) 479 { 480 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 481 482 return chunk->entries[off + 0] * 0x1000000 + 483 chunk->entries[off + 1] * 0x10000 + 484 chunk->entries[off + 2] * 0x100 + 485 chunk->entries[off + 3]; 486 } 487 488 static void 489 uc_compiler_set_u32(uc_compiler_t *compiler, size_t off, uint32_t n) 490 { 491 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 492 493 chunk->entries[off + 0] = n / 0x1000000; 494 chunk->entries[off + 1] = (n / 0x10000) % 0x100; 495 chunk->entries[off + 2] = (n / 0x100) % 0x100; 496 chunk->entries[off + 3] = n % 0x100; 497 } 498 499 static size_t 500 uc_compiler_emit_constant(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val) 501 { 502 size_t cidx = uc_program_add_constant(compiler->program, val); 503 504 uc_compiler_emit_insn(compiler, srcpos, I_LOAD); 505 uc_compiler_emit_u32(compiler, 0, cidx); 506 507 return cidx; 508 } 509 510 static size_t 511 uc_compiler_emit_regexp(uc_compiler_t *compiler, size_t srcpos, uc_value_t *val) 512 { 513 size_t cidx = uc_program_add_constant(compiler->program, val); 514 515 uc_compiler_emit_insn(compiler, srcpos, I_LREXP); 516 uc_compiler_emit_u32(compiler, 0, cidx); 517 518 return cidx; 519 } 520 521 static size_t 522 uc_compiler_emit_jmp(uc_compiler_t *compiler, size_t srcpos) 523 { 524 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 525 526 uc_compiler_emit_insn(compiler, srcpos, I_JMP); 527 uc_compiler_emit_u32(compiler, 0, 0); 528 529 return chunk->count - 5; 530 } 531 532 static size_t 533 uc_compiler_emit_jmpz(uc_compiler_t *compiler, size_t srcpos) 534 { 535 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 536 537 uc_compiler_emit_insn(compiler, srcpos, I_JMPZ); 538 uc_compiler_emit_u32(compiler, 0, 0); 539 540 return chunk->count - 5; 541 } 542 543 static size_t 544 uc_compiler_emit_jmp_dest(uc_compiler_t *compiler, size_t srcpos, uint32_t dest) 545 { 546 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 547 548 uc_compiler_emit_insn(compiler, srcpos, I_JMP); 549 uc_compiler_emit_u32(compiler, 0, uc_compiler_reladdr(compiler, chunk->count - 1, dest)); 550 551 return chunk->count - 5; 552 } 553 554 static ssize_t 555 uc_compiler_get_jmpaddr(uc_compiler_t *compiler, size_t off) 556 { 557 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 558 559 assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ); 560 assert(off + 4 < chunk->count); 561 562 return ( 563 chunk->entries[off + 1] * 0x1000000UL + 564 chunk->entries[off + 2] * 0x10000UL + 565 chunk->entries[off + 3] * 0x100UL + 566 chunk->entries[off + 4] 567 ) - 0x7fffffff; 568 } 569 570 static void 571 uc_compiler_set_jmpaddr(uc_compiler_t *compiler, size_t off, uint32_t dest) 572 { 573 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 574 size_t addr = uc_compiler_reladdr(compiler, off, dest); 575 576 assert(chunk->entries[off] == I_JMP || chunk->entries[off] == I_JMPZ); 577 assert(off + 4 < chunk->count); 578 579 chunk->entries[off + 1] = addr / 0x1000000; 580 chunk->entries[off + 2] = (addr / 0x10000) % 0x100; 581 chunk->entries[off + 3] = (addr / 0x100) % 0x100; 582 chunk->entries[off + 4] = addr % 0x100; 583 } 584 585 static uc_function_t * 586 uc_compiler_finish(uc_compiler_t *compiler) 587 { 588 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 589 uc_locals_t *locals = &compiler->locals; 590 uc_upvals_t *upvals = &compiler->upvals; 591 size_t i; 592 593 uc_compiler_emit_insn(compiler, 0, I_LNULL); 594 uc_compiler_emit_insn(compiler, 0, I_RETURN); 595 596 for (i = 0; i < locals->count; i++) { 597 uc_chunk_debug_add_variable(chunk, 598 locals->entries[i].from, 599 chunk->count, 600 i, 601 false, 602 locals->entries[i].name); 603 604 ucv_put(locals->entries[i].name); 605 } 606 607 for (i = 0; i < upvals->count; i++) { 608 uc_chunk_debug_add_variable(chunk, 609 0, 610 chunk->count, 611 i, 612 true, 613 upvals->entries[i].name); 614 615 ucv_put(upvals->entries[i].name); 616 } 617 618 uc_vector_clear(locals); 619 uc_vector_clear(upvals); 620 621 if (compiler->parser->error) { 622 uc_program_function_free(compiler->function); 623 624 return NULL; 625 } 626 627 return compiler->function; 628 } 629 630 static void 631 uc_compiler_enter_scope(uc_compiler_t *compiler) 632 { 633 compiler->scope_depth++; 634 } 635 636 static void 637 uc_compiler_leave_scope(uc_compiler_t *compiler) 638 { 639 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 640 uc_locals_t *locals = &compiler->locals; 641 642 compiler->scope_depth--; 643 644 while (locals->count > 0 && locals->entries[locals->count - 1].depth > (ssize_t)compiler->scope_depth) { 645 locals->count--; 646 647 uc_chunk_debug_add_variable(chunk, 648 locals->entries[locals->count].from, 649 chunk->count, 650 locals->count, 651 false, 652 locals->entries[locals->count].name); 653 654 ucv_put(locals->entries[locals->count].name); 655 locals->entries[locals->count].name = NULL; 656 657 uc_compiler_emit_insn(compiler, 0, 658 locals->entries[locals->count].captured ? I_CUPV : I_POP); 659 } 660 } 661 662 static bool 663 uc_compiler_is_strict(uc_compiler_t *compiler) 664 { 665 uc_function_t *fn = (uc_function_t *)compiler->function; 666 667 return fn->strict; 668 } 669 670 static ssize_t 671 uc_compiler_declare_local(uc_compiler_t *compiler, uc_value_t *name, bool constant) 672 { 673 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 674 uc_locals_t *locals = &compiler->locals; 675 const char *str1, *str2; 676 size_t i, len1, len2; 677 678 if (locals->count >= 0x00FFFFFF) { 679 uc_compiler_syntax_error(compiler, 0, "Too many local variables"); 680 681 return -1; 682 } 683 684 str1 = ucv_string_get(name); 685 len1 = ucv_string_length(name); 686 687 for (i = locals->count; i > 0; i--) { 688 if (locals->entries[i - 1].depth != -1 && locals->entries[i - 1].depth < (ssize_t)compiler->scope_depth) 689 break; 690 691 str2 = ucv_string_get(locals->entries[i - 1].name); 692 len2 = ucv_string_length(locals->entries[i - 1].name); 693 694 if (len1 == len2 && !strcmp(str1, str2)) { 695 if (uc_compiler_is_strict(compiler)) { 696 uc_compiler_syntax_error(compiler, 0, "Variable '%s' redeclared", str2); 697 698 return -1; 699 } 700 701 return i - 1; 702 } 703 } 704 705 uc_vector_grow(locals); 706 707 locals->entries[locals->count].name = ucv_get(name); 708 locals->entries[locals->count].depth = -1; 709 locals->entries[locals->count].captured = false; 710 locals->entries[locals->count].from = chunk->count; 711 locals->entries[locals->count].constant = constant; 712 locals->count++; 713 714 return -1; 715 } 716 717 static ssize_t 718 uc_compiler_initialize_local(uc_compiler_t *compiler) 719 { 720 uc_locals_t *locals = &compiler->locals; 721 722 locals->entries[locals->count - 1].depth = compiler->scope_depth; 723 724 return locals->count - 1; 725 } 726 727 static ssize_t 728 uc_compiler_resolve_local(uc_compiler_t *compiler, uc_value_t *name, bool *constant) 729 { 730 uc_locals_t *locals = &compiler->locals; 731 const char *str1, *str2; 732 size_t i, len1, len2; 733 734 str1 = ucv_string_get(name); 735 len1 = ucv_string_length(name); 736 737 for (i = locals->count; i > 0; i--) { 738 str2 = ucv_string_get(locals->entries[i - 1].name); 739 len2 = ucv_string_length(locals->entries[i - 1].name); 740 741 if (len1 != len2 || strcmp(str1, str2)) 742 continue; 743 744 if (locals->entries[i - 1].depth == -1) { 745 uc_compiler_syntax_error(compiler, 0, 746 "Can't access lexical declaration '%s' before initialization", str2); 747 748 return -1; 749 } 750 751 *constant = locals->entries[i - 1].constant; 752 753 return i - 1; 754 } 755 756 return -1; 757 } 758 759 static ssize_t 760 uc_compiler_add_upval(uc_compiler_t *compiler, size_t idx, bool local, uc_value_t *name, bool constant) 761 { 762 uc_function_t *function = (uc_function_t *)compiler->function; 763 uc_upvals_t *upvals = &compiler->upvals; 764 uc_upval_t *uv; 765 size_t i; 766 767 for (i = 0, uv = upvals->entries; i < upvals->count; i++, uv = upvals->entries + i) 768 if (uv->index == idx && uv->local == local) 769 return i; 770 771 /* XXX: encoding... */ 772 if (upvals->count >= (2 << 14)) { 773 uc_compiler_syntax_error(compiler, 0, "Too many upvalues"); 774 775 return -1; 776 } 777 778 uc_vector_grow(upvals); 779 780 upvals->entries[upvals->count].local = local; 781 upvals->entries[upvals->count].index = idx; 782 upvals->entries[upvals->count].name = ucv_get(name); 783 upvals->entries[upvals->count].constant = constant; 784 785 function->nupvals++; 786 787 return upvals->count++; 788 } 789 790 static ssize_t 791 uc_compiler_resolve_upval(uc_compiler_t *compiler, uc_value_t *name, bool *constant) 792 { 793 ssize_t idx; 794 795 if (!compiler->parent) 796 return -1; 797 798 idx = uc_compiler_resolve_local(compiler->parent, name, constant); 799 800 if (idx > -1) { 801 compiler->parent->locals.entries[idx].captured = true; 802 803 return uc_compiler_add_upval(compiler, idx, true, name, *constant); 804 } 805 806 idx = uc_compiler_resolve_upval(compiler->parent, name, constant); 807 808 if (idx > -1) 809 return uc_compiler_add_upval(compiler, idx, false, name, *constant); 810 811 return -1; 812 } 813 814 static void 815 uc_compiler_backpatch(uc_compiler_t *compiler, size_t break_addr, size_t next_addr) 816 { 817 uc_patchlist_t *pl = compiler->patchlist; 818 uc_patchlist_t *pp = pl->parent; 819 volatile ssize_t jmpaddr; 820 size_t i; 821 822 for (i = 0; i < pl->count; i++) { 823 jmpaddr = uc_compiler_get_jmpaddr(compiler, pl->entries[i]); 824 825 switch (jmpaddr) { 826 case TK_BREAK: 827 /* if we have a break addr, patch instruction */ 828 if (break_addr) { 829 uc_compiler_set_jmpaddr(compiler, pl->entries[i], break_addr); 830 continue; 831 } 832 833 break; 834 835 case TK_CONTINUE: 836 /* if we have a continue addr, patch instruction */ 837 if (next_addr) { 838 uc_compiler_set_jmpaddr(compiler, pl->entries[i], next_addr); 839 continue; 840 } 841 842 break; 843 } 844 845 /* propagate unhandled patch instructions to parent patch list */ 846 if (pp) { 847 uc_vector_grow(pp); 848 pp->entries[pp->count++] = pl->entries[i]; 849 } 850 } 851 852 free(pl->entries); 853 854 compiler->patchlist = pl->parent; 855 } 856 857 static void 858 uc_compiler_emit_inc_dec(uc_compiler_t *compiler, uc_tokentype_t toktype, bool is_postfix) 859 { 860 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 861 uc_value_t *varname = NULL; 862 uc_vm_insn_t type; 863 uint32_t cidx = 0; 864 int insn; 865 866 /* determine kind of emitted load instruction and operand value (if any) */ 867 type = chunk->entries ? chunk->entries[compiler->last_insn] : 0; 868 869 if (type == I_LVAR || type == I_LLOC || type == I_LUPV) { 870 cidx = uc_compiler_get_u32(compiler, compiler->last_insn + 1); 871 872 if (type == I_LLOC && compiler->locals.entries[cidx].constant) 873 varname = compiler->locals.entries[cidx].name; 874 else if (type == I_LUPV && compiler->upvals.entries[cidx].constant) 875 varname = compiler->upvals.entries[cidx].name; 876 877 if (varname) 878 uc_compiler_syntax_error(compiler, 0, 879 "Invalid increment/decrement of constant '%s'", 880 ucv_string_get(varname)); 881 882 uc_chunk_pop(chunk); 883 uc_chunk_pop(chunk); 884 uc_chunk_pop(chunk); 885 uc_chunk_pop(chunk); 886 uc_chunk_pop(chunk); 887 } 888 889 /* if we're mutating an object or array field, pop the last lval instruction 890 * to leave object + last field name value on stack */ 891 else if (type == I_LVAL && !uc_compiler_exprstack_is(compiler, F_OPTCHAINING)) { 892 uc_chunk_pop(chunk); 893 } 894 else { 895 uc_compiler_syntax_error(compiler, 0, "Invalid increment/decrement operand"); 896 897 return; 898 } 899 900 insn = (toktype == TK_INC) ? I_PLUS : I_MINUS; 901 902 /* add / substract 1 */ 903 uc_compiler_emit_insn(compiler, 0, I_LOAD8); 904 uc_compiler_emit_u8(compiler, 0, 1); 905 906 /* depending on variable type, emit corresponding increment instruction */ 907 switch (type) { 908 case I_LVAR: 909 uc_compiler_emit_insn(compiler, 0, I_UVAR); 910 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx); 911 break; 912 913 case I_LLOC: 914 uc_compiler_emit_insn(compiler, 0, I_ULOC); 915 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx); 916 break; 917 918 case I_LUPV: 919 uc_compiler_emit_insn(compiler, 0, I_UUPV); 920 uc_compiler_emit_u32(compiler, 0, (insn << 24) | cidx); 921 break; 922 923 case I_LVAL: 924 uc_compiler_emit_insn(compiler, 0, I_UVAL); 925 uc_compiler_emit_u8(compiler, 0, insn); 926 break; 927 928 default: 929 break; 930 } 931 932 /* for post increment or decrement, add/substract 1 to yield final value */ 933 if (is_postfix) { 934 uc_compiler_emit_insn(compiler, 0, I_LOAD8); 935 uc_compiler_emit_u8(compiler, 0, 1); 936 937 uc_compiler_emit_insn(compiler, 0, (toktype == TK_INC) ? I_SUB : I_ADD); 938 } 939 } 940 941 942 static void 943 uc_compiler_compile_unary(uc_compiler_t *compiler) 944 { 945 uc_tokentype_t type = compiler->parser->prev.type; 946 947 uc_compiler_parse_precedence(compiler, P_UNARY); 948 949 switch (type) { 950 case TK_SUB: 951 uc_compiler_emit_insn(compiler, 0, I_MINUS); 952 break; 953 954 case TK_ADD: 955 uc_compiler_emit_insn(compiler, 0, I_PLUS); 956 break; 957 958 case TK_NOT: 959 uc_compiler_emit_insn(compiler, 0, I_NOT); 960 break; 961 962 case TK_COMPL: 963 uc_compiler_emit_insn(compiler, 0, I_COMPL); 964 break; 965 966 case TK_INC: 967 case TK_DEC: 968 uc_compiler_emit_inc_dec(compiler, type, false); 969 break; 970 971 default: 972 return; 973 } 974 } 975 976 static void 977 uc_compiler_compile_binary(uc_compiler_t *compiler) 978 { 979 uc_tokentype_t type = compiler->parser->prev.type; 980 981 uc_compiler_parse_precedence(compiler, uc_compiler_parse_rule(type)->precedence + 1); 982 uc_compiler_emit_insn(compiler, 0, I_BOR + (type - TK_BOR)); 983 } 984 985 static void 986 uc_compiler_compile_delete(uc_compiler_t *compiler) 987 { 988 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 989 uc_vm_insn_t type; 990 991 uc_compiler_parse_precedence(compiler, P_UNARY); 992 993 type = chunk->entries[compiler->last_insn]; 994 995 if (type != I_LVAL) 996 uc_compiler_syntax_error(compiler, 0, 997 "expecting a property access expression"); 998 999 chunk->entries[compiler->last_insn] = I_DELETE; 1000 } 1001 1002 static uc_vm_insn_t 1003 uc_compiler_emit_variable_rw(uc_compiler_t *compiler, uc_value_t *varname, uc_tokentype_t type) 1004 { 1005 uc_vm_insn_t insn; 1006 uint32_t sub_insn; 1007 bool constant; 1008 ssize_t idx; 1009 1010 switch (type) { 1011 case TK_ASADD: sub_insn = I_ADD; break; 1012 case TK_ASSUB: sub_insn = I_SUB; break; 1013 case TK_ASMUL: sub_insn = I_MUL; break; 1014 case TK_ASDIV: sub_insn = I_DIV; break; 1015 case TK_ASMOD: sub_insn = I_MOD; break; 1016 case TK_ASBAND: sub_insn = I_BAND; break; 1017 case TK_ASBXOR: sub_insn = I_BXOR; break; 1018 case TK_ASBOR: sub_insn = I_BOR; break; 1019 case TK_ASLEFT: sub_insn = I_LSHIFT; break; 1020 case TK_ASRIGHT: sub_insn = I_RSHIFT; break; 1021 case TK_ASAND: sub_insn = I_LTRUE; break; 1022 case TK_ASOR: sub_insn = I_LFALSE; break; 1023 case TK_ASEXP: sub_insn = I_EXP; break; 1024 case TK_ASNULLISH: sub_insn = I_LNULL; break; 1025 default: sub_insn = 0; break; 1026 } 1027 1028 if (!varname) { 1029 if (sub_insn != 0) 1030 insn = I_UVAL; 1031 else if (type == TK_QDOT || type == TK_QLBRACK) 1032 insn = I_QLVAL; 1033 else if (type != 0) 1034 insn = I_SVAL; 1035 else 1036 insn = I_LVAL; 1037 1038 if ((insn == I_UVAL || insn == I_SVAL) && uc_compiler_exprstack_is(compiler, F_OPTCHAINING)) 1039 uc_compiler_syntax_error(compiler, 0, 1040 "Invalid left-hand side expression for assignment"); 1041 1042 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn); 1043 1044 if (sub_insn) 1045 uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, sub_insn); 1046 } 1047 else if ((idx = uc_compiler_resolve_local(compiler, varname, &constant)) > -1) { 1048 insn = sub_insn ? I_ULOC : (type ? I_SLOC : I_LLOC); 1049 1050 if (insn != I_LLOC && constant) 1051 uc_compiler_syntax_error(compiler, 0, 1052 "Invalid assignment to constant '%s'", ucv_string_get(varname)); 1053 1054 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn); 1055 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, 1056 ((sub_insn & 0xff) << 24) | idx); 1057 } 1058 else if ((idx = uc_compiler_resolve_upval(compiler, varname, &constant)) > -1) { 1059 insn = sub_insn ? I_UUPV : (type ? I_SUPV : I_LUPV); 1060 1061 if (insn != I_LUPV && constant) 1062 uc_compiler_syntax_error(compiler, 0, 1063 "Invalid assignment to constant '%s'", ucv_string_get(varname)); 1064 1065 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn); 1066 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, 1067 ((sub_insn & 0xff) << 24) | idx); 1068 } 1069 else { 1070 idx = uc_program_add_constant(compiler->program, varname); 1071 insn = sub_insn ? I_UVAR : (type ? I_SVAR : I_LVAR); 1072 1073 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, insn); 1074 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, 1075 ((sub_insn & 0xff) << 24) | idx); 1076 } 1077 1078 return insn; 1079 } 1080 1081 static void 1082 uc_compiler_compile_expression(uc_compiler_t *compiler) 1083 { 1084 uc_compiler_parse_precedence(compiler, P_COMMA); 1085 } 1086 1087 static bool 1088 uc_compiler_compile_assignment(uc_compiler_t *compiler, uc_value_t *var) 1089 { 1090 uc_tokentype_t type = compiler->parser->curr.type; 1091 1092 if (uc_compiler_parse_at_assignment_op(compiler)) { 1093 uc_compiler_parse_advance(compiler); 1094 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1095 uc_compiler_emit_variable_rw(compiler, var, type); 1096 1097 return true; 1098 } 1099 1100 return false; 1101 } 1102 1103 static bool 1104 uc_compiler_compile_arrowfn(uc_compiler_t *compiler, uc_value_t *args, bool restarg) 1105 { 1106 bool array = (ucv_type(args) == UC_ARRAY); 1107 uc_compiler_t fncompiler = { 0 }; 1108 size_t i, pos, load_off; 1109 uc_function_t *fn; 1110 ssize_t slot; 1111 1112 if (!uc_compiler_parse_match(compiler, TK_ARROW)) 1113 return false; 1114 1115 pos = compiler->parser->prev.pos; 1116 1117 uc_compiler_init(&fncompiler, NULL, compiler->parser->prev.pos, 1118 compiler->program, 1119 uc_compiler_is_strict(compiler)); 1120 1121 fncompiler.parent = compiler; 1122 fncompiler.parser = compiler->parser; 1123 fncompiler.exprstack = compiler->exprstack; 1124 1125 fn = (uc_function_t *)fncompiler.function; 1126 fn->arrow = true; 1127 fn->vararg = args ? restarg : false; 1128 fn->nargs = array ? ucv_array_length(args) : !!args; 1129 1130 uc_compiler_enter_scope(&fncompiler); 1131 1132 /* declare local variables for arguments */ 1133 for (i = 0; i < fn->nargs; i++) { 1134 slot = uc_compiler_declare_local(&fncompiler, 1135 array ? ucv_array_get(args, i) : args, false); 1136 1137 if (slot != -1) 1138 uc_compiler_syntax_error(&fncompiler, pos, 1139 "Duplicate argument names are not allowed in this context"); 1140 1141 uc_compiler_initialize_local(&fncompiler); 1142 } 1143 1144 /* parse and compile body */ 1145 if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) { 1146 while (!uc_compiler_parse_check(&fncompiler, TK_RBRACE) && 1147 !uc_compiler_parse_check(&fncompiler, TK_EOF)) 1148 uc_compiler_compile_declaration(&fncompiler); 1149 1150 uc_compiler_parse_consume(&fncompiler, TK_RBRACE); 1151 1152 /* overwrite last pop result with return */ 1153 if (fn->chunk.count) { 1154 uc_chunk_pop(&fn->chunk); 1155 uc_compiler_emit_insn(&fncompiler, 0, I_RETURN); 1156 } 1157 } 1158 else { 1159 uc_compiler_parse_precedence(&fncompiler, P_ASSIGN); 1160 uc_compiler_emit_insn(&fncompiler, 0, I_RETURN); 1161 } 1162 1163 /* emit load instruction for function value */ 1164 uc_compiler_emit_insn(compiler, pos, I_ARFN); 1165 load_off = uc_compiler_emit_u32(compiler, 0, 0); 1166 1167 /* encode upvalue information */ 1168 for (i = 0; i < fn->nupvals; i++) 1169 uc_compiler_emit_s32(compiler, 0, 1170 fncompiler.upvals.entries[i].local 1171 ? -(fncompiler.upvals.entries[i].index + 1) 1172 : fncompiler.upvals.entries[i].index); 1173 1174 /* finalize function compiler */ 1175 fn = uc_compiler_finish(&fncompiler); 1176 1177 if (fn) 1178 uc_compiler_set_u32(compiler, load_off, 1179 uc_program_function_id(compiler->program, fn)); 1180 1181 return true; 1182 } 1183 1184 static uc_tokentype_t 1185 uc_compiler_compile_var_or_arrowfn(uc_compiler_t *compiler, uc_value_t *name) 1186 { 1187 uc_tokentype_t rv; 1188 1189 if (uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) && uc_compiler_compile_assignment(compiler, name)) { 1190 rv = TK_ASSIGN; 1191 } 1192 else if (uc_compiler_compile_arrowfn(compiler, name, false)) { 1193 rv = TK_ARROW; 1194 } 1195 else { 1196 uc_compiler_emit_variable_rw(compiler, name, 0); 1197 rv = TK_LABEL; 1198 } 1199 1200 return rv; 1201 } 1202 1203 static void 1204 uc_compiler_compile_paren(uc_compiler_t *compiler) 1205 { 1206 uc_value_t *varnames = NULL, *varname; 1207 bool maybe_arrowfn = false; 1208 bool restarg = false; 1209 1210 /* First try to parse a complete parameter expression and remember the 1211 * consumed label tokens as we go. */ 1212 while (true) { 1213 if (uc_compiler_parse_check(compiler, TK_LABEL)) { 1214 if (!varnames) 1215 varnames = ucv_array_new(NULL); 1216 1217 ucv_array_push(varnames, ucv_get(compiler->parser->curr.uv)); 1218 1219 /* A subsequent slash cannot be a regular expression literal */ 1220 compiler->parser->lex.no_regexp = true; 1221 uc_compiler_parse_advance(compiler); 1222 } 1223 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) { 1224 uc_compiler_parse_consume(compiler, TK_LABEL); 1225 1226 if (!varnames) 1227 varnames = ucv_array_new(NULL); 1228 1229 ucv_array_push(varnames, ucv_get(compiler->parser->prev.uv)); 1230 1231 /* A subsequent slash cannot be a regular expression literal */ 1232 compiler->parser->lex.no_regexp = true; 1233 uc_compiler_parse_consume(compiler, TK_RPAREN); 1234 1235 maybe_arrowfn = true; 1236 restarg = true; 1237 1238 break; 1239 } 1240 else if (uc_compiler_parse_check(compiler, TK_COMMA)) { 1241 /* Reject consecutive commas */ 1242 if (compiler->parser->prev.type == TK_COMMA) 1243 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 1244 "Expecting expression"); 1245 1246 uc_compiler_parse_advance(compiler); 1247 1248 continue; 1249 } 1250 else { 1251 maybe_arrowfn = uc_compiler_parse_check(compiler, TK_RPAREN); 1252 1253 if (maybe_arrowfn) { 1254 /* A subsequent slash cannot be a regular expression literal */ 1255 compiler->parser->lex.no_regexp = true; 1256 uc_compiler_parse_advance(compiler); 1257 } 1258 1259 /* If we encouter a dot, treat potential subsequent keyword as label */ 1260 if (uc_compiler_parse_check(compiler, TK_DOT) || 1261 uc_compiler_parse_check(compiler, TK_QDOT)) 1262 compiler->parser->lex.no_keyword = true; 1263 1264 break; 1265 } 1266 } 1267 1268 /* The lhs we parsed so far is elligible for an arrow function arg list, 1269 * try to continue compiling into arrow function... */ 1270 if (maybe_arrowfn) { 1271 /* If we can parse the remainder as arrow function, we're done */ 1272 if (uc_compiler_compile_arrowfn(compiler, varnames, restarg)) 1273 goto out; 1274 1275 /* ... otherwise disallow the `...` spread operator and empty 1276 * parenthesized expressions */ 1277 if (restarg || !varnames) { 1278 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 1279 "Expecting '=>' after parameter list"); 1280 1281 goto out; 1282 } 1283 } 1284 1285 /* If we reach this, the expression we parsed so far cannot be a parameter 1286 * list for an arrow function and we might have consumed one or multiple 1287 * consecutive labels. */ 1288 if (varnames) { 1289 /* Get last variable name */ 1290 varname = ucv_array_get(varnames, 1291 ucv_array_length(varnames) - 1); 1292 1293 /* If we consumed the right paren, the expression is complete and we 1294 * only need to emit a variable read operation for the last parsed 1295 * label since previous read operations are shadowed by subsequent ones 1296 * in comma expressions and since pure variable reads are without 1297 * side effects. */ 1298 if (maybe_arrowfn) { 1299 uc_compiler_emit_variable_rw(compiler, varname, 0); 1300 1301 goto out; 1302 } 1303 1304 /* ... otherwise if the last token was a label, try continue parsing as 1305 * assignment or arrow function expression and if that fails, as 1306 * relational one */ 1307 if (compiler->parser->prev.type == TK_LABEL) { 1308 uc_compiler_exprstack_push(compiler, TK_LABEL, F_ASSIGNABLE); 1309 1310 if (uc_compiler_compile_var_or_arrowfn(compiler, varname) == TK_LABEL) { 1311 /* parse operand and rhs */ 1312 while (P_TERNARY <= uc_compiler_parse_rule(compiler->parser->curr.type)->precedence) { 1313 uc_compiler_parse_advance(compiler); 1314 uc_compiler_parse_rule(compiler->parser->prev.type)->infix(compiler); 1315 } 1316 } 1317 1318 /* If we're not at the end of the expression, we require a comma. 1319 * Also pop intermediate result in this case. */ 1320 if (!uc_compiler_parse_check(compiler, TK_RPAREN)) { 1321 uc_compiler_emit_insn(compiler, 0, I_POP); 1322 uc_compiler_parse_consume(compiler, TK_COMMA); 1323 } 1324 1325 uc_compiler_exprstack_pop(compiler); 1326 } 1327 } 1328 1329 /* When we reach this point, all already complete expression possibilities 1330 * have been eliminated and we either need to compile the next, non-label 1331 * expression or reached the closing paren. If neither applies, we have a 1332 * syntax error. */ 1333 if (!uc_compiler_parse_check(compiler, TK_RPAREN)) 1334 uc_compiler_compile_expression(compiler); 1335 1336 /* A subsequent slash cannot be a regular expression literal */ 1337 compiler->parser->lex.no_regexp = true; 1338 1339 /* At this point we expect the end of the parenthesized expression, anything 1340 * else is a syntax error */ 1341 uc_compiler_parse_consume(compiler, TK_RPAREN); 1342 1343 out: 1344 ucv_put(varnames); 1345 } 1346 1347 static void 1348 uc_compiler_compile_call(uc_compiler_t *compiler) 1349 { 1350 bool optional_chaining = (compiler->parser->prev.type == TK_QLPAREN); 1351 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 1352 uc_jmplist_t spreads = { 0 }; 1353 uc_vm_insn_t type; 1354 size_t i, nargs = 0; 1355 1356 /* flag optional chaining usage in current expression */ 1357 compiler->exprstack->flags |= optional_chaining ? F_OPTCHAINING : 0; 1358 1359 /* determine the kind of the lhs */ 1360 type = chunk->entries[compiler->last_insn]; 1361 1362 /* if lhs is a dot or bracket expression, pop the LVAL instruction */ 1363 if (type == I_LVAL || type == I_QLVAL) 1364 uc_chunk_pop(chunk); 1365 1366 /* compile arguments */ 1367 if (!uc_compiler_parse_check(compiler, TK_RPAREN)) { 1368 do { 1369 /* if this is a spread arg, remember the argument index */ 1370 if (uc_compiler_parse_match(compiler, TK_ELLIP)) { 1371 uc_vector_grow(&spreads); 1372 spreads.entries[spreads.count++] = nargs; 1373 } 1374 1375 /* compile argument expression */ 1376 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1377 nargs++; 1378 } 1379 while (uc_compiler_parse_match(compiler, TK_COMMA)); 1380 } 1381 1382 /* after a function call expression, no regexp literal can follow */ 1383 compiler->parser->lex.no_regexp = true; 1384 uc_compiler_parse_consume(compiler, TK_RPAREN); 1385 1386 /* if lhs is a dot or bracket expression, emit a method call */ 1387 if (type == I_LVAL || type == I_QLVAL) 1388 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, optional_chaining ? I_QMCALL : I_MCALL); 1389 /* else ordinary call */ 1390 else 1391 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, optional_chaining ? I_QCALL : I_CALL); 1392 1393 if (nargs > 0xffff || spreads.count > 0xffff) 1394 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 1395 "Too many function call arguments"); 1396 1397 /* encode ordinary (low 16 bit) and spread argument (high 16 bit) count */ 1398 uc_compiler_emit_u32(compiler, 0, ((spreads.count & 0xffff) << 16) | nargs); 1399 1400 /* encode spread arg positions */ 1401 for (i = 0; i < spreads.count; i++) 1402 uc_compiler_emit_u16(compiler, 0, nargs - spreads.entries[i] - 1); 1403 1404 uc_vector_clear(&spreads); 1405 } 1406 1407 static void 1408 uc_compiler_compile_post_inc(uc_compiler_t *compiler) 1409 { 1410 uc_compiler_emit_inc_dec(compiler, compiler->parser->prev.type, true); 1411 } 1412 1413 static bool 1414 uc_compiler_is_use_strict_pragma(uc_compiler_t *compiler) 1415 { 1416 uc_value_t *v; 1417 1418 if (uc_compiler_current_chunk(compiler)->count > 0) 1419 return false; 1420 1421 if (compiler->parser->lex.block != STATEMENTS) 1422 return false; 1423 1424 v = compiler->parser->prev.uv; 1425 1426 return (strcmp(ucv_string_get(v), "use strict") == 0); 1427 } 1428 1429 static void 1430 uc_compiler_compile_constant(uc_compiler_t *compiler) 1431 { 1432 uc_function_t *fn; 1433 uint64_t u; 1434 1435 switch (compiler->parser->prev.type) { 1436 case TK_THIS: 1437 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LTHIS); 1438 break; 1439 1440 case TK_NULL: 1441 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL); 1442 break; 1443 1444 case TK_TRUE: 1445 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LTRUE); 1446 break; 1447 1448 case TK_FALSE: 1449 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LFALSE); 1450 break; 1451 1452 case TK_STRING: 1453 if (uc_compiler_is_use_strict_pragma(compiler)) { 1454 fn = (uc_function_t *)compiler->function; 1455 fn->strict = true; 1456 } 1457 1458 /* fall through */ 1459 1460 case TK_DOUBLE: 1461 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 1462 break; 1463 1464 case TK_REGEXP: 1465 uc_compiler_emit_regexp(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 1466 break; 1467 1468 case TK_NUMBER: 1469 u = ucv_uint64_get(compiler->parser->prev.uv); 1470 assert(errno == 0); 1471 1472 if (u <= 0xff) { 1473 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD8); 1474 uc_compiler_emit_u8(compiler, compiler->parser->prev.pos, u); 1475 } 1476 else if (u <= 0xffff) { 1477 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD16); 1478 uc_compiler_emit_u16(compiler, compiler->parser->prev.pos, u); 1479 } 1480 else if (u <= 0xffffffff) { 1481 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LOAD32); 1482 uc_compiler_emit_u32(compiler, compiler->parser->prev.pos, u); 1483 } 1484 else { 1485 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 1486 } 1487 1488 break; 1489 1490 default: 1491 break; 1492 } 1493 } 1494 1495 static void 1496 uc_compiler_compile_template(uc_compiler_t *compiler) 1497 { 1498 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 1499 1500 while (true) { 1501 if (uc_compiler_parse_match(compiler, TK_TEMPLATE)) { 1502 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 1503 uc_compiler_emit_insn(compiler, 0, I_ADD); 1504 } 1505 else if (uc_compiler_parse_match(compiler, TK_PLACEH)) { 1506 uc_compiler_compile_expression(compiler); 1507 uc_compiler_emit_insn(compiler, 0, I_ADD); 1508 uc_compiler_parse_consume(compiler, TK_RBRACE); 1509 } 1510 else { 1511 break; 1512 } 1513 } 1514 } 1515 1516 static void 1517 uc_compiler_compile_comma(uc_compiler_t *compiler) 1518 { 1519 uc_compiler_emit_insn(compiler, 0, I_POP); 1520 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1521 } 1522 1523 static void 1524 uc_compiler_compile_labelexpr(uc_compiler_t *compiler) 1525 { 1526 uc_value_t *label = ucv_get(compiler->parser->prev.uv); 1527 1528 uc_compiler_compile_var_or_arrowfn(compiler, label); 1529 ucv_put(label); 1530 } 1531 1532 static bool 1533 uc_compiler_compile_delimitted_block(uc_compiler_t *compiler, uc_tokentype_t endtype) 1534 { 1535 while (!uc_compiler_parse_check(compiler, endtype) && 1536 !uc_compiler_parse_check(compiler, TK_EOF)) 1537 uc_compiler_compile_declaration(compiler); 1538 1539 return uc_compiler_parse_check(compiler, endtype); 1540 } 1541 1542 static void 1543 uc_compiler_compile_function(uc_compiler_t *compiler) 1544 { 1545 uc_compiler_t fncompiler = { 0 }; 1546 uc_value_t *name = NULL; 1547 ssize_t slot = -1, pos; 1548 uc_tokentype_t type; 1549 size_t i, load_off; 1550 uc_function_t *fn; 1551 1552 pos = compiler->parser->prev.pos; 1553 type = compiler->parser->prev.type; 1554 1555 if (uc_compiler_parse_match(compiler, TK_LABEL)) { 1556 name = compiler->parser->prev.uv; 1557 1558 /* Named functions are syntactic sugar for local variable declaration 1559 * with function value assignment. If a name token was encountered, 1560 * initialize a local variable for it... */ 1561 slot = uc_compiler_declare_local(compiler, name, false); 1562 1563 if (slot == -1) 1564 uc_compiler_initialize_local(compiler); 1565 } 1566 1567 uc_compiler_init(&fncompiler, 1568 name ? ucv_string_get(name) : NULL, compiler->parser->prev.pos, 1569 compiler->program, 1570 uc_compiler_is_strict(compiler)); 1571 1572 fncompiler.parent = compiler; 1573 fncompiler.parser = compiler->parser; 1574 fncompiler.exprstack = compiler->exprstack; 1575 fn = (uc_function_t *)fncompiler.function; 1576 1577 uc_compiler_parse_consume(&fncompiler, TK_LPAREN); 1578 1579 uc_compiler_enter_scope(&fncompiler); 1580 1581 /* compile argument specification */ 1582 while (true) { 1583 if (uc_compiler_parse_check(&fncompiler, TK_RPAREN)) 1584 break; 1585 1586 if (uc_compiler_parse_match(&fncompiler, TK_ELLIP)) 1587 fn->vararg = true; 1588 1589 if (uc_compiler_parse_match(&fncompiler, TK_LABEL)) { 1590 fn->nargs++; 1591 1592 uc_compiler_declare_local(&fncompiler, fncompiler.parser->prev.uv, false); 1593 uc_compiler_initialize_local(&fncompiler); 1594 1595 if (fn->vararg || 1596 !uc_compiler_parse_match(&fncompiler, TK_COMMA)) 1597 break; 1598 } 1599 else { 1600 uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos, 1601 "Expecting Label"); 1602 1603 return; 1604 } 1605 } 1606 1607 uc_compiler_parse_consume(&fncompiler, TK_RPAREN); 1608 1609 /* parse and compile function body */ 1610 if (uc_compiler_parse_match(&fncompiler, TK_COLON)) { 1611 uc_compiler_compile_delimitted_block(&fncompiler, TK_ENDFUNC); 1612 uc_compiler_parse_consume(&fncompiler, TK_ENDFUNC); 1613 } 1614 else if (uc_compiler_parse_match(&fncompiler, TK_LBRACE)) { 1615 uc_compiler_compile_delimitted_block(&fncompiler, TK_RBRACE); 1616 uc_compiler_parse_consume(&fncompiler, TK_RBRACE); 1617 } 1618 else { 1619 uc_compiler_syntax_error(&fncompiler, fncompiler.parser->curr.pos, 1620 "Expecting '{' or ':' after function parameters"); 1621 } 1622 1623 /* emit load instruction for function value */ 1624 uc_compiler_emit_insn(compiler, pos, (type == TK_ARROW) ? I_ARFN : I_CLFN); 1625 load_off = uc_compiler_emit_u32(compiler, 0, 0); 1626 1627 /* encode upvalue information */ 1628 for (i = 0; i < fn->nupvals; i++) 1629 uc_compiler_emit_s32(compiler, 0, 1630 fncompiler.upvals.entries[i].local 1631 ? -(fncompiler.upvals.entries[i].index + 1) 1632 : fncompiler.upvals.entries[i].index); 1633 1634 /* finalize function compiler */ 1635 fn = uc_compiler_finish(&fncompiler); 1636 1637 if (fn) 1638 uc_compiler_set_u32(compiler, load_off, 1639 uc_program_function_id(compiler->program, fn)); 1640 1641 /* if a local variable of the same name already existed, overwrite its value 1642 * with the compiled function here */ 1643 if (slot != -1) { 1644 uc_compiler_emit_insn(compiler, 0, I_SLOC); 1645 uc_compiler_emit_u32(compiler, 0, slot); 1646 uc_compiler_emit_insn(compiler, 0, I_POP); 1647 } 1648 } 1649 1650 static void 1651 uc_compiler_compile_and(uc_compiler_t *compiler) 1652 { 1653 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 1654 size_t jmpz_off; 1655 1656 uc_compiler_emit_insn(compiler, 0, I_COPY); 1657 uc_compiler_emit_u8(compiler, 0, 0); 1658 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 1659 uc_compiler_emit_insn(compiler, 0, I_POP); 1660 uc_compiler_parse_precedence(compiler, P_AND); 1661 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 1662 } 1663 1664 static void 1665 uc_compiler_compile_or(uc_compiler_t *compiler) 1666 { 1667 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 1668 size_t jmpz_off, jmp_off; 1669 1670 uc_compiler_emit_insn(compiler, 0, I_COPY); 1671 uc_compiler_emit_u8(compiler, 0, 0); 1672 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 1673 jmp_off = uc_compiler_emit_jmp(compiler, 0); 1674 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 1675 uc_compiler_emit_insn(compiler, 0, I_POP); 1676 uc_compiler_parse_precedence(compiler, P_OR); 1677 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 1678 } 1679 1680 static void 1681 uc_compiler_compile_nullish(uc_compiler_t *compiler) 1682 { 1683 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 1684 size_t jmpz_off, jmp_off; 1685 1686 uc_compiler_emit_insn(compiler, 0, I_COPY); 1687 uc_compiler_emit_u8(compiler, 0, 0); 1688 uc_compiler_emit_insn(compiler, 0, I_LNULL); 1689 uc_compiler_emit_insn(compiler, 0, I_NES); 1690 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 1691 jmp_off = uc_compiler_emit_jmp(compiler, 0); 1692 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 1693 uc_compiler_emit_insn(compiler, 0, I_POP); 1694 uc_compiler_parse_precedence(compiler, P_OR); 1695 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 1696 } 1697 1698 static void 1699 uc_compiler_compile_dot(uc_compiler_t *compiler) 1700 { 1701 bool optional_chaining = (compiler->parser->prev.type == TK_QDOT); 1702 1703 /* flag optional chaining usage in current expression */ 1704 compiler->exprstack->flags |= optional_chaining ? F_OPTCHAINING : 0; 1705 1706 /* no regexp literal possible after property access */ 1707 compiler->parser->lex.no_regexp = true; 1708 1709 /* parse label lhs */ 1710 uc_compiler_parse_consume(compiler, TK_LABEL); 1711 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 1712 1713 /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */ 1714 if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL)) 1715 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QDOT : 0); 1716 } 1717 1718 static void 1719 uc_compiler_compile_subscript(uc_compiler_t *compiler) 1720 { 1721 bool optional_chaining = (compiler->parser->prev.type == TK_QLBRACK); 1722 1723 /* flag optional chaining usage in current expression */ 1724 compiler->exprstack->flags |= optional_chaining ? F_OPTCHAINING : 0; 1725 1726 /* compile lhs */ 1727 uc_compiler_compile_expression(compiler); 1728 1729 /* no regexp literal possible after computed property access */ 1730 compiler->parser->lex.no_regexp = true; 1731 uc_compiler_parse_consume(compiler, TK_RBRACK); 1732 1733 /* depending on context, compile into I_UVAL, I_SVAL or I_LVAL operation */ 1734 if (!uc_compiler_exprstack_is(compiler, F_ASSIGNABLE) || !uc_compiler_compile_assignment(compiler, NULL)) 1735 uc_compiler_emit_variable_rw(compiler, NULL, optional_chaining ? TK_QLBRACK : 0); 1736 } 1737 1738 static void 1739 uc_compiler_compile_ternary(uc_compiler_t *compiler) 1740 { 1741 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 1742 size_t jmpz_off, jmp_off; 1743 1744 /* jump to false branch */ 1745 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 1746 1747 /* compile true branch */ 1748 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1749 1750 /* jump after false branch */ 1751 jmp_off = uc_compiler_emit_jmp(compiler, 0); 1752 1753 uc_compiler_parse_consume(compiler, TK_COLON); 1754 1755 /* compile false branch */ 1756 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 1757 uc_compiler_parse_precedence(compiler, P_TERNARY); 1758 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 1759 } 1760 1761 static void 1762 uc_compiler_compile_array(uc_compiler_t *compiler) 1763 { 1764 size_t hint_off, hint_count = 0, len = 0; 1765 1766 /* create empty array on stack */ 1767 uc_compiler_emit_insn(compiler, 0, I_NARR); 1768 hint_off = uc_compiler_emit_u32(compiler, 0, 0); 1769 1770 /* parse initializer values */ 1771 do { 1772 if (uc_compiler_parse_check(compiler, TK_RBRACK)) { 1773 break; 1774 } 1775 else if (uc_compiler_parse_match(compiler, TK_ELLIP)) { 1776 /* push items on stack so far... */ 1777 if (len > 0) { 1778 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR); 1779 uc_compiler_emit_u32(compiler, 0, len); 1780 len = 0; 1781 } 1782 1783 /* compile spread value expression */ 1784 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1785 1786 /* emit merge operation */ 1787 uc_compiler_emit_insn(compiler, 0, I_MARR); 1788 } 1789 else { 1790 /* push items on stack so far... */ 1791 if (len >= 0xffffffff) { 1792 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR); 1793 uc_compiler_emit_u32(compiler, 0, len); 1794 len = 0; 1795 } 1796 1797 /* compile item value expression */ 1798 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1799 1800 hint_count++; 1801 len++; 1802 } 1803 } 1804 while (uc_compiler_parse_match(compiler, TK_COMMA)); 1805 1806 /* no regexp literal possible after array literal */ 1807 compiler->parser->lex.no_regexp = true; 1808 uc_compiler_parse_consume(compiler, TK_RBRACK); 1809 1810 /* push items on stack */ 1811 if (len > 0) { 1812 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_PARR); 1813 uc_compiler_emit_u32(compiler, 0, len); 1814 } 1815 1816 /* set initial size hint */ 1817 uc_compiler_set_u32(compiler, hint_off, hint_count); 1818 } 1819 1820 static void 1821 uc_compiler_compile_object(uc_compiler_t *compiler) 1822 { 1823 size_t hint_off, hint_count = 0, len = 0; 1824 1825 /* create empty object on stack */ 1826 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_NOBJ); 1827 hint_off = uc_compiler_emit_u32(compiler, 0, 0); 1828 1829 /* parse initializer values */ 1830 do { 1831 /* End of object literal */ 1832 if (uc_compiler_parse_check(compiler, TK_RBRACE)) 1833 break; 1834 1835 /* Spread operator */ 1836 if (uc_compiler_parse_match(compiler, TK_ELLIP)) { 1837 /* set items on stack so far... */ 1838 if (len > 0) { 1839 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ); 1840 uc_compiler_emit_u32(compiler, 0, len); 1841 len = 0; 1842 } 1843 1844 /* compile spread value expression */ 1845 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1846 1847 /* emit merge operation */ 1848 uc_compiler_emit_insn(compiler, 0, I_MOBJ); 1849 1850 continue; 1851 } 1852 1853 /* Computed property name */ 1854 if (uc_compiler_parse_match(compiler, TK_LBRACK)) { 1855 /* parse property name expression */ 1856 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1857 1858 /* cosume closing bracket and colon */ 1859 uc_compiler_parse_consume(compiler, TK_RBRACK); 1860 uc_compiler_parse_consume(compiler, TK_COLON); 1861 1862 /* parse value expression */ 1863 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1864 } 1865 1866 /* Property/value tuple or property shorthand */ 1867 else { 1868 /* parse key expression */ 1869 if (!uc_compiler_parse_match(compiler, TK_LABEL) && 1870 !uc_compiler_parse_match(compiler, TK_STRING)) 1871 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 1872 "Expecting label"); 1873 1874 /* load label */ 1875 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, 1876 compiler->parser->prev.uv); 1877 1878 /* If the property name is a plain label followed by a comma or 1879 * closing curly brace, treat it as ES2015 property shorthand 1880 * notation... */ 1881 if (compiler->parser->prev.type == TK_LABEL && 1882 (uc_compiler_parse_check(compiler, TK_COMMA) || 1883 uc_compiler_parse_check(compiler, TK_RBRACE))) { 1884 /* disallow keywords in this case */ 1885 if (uc_lexer_is_keyword(compiler->parser->prev.uv)) 1886 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 1887 "Invalid identifier"); 1888 1889 uc_compiler_emit_variable_rw(compiler, 1890 compiler->parser->prev.uv, 0); 1891 } 1892 1893 /* ... otherwise treat it as ordinary `key: value` tuple */ 1894 else { 1895 uc_compiler_parse_consume(compiler, TK_COLON); 1896 1897 /* parse value expression */ 1898 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1899 } 1900 } 1901 1902 /* set items on stack so far... */ 1903 if (len >= 0xfffffffe) { 1904 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ); 1905 uc_compiler_emit_u32(compiler, 0, len); 1906 len = 0; 1907 } 1908 1909 hint_count += 2; 1910 len += 2; 1911 1912 compiler->parser->lex.no_keyword = true; 1913 } 1914 while (uc_compiler_parse_match(compiler, TK_COMMA)); 1915 1916 /* no regexp literal possible after object literal */ 1917 compiler->parser->lex.no_regexp = true; 1918 uc_compiler_parse_consume(compiler, TK_RBRACE); 1919 1920 /* set items on stack */ 1921 if (len > 0) { 1922 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_SOBJ); 1923 uc_compiler_emit_u32(compiler, 0, len); 1924 } 1925 1926 /* set initial size hint */ 1927 uc_compiler_set_u32(compiler, hint_off, hint_count); 1928 } 1929 1930 1931 static void 1932 uc_compiler_declare_local_null(uc_compiler_t *compiler, size_t srcpos, uc_value_t *varname) 1933 { 1934 ssize_t existing_slot = uc_compiler_declare_local(compiler, varname, false); 1935 1936 uc_compiler_emit_insn(compiler, srcpos, I_LNULL); 1937 1938 if (existing_slot == -1) { 1939 uc_compiler_initialize_local(compiler); 1940 } 1941 else { 1942 uc_compiler_emit_insn(compiler, 0, I_SLOC); 1943 uc_compiler_emit_u32(compiler, 0, existing_slot); 1944 uc_compiler_emit_insn(compiler, 0, I_POP); 1945 } 1946 } 1947 1948 static size_t 1949 uc_compiler_declare_internal(uc_compiler_t *compiler, size_t srcpos, const char *name) 1950 { 1951 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 1952 uc_locals_t *locals = &compiler->locals; 1953 1954 uc_vector_grow(locals); 1955 1956 locals->entries[locals->count].name = ucv_string_new(name); 1957 locals->entries[locals->count].depth = compiler->scope_depth; 1958 locals->entries[locals->count].captured = false; 1959 locals->entries[locals->count].from = chunk->count; 1960 1961 return locals->count++; 1962 } 1963 1964 static void 1965 uc_compiler_compile_declexpr(uc_compiler_t *compiler, bool constant) 1966 { 1967 ssize_t slot; 1968 1969 do { 1970 /* parse variable name */ 1971 if (!uc_compiler_parse_match(compiler, TK_LABEL)) { 1972 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 1973 "Expecting variable name"); 1974 1975 return; 1976 } 1977 1978 /* declare local variable */ 1979 slot = uc_compiler_declare_local(compiler, compiler->parser->prev.uv, constant); 1980 1981 /* if followed by '=', parse initializer expression */ 1982 if (uc_compiler_parse_match(compiler, TK_ASSIGN)) 1983 uc_compiler_parse_precedence(compiler, P_ASSIGN); 1984 /* otherwise, for writable variables, load implicit null */ 1985 else if (!constant) 1986 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL); 1987 /* for constant variables, a missing initializer is a syntax error */ 1988 else 1989 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 1990 "Expecting initializer expression"); 1991 1992 /* initialize local */ 1993 if (slot == -1) { 1994 uc_compiler_initialize_local(compiler); 1995 } 1996 /* if the variable was redeclared, overwrite it */ 1997 else { 1998 uc_compiler_emit_insn(compiler, 0, I_SLOC); 1999 uc_compiler_emit_u32(compiler, 0, slot); 2000 uc_compiler_emit_insn(compiler, 0, I_POP); 2001 } 2002 } 2003 while (uc_compiler_parse_match(compiler, TK_COMMA)); 2004 } 2005 2006 static void 2007 uc_compiler_compile_local(uc_compiler_t *compiler) 2008 { 2009 uc_compiler_compile_declexpr(compiler, false); 2010 uc_compiler_parse_consume(compiler, TK_SCOL); 2011 } 2012 2013 static void 2014 uc_compiler_compile_const(uc_compiler_t *compiler) 2015 { 2016 uc_compiler_compile_declexpr(compiler, true); 2017 uc_compiler_parse_consume(compiler, TK_SCOL); 2018 } 2019 2020 static uc_tokentype_t 2021 uc_compiler_compile_altifblock(uc_compiler_t *compiler) 2022 { 2023 uc_compiler_enter_scope(compiler); 2024 2025 while (true) { 2026 switch (compiler->parser->curr.type) { 2027 case TK_ELIF: 2028 case TK_ELSE: 2029 case TK_ENDIF: 2030 case TK_EOF: 2031 uc_compiler_leave_scope(compiler); 2032 2033 return compiler->parser->curr.type; 2034 2035 default: 2036 uc_compiler_compile_declaration(compiler); 2037 break; 2038 } 2039 } 2040 2041 return 0; 2042 } 2043 2044 static void 2045 uc_compiler_compile_if(uc_compiler_t *compiler) 2046 { 2047 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2048 size_t jmpz_off, jmp_off, i; 2049 bool expect_endif = false; 2050 uc_jmplist_t elifs = { 0 }; 2051 uc_tokentype_t type; 2052 2053 /* parse & compile condition expression */ 2054 uc_compiler_parse_consume(compiler, TK_LPAREN); 2055 uc_compiler_compile_expression(compiler); 2056 uc_compiler_parse_consume(compiler, TK_RPAREN); 2057 2058 /* conditional jump to else/elif branch */ 2059 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2060 2061 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2062 compiler->exprstack->flags |= F_ALTBLOCKMODE; 2063 2064 while (true) { 2065 /* compile elsif or else branch */ 2066 type = uc_compiler_compile_altifblock(compiler); 2067 2068 /* we just compiled an elsif block */ 2069 if (!expect_endif && type == TK_ELIF) { 2070 /* emit jump to skip to the end */ 2071 uc_vector_grow(&elifs); 2072 elifs.entries[elifs.count++] = uc_compiler_emit_jmp(compiler, 0); 2073 2074 /* point previous conditional jump to beginning of branch */ 2075 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2076 2077 /* parse & compile elsif condition */ 2078 uc_compiler_parse_advance(compiler); 2079 uc_compiler_parse_consume(compiler, TK_LPAREN); 2080 uc_compiler_compile_expression(compiler); 2081 uc_compiler_parse_consume(compiler, TK_RPAREN); 2082 uc_compiler_parse_consume(compiler, TK_COLON); 2083 2084 /* conditional jump to else/elif branch */ 2085 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2086 } 2087 else if (!expect_endif && type == TK_ELSE) { 2088 /* emit jump to skip to the end */ 2089 uc_vector_grow(&elifs); 2090 elifs.entries[elifs.count++] = uc_compiler_emit_jmp(compiler, 0); 2091 2092 /* point previous conditional jump to beginning of branch */ 2093 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2094 jmpz_off = 0; 2095 2096 /* skip "else" keyword */ 2097 uc_compiler_parse_advance(compiler); 2098 2099 expect_endif = true; 2100 } 2101 else if (type == TK_ENDIF) { 2102 /* if no else clause, point previous conditional jump after block */ 2103 if (jmpz_off) 2104 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2105 2106 /* patch the elif branch jumps to point here after the else */ 2107 for (i = 0; i < elifs.count; i++) 2108 uc_compiler_set_jmpaddr(compiler, elifs.entries[i], 2109 chunk->count); 2110 2111 /* skip the "endif" keyword */ 2112 uc_compiler_parse_advance(compiler); 2113 break; 2114 } 2115 else { 2116 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2117 expect_endif 2118 ? "Expecting 'endif'" 2119 : "Expecting 'elif', 'else' or 'endif'"); 2120 2121 break; 2122 } 2123 } 2124 2125 uc_vector_clear(&elifs); 2126 } 2127 else { 2128 /* compile true branch */ 2129 uc_compiler_compile_statement(compiler); 2130 2131 /* ... when present, handle false branch */ 2132 if (uc_compiler_parse_match(compiler, TK_ELSE)) { 2133 /* jump to skip else branch */ 2134 jmp_off = uc_compiler_emit_jmp(compiler, 0); 2135 2136 /* set conditional jump address */ 2137 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2138 2139 /* compile false branch */ 2140 uc_compiler_compile_statement(compiler); 2141 2142 /* set else skip jump address */ 2143 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 2144 } 2145 /* ... otherwise point the conditional jump after the true branch */ 2146 else { 2147 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2148 } 2149 } 2150 } 2151 2152 static void 2153 uc_compiler_compile_while(uc_compiler_t *compiler) 2154 { 2155 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2156 uc_patchlist_t p = { .depth = compiler->scope_depth }; 2157 size_t cond_off, jmpz_off, end_off; 2158 2159 p.parent = compiler->patchlist; 2160 compiler->patchlist = &p; 2161 2162 cond_off = chunk->count; 2163 2164 /* parse & compile loop condition */ 2165 uc_compiler_parse_consume(compiler, TK_LPAREN); 2166 uc_compiler_compile_expression(compiler); 2167 uc_compiler_parse_consume(compiler, TK_RPAREN); 2168 2169 /* conditional jump to end */ 2170 jmpz_off = uc_compiler_emit_jmpz(compiler, 0); 2171 2172 /* compile loop body */ 2173 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2174 uc_compiler_enter_scope(compiler); 2175 2176 if (!uc_compiler_compile_delimitted_block(compiler, TK_ENDWHILE)) 2177 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2178 "Expecting 'endwhile'"); 2179 else 2180 uc_compiler_parse_advance(compiler); 2181 2182 uc_compiler_leave_scope(compiler); 2183 } 2184 else { 2185 uc_compiler_compile_statement(compiler); 2186 } 2187 2188 end_off = chunk->count; 2189 2190 /* jump back to condition */ 2191 uc_compiler_emit_jmp_dest(compiler, 0, cond_off); 2192 2193 /* set conditional jump target */ 2194 uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); 2195 2196 /* patch up break/continue */ 2197 uc_compiler_backpatch(compiler, chunk->count, end_off); 2198 } 2199 2200 static void 2201 uc_compiler_compile_for_in(uc_compiler_t *compiler, bool local, uc_token_t *kvar, uc_token_t *vvar) 2202 { 2203 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2204 uc_patchlist_t p = { .depth = compiler->scope_depth + 1 }; 2205 size_t skip_jmp, test_jmp, key_slot, val_slot; 2206 2207 p.parent = compiler->patchlist; 2208 compiler->patchlist = &p; 2209 2210 uc_compiler_enter_scope(compiler); 2211 2212 /* declare internal loop variables */ 2213 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2214 key_slot = uc_compiler_declare_internal(compiler, 0, "(for in key)"); 2215 2216 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2217 val_slot = uc_compiler_declare_internal(compiler, 0, "(for in value)"); 2218 2219 /* declare loop variables */ 2220 if (local) { 2221 uc_compiler_declare_local_null(compiler, kvar->pos, kvar->uv); 2222 2223 if (vvar) 2224 uc_compiler_declare_local_null(compiler, vvar->pos, vvar->uv); 2225 } 2226 2227 /* value to iterate */ 2228 uc_compiler_compile_expression(compiler); 2229 uc_compiler_parse_consume(compiler, TK_RPAREN); 2230 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2231 uc_compiler_emit_u32(compiler, 0, val_slot); 2232 2233 /* initial key value */ 2234 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2235 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2236 uc_compiler_emit_u32(compiler, 0, key_slot); 2237 2238 /* jump over variable read for first cycle */ 2239 skip_jmp = uc_compiler_emit_jmp(compiler, 0); 2240 2241 /* read value */ 2242 uc_compiler_emit_insn(compiler, 0, I_LLOC); 2243 uc_compiler_emit_u32(compiler, 0, val_slot); 2244 2245 /* read key */ 2246 uc_compiler_emit_insn(compiler, 0, I_LLOC); 2247 uc_compiler_emit_u32(compiler, 0, key_slot); 2248 2249 /* backpatch skip jump */ 2250 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); 2251 2252 /* load loop variable and get next key from object */ 2253 uc_compiler_emit_insn(compiler, 0, vvar ? I_NEXTKV : I_NEXTK); 2254 2255 /* set internal key variable */ 2256 uc_compiler_emit_insn(compiler, 0, I_SLOC); 2257 uc_compiler_emit_u32(compiler, 0, key_slot); 2258 2259 /* test for != null */ 2260 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2261 uc_compiler_emit_insn(compiler, 0, I_NES); 2262 2263 /* jump after loop body if no next key */ 2264 test_jmp = uc_compiler_emit_jmpz(compiler, 0); 2265 2266 /* set key and value variables */ 2267 if (vvar) { 2268 uc_compiler_emit_variable_rw(compiler, vvar->uv, TK_ASSIGN); 2269 uc_compiler_emit_insn(compiler, 0, I_POP); 2270 } 2271 2272 /* set key variable */ 2273 uc_compiler_emit_variable_rw(compiler, kvar->uv, TK_ASSIGN); 2274 uc_compiler_emit_insn(compiler, 0, I_POP); 2275 2276 /* compile loop body */ 2277 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2278 uc_compiler_enter_scope(compiler); 2279 2280 if (!uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR)) 2281 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2282 "Expecting 'endfor'"); 2283 else 2284 uc_compiler_parse_advance(compiler); 2285 2286 uc_compiler_leave_scope(compiler); 2287 } 2288 else { 2289 uc_compiler_compile_statement(compiler); 2290 } 2291 2292 /* jump back to retrieve next key */ 2293 uc_compiler_emit_jmp_dest(compiler, 0, skip_jmp + 5); 2294 2295 /* back patch conditional jump */ 2296 uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count); 2297 2298 /* pop loop variables */ 2299 uc_compiler_emit_insn(compiler, 0, I_POP); 2300 2301 if (vvar) 2302 uc_compiler_emit_insn(compiler, 0, I_POP); 2303 2304 /* patch up break/continue */ 2305 uc_compiler_backpatch(compiler, chunk->count, skip_jmp + 5); 2306 2307 uc_compiler_leave_scope(compiler); 2308 } 2309 2310 static void 2311 uc_compiler_compile_for_count(uc_compiler_t *compiler, bool local, uc_token_t *var) 2312 { 2313 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2314 size_t test_off = 0, incr_off, skip_off, cond_off = 0; 2315 uc_patchlist_t p = { .depth = compiler->scope_depth + 1 }; 2316 2317 p.parent = compiler->patchlist; 2318 compiler->patchlist = &p; 2319 2320 uc_compiler_enter_scope(compiler); 2321 2322 /* Initializer ---------------------------------------------------------- */ 2323 2324 /* If we parsed at least one label, try continue parsing as variable 2325 * expression... */ 2326 if (var) { 2327 /* We parsed a `local x` or `local x, y` expression, so (re)declare 2328 * last label as local initializer variable */ 2329 if (local) 2330 uc_compiler_declare_local_null(compiler, var->pos, var->uv); 2331 2332 uc_compiler_exprstack_push(compiler, TK_FOR, F_ASSIGNABLE); 2333 2334 uc_compiler_compile_labelexpr(compiler); 2335 uc_compiler_emit_insn(compiler, 0, I_POP); 2336 2337 /* If followed by a comma, continue parsing expression */ 2338 if (uc_compiler_parse_match(compiler, TK_COMMA)) { 2339 /* Is a continuation of a declaration list... */ 2340 if (local) { 2341 uc_compiler_compile_declexpr(compiler, false); 2342 } 2343 /* ... otherwise an unrelated expression */ 2344 else { 2345 uc_compiler_compile_expression(compiler); 2346 uc_compiler_emit_insn(compiler, 0, I_POP); 2347 } 2348 } 2349 2350 uc_compiler_exprstack_pop(compiler); 2351 } 2352 /* ... otherwise try parsing an entire expression (which might be absent) */ 2353 else if (!uc_compiler_parse_check(compiler, TK_SCOL)) { 2354 uc_compiler_compile_expression(compiler); 2355 uc_compiler_emit_insn(compiler, 0, I_POP); 2356 } 2357 2358 uc_compiler_parse_consume(compiler, TK_SCOL); 2359 2360 2361 /* Condition ------------------------------------------------------------ */ 2362 if (!uc_compiler_parse_check(compiler, TK_SCOL)) { 2363 cond_off = chunk->count; 2364 2365 uc_compiler_compile_expression(compiler); 2366 2367 test_off = uc_compiler_emit_jmpz(compiler, 0); 2368 } 2369 2370 uc_compiler_parse_consume(compiler, TK_SCOL); 2371 2372 /* jump over incrementer */ 2373 skip_off = uc_compiler_emit_jmp(compiler, 0); 2374 2375 2376 /* Incrementer ---------------------------------------------------------- */ 2377 incr_off = chunk->count; 2378 2379 if (!uc_compiler_parse_check(compiler, TK_RPAREN)) { 2380 uc_compiler_compile_expression(compiler); 2381 uc_compiler_emit_insn(compiler, 0, I_POP); 2382 } 2383 2384 uc_compiler_parse_consume(compiler, TK_RPAREN); 2385 2386 /* if we have a condition, jump back to it, else continue to the loop body */ 2387 if (cond_off) 2388 uc_compiler_emit_jmp_dest(compiler, 0, cond_off); 2389 2390 /* back patch skip address */ 2391 uc_compiler_set_jmpaddr(compiler, skip_off, chunk->count); 2392 2393 2394 /* Body ----------------------------------------------------------------- */ 2395 if (uc_compiler_parse_match(compiler, TK_COLON)) { 2396 uc_compiler_enter_scope(compiler); 2397 2398 if (!uc_compiler_compile_delimitted_block(compiler, TK_ENDFOR)) 2399 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2400 "Expecting 'endfor'"); 2401 else 2402 uc_compiler_parse_advance(compiler); 2403 2404 uc_compiler_leave_scope(compiler); 2405 } 2406 else { 2407 uc_compiler_compile_statement(compiler); 2408 } 2409 2410 /* jump back to incrementer */ 2411 uc_compiler_emit_jmp_dest(compiler, 0, incr_off); 2412 2413 /* back patch conditional jump */ 2414 if (test_off) 2415 uc_compiler_set_jmpaddr(compiler, test_off, chunk->count); 2416 2417 /* patch up break/continue */ 2418 uc_compiler_backpatch(compiler, chunk->count, incr_off); 2419 2420 uc_compiler_leave_scope(compiler); 2421 } 2422 2423 static void 2424 uc_compiler_compile_for(uc_compiler_t *compiler) 2425 { 2426 uc_token_t keyvar = { 0 }, valvar = { 0 }; 2427 bool local; 2428 2429 uc_compiler_parse_consume(compiler, TK_LPAREN); 2430 2431 /* check the next few tokens and see if we have either a 2432 * `let x in` / `let x, y` expression or an ordinary initializer 2433 * statement */ 2434 2435 local = uc_compiler_parse_match(compiler, TK_LOCAL); 2436 2437 if (uc_compiler_parse_match(compiler, TK_LABEL)) { 2438 keyvar = compiler->parser->prev; 2439 ucv_get(keyvar.uv); 2440 2441 if (uc_compiler_parse_match(compiler, TK_COMMA)) { 2442 uc_compiler_parse_consume(compiler, TK_LABEL); 2443 2444 valvar = compiler->parser->prev; 2445 ucv_get(valvar.uv); 2446 } 2447 2448 /* is a for-in loop */ 2449 if (uc_compiler_parse_match(compiler, TK_IN)) { 2450 uc_compiler_compile_for_in(compiler, local, &keyvar, 2451 valvar.type ? &valvar : NULL); 2452 2453 goto out; 2454 } 2455 } 2456 else if (local) { 2457 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2458 "Expecting label after 'local'"); 2459 2460 goto out; 2461 } 2462 2463 /* 2464 * The previous expression ruled out a for-in loop, so continue parsing 2465 * as counting for loop... 2466 */ 2467 uc_compiler_compile_for_count(compiler, local, 2468 valvar.uv ? &valvar : (keyvar.uv ? &keyvar : NULL)); 2469 2470 out: 2471 ucv_put(keyvar.uv); 2472 ucv_put(valvar.uv); 2473 } 2474 2475 static void 2476 uc_compiler_compile_switch(uc_compiler_t *compiler) 2477 { 2478 size_t i, test_jmp, skip_jmp, next_jmp, value_slot, default_off = 0; 2479 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2480 uc_patchlist_t p = { .depth = compiler->scope_depth }; 2481 uc_locals_t *locals = &compiler->locals; 2482 uc_jmplist_t cases = { 0 }; 2483 2484 p.parent = compiler->patchlist; 2485 compiler->patchlist = &p; 2486 2487 uc_compiler_enter_scope(compiler); 2488 2489 /* parse and compile match value */ 2490 uc_compiler_parse_consume(compiler, TK_LPAREN); 2491 uc_compiler_compile_expression(compiler); 2492 uc_compiler_parse_consume(compiler, TK_RPAREN); 2493 uc_compiler_parse_consume(compiler, TK_LBRACE); 2494 2495 value_slot = uc_compiler_declare_internal(compiler, 0, "(switch value)"); 2496 2497 /* jump to branch tests */ 2498 test_jmp = uc_compiler_emit_jmp(compiler, 0); 2499 2500 /* parse and compile case matches */ 2501 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 2502 !uc_compiler_parse_check(compiler, TK_EOF)) { 2503 /* handle `default:` */ 2504 if (uc_compiler_parse_match(compiler, TK_DEFAULT)) { 2505 if (default_off) { 2506 uc_vector_clear(&cases); 2507 uc_compiler_syntax_error(compiler, compiler->parser->prev.pos, 2508 "more than one switch default case"); 2509 2510 break; 2511 } 2512 2513 uc_compiler_parse_consume(compiler, TK_COLON); 2514 2515 /* remember address of default branch */ 2516 default_off = chunk->count; 2517 2518 /* Store three values in case offset list: 2519 * 1) amount of local variables declared so far 2520 * 2) beginning of condition expression 2521 * 3) end of condition expression 2522 * For the `default` case, beginning and end offsets of the 2523 * condition expression are equal. 2524 */ 2525 uc_vector_grow(&cases); 2526 cases.entries[cases.count++] = (locals->count - 1) - value_slot; 2527 2528 uc_vector_grow(&cases); 2529 cases.entries[cases.count++] = chunk->count; 2530 2531 uc_vector_grow(&cases); 2532 cases.entries[cases.count++] = chunk->count; 2533 } 2534 2535 /* handle `case …:` */ 2536 else if (uc_compiler_parse_match(compiler, TK_CASE)) { 2537 /* jump over `case …:` label expression */ 2538 skip_jmp = uc_compiler_emit_jmp(compiler, 0); 2539 2540 /* compile case value expression */ 2541 uc_compiler_compile_expression(compiler); 2542 uc_compiler_parse_consume(compiler, TK_COLON); 2543 2544 /* Store three values in case offset list: 2545 * 1) amount of local variables declared so far 2546 * 2) beginning of condition expression 2547 * 3) end of condition expression 2548 */ 2549 uc_vector_grow(&cases); 2550 cases.entries[cases.count++] = (locals->count - 1) - value_slot; 2551 2552 uc_vector_grow(&cases); 2553 cases.entries[cases.count++] = skip_jmp + 5; 2554 2555 uc_vector_grow(&cases); 2556 cases.entries[cases.count++] = uc_compiler_emit_jmp(compiler, 0); 2557 2558 /* patch jump skipping over the case value */ 2559 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); 2560 } 2561 2562 /* handle interleaved statement */ 2563 else if (cases.count) { 2564 uc_compiler_compile_declaration(compiler); 2565 } 2566 2567 /* a statement or expression preceeding any `default` or `case` is a 2568 * syntax error */ 2569 else { 2570 uc_compiler_syntax_error(compiler, compiler->parser->curr.pos, 2571 "Expecting 'case' or 'default'"); 2572 2573 break; 2574 } 2575 } 2576 2577 uc_compiler_parse_consume(compiler, TK_RBRACE); 2578 2579 /* evaluate case matches */ 2580 if (cases.count) { 2581 skip_jmp = uc_compiler_emit_jmp(compiler, 0); 2582 2583 uc_compiler_set_jmpaddr(compiler, test_jmp, chunk->count); 2584 2585 for (i = 0, default_off = cases.count; i < cases.count; i += 3) { 2586 /* remember and skip default case */ 2587 if (cases.entries[i + 1] == cases.entries[i + 2]) { 2588 default_off = i; 2589 continue; 2590 } 2591 2592 /* read switch match value */ 2593 uc_compiler_emit_insn(compiler, 0, I_LLOC); 2594 uc_compiler_emit_u32(compiler, 0, value_slot); 2595 2596 /* jump to case value expression code */ 2597 uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 1]); 2598 2599 /* patch final case value expression jump back here */ 2600 uc_compiler_set_jmpaddr(compiler, cases.entries[i + 2], chunk->count); 2601 2602 /* strict equal test */ 2603 uc_compiler_emit_insn(compiler, 0, I_EQS); 2604 2605 /* conditional jump to next match */ 2606 next_jmp = uc_compiler_emit_jmpz(compiler, 0); 2607 2608 /* fill local slots */ 2609 while (cases.entries[i + 0] > 0) { 2610 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2611 cases.entries[i + 0]--; 2612 } 2613 2614 /* jump to target code */ 2615 uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[i + 2] + 5); 2616 2617 /* patch next jump */ 2618 uc_compiler_set_jmpaddr(compiler, next_jmp, chunk->count); 2619 } 2620 2621 /* handle default case (if any) */ 2622 if (default_off < cases.count) { 2623 /* fill local slots */ 2624 while (cases.entries[default_off + 0] > 0) { 2625 uc_compiler_emit_insn(compiler, 0, I_LNULL); 2626 cases.entries[default_off + 0]--; 2627 } 2628 2629 /* jump to target */ 2630 uc_compiler_emit_jmp_dest(compiler, 0, cases.entries[default_off + 2]); 2631 } 2632 2633 uc_compiler_set_jmpaddr(compiler, skip_jmp, chunk->count); 2634 } 2635 else { 2636 uc_compiler_set_jmpaddr(compiler, test_jmp, test_jmp + 5); 2637 } 2638 2639 uc_vector_clear(&cases); 2640 2641 uc_compiler_leave_scope(compiler); 2642 2643 uc_compiler_backpatch(compiler, chunk->count, 0); 2644 } 2645 2646 static void 2647 uc_compiler_compile_try(uc_compiler_t *compiler) 2648 { 2649 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2650 size_t try_from = 0, try_to = 0, jmp_off = 0, ehvar_slot = 0; 2651 uc_ehranges_t *ranges = &chunk->ehranges; 2652 2653 try_from = chunk->count; 2654 ehvar_slot = compiler->locals.count; 2655 2656 /* Try block ------------------------------------------------------------ */ 2657 uc_compiler_enter_scope(compiler); 2658 2659 uc_compiler_parse_consume(compiler, TK_LBRACE); 2660 2661 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 2662 !uc_compiler_parse_check(compiler, TK_EOF)) 2663 uc_compiler_compile_declaration(compiler); 2664 2665 uc_compiler_parse_consume(compiler, TK_RBRACE); 2666 2667 uc_compiler_leave_scope(compiler); 2668 2669 /* jump beyond catch branch */ 2670 try_to = chunk->count; 2671 jmp_off = uc_compiler_emit_jmp(compiler, 0); 2672 2673 2674 /* Catch block ---------------------------------------------------------- */ 2675 if (try_to > try_from) { 2676 uc_vector_grow(ranges); 2677 2678 ranges->entries[ranges->count].from = try_from; 2679 ranges->entries[ranges->count].to = try_to; 2680 ranges->entries[ranges->count].target = chunk->count; 2681 ranges->entries[ranges->count].slot = ehvar_slot; 2682 ranges->count++; 2683 } 2684 2685 uc_compiler_enter_scope(compiler); 2686 2687 uc_compiler_parse_consume(compiler, TK_CATCH); 2688 2689 /* have exception variable */ 2690 if (uc_compiler_parse_match(compiler, TK_LPAREN)) { 2691 uc_compiler_parse_consume(compiler, TK_LABEL); 2692 2693 uc_compiler_declare_local(compiler, compiler->parser->prev.uv, false); 2694 uc_compiler_initialize_local(compiler); 2695 2696 uc_compiler_parse_consume(compiler, TK_RPAREN); 2697 } 2698 /* ... else pop exception object from stack */ 2699 else { 2700 uc_compiler_emit_insn(compiler, 0, I_POP); 2701 } 2702 2703 uc_compiler_parse_consume(compiler, TK_LBRACE); 2704 2705 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 2706 !uc_compiler_parse_check(compiler, TK_EOF)) 2707 uc_compiler_compile_declaration(compiler); 2708 2709 uc_compiler_parse_consume(compiler, TK_RBRACE); 2710 2711 uc_compiler_leave_scope(compiler); 2712 2713 uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); 2714 } 2715 2716 static void 2717 uc_compiler_compile_control(uc_compiler_t *compiler) 2718 { 2719 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2720 uc_tokentype_t type = compiler->parser->prev.type; 2721 uc_patchlist_t *p = compiler->patchlist; 2722 uc_locals_t *locals = &compiler->locals; 2723 size_t i, pos = compiler->parser->prev.pos; 2724 2725 if (!p) { 2726 uc_compiler_syntax_error(compiler, pos, 2727 (type == TK_BREAK) 2728 ? "break must be inside loop or switch" 2729 : "continue must be inside loop"); 2730 2731 return; 2732 } 2733 2734 /* pop locals in scope up to this point */ 2735 for (i = locals->count; i > 0 && (size_t)locals->entries[i - 1].depth > p->depth; i--) 2736 uc_compiler_emit_insn(compiler, 0, I_POP); 2737 2738 uc_vector_grow(p); 2739 2740 p->entries[p->count++] = 2741 uc_compiler_emit_jmp_dest(compiler, pos, chunk->count + type); 2742 2743 uc_compiler_parse_consume(compiler, TK_SCOL); 2744 } 2745 2746 static void 2747 uc_compiler_compile_return(uc_compiler_t *compiler) 2748 { 2749 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2750 size_t off = chunk->count; 2751 2752 uc_compiler_compile_expstmt(compiler); 2753 2754 /* if we compiled an empty expression statement (`;`), load implicit null */ 2755 if (chunk->count == off) 2756 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_LNULL); 2757 /* otherwise overwrite the final I_POP instruction with I_RETURN */ 2758 else 2759 uc_chunk_pop(chunk); 2760 2761 uc_compiler_emit_insn(compiler, compiler->parser->prev.pos, I_RETURN); 2762 } 2763 2764 static void 2765 uc_compiler_compile_tplexp(uc_compiler_t *compiler) 2766 { 2767 uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); 2768 size_t off = chunk->count; 2769 2770 uc_compiler_compile_expression(compiler); 2771 2772 /* XXX: the lexer currently emits a superfluous trailing semicolon... */ 2773 uc_compiler_parse_match(compiler, TK_SCOL); 2774 2775 uc_compiler_parse_consume(compiler, TK_REXP); 2776 2777 if (chunk->count > off) 2778 uc_compiler_emit_insn(compiler, 0, I_PRINT); 2779 } 2780 2781 static void 2782 uc_compiler_compile_text(uc_compiler_t *compiler) 2783 { 2784 uc_compiler_emit_constant(compiler, compiler->parser->prev.pos, compiler->parser->prev.uv); 2785 uc_compiler_emit_insn(compiler, 0, I_PRINT); 2786 } 2787 2788 static void 2789 uc_compiler_compile_block(uc_compiler_t *compiler) 2790 { 2791 uc_compiler_enter_scope(compiler); 2792 2793 while (!uc_compiler_parse_check(compiler, TK_RBRACE) && 2794 !uc_compiler_parse_check(compiler, TK_EOF)) 2795 uc_compiler_compile_declaration(compiler); 2796 2797 uc_compiler_parse_consume(compiler, TK_RBRACE); 2798 2799 uc_compiler_leave_scope(compiler); 2800 } 2801 2802 static void 2803 uc_compiler_compile_expstmt(uc_compiler_t *compiler) 2804 { 2805 /* empty statement */ 2806 if (uc_compiler_parse_match(compiler, TK_SCOL)) 2807 return; 2808 2809 uc_compiler_compile_expression(compiler); 2810 2811 /* allow omitting final semicolon */ 2812 switch (compiler->parser->curr.type) { 2813 case TK_RBRACE: 2814 case TK_ELIF: 2815 case TK_ENDIF: 2816 case TK_ENDFOR: 2817 case TK_ENDWHILE: 2818 case TK_ENDFUNC: 2819 case TK_EOF: 2820 break; 2821 2822 case TK_ELSE: 2823 if (!uc_compiler_exprstack_is(compiler, F_ALTBLOCKMODE)) 2824 uc_compiler_parse_consume(compiler, TK_SCOL); 2825 2826 break; 2827 2828 default: 2829 uc_compiler_parse_consume(compiler, TK_SCOL); 2830 2831 break; 2832 } 2833 2834 uc_compiler_emit_insn(compiler, 0, I_POP); 2835 } 2836 2837 static void 2838 uc_compiler_compile_statement(uc_compiler_t *compiler) 2839 { 2840 uc_exprstack_t expr = { 2841 .token = compiler->parser->curr.type, 2842 .parent = compiler->exprstack 2843 }; 2844 2845 compiler->exprstack = &expr; 2846 2847 if (uc_compiler_parse_match(compiler, TK_IF)) 2848 uc_compiler_compile_if(compiler); 2849 else if (uc_compiler_parse_match(compiler, TK_WHILE)) 2850 uc_compiler_compile_while(compiler); 2851 else if (uc_compiler_parse_match(compiler, TK_FOR)) 2852 uc_compiler_compile_for(compiler); 2853 else if (uc_compiler_parse_match(compiler, TK_SWITCH)) 2854 uc_compiler_compile_switch(compiler); 2855 else if (uc_compiler_parse_match(compiler, TK_TRY)) 2856 uc_compiler_compile_try(compiler); 2857 else if (uc_compiler_parse_match(compiler, TK_FUNC)) 2858 uc_compiler_compile_function(compiler); 2859 else if (uc_compiler_parse_match(compiler, TK_BREAK)) 2860 uc_compiler_compile_control(compiler); 2861 else if (uc_compiler_parse_match(compiler, TK_CONTINUE)) 2862 uc_compiler_compile_control(compiler); 2863 else if (uc_compiler_parse_match(compiler, TK_RETURN)) 2864 uc_compiler_compile_return(compiler); 2865 else if (uc_compiler_parse_match(compiler, TK_TEXT)) 2866 uc_compiler_compile_text(compiler); 2867 else if (uc_compiler_parse_match(compiler, TK_LEXP)) 2868 uc_compiler_compile_tplexp(compiler); 2869 else if (uc_compiler_parse_match(compiler, TK_LBRACE)) 2870 uc_compiler_compile_block(compiler); 2871 else 2872 uc_compiler_compile_expstmt(compiler); 2873 2874 compiler->exprstack = expr.parent; 2875 } 2876 2877 static void 2878 uc_compiler_compile_declaration(uc_compiler_t *compiler) 2879 { 2880 2881 if (uc_compiler_parse_match(compiler, TK_LOCAL)) 2882 uc_compiler_compile_local(compiler); 2883 else if (uc_compiler_parse_match(compiler, TK_CONST)) 2884 uc_compiler_compile_const(compiler); 2885 else 2886 uc_compiler_compile_statement(compiler); 2887 2888 if (compiler->parser->synchronizing) 2889 uc_compiler_parse_synchronize(compiler); 2890 } 2891 2892 #endif /* NO_COMPILE */ 2893 2894 2895 static uc_program_t * 2896 uc_compile_from_source(uc_parse_config_t *config, uc_source_t *source, char **errp) 2897 { 2898 #ifdef NO_COMPILE 2899 if (errp) 2900 xasprintf(errp, "Source code compilation not supported\n"); 2901 2902 return NULL; 2903 #else 2904 uc_exprstack_t expr = { .token = TK_EOF }; 2905 uc_parser_t parser = { .config = config }; 2906 uc_compiler_t compiler = { .parser = &parser, .exprstack = &expr }; 2907 uc_program_t *prog; 2908 uc_function_t *fn; 2909 2910 prog = uc_program_new(source); 2911 2912 uc_lexer_init(&parser.lex, config, source); 2913 uc_compiler_init(&compiler, "main", 0, prog, 2914 config && config->strict_declarations); 2915 2916 uc_compiler_parse_advance(&compiler); 2917 2918 while (!uc_compiler_parse_match(&compiler, TK_EOF)) 2919 uc_compiler_compile_declaration(&compiler); 2920 2921 fn = uc_compiler_finish(&compiler); 2922 2923 if (errp) { 2924 *errp = parser.error ? parser.error->buf : NULL; 2925 free(parser.error); 2926 } 2927 else { 2928 printbuf_free(parser.error); 2929 } 2930 2931 uc_lexer_free(&parser.lex); 2932 2933 if (!fn) { 2934 ucv_put(&prog->header); 2935 2936 return NULL; 2937 } 2938 2939 return prog; 2940 #endif 2941 } 2942 2943 static uc_program_t * 2944 uc_compile_from_bytecode(uc_parse_config_t *config, uc_source_t *source, char **errp) 2945 { 2946 uc_program_t *prog; 2947 2948 prog = uc_program_load(source, errp); 2949 2950 if (prog && !uc_program_entry(prog)) { 2951 if (errp) 2952 xasprintf(errp, "Program file contains no entry function\n"); 2953 2954 ucv_put(&prog->header); 2955 } 2956 2957 return prog; 2958 } 2959 2960 uc_program_t * 2961 uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp) 2962 { 2963 uc_program_t *prog = NULL; 2964 2965 switch (uc_source_type_test(source)) { 2966 case UC_SOURCE_TYPE_PLAIN: 2967 prog = uc_compile_from_source(config, source, errp); 2968 break; 2969 2970 case UC_SOURCE_TYPE_PRECOMPILED: 2971 prog = uc_compile_from_bytecode(config, source, errp); 2972 break; 2973 2974 default: 2975 if (errp) 2976 xasprintf(errp, "Unrecognized source type\n"); 2977 2978 break; 2979 } 2980 2981 return prog; 2982 } 2983
This page was automatically generated by LXR 0.3.1. • OpenWrt