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