MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 5781 lines 182 kB view raw
1#include "silver/ast.h" 2#include "silver/compile_ctx.h" 3#include "silver/engine.h" 4#include "silver/compiler.h" 5#include "silver/directives.h" 6 7#include "internal.h" 8#include "debug.h" 9#include "tokens.h" 10#include "runtime.h" 11#include "utils.h" 12#include "ops/coercion.h" 13 14#include <stdlib.h> 15#include <string.h> 16#include <stdio.h> 17 18enum { 19 SV_ITER_HINT_GENERIC = 0, 20 SV_ITER_HINT_ARRAY = 1, 21 SV_ITER_HINT_STRING = 4, 22}; 23 24static const char *pin_source_text(const char *source, ant_offset_t source_len) { 25 if (!source || source_len <= 0) return source; 26 const char *pinned = code_arena_alloc(source, (size_t)source_len); 27 return pinned ? pinned : source; 28} 29 30static void emit(sv_compiler_t *c, uint8_t byte) { 31 if (c->code_len >= c->code_cap) { 32 c->code_cap = c->code_cap ? c->code_cap * 2 : 256; 33 c->code = realloc(c->code, (size_t)c->code_cap); 34 } 35 c->code[c->code_len++] = byte; 36} 37 38static void emit_u16(sv_compiler_t *c, uint16_t val) { 39 emit(c, (uint8_t)(val & 0xFF)); 40 emit(c, (uint8_t)(val >> 8)); 41} 42 43static void emit_u32(sv_compiler_t *c, uint32_t val) { 44 emit(c, (uint8_t)(val & 0xFF)); 45 emit(c, (uint8_t)((val >> 8) & 0xFF)); 46 emit(c, (uint8_t)((val >> 16) & 0xFF)); 47 emit(c, (uint8_t)((val >> 24) & 0xFF)); 48} 49 50static void emit_i32(sv_compiler_t *c, int32_t val) { 51 uint32_t u; 52 memcpy(&u, &val, 4); 53 emit_u32(c, u); 54} 55 56static void emit_op(sv_compiler_t *c, sv_op_t op) { 57 emit(c, (uint8_t)op); 58} 59 60static void compile_receiver_property_get(sv_compiler_t *c, sv_ast_t *node); 61static void compile_truthy_test_expr(sv_compiler_t *c, sv_ast_t *node); 62 63static void emit_srcpos(sv_compiler_t *c, sv_ast_t *node) { 64 if (!node) return; 65 const char *code = c->source; 66 ant_offset_t clen = c->source_len; 67 if (!code || clen <= 0) return; 68 69 uint32_t off = node->src_off; 70 if (off > clen) off = (uint32_t)clen; 71 uint32_t end = node->src_end; 72 if (end > clen) end = (uint32_t)clen; 73 if (end < off) end = off; 74 if (end == off && off < (uint32_t)clen) end = off + 1; 75 if (end == off) return; 76 77 if (c->srcpos_count > 0 && c->last_srcpos_off == off && c->last_srcpos_end == end) return; 78 79 uint32_t line, col; 80 if (c->line_table) sv_compile_ctx_line_table_lookup(c->line_table, off, &line, &col); 81 else if (c->srcpos_count > 0 && off >= c->last_srcpos_off) { 82 line = c->srcpos[c->srcpos_count - 1].line; 83 col = c->srcpos[c->srcpos_count - 1].col; 84 for (uint32_t i = c->last_srcpos_off; i < off; i++) { 85 if (code[i] == '\n') { line++; col = 1; } 86 else col++; 87 } 88 } else { 89 line = 1; col = 1; 90 for (uint32_t i = 0; i < off; i++) { 91 if (code[i] == '\n') { line++; col = 1; } 92 else col++; 93 } 94 } 95 96 if (c->srcpos_count >= c->srcpos_cap) { 97 c->srcpos_cap = c->srcpos_cap ? c->srcpos_cap * 2 : 32; 98 c->srcpos = realloc(c->srcpos, (size_t)c->srcpos_cap * sizeof(sv_srcpos_t)); 99 } 100 c->srcpos[c->srcpos_count++] = (sv_srcpos_t){ 101 .bc_offset = (uint32_t)c->code_len, 102 .line = line, 103 .col = col, 104 .src_off = off, 105 .src_end = end, 106 }; 107 c->last_srcpos_off = off; 108 c->last_srcpos_end = end; 109} 110 111static void patch_u32(sv_compiler_t *c, int offset, uint32_t val) { 112 c->code[offset] = (uint8_t)(val & 0xFF); 113 c->code[offset + 1] = (uint8_t)((val >> 8) & 0xFF); 114 c->code[offset + 2] = (uint8_t)((val >> 16) & 0xFF); 115 c->code[offset + 3] = (uint8_t)((val >> 24) & 0xFF); 116} 117 118static int add_constant(sv_compiler_t *c, ant_value_t val) { 119 if (vtype(val) == T_STR) { 120 ant_offset_t slen; 121 ant_offset_t off = vstr(c->js, val, &slen); 122 const char *sptr = (const char *)(uintptr_t)off; 123 124 const_dedup_entry_t *found = NULL; 125 HASH_FIND(hh, c->const_dedup, sptr, (size_t)slen, found); 126 if (found) return found->index; 127 128 int idx = c->const_count; 129 if (c->const_count >= c->const_cap) { 130 c->const_cap = c->const_cap ? c->const_cap * 2 : 16; 131 c->constants = realloc(c->constants, (size_t)c->const_cap * sizeof(ant_value_t)); 132 } 133 c->constants[c->const_count++] = val; 134 135 const_dedup_entry_t *entry = malloc(sizeof(const_dedup_entry_t)); 136 if (entry) { 137 entry->str = sptr; 138 entry->len = (size_t)slen; 139 entry->index = idx; 140 HASH_ADD_KEYPTR(hh, c->const_dedup, entry->str, entry->len, entry); 141 } 142 return idx; 143 } 144 145 if (c->const_count >= c->const_cap) { 146 c->const_cap = c->const_cap ? c->const_cap * 2 : 16; 147 c->constants = realloc(c->constants, (size_t)c->const_cap * sizeof(ant_value_t)); 148 } 149 c->constants[c->const_count] = val; 150 return c->const_count++; 151} 152 153static void build_gc_const_tables(sv_func_t *func) { 154 if (!func || func->const_count <= 0 || !func->constants) return; 155 156 int child_count = 0; 157 for (int i = 0; i < func->const_count; i++) { 158 if (vtype(func->constants[i]) == T_NTARG) child_count++; 159 } 160 161 if (child_count > 0) { 162 func->child_funcs = code_arena_bump((size_t)child_count * sizeof(sv_func_t *)); 163 if (func->child_funcs) { 164 int out = 0; 165 for (int i = 0; i < func->const_count; i++) { 166 if (vtype(func->constants[i]) != T_NTARG) continue; 167 func->child_funcs[out++] = (sv_func_t *)(uintptr_t)vdata(func->constants[i]); 168 } func->child_func_count = child_count; 169 } 170 } 171 172 uint8_t *marked_slots = calloc((size_t)func->const_count, sizeof(uint8_t)); 173 if (!marked_slots) return; 174 175 int slot_count = 0; 176 for (int pc = 0; pc < func->code_len;) { 177 sv_op_t op = (sv_op_t)func->code[pc]; 178 int size = (op < OP__COUNT) ? sv_op_size[op] : 0; 179 if (size <= 0) break; 180 181 if (op == OP_PUT_CONST) { 182 uint32_t idx = sv_get_u32(func->code + pc + 1); 183 if (idx < (uint32_t)func->const_count && !marked_slots[idx]) { 184 marked_slots[idx] = 1; slot_count++; 185 } 186 } 187 188 pc += size; 189 } 190 191 if (slot_count > 0) { 192 func->gc_const_slots = code_arena_bump((size_t)slot_count * sizeof(uint32_t)); 193 if (func->gc_const_slots) { 194 int out = 0; 195 for (int i = 0; i < func->const_count; i++) { 196 if (!marked_slots[i]) continue; 197 func->gc_const_slots[out++] = (uint32_t)i; 198 } 199 func->gc_const_slot_count = slot_count; 200 } 201 } 202 203 free(marked_slots); 204} 205 206static void emit_constant(sv_compiler_t *c, ant_value_t val) { 207 int idx = add_constant(c, val); 208 if (idx <= 255) { 209 emit_op(c, OP_CONST8); 210 emit(c, (uint8_t)idx); 211 } else { 212 emit_op(c, OP_CONST); 213 emit_u32(c, (uint32_t)idx); 214 } 215} 216 217static void emit_number(sv_compiler_t *c, double num) { 218 if (num >= -128 && num <= 127 && num == (int)num && num != -0.0) { 219 emit_op(c, OP_CONST_I8); 220 emit(c, (uint8_t)(int8_t)num); 221 } else emit_constant(c, tov(num)); 222} 223 224 225static inline bool is_quoted_ident_key(const sv_ast_t *node) { 226 if (!node || node->type != N_IDENT || !node->str || node->len < 2) return false; 227 char open = node->str[0]; 228 char close = node->str[node->len - 1]; 229 return ((open == '\'' && close == '\'') || (open == '"' && close == '"')); 230} 231 232static inline bool is_template_segment(const sv_ast_t *node) { 233 return node && node->type == N_STRING && (node->flags & FN_TEMPLATE_SEGMENT); 234} 235 236static inline bool is_invalid_cooked_string(const sv_ast_t *node) { 237 return is_template_segment(node) && (node->flags & FN_INVALID_COOKED); 238} 239 240static inline ant_value_t ast_string_const(sv_compiler_t *c, const sv_ast_t *node) { 241 if (!node || !node->str) return js_mkstr_permanent(c->js, "", 0); 242 return js_mkstr_permanent(c->js, node->str, node->len); 243} 244 245static inline void compile_static_property_key(sv_compiler_t *c, sv_ast_t *key) { 246 if (!key) { 247 emit_op(c, OP_UNDEF); 248 return; 249 } 250 251 if (key->type == N_STRING) { 252 emit_constant(c, ast_string_const(c, key)); 253 return; 254 } 255 256 if (key->type == N_NUMBER) { 257 char buf[32]; 258 int n = snprintf(buf, sizeof(buf), "%g", key->num); 259 emit_constant(c, js_mkstr_permanent(c->js, buf, (size_t)n)); 260 return; 261 } 262 263 if (key->type == N_IDENT) { 264 if (is_quoted_ident_key(key)) 265 emit_constant(c, js_mkstr_permanent(c->js, key->str + 1, key->len - 2)); 266 else 267 emit_constant(c, js_mkstr_permanent(c->js, key->str, key->len)); 268 return; 269 } 270 271 compile_expr(c, key); 272} 273 274enum { 275 SV_COMP_PRIVATE_FIELD = 0, 276 SV_COMP_PRIVATE_METHOD = 1, 277 SV_COMP_PRIVATE_GETTER = 3, 278 SV_COMP_PRIVATE_SETTER = 4 279}; 280 281static int local_to_frame_slot(sv_compiler_t *c, int local_idx); 282static int add_upvalue(sv_compiler_t *c, uint16_t index, bool is_local, bool is_const); 283static void emit_get_local(sv_compiler_t *c, int local_idx); 284 285static inline bool is_private_name_node(const sv_ast_t *node) { 286 return node && node->type == N_IDENT && node->str && node->len > 0 && node->str[0] == '#'; 287} 288 289static sv_private_name_t *private_scope_find_current( 290 sv_private_scope_t *scope, const char *name, uint32_t len 291) { 292 if (!scope || !name) return NULL; 293 for (int i = 0; i < scope->count; i++) { 294 sv_private_name_t *p = &scope->names[i]; 295 if (p->len == len && memcmp(p->name, name, len) == 0) return p; 296 } 297 return NULL; 298} 299 300static sv_private_name_t *private_scope_resolve( 301 sv_compiler_t *c, const char *name, uint32_t len 302) { 303 for (sv_private_scope_t *scope = c->private_scope; scope; scope = scope->parent) { 304 sv_private_name_t *p = private_scope_find_current(scope, name, len); 305 if (p) return p; 306 } 307 return NULL; 308} 309 310static bool private_scope_add( 311 sv_compiler_t *c, sv_private_scope_t *scope, 312 sv_ast_t *name, uint8_t kind, bool is_static 313) { 314 if (!is_private_name_node(name)) return true; 315 316 if (name->len == 12 && memcmp(name->str, "#constructor", 12) == 0) { 317 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Classes may not declare private constructor names"); 318 return false; 319 } 320 321 sv_private_name_t *existing = private_scope_find_current(scope, name->str, name->len); 322 bool is_accessor = kind == SV_COMP_PRIVATE_GETTER || kind == SV_COMP_PRIVATE_SETTER; 323 if (existing) { 324 bool existing_accessor = existing->kind == SV_COMP_PRIVATE_GETTER || 325 existing->kind == SV_COMP_PRIVATE_SETTER; 326 if (!is_accessor || !existing_accessor || existing->is_static != is_static) { 327 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Duplicate private name '%.*s'", (int)name->len, name->str); 328 return false; 329 } 330 if ((kind == SV_COMP_PRIVATE_GETTER && existing->has_getter) || 331 (kind == SV_COMP_PRIVATE_SETTER && existing->has_setter)) { 332 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Duplicate private accessor '%.*s'", (int)name->len, name->str); 333 return false; 334 } 335 if (kind == SV_COMP_PRIVATE_GETTER) existing->has_getter = true; 336 if (kind == SV_COMP_PRIVATE_SETTER) existing->has_setter = true; 337 return true; 338 } 339 340 if (scope->count >= scope->cap) { 341 int new_cap = scope->cap ? scope->cap * 2 : 8; 342 sv_private_name_t *new_names = realloc(scope->names, (size_t)new_cap * sizeof(*scope->names)); 343 if (!new_names) return false; 344 scope->names = new_names; 345 scope->cap = new_cap; 346 } 347 348 sv_private_name_t *p = &scope->names[scope->count++]; 349 350 uint64_t hash64 = hash_key(name->str, (size_t)name->len); 351 uint32_t hash = (uint32_t)(hash64 ^ (hash64 >> 32)); 352 353 *p = (sv_private_name_t){ 354 .name = name->str, 355 .len = name->len, 356 .kind = kind, 357 .hash = hash, 358 .is_static = is_static, 359 .has_getter = kind == SV_COMP_PRIVATE_GETTER, 360 .has_setter = kind == SV_COMP_PRIVATE_SETTER, 361 .owner = NULL, 362 .local = -1 363 }; 364 365 return true; 366} 367 368static int resolve_private_upvalue(sv_compiler_t *c, sv_private_name_t *p) { 369 if (!c->enclosing || !p || !p->owner || p->local < 0) return -1; 370 371 if (c->enclosing == p->owner) { 372 p->owner->locals[p->local].captured = true; 373 uint16_t slot = (uint16_t)local_to_frame_slot(p->owner, p->local); 374 return add_upvalue(c, slot, true, false); 375 } 376 377 int upvalue = resolve_private_upvalue(c->enclosing, p); 378 if (upvalue == -1) return -1; 379 return add_upvalue(c, (uint16_t)upvalue, false, false); 380} 381 382static bool emit_private_token(sv_compiler_t *c, sv_ast_t *name) { 383 sv_private_name_t *p = private_scope_resolve(c, name->str, name->len); 384 if (!p) { 385 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Private name '%.*s' is not declared", (int)name->len, name->str); 386 emit_op(c, OP_UNDEF); 387 return false; 388 } 389 if (!p->owner || p->local < 0) { 390 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Private name '%.*s' is not initialized", (int)name->len, name->str); 391 emit_op(c, OP_UNDEF); 392 return false; 393 } 394 if (p->owner == c) { 395 emit_get_local(c, p->local); 396 return true; 397 } 398 int upvalue = resolve_private_upvalue(c, p); 399 if (upvalue == -1) { 400 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Private name '%.*s' is not in scope", (int)name->len, name->str); 401 emit_op(c, OP_UNDEF); 402 return false; 403 } 404 emit_op(c, OP_GET_UPVAL); 405 emit_u16(c, (uint16_t)upvalue); 406 return true; 407} 408 409static int add_atom(sv_compiler_t *c, const char *str, uint32_t len) { 410 const char *interned = intern_string(str, (size_t)len); 411 const char *stored = interned; 412 if (!stored) { 413 char *copy = code_arena_bump(len); 414 memcpy(copy, str, len); 415 stored = copy; 416 } 417 418 for (int i = 0; i < c->atom_count; i++) { 419 if (c->atoms[i].len == len && c->atoms[i].str == stored) 420 return i; 421 } 422 if (c->atom_count >= c->atom_cap) { 423 c->atom_cap = c->atom_cap ? c->atom_cap * 2 : 16; 424 c->atoms = realloc(c->atoms, (size_t)c->atom_cap * sizeof(sv_atom_t)); 425 } 426 c->atoms[c->atom_count] = (sv_atom_t){ .str = stored, .len = len }; 427 return c->atom_count++; 428} 429 430static inline bool sv_op_has_ic_slot(sv_op_t op) { 431 return op == OP_GET_GLOBAL || op == OP_GET_GLOBAL_UNDEF || 432 op == OP_GET_FIELD || op == OP_GET_FIELD2 || op == OP_PUT_FIELD; 433} 434 435static uint16_t alloc_ic_idx(sv_compiler_t *c) { 436 if (!c || c->ic_count >= (int)UINT16_MAX) return UINT16_MAX; 437 return (uint16_t)c->ic_count++; 438} 439 440static void sv_func_init_obj_sites(sv_func_t *func) { 441 if (!func || !func->code || func->code_len <= 0) return; 442 443 uint32_t count = 0; 444 for (int pc = 0; pc < func->code_len; ) { 445 sv_op_t op = (sv_op_t)func->code[pc]; 446 if (op == OP_OBJECT) count++; 447 uint8_t size = (op < OP__COUNT) ? sv_op_size[op] : 1; 448 pc += (size > 0) ? size : 1; 449 } 450 if (count == 0) return; 451 452 func->obj_sites = code_arena_bump((size_t)count * sizeof(sv_obj_site_cache_t)); 453 memset(func->obj_sites, 0, (size_t)count * sizeof(sv_obj_site_cache_t)); 454 func->obj_site_count = (uint16_t)count; 455 456 uint32_t idx = 0; 457 for (int pc = 0; pc < func->code_len && idx < count; ) { 458 sv_op_t op = (sv_op_t)func->code[pc]; 459 if (op == OP_OBJECT) func->obj_sites[idx++].bc_off = (uint32_t)pc; 460 uint8_t size = (op < OP__COUNT) ? sv_op_size[op] : 1; 461 pc += (size > 0) ? size : 1; 462 } 463} 464 465static void emit_atom_idx_op(sv_compiler_t *c, sv_op_t op, uint32_t atom_idx) { 466 emit_op(c, op); 467 emit_u32(c, atom_idx); 468 if (sv_op_has_ic_slot(op)) 469 emit_u16(c, alloc_ic_idx(c)); 470} 471 472static void emit_atom_op(sv_compiler_t *c, sv_op_t op, const char *str, uint32_t len) { 473 int idx = add_atom(c, str, len); 474 emit_atom_idx_op(c, op, (uint32_t)idx); 475} 476 477static inline void emit_set_function_name( 478 sv_compiler_t *c, 479 const char *name, uint32_t len 480) { 481 if (!name) { name = ""; len = 0; } 482 emit_atom_op(c, OP_SET_NAME, name, len); 483} 484 485static inline bool node_needs_inferred_function_name(const sv_ast_t *node) { 486 return node && 487 (node->type == N_FUNC || node->type == N_CLASS) && 488 (!node->str || node->len == 0); 489} 490 491static void compile_expr_with_inferred_name( 492 sv_compiler_t *c, sv_ast_t *node, 493 const char *name, uint32_t len 494) { 495 if (!node_needs_inferred_function_name(node) || !name) { 496 compile_expr(c, node); 497 return; 498 } 499 500 const char *saved_name = c->inferred_name; 501 uint32_t saved_len = c->inferred_name_len; 502 503 c->inferred_name = name; 504 c->inferred_name_len = len; 505 compile_expr(c, node); 506 507 c->inferred_name = saved_name; 508 c->inferred_name_len = saved_len; 509} 510 511static void emit_const_assign_error(sv_compiler_t *c, const char *name, uint32_t len) { 512 static const char prefix[] = "Assignment to constant variable '"; 513 static const char suffix[] = "'"; 514 515 uint32_t mlen = (uint32_t)(sizeof(prefix) - 1 + len + sizeof(suffix) - 1); 516 char *buf = code_arena_bump(mlen); 517 518 memcpy(buf, prefix, sizeof(prefix) - 1); 519 memcpy(buf + sizeof(prefix) - 1, name, len); 520 memcpy(buf + sizeof(prefix) - 1 + len, suffix, sizeof(suffix) - 1); 521 522 int atom = add_atom(c, buf, mlen); 523 emit_op(c, OP_THROW_ERROR); 524 emit_u32(c, (uint32_t)atom); 525 emit(c, (uint8_t)JS_ERR_TYPE); 526} 527 528static inline bool is_ident_str( 529 const char *name, uint32_t len, 530 const char *lit, uint32_t lit_len 531) { 532 return len == lit_len && memcmp(name, lit, lit_len) == 0; 533} 534 535static inline bool is_strict_restricted_ident(const char *name, uint32_t len) { 536 return 537 is_ident_str(name, len, "eval", 4) || 538 is_ident_str(name, len, "arguments", 9); 539} 540 541static inline bool is_repl_top_level(const sv_compiler_t *c) { 542 return 543 c->mode == SV_COMPILE_REPL && c->scope_depth == 0 && 544 c->enclosing && !c->enclosing->enclosing && 545 !c->is_strict; 546} 547 548static inline bool has_completion_value(const sv_compiler_t *c) { 549 return c && (c->mode == SV_COMPILE_EVAL || c->mode == SV_COMPILE_REPL); 550} 551 552static inline bool is_completion_top_level(const sv_compiler_t *c) { 553 return has_completion_value(c) && c->enclosing && !c->enclosing->enclosing; 554} 555 556static inline bool has_completion_accumulator(const sv_compiler_t *c) { 557 return c && c->completion_local >= 0; 558} 559 560static inline bool has_module_import_binding(const sv_compiler_t *c) { 561 for (const sv_compiler_t *cur = c; cur; cur = cur->enclosing) { 562 if (cur->mode == SV_COMPILE_MODULE) return true; 563 } 564 return false; 565} 566 567static inline bool has_implicit_arguments_obj(const sv_compiler_t *c) { 568 return c && !c->is_arrow && c->enclosing; 569} 570 571static int resolve_local(sv_compiler_t *c, const char *name, uint32_t len) { 572 if (c->local_lookup_heads && c->local_lookup_cap > 0) { 573 uint32_t hash = sv_compile_ctx_hash_local_name(name, len); 574 int bucket = (int)(hash & (uint32_t)(c->local_lookup_cap - 1)); 575 for (int i = c->local_lookup_heads[bucket]; i != -1; i = c->locals[i].lookup_next) { 576 sv_local_t *loc = &c->locals[i]; 577 if ( 578 loc->name_hash == hash && 579 loc->name_len == len && 580 memcmp(loc->name, name, len) == 0 581 ) return i; 582 } 583 return -1; 584 } 585 586 for (int i = c->local_count - 1; i >= 0; i--) { 587 sv_local_t *loc = &c->locals[i]; 588 if (loc->name_len == len && memcmp(loc->name, name, len) == 0) return i; 589 } 590 591 return -1; 592} 593 594static int add_local( 595 sv_compiler_t *c, const char *name, uint32_t len, 596 bool is_const, int depth 597) { 598 sv_compile_ctx_ensure_local_lookup_capacity(c, c->local_count + 1); 599 if (c->local_count >= c->local_cap) { 600 c->local_cap = c->local_cap ? c->local_cap * 2 : 16; 601 c->locals = realloc(c->locals, (size_t)c->local_cap * sizeof(sv_local_t)); 602 } 603 int idx = c->local_count++; 604 if (c->local_count > c->max_local_count) 605 c->max_local_count = c->local_count; 606 c->locals[idx] = (sv_local_t){ 607 .name = name, .name_len = len, 608 .name_hash = sv_compile_ctx_hash_local_name(name, len), 609 .lookup_next = -1, 610 .depth = depth, .is_const = is_const, .captured = false, 611 .inferred_type = SV_TI_UNKNOWN, 612 }; 613 sv_compile_ctx_local_lookup_insert(c, idx); 614 return idx; 615} 616 617static int reserve_hidden_locals(sv_compiler_t *c, int count) { 618 int base = c->local_count; 619 for (int i = 0; i < count; i++) 620 add_local(c, "", 0, false, c->scope_depth); 621 return base; 622} 623 624static inline bool sv_type_is_known(uint8_t t) { 625 return t != SV_TI_UNKNOWN; 626} 627 628static inline bool sv_type_is_num(uint8_t t) { 629 return t == SV_TI_NUM; 630} 631 632static void ensure_slot_type_cap(sv_compiler_t *c, int slot) { 633 if (slot < 0) return; 634 if (slot < c->slot_type_cap) return; 635 int new_cap = c->slot_type_cap ? c->slot_type_cap : 16; 636 while (new_cap <= slot) new_cap *= 2; 637 sv_type_info_t *next = realloc(c->slot_types, (size_t)new_cap * sizeof(sv_type_info_t)); 638 if (!next) return; 639 memset(next + c->slot_type_cap, 0, (size_t)(new_cap - c->slot_type_cap) * sizeof(sv_type_info_t)); 640 c->slot_types = next; 641 c->slot_type_cap = new_cap; 642} 643 644static void mark_slot_type(sv_compiler_t *c, int slot, uint8_t type) { 645 if (slot < 0) return; 646 ensure_slot_type_cap(c, slot); 647 if (!c->slot_types || slot >= c->slot_type_cap) return; 648 uint8_t old = c->slot_types[slot].type; 649 if (!sv_type_is_known(type)) { 650 c->slot_types[slot].type = SV_TI_UNKNOWN; 651 return; 652 } 653 if (!sv_type_is_known(old)) 654 c->slot_types[slot].type = type; 655 else if (old != type) 656 c->slot_types[slot].type = SV_TI_UNKNOWN; 657} 658 659static void set_local_inferred_type(sv_compiler_t *c, int local_idx, uint8_t type) { 660 if (local_idx < 0 || local_idx >= c->local_count) return; 661 c->locals[local_idx].inferred_type = type; 662 if (c->locals[local_idx].depth == -1) return; 663 int slot = local_idx - c->param_locals; 664 mark_slot_type(c, slot, type); 665} 666 667static inline uint8_t get_local_inferred_type(sv_compiler_t *c, int local_idx) { 668 if (local_idx < 0 || local_idx >= c->local_count) return SV_TI_UNKNOWN; 669 if (c->locals[local_idx].depth == -1) return SV_TI_UNKNOWN; 670 if (c->locals[local_idx].is_tdz) return SV_TI_UNKNOWN; 671 return c->locals[local_idx].inferred_type; 672} 673 674static const char *typeof_name_for_type(uint8_t type) { 675 switch (type) { 676 case SV_TI_NUM: return "number"; 677 case SV_TI_STR: return "string"; 678 case SV_TI_BOOL: return "boolean"; 679 case SV_TI_UNDEF: return "undefined"; 680 case SV_TI_ARR: 681 case SV_TI_OBJ: 682 case SV_TI_NULL: return "object"; 683 default: return NULL; 684 } 685} 686 687static uint8_t iter_hint_for_type(uint8_t type) { 688 switch (type) { 689 case SV_TI_ARR: return SV_ITER_HINT_ARRAY; 690 case SV_TI_STR: return SV_ITER_HINT_STRING; 691 default: return SV_ITER_HINT_GENERIC; 692 } 693} 694 695static int ensure_local_at_depth( 696 sv_compiler_t *c, const char *name, uint32_t len, 697 bool is_const, int depth 698) { 699 int local = resolve_local(c, name, len); 700 if (local != -1 && c->locals[local].depth == depth) 701 return local; 702 return add_local(c, name, len, is_const, depth); 703} 704 705static int local_to_frame_slot(sv_compiler_t *c, int local_idx) { 706 if (c->locals[local_idx].depth == -1) return local_idx; 707 return c->param_count + (local_idx - c->param_locals); 708} 709 710static int resolve_local_slot(sv_compiler_t *c, const char *name, uint32_t len) { 711 int local = resolve_local(c, name, len); 712 if (local == -1 || c->locals[local].depth == -1) return -1; 713 int slot = local - c->param_locals; 714 return (slot >= 0 && slot <= 255) ? slot : -1; 715} 716 717static int add_upvalue(sv_compiler_t *c, uint16_t index, bool is_local, bool is_const) { 718 for (int i = 0; i < c->upvalue_count; i++) { 719 if (c->upval_descs[i].index == index && 720 c->upval_descs[i].is_local == is_local) 721 return i; 722 } 723 if (c->upvalue_count >= c->upvalue_cap) { 724 c->upvalue_cap = c->upvalue_cap ? c->upvalue_cap * 2 : 8; 725 c->upval_descs = realloc( 726 c->upval_descs, 727 (size_t)c->upvalue_cap * sizeof(sv_upval_desc_t)); 728 } 729 int idx = c->upvalue_count++; 730 c->upval_descs[idx] = (sv_upval_desc_t){ 731 .index = index, .is_local = is_local, .is_const = is_const, 732 }; 733 return idx; 734} 735 736static int resolve_super_upvalue(sv_compiler_t *c) { 737 if (!c->enclosing) return -1; 738 sv_compiler_t *enc = c->enclosing; 739 740 if (!enc->is_arrow) { 741 if (enc->super_local < 0) return -1; 742 enc->locals[enc->super_local].captured = true; 743 uint16_t slot = (uint16_t)local_to_frame_slot(enc, enc->super_local); 744 return add_upvalue(c, slot, true, false); 745 } 746 747 int upvalue = resolve_super_upvalue(enc); 748 if (upvalue == -1) return -1; 749 return add_upvalue(c, (uint16_t)upvalue, false, false); 750} 751 752static int resolve_arguments_upvalue(sv_compiler_t *c) { 753 if (!c->enclosing) return -1; 754 sv_compiler_t *enc = c->enclosing; 755 756 if (!enc->is_arrow) { 757 if (enc->strict_args_local < 0) return -1; 758 enc->locals[enc->strict_args_local].captured = true; 759 uint16_t slot = (uint16_t)local_to_frame_slot(enc, enc->strict_args_local); 760 return add_upvalue(c, slot, true, false); 761 } 762 763 int upvalue = resolve_arguments_upvalue(enc); 764 if (upvalue == -1) return -1; 765 766 return add_upvalue(c, (uint16_t)upvalue, false, false); 767} 768 769static int resolve_upvalue(sv_compiler_t *c, const char *name, uint32_t len) { 770 if (!c->enclosing) return -1; 771 772 int local = resolve_local(c->enclosing, name, len); 773 if (local != -1) { 774 c->enclosing->locals[local].captured = true; 775 uint16_t slot = (uint16_t)local_to_frame_slot(c->enclosing, local); 776 return add_upvalue(c, slot, true, c->enclosing->locals[local].is_const); 777 } 778 779 int upvalue = resolve_upvalue(c->enclosing, name, len); 780 if (upvalue != -1) { 781 bool uv_const = c->enclosing->upval_descs[upvalue].is_const; 782 return add_upvalue(c, (uint16_t)upvalue, false, uv_const); 783 } 784 785 return -1; 786} 787 788static int emit_jump(sv_compiler_t *c, sv_op_t op) { 789 emit_op(c, op); 790 int offset = c->code_len; 791 emit_i32(c, 0); 792 return offset; 793} 794 795static void patch_jump(sv_compiler_t *c, int offset) { 796 int32_t delta = (int32_t)(c->code_len - offset - 4); 797 patch_u32(c, offset, (uint32_t)delta); 798} 799 800static void emit_loop(sv_compiler_t *c, int loop_start) { 801 emit_op(c, OP_JMP); 802 int32_t delta = (int32_t)(loop_start - c->code_len - 4); 803 emit_i32(c, delta); 804} 805 806static void patch_list_add(sv_patch_list_t *pl, int offset) { 807 if (pl->count >= pl->cap) { 808 pl->cap = pl->cap ? pl->cap * 2 : 4; 809 pl->offsets = realloc(pl->offsets, (size_t)pl->cap * sizeof(int)); 810 } 811 pl->offsets[pl->count++] = offset; 812} 813 814static void patch_list_resolve(sv_compiler_t *c, sv_patch_list_t *pl) { 815 for (int i = 0; i < pl->count; i++) 816 patch_jump(c, pl->offsets[i]); 817 free(pl->offsets); 818 *pl = (sv_patch_list_t){0}; 819} 820 821static void push_loop( 822 sv_compiler_t *c, int loop_start, 823 const char *label, uint32_t label_len, 824 bool is_switch 825) { 826 if (c->loop_count >= c->loop_cap) { 827 c->loop_cap = c->loop_cap ? c->loop_cap * 2 : 4; 828 c->loops = realloc(c->loops, (size_t)c->loop_cap * sizeof(sv_loop_t)); 829 } 830 if (!label && c->pending_label) { 831 label = c->pending_label; 832 label_len = c->pending_label_len; 833 c->pending_label = NULL; 834 c->pending_label_len = 0; 835 } 836 c->loops[c->loop_count++] = (sv_loop_t){ 837 .loop_start = loop_start, 838 .scope_depth = c->scope_depth, 839 .label = label, .label_len = label_len, 840 .is_switch = is_switch, 841 }; 842} 843 844static void pop_loop(sv_compiler_t *c) { 845 sv_loop_t *loop = &c->loops[--c->loop_count]; 846 patch_list_resolve(c, &loop->breaks); 847 free(loop->continues.offsets); 848} 849 850static void begin_scope(sv_compiler_t *c) { 851 c->scope_depth++; 852} 853 854static void end_scope(sv_compiler_t *c) { 855 while ( 856 c->local_count > 0 && 857 c->locals[c->local_count - 1].depth >= c->scope_depth 858 ) { 859 sv_local_t *loc = &c->locals[c->local_count - 1]; 860 if (loc->captured) { 861 int frame_slot = local_to_frame_slot(c, c->local_count - 1); 862 emit_op(c, OP_CLOSE_UPVAL); 863 emit_u16(c, (uint16_t)frame_slot); 864 } 865 sv_compile_ctx_local_lookup_remove(c, c->local_count - 1); 866 c->local_count--; 867 } 868 c->scope_depth--; 869} 870 871static void emit_close_upvals(sv_compiler_t *c) { 872 for (int i = 0; i < c->local_count; i++) { 873 if (c->locals[i].captured) { 874 int frame_slot = local_to_frame_slot(c, i); 875 emit_op(c, OP_CLOSE_UPVAL); 876 emit_u16(c, (uint16_t)frame_slot); 877 return; 878 }} 879} 880 881static void emit_with_get( 882 sv_compiler_t *c, const char *name, uint32_t len, 883 uint8_t fb_kind, uint16_t fb_idx 884) { 885 int atom = add_atom(c, name, len); 886 emit_op(c, OP_WITH_GET_VAR); 887 emit_u32(c, (uint32_t)atom); 888 emit(c, fb_kind); 889 emit_u16(c, fb_idx); 890} 891 892static void emit_with_put( 893 sv_compiler_t *c, const char *name, uint32_t len, 894 uint8_t fb_kind, uint16_t fb_idx 895) { 896 int atom = add_atom(c, name, len); 897 emit_op(c, OP_WITH_PUT_VAR); 898 emit_u32(c, (uint32_t)atom); 899 emit(c, fb_kind); 900 emit_u16(c, fb_idx); 901} 902 903static void emit_get_local(sv_compiler_t *c, int local_idx); 904static void emit_put_local(sv_compiler_t *c, int local_idx); 905static void emit_put_local_typed(sv_compiler_t *c, int local_idx, uint8_t type); 906 907static inline void emit_get_module_import_binding(sv_compiler_t *c) { 908 emit_op(c, OP_SPECIAL_OBJ); 909 emit(c, 3); 910} 911 912static void emit_get_var(sv_compiler_t *c, const char *name, uint32_t len) { 913 bool is_super = is_ident_str(name, len, "super", 5); 914 915 if (is_super && c->super_local >= 0) { 916 emit_get_local(c, c->super_local); 917 return; 918 } 919 920 if (is_super && c->is_arrow) { 921 int super_upval = resolve_super_upvalue(c); 922 if (super_upval != -1) { 923 emit_op(c, OP_GET_UPVAL); 924 emit_u16(c, (uint16_t)super_upval); 925 return; 926 }} 927 928 int local = resolve_local(c, name, len); 929 if (local != -1) { 930 if (c->with_depth > 0) { 931 uint8_t kind = c->locals[local].depth == -1 ? WITH_FB_ARG : WITH_FB_LOCAL; 932 uint16_t idx = kind == WITH_FB_ARG 933 ? (uint16_t)local 934 : (uint16_t)(local - c->param_locals); 935 emit_with_get(c, name, len, kind, idx); 936 return; 937 } 938 if (c->locals[local].depth == -1) { 939 emit_op(c, OP_GET_ARG); 940 emit_u16(c, (uint16_t)local); 941 } else { 942 int slot = local - c->param_locals; 943 if (c->locals[local].is_tdz) { 944 int ai = add_atom(c, name, len); 945 emit_op(c, OP_GET_LOCAL_CHK); 946 emit_u16(c, (uint16_t)slot); 947 emit_u32(c, (uint32_t)ai); 948 } else if (slot <= 255) { 949 emit_op(c, OP_GET_LOCAL8); 950 emit(c, (uint8_t)slot); 951 } else { 952 emit_op(c, OP_GET_LOCAL); 953 emit_u16(c, (uint16_t)slot); 954 } 955 } 956 return; 957 } 958 959 int upval = resolve_upvalue(c, name, len); 960 if (upval != -1) { 961 if (c->with_depth > 0) { 962 emit_with_get(c, name, len, WITH_FB_UPVAL, (uint16_t)upval); 963 return; 964 } 965 emit_op(c, OP_GET_UPVAL); 966 emit_u16(c, (uint16_t)upval); 967 return; 968 } 969 970 if (is_ident_str(name, len, "arguments", 9)) { 971 if (has_implicit_arguments_obj(c)) { 972 if (c->strict_args_local >= 0) { 973 emit_get_local(c, c->strict_args_local); 974 } else { 975 emit_op(c, OP_SPECIAL_OBJ); 976 emit(c, 0); 977 } 978 return; 979 } 980 if (c->is_arrow) { 981 int args_upval = resolve_arguments_upvalue(c); 982 if (args_upval != -1) { 983 emit_op(c, OP_GET_UPVAL); 984 emit_u16(c, (uint16_t)args_upval); 985 return; 986 } 987 } 988 } 989 990 if (has_module_import_binding(c) && is_ident_str(name, len, "import", 6)) { 991 emit_get_module_import_binding(c); 992 return; 993 } 994 995 if (c->with_depth > 0) emit_with_get(c, name, len, WITH_FB_GLOBAL, 0); 996 else emit_atom_op(c, OP_GET_GLOBAL, name, len); 997} 998 999static void emit_set_var(sv_compiler_t *c, const char *name, uint32_t len, bool keep) { 1000 int local = resolve_local(c, name, len); 1001 if (local != -1) { 1002 if (c->locals[local].is_const) { 1003 emit_const_assign_error(c, name, len); 1004 return; 1005 } 1006 set_local_inferred_type(c, local, SV_TI_UNKNOWN); 1007 1008 if (c->with_depth > 0) { 1009 uint8_t kind = c->locals[local].depth == -1 ? WITH_FB_ARG : WITH_FB_LOCAL; 1010 uint16_t idx = kind == WITH_FB_ARG 1011 ? (uint16_t)local 1012 : (uint16_t)(local - c->param_locals); 1013 if (keep) emit_op(c, OP_DUP); 1014 emit_with_put(c, name, len, kind, idx); 1015 return; 1016 } 1017 if (c->locals[local].depth == -1) { 1018 emit_op(c, keep ? OP_SET_ARG : OP_PUT_ARG); 1019 emit_u16(c, (uint16_t)local); 1020 } else { 1021 int slot = local - c->param_locals; 1022 sv_op_t op = keep 1023 ? (slot <= 255 ? OP_SET_LOCAL8 : OP_SET_LOCAL) 1024 : (slot <= 255 ? OP_PUT_LOCAL8 : OP_PUT_LOCAL); 1025 emit_op(c, op); 1026 if (slot <= 255) emit(c, (uint8_t)slot); 1027 else emit_u16(c, (uint16_t)slot); 1028 } 1029 return; 1030 } 1031 int upval = resolve_upvalue(c, name, len); 1032 if (upval != -1) { 1033 if (c->upval_descs[upval].is_const) { 1034 emit_const_assign_error(c, name, len); 1035 return; 1036 } 1037 if (c->with_depth > 0) { 1038 if (keep) emit_op(c, OP_DUP); 1039 emit_with_put(c, name, len, WITH_FB_UPVAL, (uint16_t)upval); 1040 return; 1041 } 1042 emit_op(c, keep ? OP_SET_UPVAL : OP_PUT_UPVAL); 1043 emit_u16(c, (uint16_t)upval); 1044 return; 1045 } 1046 if (has_module_import_binding(c) && is_ident_str(name, len, "import", 6)) { 1047 emit_const_assign_error(c, name, len); 1048 return; 1049 } 1050 if (c->with_depth > 0) { 1051 if (keep) emit_op(c, OP_DUP); 1052 emit_with_put(c, name, len, WITH_FB_GLOBAL, 0); 1053 } else { 1054 if (keep) { 1055 emit_op(c, OP_DUP); 1056 emit_atom_op(c, OP_PUT_GLOBAL, name, len); 1057 } else emit_atom_op(c, OP_PUT_GLOBAL, name, len); 1058 } 1059} 1060 1061static void emit_put_local_typed(sv_compiler_t *c, int local_idx, uint8_t type) { 1062 int slot = local_idx - c->param_locals; 1063 if (slot <= 255) { emit_op(c, OP_PUT_LOCAL8); emit(c, (uint8_t)slot); } 1064 else { emit_op(c, OP_PUT_LOCAL); emit_u16(c, (uint16_t)slot); } 1065 set_local_inferred_type(c, local_idx, type); 1066} 1067 1068static inline void emit_slot_op(sv_compiler_t *c, sv_op_t op, uint16_t slot) { 1069 emit_op(c, op); 1070 emit_u16(c, slot); 1071} 1072 1073static void emit_put_local(sv_compiler_t *c, int local_idx) { 1074 emit_put_local_typed(c, local_idx, SV_TI_UNKNOWN); 1075} 1076 1077static void emit_set_completion_from_stack(sv_compiler_t *c) { 1078 if (has_completion_accumulator(c)) emit_put_local(c, c->completion_local); 1079 else emit_op(c, OP_POP); 1080} 1081 1082static void emit_set_completion_undefined(sv_compiler_t *c) { 1083 if (!has_completion_accumulator(c)) return; 1084 emit_op(c, OP_UNDEF); 1085 emit_put_local(c, c->completion_local); 1086} 1087 1088static uint8_t infer_expr_type(sv_compiler_t *c, sv_ast_t *node); 1089 1090static void emit_get_local(sv_compiler_t *c, int local_idx) { 1091 int slot = local_idx - c->param_locals; 1092 if (slot <= 255) { emit_op(c, OP_GET_LOCAL8); emit(c, (uint8_t)slot); } 1093 else { emit_op(c, OP_GET_LOCAL); emit_u16(c, (uint16_t)slot); } 1094} 1095 1096static bool match_self_append_local( 1097 sv_compiler_t *c, sv_ast_t *node, 1098 int *out_local_idx, uint16_t *out_slot, sv_ast_t **out_rhs 1099) { 1100 if (!c || !node || node->type != N_ASSIGN || !node->left || node->left->type != N_IDENT) 1101 return false; 1102 if (c->with_depth > 0) return false; 1103 1104 int local = resolve_local(c, node->left->str, node->left->len); 1105 if (local < 0 || c->locals[local].is_const) return false; 1106 if (c->locals[local].is_tdz) return false; 1107 if (c->locals[local].depth == -1 && c->strict_args_local >= 0) return false; 1108 1109 sv_ast_t *rhs = NULL; 1110 if (node->op == TOK_PLUS_ASSIGN) rhs = node->right; 1111 else if ( 1112 node->op == TOK_ASSIGN && 1113 node->right && node->right->type == N_BINARY && node->right->op == TOK_PLUS && 1114 node->right->left && node->right->left->type == N_IDENT && 1115 node->right->left->len == node->left->len && 1116 memcmp(node->right->left->str, node->left->str, node->left->len) == 0 1117 ) rhs = node->right->right; 1118 1119 if (!rhs) return false; 1120 uint8_t local_type = get_local_inferred_type(c, local); 1121 uint8_t rhs_type = infer_expr_type(c, rhs); 1122 if (local_type != SV_TI_STR && rhs_type != SV_TI_STR) 1123 return false; 1124 1125 if (out_local_idx) *out_local_idx = local; 1126 if (out_slot) *out_slot = (uint16_t)local_to_frame_slot(c, local); 1127 if (out_rhs) *out_rhs = rhs; 1128 1129 return true; 1130} 1131 1132static bool is_self_append_inplace_safe_ident(sv_compiler_t *c, sv_ast_t *node) { 1133 if (!c || !node || node->type != N_IDENT) return false; 1134 1135 if (resolve_local(c, node->str, node->len) != -1) return true; 1136 if (resolve_upvalue(c, node->str, node->len) != -1) return true; 1137 1138 if (is_ident_str(node->str, node->len, "arguments", 9)) { 1139 if (has_implicit_arguments_obj(c)) return true; 1140 if (c->is_arrow && resolve_arguments_upvalue(c) != -1) return true; 1141 } 1142 1143 if (c->is_arrow && is_ident_str(node->str, node->len, "super", 5)) 1144 return resolve_super_upvalue(c) != -1; 1145 1146 if (has_module_import_binding(c) && is_ident_str(node->str, node->len, "import", 6)) 1147 return true; 1148 1149 return false; 1150} 1151 1152static bool is_self_append_inplace_safe_expr(sv_compiler_t *c, sv_ast_t *node) { 1153 if (!node) return false; 1154 1155 switch (node->type) { 1156 case N_NUMBER: 1157 case N_STRING: 1158 case N_BIGINT: 1159 case N_BOOL: 1160 case N_NULL: 1161 case N_UNDEF: 1162 return true; 1163 1164 case N_IDENT: 1165 return is_self_append_inplace_safe_ident(c, node); 1166 1167 case N_BINARY: return 1168 is_self_append_inplace_safe_expr(c, node->left) && 1169 is_self_append_inplace_safe_expr(c, node->right); 1170 1171 case N_UNARY: 1172 case N_TYPEOF: 1173 case N_VOID: 1174 return is_self_append_inplace_safe_expr(c, node->left); 1175 1176 default: 1177 return false; 1178 } 1179} 1180 1181static bool compile_self_append_stmt(sv_compiler_t *c, sv_ast_t *node) { 1182 int local = -1; 1183 uint16_t slot = 0; 1184 sv_ast_t *rhs = NULL; 1185 if (!match_self_append_local(c, node, &local, &slot, &rhs)) return false; 1186 if (is_self_append_inplace_safe_expr(c, rhs)) { 1187 compile_expr(c, rhs); 1188 emit_slot_op(c, OP_STR_APPEND_LOCAL, slot); 1189 } else { 1190 emit_slot_op(c, OP_GET_SLOT_RAW, slot); 1191 compile_expr(c, rhs); 1192 emit_slot_op(c, OP_STR_ALC_SNAPSHOT, slot); 1193 } 1194 set_local_inferred_type(c, local, SV_TI_UNKNOWN); 1195 return true; 1196} 1197 1198 1199static inline bool is_ident_name(sv_ast_t *node, const char *name) { 1200 size_t n = strlen(name); 1201 return node 1202 && node->type == N_IDENT && node->len == (uint32_t)n 1203 && memcmp(node->str, name, n) == 0; 1204} 1205 1206static void hoist_var_pattern(sv_compiler_t *c, sv_ast_t *pat) { 1207 if (!pat) return; 1208 switch (pat->type) { 1209 case N_IDENT: 1210 if (resolve_local(c, pat->str, pat->len) == -1) 1211 add_local(c, pat->str, pat->len, false, 0); 1212 break; 1213 case N_ARRAY: case N_ARRAY_PAT: 1214 for (int i = 0; i < pat->args.count; i++) 1215 hoist_var_pattern(c, pat->args.items[i]); 1216 break; 1217 case N_OBJECT: case N_OBJECT_PAT: 1218 for (int i = 0; i < pat->args.count; i++) { 1219 sv_ast_t *prop = pat->args.items[i]; 1220 if (!prop) continue; 1221 if (prop->type == N_PROPERTY) 1222 hoist_var_pattern(c, prop->right); 1223 else if (prop->type == N_REST || prop->type == N_SPREAD) 1224 hoist_var_pattern(c, prop->right); 1225 } 1226 break; 1227 case N_ASSIGN_PAT: 1228 hoist_var_pattern(c, pat->left); 1229 break; 1230 case N_ASSIGN: 1231 hoist_var_pattern(c, pat->left); 1232 break; 1233 case N_REST: case N_SPREAD: 1234 hoist_var_pattern(c, pat->right); 1235 break; 1236 default: 1237 break; 1238 } 1239} 1240 1241static void hoist_var_decls(sv_compiler_t *c, sv_ast_t *node) { 1242 if (!node) return; 1243 switch (node->type) { 1244 case N_VAR: 1245 if (node->var_kind == SV_VAR_VAR) { 1246 for (int i = 0; i < node->args.count; i++) { 1247 sv_ast_t *decl = node->args.items[i]; 1248 if (decl->type == N_VARDECL && decl->left) 1249 hoist_var_pattern(c, decl->left); 1250 } 1251 } 1252 break; 1253 case N_BLOCK: 1254 for (int i = 0; i < node->args.count; i++) 1255 hoist_var_decls(c, node->args.items[i]); 1256 break; 1257 case N_IF: 1258 hoist_var_decls(c, node->left); 1259 hoist_var_decls(c, node->right); 1260 break; 1261 case N_WHILE: case N_DO_WHILE: case N_LABEL: 1262 hoist_var_decls(c, node->body); 1263 break; 1264 case N_FOR: 1265 hoist_var_decls(c, node->init); 1266 hoist_var_decls(c, node->body); 1267 break; 1268 case N_FOR_IN: case N_FOR_OF: case N_FOR_AWAIT_OF: 1269 hoist_var_decls(c, node->left); 1270 hoist_var_decls(c, node->body); 1271 break; 1272 case N_SWITCH: 1273 for (int i = 0; i < node->args.count; i++) { 1274 sv_ast_t *cas = node->args.items[i]; 1275 for (int j = 0; j < cas->args.count; j++) 1276 hoist_var_decls(c, cas->args.items[j]); 1277 } 1278 break; 1279 case N_TRY: 1280 hoist_var_decls(c, node->body); 1281 hoist_var_decls(c, node->catch_body); 1282 hoist_var_decls(c, node->finally_body); 1283 break; 1284 case N_EXPORT: 1285 hoist_var_decls(c, node->left); 1286 break; 1287 default: break; 1288 } 1289} 1290 1291static void hoist_lexical_pattern(sv_compiler_t *c, sv_ast_t *pat, 1292 bool is_const) { 1293 if (!pat) return; 1294 1295 switch (pat->type) { 1296 case N_IDENT: 1297 ensure_local_at_depth(c, pat->str, pat->len, is_const, c->scope_depth); 1298 break; 1299 case N_ASSIGN_PAT: 1300 case N_ASSIGN: 1301 hoist_lexical_pattern(c, pat->left, is_const); 1302 break; 1303 case N_REST: 1304 case N_SPREAD: 1305 hoist_lexical_pattern(c, pat->right, is_const); 1306 break; 1307 case N_ARRAY: 1308 case N_ARRAY_PAT: 1309 for (int i = 0; i < pat->args.count; i++) 1310 hoist_lexical_pattern(c, pat->args.items[i], is_const); 1311 break; 1312 case N_OBJECT: 1313 case N_OBJECT_PAT: 1314 for (int i = 0; i < pat->args.count; i++) { 1315 sv_ast_t *prop = pat->args.items[i]; 1316 if (!prop) continue; 1317 if (prop->type == N_PROPERTY) 1318 hoist_lexical_pattern(c, prop->right, is_const); 1319 else if (prop->type == N_REST || prop->type == N_SPREAD) 1320 hoist_lexical_pattern(c, prop->right, is_const); 1321 } 1322 break; 1323 default: 1324 break; 1325 } 1326} 1327 1328static void annex_b_collect_funcs(sv_ast_t *node, sv_ast_list_t *out) { 1329 if (!node) return; 1330 if (node->type == N_FUNC && node->str && !(node->flags & (FN_ARROW | FN_PAREN))) { 1331 sv_ast_list_push(out, node); 1332 return; 1333 } 1334 if (node->type == N_IF) { 1335 annex_b_collect_funcs(node->left, out); 1336 annex_b_collect_funcs(node->right, out); 1337 } else if (node->type == N_LABEL) annex_b_collect_funcs(node->body, out); 1338} 1339 1340static void hoist_lexical_decls(sv_compiler_t *c, sv_ast_list_t *stmts) { 1341 for (int i = 0; i < stmts->count; i++) { 1342 sv_ast_t *node = stmts->items[i]; 1343 if (!node) continue; 1344 sv_ast_t *decl_node = (node->type == N_EXPORT) ? node->left : node; 1345 if (!decl_node) continue; 1346 1347 if (decl_node->type == N_VAR && decl_node->var_kind != SV_VAR_VAR) { 1348 bool is_const = 1349 (decl_node->var_kind == SV_VAR_CONST || 1350 decl_node->var_kind == SV_VAR_USING || 1351 decl_node->var_kind == SV_VAR_AWAIT_USING); 1352 int lb = c->local_count; 1353 for (int j = 0; j < decl_node->args.count; j++) { 1354 sv_ast_t *decl = decl_node->args.items[j]; 1355 if (!decl || decl->type != N_VARDECL || !decl->left) continue; 1356 hoist_lexical_pattern(c, decl->left, is_const); 1357 } 1358 for (int j = lb; j < c->local_count; j++) { 1359 c->locals[j].is_tdz = true; 1360 set_local_inferred_type(c, j, SV_TI_UNKNOWN); 1361 int slot = j - c->param_locals; 1362 emit_op(c, OP_SET_LOCAL_UNDEF); 1363 emit_u16(c, (uint16_t)slot); 1364 } 1365 } else if (decl_node->type == N_IMPORT_DECL) { 1366 for (int j = 0; j < decl_node->args.count; j++) { 1367 sv_ast_t *spec = decl_node->args.items[j]; 1368 if (!spec || spec->type != N_IMPORT_SPEC || 1369 !spec->right || spec->right->type != N_IDENT) 1370 continue; 1371 ensure_local_at_depth(c, spec->right->str, spec->right->len, true, c->scope_depth); 1372 } 1373 } else if (decl_node->type == N_CLASS && decl_node->str) { 1374 int lb = c->local_count; 1375 ensure_local_at_depth(c, decl_node->str, decl_node->len, false, c->scope_depth); 1376 if (c->local_count > lb) { 1377 c->locals[c->local_count - 1].is_tdz = true; 1378 set_local_inferred_type(c, c->local_count - 1, SV_TI_UNKNOWN); 1379 int slot = (c->local_count - 1) - c->param_locals; 1380 emit_op(c, OP_SET_LOCAL_UNDEF); 1381 emit_u16(c, (uint16_t)slot); 1382 } 1383 } else if (decl_node->type == N_FUNC && decl_node->str && !(decl_node->flags & (FN_ARROW | FN_PAREN))) { 1384 ensure_local_at_depth(c, decl_node->str, decl_node->len, false, c->scope_depth); 1385 } 1386 if (!c->is_strict && (decl_node->type == N_IF || decl_node->type == N_LABEL)) { 1387 sv_ast_list_t funcs = {0}; 1388 annex_b_collect_funcs(decl_node, &funcs); 1389 for (int j = 0; j < funcs.count; j++) { 1390 sv_ast_t *fn = funcs.items[j]; 1391 if (resolve_local(c, fn->str, fn->len) == -1) 1392 add_local(c, fn->str, fn->len, false, c->scope_depth); 1393 } 1394 } 1395 } 1396} 1397 1398static void hoist_one_func(sv_compiler_t *c, sv_ast_t *node) { 1399 sv_func_t *fn = compile_function_body(c, node, c->mode); 1400 if (!fn) return; 1401 int idx = add_constant(c, mkval(T_NTARG, (uintptr_t)fn)); 1402 emit_op(c, OP_CLOSURE); 1403 emit_u32(c, (uint32_t)idx); 1404 emit_set_function_name(c, node->str, node->len); 1405 if (is_repl_top_level(c)) { 1406 emit_atom_op(c, OP_PUT_GLOBAL, node->str, node->len); 1407 } else { 1408 int local = resolve_local(c, node->str, node->len); 1409 emit_put_local(c, local); 1410 } 1411} 1412 1413static void hoist_func_decls(sv_compiler_t *c, sv_ast_list_t *stmts) { 1414 for (int i = 0; i < stmts->count; i++) { 1415 sv_ast_t *node = stmts->items[i]; 1416 if (node && node->type == N_EXPORT && node->left) 1417 node = node->left; 1418 if (!node) continue; 1419 if (node->type == N_FUNC && node->str && !(node->flags & (FN_ARROW | FN_PAREN))) { 1420 hoist_one_func(c, node); 1421 } 1422 if (!c->is_strict && (node->type == N_IF || node->type == N_LABEL)) { 1423 sv_ast_list_t funcs = {0}; 1424 annex_b_collect_funcs(node, &funcs); 1425 for (int j = 0; j < funcs.count; j++) 1426 hoist_one_func(c, funcs.items[j]); 1427 } 1428 } 1429} 1430 1431static uint8_t infer_expr_type(sv_compiler_t *c, sv_ast_t *node) { 1432 if (!node) return SV_TI_UNDEF; 1433 1434 switch (node->type) { 1435 case N_NUMBER: return SV_TI_NUM; 1436 case N_STRING: return SV_TI_STR; 1437 case N_BOOL: return SV_TI_BOOL; 1438 case N_NULL: return SV_TI_NULL; 1439 case N_UNDEF: return SV_TI_UNDEF; 1440 case N_ARRAY: return SV_TI_ARR; 1441 case N_OBJECT: return SV_TI_OBJ; 1442 case N_TEMPLATE: return SV_TI_STR; 1443 case N_TYPEOF: return SV_TI_STR; 1444 case N_VOID: return SV_TI_UNDEF; 1445 case N_NEW: return SV_TI_OBJ; 1446 1447 case N_IDENT: { 1448 int local = resolve_local(c, node->str, node->len); 1449 if (local >= 0) return get_local_inferred_type(c, local); 1450 return SV_TI_UNKNOWN; 1451 } 1452 1453 case N_SEQUENCE: 1454 return infer_expr_type(c, node->right); 1455 1456 case N_TERNARY: { 1457 uint8_t lt = infer_expr_type(c, node->left); 1458 uint8_t rhs_type = infer_expr_type(c, node->right); 1459 if (lt == rhs_type && sv_type_is_known(lt)) return lt; 1460 return SV_TI_UNKNOWN; 1461 } 1462 1463 case N_UNARY: { 1464 uint8_t rhs_type = infer_expr_type(c, node->right); 1465 switch (node->op) { 1466 case TOK_UPLUS: 1467 case TOK_UMINUS: 1468 return sv_type_is_num(rhs_type) ? SV_TI_NUM : SV_TI_UNKNOWN; 1469 case TOK_NOT: 1470 return SV_TI_BOOL; 1471 default: 1472 return SV_TI_UNKNOWN; 1473 } 1474 } 1475 1476 case N_BINARY: { 1477 uint8_t lt = infer_expr_type(c, node->left); 1478 uint8_t rhs_type = infer_expr_type(c, node->right); 1479 switch (node->op) { 1480 case TOK_PLUS: 1481 if (lt == SV_TI_NUM && rhs_type == SV_TI_NUM) return SV_TI_NUM; 1482 if (lt == SV_TI_STR && rhs_type == SV_TI_STR) return SV_TI_STR; 1483 return SV_TI_UNKNOWN; 1484 case TOK_MINUS: 1485 case TOK_MUL: 1486 case TOK_DIV: 1487 return (lt == SV_TI_NUM && rhs_type == SV_TI_NUM) ? SV_TI_NUM : SV_TI_UNKNOWN; 1488 case TOK_LT: 1489 case TOK_LE: 1490 case TOK_GT: 1491 case TOK_GE: 1492 case TOK_EQ: 1493 case TOK_NE: 1494 case TOK_SEQ: 1495 case TOK_SNE: 1496 case TOK_INSTANCEOF: 1497 case TOK_IN: 1498 return SV_TI_BOOL; 1499 case TOK_LAND: 1500 case TOK_LOR: 1501 case TOK_NULLISH: 1502 if (lt == rhs_type && sv_type_is_known(lt)) return lt; 1503 return SV_TI_UNKNOWN; 1504 default: 1505 return SV_TI_UNKNOWN; 1506 } 1507 } 1508 1509 default: 1510 return SV_TI_UNKNOWN; 1511 } 1512} 1513 1514static void compile_yield_star_expr(sv_compiler_t *c, sv_ast_t *node) { 1515 if (node->right) compile_expr(c, node->right); 1516 else emit_op(c, OP_UNDEF); 1517 1518 int base_local = reserve_hidden_locals(c, 4); 1519 uint16_t base_slot = (uint16_t)(base_local - c->param_locals); 1520 1521 emit_op(c, OP_YIELD_STAR_INIT); 1522 emit_u16(c, base_slot); 1523 1524 emit_op(c, OP_UNDEF); 1525 emit_op(c, OP_YIELD_STAR_NEXT); 1526 emit_u16(c, base_slot); 1527} 1528 1529void compile_expr(sv_compiler_t *c, sv_ast_t *node) { 1530 if (!node) { emit_op(c, OP_UNDEF); return; } 1531 emit_srcpos(c, node); 1532 1533 switch (node->type) { 1534 case N_NUMBER: 1535 emit_number(c, node->num); 1536 break; 1537 1538 case N_STRING: { 1539 emit_constant(c, ast_string_const(c, node)); 1540 break; 1541 } 1542 1543 case N_BIGINT: { 1544 bool neg = false; 1545 const char *digits = node->str; 1546 uint32_t dlen = node->len; 1547 if (dlen > 0 && digits[0] == '-') { 1548 neg = true; digits++; dlen--; 1549 } 1550 if (dlen > 0 && digits[dlen - 1] == 'n') dlen--; 1551 ant_value_t bi = js_mkbigint(c->js, digits, dlen, neg); 1552 emit_constant(c, bi); 1553 break; 1554 } 1555 1556 case N_BOOL: 1557 emit_op(c, node->num != 0.0 ? OP_TRUE : OP_FALSE); 1558 break; 1559 1560 case N_NULL: 1561 emit_op(c, OP_NULL); 1562 break; 1563 1564 case N_UNDEF: 1565 emit_op(c, OP_UNDEF); 1566 break; 1567 1568 case N_THIS: 1569 emit_op(c, OP_THIS); 1570 break; 1571 1572 case N_GLOBAL_THIS: 1573 emit_op(c, OP_GLOBAL); 1574 break; 1575 1576 case N_NEW_TARGET: { 1577 static const char nt_name[] = "\x01new.target"; 1578 int local = resolve_local(c, nt_name, sizeof(nt_name) - 1); 1579 if (local >= 0) { 1580 emit_get_local(c, local); 1581 } else { 1582 int upval = resolve_upvalue(c, nt_name, sizeof(nt_name) - 1); 1583 if (upval >= 0) { 1584 emit_op(c, OP_GET_UPVAL); 1585 emit_u16(c, (uint16_t)upval); 1586 } else { 1587 emit_op(c, OP_UNDEF); 1588 } 1589 } 1590 break; 1591 } 1592 1593 case N_IDENT: 1594 if (is_private_name_node(node)) { 1595 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Private names may only be used as class member names"); 1596 emit_op(c, OP_UNDEF); 1597 break; 1598 } 1599 emit_get_var(c, node->str, node->len); 1600 break; 1601 1602 case N_BINARY: 1603 compile_binary(c, node); 1604 break; 1605 1606 case N_UNARY: 1607 compile_unary(c, node); 1608 break; 1609 1610 case N_UPDATE: 1611 compile_update(c, node); 1612 break; 1613 1614 case N_ASSIGN: 1615 compile_assign(c, node); 1616 break; 1617 1618 case N_TERNARY: 1619 compile_ternary(c, node); 1620 break; 1621 1622 case N_CALL: 1623 compile_call(c, node); 1624 break; 1625 1626 case N_NEW: 1627 compile_new(c, node); 1628 break; 1629 1630 case N_MEMBER: 1631 compile_member(c, node); 1632 break; 1633 1634 case N_OPTIONAL: 1635 compile_optional(c, node); 1636 break; 1637 1638 case N_ARRAY: 1639 compile_array(c, node); 1640 break; 1641 1642 case N_OBJECT: 1643 compile_object(c, node); 1644 break; 1645 1646 case N_FUNC: 1647 compile_func_expr(c, node); 1648 break; 1649 1650 case N_CLASS: 1651 compile_class(c, node); 1652 break; 1653 1654 case N_SEQUENCE: 1655 compile_expr(c, node->left); 1656 emit_op(c, OP_POP); 1657 compile_expr(c, node->right); 1658 break; 1659 1660 case N_TYPEOF: 1661 compile_typeof(c, node); 1662 break; 1663 1664 case N_VOID: 1665 compile_expr(c, node->right); 1666 emit_op(c, OP_VOID); 1667 break; 1668 1669 case N_DELETE: 1670 compile_delete(c, node); 1671 break; 1672 1673 case N_SPREAD: 1674 compile_expr(c, node->right); 1675 break; 1676 1677 case N_TEMPLATE: 1678 compile_template(c, node); 1679 break; 1680 1681 case N_AWAIT: 1682 compile_expr(c, node->right); 1683 emit_op(c, OP_AWAIT); 1684 if (c->enclosing && !c->enclosing->enclosing) 1685 c->is_tla = true; 1686 break; 1687 1688 case N_YIELD: 1689 if (node->flags) compile_yield_star_expr(c, node); 1690 else { 1691 if (node->right) compile_expr(c, node->right); 1692 else emit_op(c, OP_UNDEF); 1693 emit_op(c, OP_YIELD); 1694 } 1695 break; 1696 1697 case N_THROW: 1698 compile_expr(c, node->right); 1699 emit_op(c, OP_THROW); 1700 break; 1701 1702 case N_TAGGED_TEMPLATE: { 1703 compile_expr(c, node->left); 1704 sv_ast_t *tpl = node->right; 1705 int n = tpl->args.count; 1706 int n_strings = 0, n_exprs = 0; 1707 for (int i = 0; i < n; i++) { 1708 if (is_template_segment(tpl->args.items[i])) n_strings++; 1709 else n_exprs++; 1710 } 1711 int cache_idx = add_constant(c, js_mkundef()); 1712 emit_op(c, OP_CONST); 1713 emit_u32(c, (uint32_t)cache_idx); 1714 int skip_jump = emit_jump(c, OP_JMP_TRUE_PEEK); 1715 emit_op(c, OP_POP); 1716 for (int i = 0; i < n; i++) { 1717 sv_ast_t *item = tpl->args.items[i]; 1718 if (!is_template_segment(item)) continue; 1719 if (is_invalid_cooked_string(item)) 1720 emit_op(c, OP_UNDEF); 1721 else emit_constant(c, ast_string_const(c, item)); 1722 } 1723 emit_op(c, OP_ARRAY); 1724 emit_u16(c, (uint16_t)n_strings); 1725 for (int i = 0; i < n; i++) { 1726 sv_ast_t *item = tpl->args.items[i]; 1727 if (!is_template_segment(item)) continue; 1728 const char *raw = item->aux ? item->aux : item->str; 1729 uint32_t raw_len = item->aux ? item->aux_len : item->len; 1730 emit_constant(c, js_mkstr_permanent(c->js, raw ? raw : "", raw_len)); 1731 } 1732 emit_op(c, OP_ARRAY); 1733 emit_u16(c, (uint16_t)n_strings); 1734 emit_atom_op(c, OP_GET_GLOBAL, "Object", 6); 1735 emit_atom_op(c, OP_GET_FIELD2, "freeze", 6); 1736 emit_op(c, OP_ROT3L); 1737 emit_op(c, OP_CALL_METHOD); 1738 emit_u16(c, 1); 1739 emit_atom_op(c, OP_DEFINE_FIELD, "raw", 3); 1740 emit_atom_op(c, OP_GET_GLOBAL, "Object", 6); 1741 emit_atom_op(c, OP_GET_FIELD2, "freeze", 6); 1742 emit_op(c, OP_ROT3L); 1743 emit_op(c, OP_CALL_METHOD); 1744 emit_u16(c, 1); 1745 emit_op(c, OP_SET_BRAND); 1746 emit(c, BRAND_TEMPLATE_OBJECT); 1747 emit_op(c, OP_DUP); 1748 emit_op(c, OP_PUT_CONST); 1749 emit_u32(c, (uint32_t)cache_idx); 1750 patch_jump(c, skip_jump); 1751 for (int i = 0; i < n; i++) { 1752 sv_ast_t *item = tpl->args.items[i]; 1753 if (is_template_segment(item)) continue; 1754 compile_expr(c, item); 1755 } 1756 emit_op(c, OP_CALL); 1757 emit_u16(c, (uint16_t)(1 + n_exprs)); 1758 break; 1759 } 1760 1761 case N_IMPORT: 1762 compile_expr(c, node->right); 1763 if (has_module_import_binding(c)) { 1764 emit_get_module_import_binding(c); 1765 emit_op(c, OP_SWAP); 1766 emit_op(c, OP_CALL); 1767 emit_u16(c, 1); 1768 } else emit_op(c, OP_IMPORT); 1769 break; 1770 1771 case N_REGEXP: 1772 emit_constant(c, js_mkstr_permanent(c->js, node->str ? node->str : "", node->len)); 1773 emit_constant(c, js_mkstr_permanent(c->js, node->aux ? node->aux : "", node->aux_len)); 1774 emit_op(c, OP_REGEXP); 1775 break; 1776 1777 default: 1778 emit_op(c, OP_UNDEF); 1779 break; 1780 } 1781} 1782 1783void compile_binary(sv_compiler_t *c, sv_ast_t *node) { 1784 uint8_t op = node->op; 1785 1786 if (op == TOK_LAND) { 1787 compile_expr(c, node->left); 1788 int jump = emit_jump(c, OP_JMP_FALSE_PEEK); 1789 emit_op(c, OP_POP); 1790 compile_expr(c, node->right); 1791 patch_jump(c, jump); 1792 return; 1793 } 1794 1795 if (op == TOK_LOR) { 1796 compile_expr(c, node->left); 1797 int jump = emit_jump(c, OP_JMP_TRUE_PEEK); 1798 emit_op(c, OP_POP); 1799 compile_expr(c, node->right); 1800 patch_jump(c, jump); 1801 return; 1802 } 1803 1804 if (op == TOK_NULLISH) { 1805 compile_expr(c, node->left); 1806 int jump = emit_jump(c, OP_JMP_NOT_NULLISH); 1807 emit_op(c, OP_POP); 1808 compile_expr(c, node->right); 1809 patch_jump(c, jump); 1810 return; 1811 } 1812 1813 if (op == TOK_IN && node->left->type == N_IDENT && 1814 node->left->len > 0 && node->left->str[0] == '#') { 1815 compile_expr(c, node->right); 1816 emit_private_token(c, node->left); 1817 emit_op(c, OP_HAS_PRIVATE); 1818 return; 1819 } 1820 1821 uint8_t left_type = SV_TI_UNKNOWN; 1822 uint8_t right_type = SV_TI_UNKNOWN; 1823 if (op == TOK_PLUS || op == TOK_MINUS || op == TOK_MUL || op == TOK_DIV) { 1824 left_type = infer_expr_type(c, node->left); 1825 right_type = infer_expr_type(c, node->right); 1826 } 1827 1828 compile_expr(c, node->left); 1829 compile_expr(c, node->right); 1830 1831 switch (op) { 1832 case TOK_PLUS: 1833 emit_op(c, (left_type == SV_TI_NUM && right_type == SV_TI_NUM) ? OP_ADD_NUM : OP_ADD); 1834 break; 1835 case TOK_MINUS: 1836 emit_op(c, (left_type == SV_TI_NUM && right_type == SV_TI_NUM) ? OP_SUB_NUM : OP_SUB); 1837 break; 1838 case TOK_MUL: 1839 emit_op(c, (left_type == SV_TI_NUM && right_type == SV_TI_NUM) ? OP_MUL_NUM : OP_MUL); 1840 break; 1841 case TOK_DIV: 1842 emit_op(c, (left_type == SV_TI_NUM && right_type == SV_TI_NUM) ? OP_DIV_NUM : OP_DIV); 1843 break; 1844 case TOK_REM: emit_op(c, OP_MOD); break; 1845 case TOK_EXP: emit_op(c, OP_EXP); break; 1846 case TOK_LT: emit_op(c, OP_LT); break; 1847 case TOK_LE: emit_op(c, OP_LE); break; 1848 case TOK_GT: emit_op(c, OP_GT); break; 1849 case TOK_GE: emit_op(c, OP_GE); break; 1850 case TOK_EQ: emit_op(c, OP_EQ); break; 1851 case TOK_NE: emit_op(c, OP_NE); break; 1852 case TOK_SEQ: emit_op(c, OP_SEQ); break; 1853 case TOK_SNE: emit_op(c, OP_SNE); break; 1854 case TOK_AND: emit_op(c, OP_BAND); break; 1855 case TOK_OR: emit_op(c, OP_BOR); break; 1856 case TOK_XOR: emit_op(c, OP_BXOR); break; 1857 case TOK_SHL: emit_op(c, OP_SHL); break; 1858 case TOK_SHR: emit_op(c, OP_SHR); break; 1859 case TOK_ZSHR: emit_op(c, OP_USHR); break; 1860 case TOK_INSTANCEOF: 1861 emit_op(c, OP_INSTANCEOF); 1862 emit_u16(c, alloc_ic_idx(c)); 1863 break; 1864 case TOK_IN: emit_op(c, OP_IN); break; 1865 default: emit_op(c, OP_UNDEF); break; 1866 } 1867} 1868 1869void compile_unary(sv_compiler_t *c, sv_ast_t *node) { 1870 compile_expr(c, node->right); 1871 switch (node->op) { 1872 case TOK_NOT: emit_op(c, OP_NOT); break; 1873 case TOK_TILDA: emit_op(c, OP_BNOT); break; 1874 case TOK_UPLUS: emit_op(c, OP_UPLUS); break; 1875 case TOK_UMINUS: emit_op(c, OP_NEG); break; 1876 default: break; 1877 } 1878} 1879 1880 1881void compile_update(sv_compiler_t *c, sv_ast_t *node) { 1882 bool prefix = (node->flags & 1); 1883 bool is_inc = (node->op == TOK_POSTINC); 1884 sv_ast_t *target = node->right; 1885 1886 if (target->type == N_IDENT) { 1887 if (prefix) { 1888 emit_get_var(c, target->str, target->len); 1889 emit_op(c, is_inc ? OP_INC : OP_DEC); 1890 emit_set_var(c, target->str, target->len, true); 1891 } else { 1892 emit_get_var(c, target->str, target->len); 1893 emit_op(c, is_inc ? OP_POST_INC : OP_POST_DEC); 1894 emit_set_var(c, target->str, target->len, false); 1895 } 1896 } else if (target->type == N_MEMBER && !(target->flags & 1) && is_private_name_node(target->right)) { 1897 compile_expr(c, target->left); 1898 emit_op(c, OP_DUP); 1899 emit_private_token(c, target->right); 1900 emit_op(c, OP_GET_PRIVATE); 1901 if (prefix) { 1902 emit_op(c, is_inc ? OP_INC : OP_DEC); 1903 emit_private_token(c, target->right); 1904 emit_op(c, OP_PUT_PRIVATE); 1905 } else { 1906 emit_op(c, is_inc ? OP_POST_INC : OP_POST_DEC); 1907 emit_op(c, OP_SWAP_UNDER); 1908 emit_private_token(c, target->right); 1909 emit_op(c, OP_PUT_PRIVATE); 1910 emit_op(c, OP_POP); 1911 } 1912 } else if (target->type == N_MEMBER && !(target->flags & 1)) { 1913 compile_expr(c, target->left); 1914 emit_op(c, OP_DUP); 1915 int atom = add_atom(c, target->right->str, target->right->len); 1916 emit_atom_idx_op(c, OP_GET_FIELD, (uint32_t)atom); 1917 if (prefix) { 1918 emit_op(c, is_inc ? OP_INC : OP_DEC); 1919 emit_op(c, OP_INSERT2); 1920 emit_atom_idx_op(c, OP_PUT_FIELD, (uint32_t)atom); 1921 } else { 1922 emit_op(c, is_inc ? OP_POST_INC : OP_POST_DEC); 1923 emit_op(c, OP_SWAP_UNDER); 1924 emit_atom_idx_op(c, OP_PUT_FIELD, (uint32_t)atom); 1925 } 1926 } else if (target->type == N_MEMBER && (target->flags & 1)) { 1927 compile_expr(c, target->left); 1928 compile_expr(c, target->right); 1929 emit_op(c, OP_DUP2); 1930 emit_op(c, OP_GET_ELEM); 1931 if (prefix) { 1932 emit_op(c, is_inc ? OP_INC : OP_DEC); 1933 emit_op(c, OP_INSERT3); 1934 emit_op(c, OP_PUT_ELEM); 1935 } else { 1936 emit_op(c, is_inc ? OP_POST_INC : OP_POST_DEC); 1937 emit_op(c, OP_ROT4_UNDER); 1938 emit_op(c, OP_PUT_ELEM); 1939 } 1940 } else { 1941 emit_op(c, OP_UNDEF); 1942 } 1943} 1944 1945void compile_assign(sv_compiler_t *c, sv_ast_t *node) { 1946 sv_ast_t *target = node->left; 1947 uint8_t op = node->op; 1948 int append_local = -1; 1949 uint16_t append_slot = 0; 1950 sv_ast_t *append_rhs = NULL; 1951 1952 bool can_append_builder = match_self_append_local( 1953 c, node, &append_local, 1954 &append_slot, &append_rhs 1955 ); 1956 1957 if (op == TOK_ASSIGN) { 1958 if (target->type == N_MEMBER && !(target->flags & 1) && is_private_name_node(target->right)) { 1959 compile_expr(c, target->left); 1960 compile_expr(c, node->right); 1961 emit_private_token(c, target->right); 1962 emit_op(c, OP_PUT_PRIVATE); 1963 return; 1964 } 1965 1966 if (target->type == N_MEMBER && !(target->flags & 1)) { 1967 int atom = add_atom(c, target->right->str, target->right->len); 1968 compile_expr(c, target->left); 1969 compile_expr(c, node->right); 1970 emit_op(c, OP_INSERT2); 1971 emit_atom_idx_op(c, OP_PUT_FIELD, (uint32_t)atom); 1972 return; 1973 } 1974 1975 if (target->type == N_MEMBER && (target->flags & 1)) { 1976 compile_expr(c, target->left); 1977 compile_expr(c, target->right); 1978 compile_expr(c, node->right); 1979 emit_op(c, OP_INSERT3); 1980 emit_op(c, OP_PUT_ELEM); 1981 return; 1982 } 1983 1984 if (can_append_builder) { 1985 if (is_self_append_inplace_safe_expr(c, append_rhs)) { 1986 compile_expr(c, append_rhs); 1987 emit_slot_op(c, OP_STR_APPEND_LOCAL, append_slot); 1988 } else { 1989 emit_slot_op(c, OP_GET_SLOT_RAW, append_slot); 1990 compile_expr(c, append_rhs); 1991 emit_slot_op(c, OP_STR_ALC_SNAPSHOT, append_slot); 1992 } 1993 emit_get_var(c, target->str, target->len); 1994 set_local_inferred_type(c, append_local, SV_TI_UNKNOWN); 1995 return; 1996 } 1997 1998 compile_expr(c, node->right); 1999 compile_lhs_set(c, target, true); 2000 return; 2001 } 2002 2003 if (target->type == N_IDENT) { 2004 int lhs_local = resolve_local(c, target->str, target->len); 2005 uint8_t lhs_type = (lhs_local >= 0) ? get_local_inferred_type(c, lhs_local) : SV_TI_UNKNOWN; 2006 uint8_t rhs_type = infer_expr_type(c, node->right); 2007 2008 if (can_append_builder) { 2009 if (is_self_append_inplace_safe_expr(c, append_rhs)) { 2010 compile_expr(c, append_rhs); 2011 emit_slot_op(c, OP_STR_APPEND_LOCAL, append_slot); 2012 } else { 2013 emit_slot_op(c, OP_GET_SLOT_RAW, append_slot); 2014 compile_expr(c, append_rhs); 2015 emit_slot_op(c, OP_STR_ALC_SNAPSHOT, append_slot); 2016 } 2017 emit_get_var(c, target->str, target->len); 2018 set_local_inferred_type(c, append_local, SV_TI_UNKNOWN); 2019 return; 2020 } 2021 2022 if (op == TOK_PLUS_ASSIGN) { 2023 int slot = resolve_local_slot(c, target->str, target->len); 2024 if (slot >= 0 && !c->locals[slot + c->param_locals].is_const) { 2025 sv_ast_t *rhs = node->right; 2026 bool rhs_pure = rhs && ( 2027 rhs->type == N_NUMBER || rhs->type == N_STRING || 2028 rhs->type == N_BOOL || rhs->type == N_NULL || 2029 rhs->type == N_UNDEF || rhs->type == N_IDENT 2030 ); 2031 if (rhs_pure) { 2032 compile_expr(c, rhs); 2033 emit_op(c, OP_ADD_LOCAL); 2034 emit(c, (uint8_t)slot); 2035 emit_get_local(c, c->param_locals + slot); 2036 set_local_inferred_type(c, c->param_locals + slot, SV_TI_UNKNOWN); 2037 return; 2038 } 2039 } 2040 } 2041 2042 if (op == TOK_LOR_ASSIGN || op == TOK_LAND_ASSIGN || 2043 op == TOK_NULLISH_ASSIGN) { 2044 emit_get_var(c, target->str, target->len); 2045 int skip = emit_jump(c, 2046 op == TOK_LOR_ASSIGN ? OP_JMP_TRUE_PEEK : 2047 op == TOK_LAND_ASSIGN ? OP_JMP_FALSE_PEEK : OP_JMP_NOT_NULLISH); 2048 emit_op(c, OP_POP); 2049 compile_expr(c, node->right); 2050 emit_set_var(c, target->str, target->len, true); 2051 patch_jump(c, skip); 2052 return; 2053 } 2054 2055 emit_get_var(c, target->str, target->len); 2056 compile_expr(c, node->right); 2057 switch (op) { 2058 case TOK_PLUS_ASSIGN: 2059 emit_op(c, (lhs_type == SV_TI_NUM && rhs_type == SV_TI_NUM) ? OP_ADD_NUM : OP_ADD); 2060 break; 2061 case TOK_MINUS_ASSIGN: 2062 emit_op(c, (lhs_type == SV_TI_NUM && rhs_type == SV_TI_NUM) ? OP_SUB_NUM : OP_SUB); 2063 break; 2064 case TOK_MUL_ASSIGN: 2065 emit_op(c, (lhs_type == SV_TI_NUM && rhs_type == SV_TI_NUM) ? OP_MUL_NUM : OP_MUL); 2066 break; 2067 case TOK_DIV_ASSIGN: 2068 emit_op(c, (lhs_type == SV_TI_NUM && rhs_type == SV_TI_NUM) ? OP_DIV_NUM : OP_DIV); 2069 break; 2070 case TOK_REM_ASSIGN: emit_op(c, OP_MOD); break; 2071 case TOK_SHL_ASSIGN: emit_op(c, OP_SHL); break; 2072 case TOK_SHR_ASSIGN: emit_op(c, OP_SHR); break; 2073 case TOK_ZSHR_ASSIGN: emit_op(c, OP_USHR); break; 2074 case TOK_AND_ASSIGN: emit_op(c, OP_BAND); break; 2075 case TOK_XOR_ASSIGN: emit_op(c, OP_BXOR); break; 2076 case TOK_OR_ASSIGN: emit_op(c, OP_BOR); break; 2077 case TOK_EXP_ASSIGN: emit_op(c, OP_EXP); break; 2078 default: break; 2079 } 2080 emit_set_var(c, target->str, target->len, true); 2081 } else if (target->type == N_MEMBER && !(target->flags & 1) && is_private_name_node(target->right)) { 2082 if (op == TOK_LOR_ASSIGN || op == TOK_LAND_ASSIGN || 2083 op == TOK_NULLISH_ASSIGN) { 2084 compile_expr(c, target->left); 2085 emit_op(c, OP_DUP); 2086 emit_private_token(c, target->right); 2087 emit_op(c, OP_GET_PRIVATE); 2088 int skip = emit_jump(c, 2089 op == TOK_LOR_ASSIGN ? OP_JMP_TRUE_PEEK : 2090 op == TOK_LAND_ASSIGN ? OP_JMP_FALSE_PEEK : OP_JMP_NOT_NULLISH); 2091 emit_op(c, OP_POP); 2092 compile_expr(c, node->right); 2093 emit_private_token(c, target->right); 2094 emit_op(c, OP_PUT_PRIVATE); 2095 int end = emit_jump(c, OP_JMP); 2096 patch_jump(c, skip); 2097 emit_op(c, OP_NIP); 2098 patch_jump(c, end); 2099 return; 2100 } 2101 2102 compile_expr(c, target->left); 2103 emit_op(c, OP_DUP); 2104 emit_private_token(c, target->right); 2105 emit_op(c, OP_GET_PRIVATE); 2106 compile_expr(c, node->right); 2107 switch (op) { 2108 case TOK_PLUS_ASSIGN: emit_op(c, OP_ADD); break; 2109 case TOK_MINUS_ASSIGN: emit_op(c, OP_SUB); break; 2110 case TOK_MUL_ASSIGN: emit_op(c, OP_MUL); break; 2111 case TOK_DIV_ASSIGN: emit_op(c, OP_DIV); break; 2112 case TOK_REM_ASSIGN: emit_op(c, OP_MOD); break; 2113 case TOK_SHL_ASSIGN: emit_op(c, OP_SHL); break; 2114 case TOK_SHR_ASSIGN: emit_op(c, OP_SHR); break; 2115 case TOK_ZSHR_ASSIGN: emit_op(c, OP_USHR); break; 2116 case TOK_AND_ASSIGN: emit_op(c, OP_BAND); break; 2117 case TOK_XOR_ASSIGN: emit_op(c, OP_BXOR); break; 2118 case TOK_OR_ASSIGN: emit_op(c, OP_BOR); break; 2119 case TOK_EXP_ASSIGN: emit_op(c, OP_EXP); break; 2120 default: break; 2121 } 2122 emit_private_token(c, target->right); 2123 emit_op(c, OP_PUT_PRIVATE); 2124 } else if (target->type == N_MEMBER && !(target->flags & 1)) { 2125 int atom = add_atom(c, target->right->str, target->right->len); 2126 2127 if (op == TOK_LOR_ASSIGN || op == TOK_LAND_ASSIGN || 2128 op == TOK_NULLISH_ASSIGN) { 2129 compile_expr(c, target->left); 2130 emit_op(c, OP_DUP); 2131 emit_atom_idx_op(c, OP_GET_FIELD, (uint32_t)atom); 2132 int skip = emit_jump(c, 2133 op == TOK_LOR_ASSIGN ? OP_JMP_TRUE_PEEK : 2134 op == TOK_LAND_ASSIGN ? OP_JMP_FALSE_PEEK : OP_JMP_NOT_NULLISH); 2135 emit_op(c, OP_POP); 2136 compile_expr(c, node->right); 2137 emit_op(c, OP_INSERT2); 2138 emit_atom_idx_op(c, OP_PUT_FIELD, (uint32_t)atom); 2139 int end = emit_jump(c, OP_JMP); 2140 patch_jump(c, skip); 2141 emit_op(c, OP_NIP); 2142 patch_jump(c, end); 2143 return; 2144 } 2145 2146 compile_expr(c, target->left); 2147 emit_op(c, OP_DUP); 2148 emit_atom_idx_op(c, OP_GET_FIELD, (uint32_t)atom); 2149 compile_expr(c, node->right); 2150 switch (op) { 2151 case TOK_PLUS_ASSIGN: emit_op(c, OP_ADD); break; 2152 case TOK_MINUS_ASSIGN: emit_op(c, OP_SUB); break; 2153 case TOK_MUL_ASSIGN: emit_op(c, OP_MUL); break; 2154 case TOK_DIV_ASSIGN: emit_op(c, OP_DIV); break; 2155 case TOK_REM_ASSIGN: emit_op(c, OP_MOD); break; 2156 case TOK_SHL_ASSIGN: emit_op(c, OP_SHL); break; 2157 case TOK_SHR_ASSIGN: emit_op(c, OP_SHR); break; 2158 case TOK_ZSHR_ASSIGN: emit_op(c, OP_USHR); break; 2159 case TOK_AND_ASSIGN: emit_op(c, OP_BAND); break; 2160 case TOK_XOR_ASSIGN: emit_op(c, OP_BXOR); break; 2161 case TOK_OR_ASSIGN: emit_op(c, OP_BOR); break; 2162 case TOK_EXP_ASSIGN: emit_op(c, OP_EXP); break; 2163 default: break; 2164 } 2165 emit_op(c, OP_INSERT2); 2166 emit_atom_idx_op(c, OP_PUT_FIELD, (uint32_t)atom); 2167 } else if (target->type == N_MEMBER && (target->flags & 1)) { 2168 2169 if (op == TOK_LOR_ASSIGN || op == TOK_LAND_ASSIGN || 2170 op == TOK_NULLISH_ASSIGN) { 2171 compile_expr(c, target->left); 2172 compile_expr(c, target->right); 2173 emit_op(c, OP_DUP2); 2174 emit_op(c, OP_GET_ELEM); 2175 int skip = emit_jump(c, 2176 op == TOK_LOR_ASSIGN ? OP_JMP_TRUE_PEEK : 2177 op == TOK_LAND_ASSIGN ? OP_JMP_FALSE_PEEK : OP_JMP_NOT_NULLISH); 2178 emit_op(c, OP_POP); 2179 compile_expr(c, node->right); 2180 emit_op(c, OP_INSERT3); 2181 emit_op(c, OP_PUT_ELEM); 2182 int end = emit_jump(c, OP_JMP); 2183 patch_jump(c, skip); 2184 emit_op(c, OP_NIP2); 2185 patch_jump(c, end); 2186 return; 2187 } 2188 2189 compile_expr(c, target->left); 2190 compile_expr(c, target->right); 2191 emit_op(c, OP_DUP2); 2192 emit_op(c, OP_GET_ELEM); 2193 compile_expr(c, node->right); 2194 switch (op) { 2195 case TOK_PLUS_ASSIGN: emit_op(c, OP_ADD); break; 2196 case TOK_MINUS_ASSIGN: emit_op(c, OP_SUB); break; 2197 case TOK_MUL_ASSIGN: emit_op(c, OP_MUL); break; 2198 case TOK_DIV_ASSIGN: emit_op(c, OP_DIV); break; 2199 case TOK_REM_ASSIGN: emit_op(c, OP_MOD); break; 2200 case TOK_SHL_ASSIGN: emit_op(c, OP_SHL); break; 2201 case TOK_SHR_ASSIGN: emit_op(c, OP_SHR); break; 2202 case TOK_ZSHR_ASSIGN: emit_op(c, OP_USHR); break; 2203 case TOK_AND_ASSIGN: emit_op(c, OP_BAND); break; 2204 case TOK_XOR_ASSIGN: emit_op(c, OP_BXOR); break; 2205 case TOK_OR_ASSIGN: emit_op(c, OP_BOR); break; 2206 case TOK_EXP_ASSIGN: emit_op(c, OP_EXP); break; 2207 default: break; 2208 } 2209 emit_op(c, OP_INSERT3); 2210 emit_op(c, OP_PUT_ELEM); 2211 } else { 2212 compile_expr(c, node->right); 2213 } 2214} 2215 2216void compile_lhs_set(sv_compiler_t *c, sv_ast_t *target, bool keep) { 2217 if (target->type == N_IDENT) { 2218 emit_set_var(c, target->str, target->len, keep); 2219 } else if (target->type == N_MEMBER && !(target->flags & 1) && is_private_name_node(target->right)) { 2220 (void)keep; 2221 compile_expr(c, target->left); 2222 emit_op(c, OP_SWAP); 2223 emit_private_token(c, target->right); 2224 emit_op(c, OP_PUT_PRIVATE); 2225 } else if (target->type == N_MEMBER && !(target->flags & 1)) { 2226 if (keep) emit_op(c, OP_DUP); 2227 compile_expr(c, target->left); 2228 emit_op(c, OP_SWAP); 2229 emit_atom_op(c, OP_PUT_FIELD, target->right->str, target->right->len); 2230 } else if (target->type == N_MEMBER && (target->flags & 1)) { 2231 if (keep) emit_op(c, OP_DUP); 2232 compile_expr(c, target->left); 2233 compile_expr(c, target->right); 2234 emit_op(c, OP_ROT3L); 2235 emit_op(c, OP_PUT_ELEM); 2236 } else if (target->type == N_ARRAY_PAT || target->type == N_ARRAY) { 2237 compile_array_destructure(c, target, keep); 2238 } else if (target->type == N_OBJECT_PAT || target->type == N_OBJECT) { 2239 compile_object_destructure(c, target, keep); 2240 } 2241} 2242 2243void compile_ternary(sv_compiler_t *c, sv_ast_t *node) { 2244 compile_truthy_test_expr(c, node->cond); 2245 int else_jump = emit_jump(c, OP_JMP_FALSE); 2246 compile_expr(c, node->left); 2247 int end_jump = emit_jump(c, OP_JMP); 2248 patch_jump(c, else_jump); 2249 compile_expr(c, node->right); 2250 patch_jump(c, end_jump); 2251} 2252 2253void compile_typeof(sv_compiler_t *c, sv_ast_t *node) { 2254 sv_ast_t *arg = node->right; 2255 if (arg->type == N_IDENT) { 2256 int local = resolve_local(c, arg->str, arg->len); 2257 if (local != -1) { 2258 uint8_t inferred = get_local_inferred_type(c, local); 2259 const char *known = typeof_name_for_type(inferred); 2260 if (known) { 2261 emit_constant(c, js_mkstr_permanent(c->js, known, strlen(known))); 2262 return; 2263 } 2264 emit_get_var(c, arg->str, arg->len); 2265 } else { 2266 int upval = resolve_upvalue(c, arg->str, arg->len); 2267 if (upval != -1) { 2268 emit_op(c, OP_GET_UPVAL); 2269 emit_u16(c, (uint16_t)upval); 2270 } else if ( 2271 has_implicit_arguments_obj(c) && 2272 is_ident_str(arg->str, arg->len, "arguments", 9) 2273 ) { 2274 if (c->strict_args_local >= 0) { 2275 emit_get_local(c, c->strict_args_local); 2276 } else { 2277 emit_op(c, OP_SPECIAL_OBJ); 2278 emit(c, 0); 2279 } 2280 } else emit_atom_op(c, OP_GET_GLOBAL_UNDEF, arg->str, arg->len); 2281 } 2282 } else compile_expr(c, arg); 2283 emit_op(c, OP_TYPEOF); 2284} 2285 2286static bool sv_node_has_optional_base(sv_ast_t *n) { 2287 while (n) { 2288 if (n->type == N_OPTIONAL) return true; 2289 if (n->type == N_MEMBER || n->type == N_CALL) n = n->left; 2290 else break; 2291 } 2292 return false; 2293} 2294 2295static void compile_delete_optional(sv_compiler_t *c, sv_ast_t *arg) { 2296 compile_expr(c, arg->left); 2297 int ok_jump = emit_jump(c, OP_JMP_NOT_NULLISH); 2298 emit_op(c, OP_POP); 2299 emit_op(c, OP_TRUE); 2300 int end_jump = emit_jump(c, OP_JMP); 2301 patch_jump(c, ok_jump); 2302 if (arg->flags & 1) { 2303 compile_expr(c, arg->right); 2304 } else { 2305 ant_value_t key = js_mkstr_permanent(c->js, arg->right->str, arg->right->len); 2306 emit_constant(c, key); 2307 } 2308 emit_op(c, OP_DELETE); 2309 patch_jump(c, end_jump); 2310} 2311 2312void compile_delete(sv_compiler_t *c, sv_ast_t *node) { 2313 sv_ast_t *arg = node->right; 2314 if ((arg->type == N_MEMBER || arg->type == N_OPTIONAL) && 2315 arg->right && is_private_name_node(arg->right)) { 2316 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Cannot delete private fields"); 2317 emit_op(c, OP_TRUE); 2318 return; 2319 } 2320 if (arg->type == N_OPTIONAL) { 2321 compile_delete_optional(c, arg); 2322 } else if (arg->type == N_MEMBER && sv_node_has_optional_base(arg->left)) { 2323 compile_delete_optional(c, arg); 2324 } else if (arg->type == N_MEMBER && !(arg->flags & 1)) { 2325 compile_expr(c, arg->left); 2326 ant_value_t key = js_mkstr_permanent(c->js, arg->right->str, arg->right->len); 2327 emit_constant(c, key); 2328 emit_op(c, OP_DELETE); 2329 } else if (arg->type == N_MEMBER && (arg->flags & 1)) { 2330 compile_expr(c, arg->left); 2331 compile_expr(c, arg->right); 2332 emit_op(c, OP_DELETE); 2333 } else if (arg->type == N_IDENT) { 2334 emit_atom_op(c, OP_DELETE_VAR, arg->str, arg->len); 2335 } else { 2336 compile_expr(c, arg); 2337 emit_op(c, OP_POP); 2338 emit_op(c, OP_TRUE); 2339 } 2340} 2341 2342void compile_template(sv_compiler_t *c, sv_ast_t *node) { 2343 int n = node->args.count; 2344 if (n == 0) { 2345 emit_constant(c, js_mkstr_permanent(c->js, "", 0)); 2346 return; 2347 } 2348 for (int i = 0; i < n; i++) { 2349 sv_ast_t *item = node->args.items[i]; 2350 if (is_invalid_cooked_string(item)) { 2351 static const char msg[] = "Invalid or unexpected token"; 2352 int atom = add_atom(c, msg, sizeof(msg) - 1); 2353 emit_op(c, OP_THROW_ERROR); 2354 emit_u32(c, (uint32_t)atom); 2355 emit(c, (uint8_t)JS_ERR_SYNTAX); 2356 return; 2357 } 2358 } 2359 compile_expr(c, node->args.items[0]); 2360 if (!is_template_segment(node->args.items[0])) 2361 emit_op(c, OP_TO_PROPKEY); 2362 for (int i = 1; i < n; i++) { 2363 compile_expr(c, node->args.items[i]); 2364 if (!is_template_segment(node->args.items[i])) 2365 emit_op(c, OP_TO_PROPKEY); 2366 emit_op(c, OP_ADD); 2367 } 2368} 2369 2370static bool call_has_spread_arg(const sv_ast_t *node) { 2371 if (!node) return false; 2372 for (int i = 0; i < node->args.count; i++) { 2373 sv_ast_t *arg = node->args.items[i]; 2374 if (arg && arg->type == N_SPREAD) return true; 2375 } 2376 return false; 2377} 2378 2379static void compile_push_arg_to_array(sv_compiler_t *c, sv_ast_t *arg) { 2380 emit_op(c, OP_DUP); 2381 emit_op(c, OP_DUP); 2382 emit_atom_op(c, OP_GET_FIELD, "push", 4); 2383 compile_expr(c, arg); 2384 emit_op(c, OP_CALL_METHOD); 2385 emit_u16(c, 1); 2386 emit_op(c, OP_POP); 2387} 2388 2389static void compile_concat_spread_to_array(sv_compiler_t *c, sv_ast_t *spread_arg) { 2390 compile_expr(c, spread_arg->right); 2391 emit_op(c, OP_SPREAD); 2392} 2393 2394static void compile_call_args_array(sv_compiler_t *c, sv_ast_t *call_node) { 2395 emit_op(c, OP_ARRAY); 2396 emit_u16(c, 0); 2397 for (int i = 0; i < call_node->args.count; i++) { 2398 sv_ast_t *arg = call_node->args.items[i]; 2399 if (arg && arg->type == N_SPREAD) compile_concat_spread_to_array(c, arg); 2400 else compile_push_arg_to_array(c, arg); 2401 } 2402} 2403 2404typedef enum { 2405 SV_CALL_DIRECT = 0, 2406 SV_CALL_METHOD = 1, 2407 SV_CALL_SUPER = 2, 2408} sv_call_kind_t; 2409 2410static inline bool sv_call_kind_has_receiver(sv_call_kind_t kind) { 2411 return kind == SV_CALL_METHOD || kind == SV_CALL_SUPER; 2412} 2413 2414static void compile_receiver_property_get(sv_compiler_t *c, sv_ast_t *node) { 2415 emit_op(c, OP_DUP); 2416 if (node->flags & 1) { 2417 compile_expr(c, node->right); 2418 emit_op(c, OP_GET_ELEM); 2419 } else if (is_private_name_node(node->right)) { 2420 emit_private_token(c, node->right); 2421 emit_op(c, OP_GET_PRIVATE); 2422 } else { 2423 emit_srcpos(c, node->right); 2424 emit_atom_op(c, OP_GET_FIELD, node->right->str, node->right->len); 2425 } 2426} 2427 2428static void compile_call_emit_invoke( 2429 sv_compiler_t *c, sv_ast_t *node, 2430 sv_call_kind_t kind, bool has_spread 2431) { 2432 int argc = node->args.count; 2433 if (has_spread) { 2434 if (sv_call_kind_has_receiver(kind)) emit_op(c, OP_SWAP); 2435 else emit_op(c, OP_GLOBAL); 2436 compile_call_args_array(c, node); 2437 emit_op(c, kind == SV_CALL_SUPER ? OP_SUPER_APPLY : OP_APPLY); 2438 emit_u16(c, 1); 2439 return; 2440 } 2441 2442 for (int i = 0; i < argc; i++) 2443 compile_expr(c, node->args.items[i]); 2444 emit_op(c, sv_call_kind_has_receiver(kind) ? OP_CALL_METHOD : OP_CALL); 2445 emit_u16(c, (uint16_t)argc); 2446} 2447 2448static sv_call_kind_t compile_call_setup_non_optional(sv_compiler_t *c, sv_ast_t *callee) { 2449 if (is_ident_name(callee, "super")) { 2450 emit_op(c, OP_THIS); 2451 emit_get_var(c, "super", 5); 2452 return SV_CALL_SUPER; 2453 } 2454 2455 if (callee->type == N_MEMBER && is_ident_name(callee->left, "super")) { 2456 if (!(callee->flags & 1) && is_private_name_node(callee->right)) { 2457 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Cannot access private member through super"); 2458 emit_op(c, OP_UNDEF); 2459 return SV_CALL_DIRECT; 2460 } 2461 emit_op(c, OP_THIS); 2462 emit_op(c, OP_THIS); 2463 emit_get_var(c, "super", 5); 2464 if (callee->flags & 1) 2465 compile_expr(c, callee->right); 2466 else 2467 emit_constant(c, js_mkstr_permanent(c->js, callee->right->str, callee->right->len)); 2468 emit_op(c, OP_GET_SUPER_VAL); 2469 return SV_CALL_METHOD; 2470 } 2471 2472 if (callee->type == N_MEMBER) { 2473 compile_expr(c, callee->left); 2474 compile_receiver_property_get(c, callee); 2475 return SV_CALL_METHOD; 2476 } 2477 2478 compile_expr(c, callee); 2479 return SV_CALL_DIRECT; 2480} 2481 2482static bool compile_call_is_proto_intrinsic( 2483 sv_compiler_t *c, sv_ast_t *node, bool has_spread 2484) { 2485 if (!node || has_spread || node->args.count != 1) return false; 2486 sv_ast_t *callee = node->left; 2487 if (!callee || callee->type != N_MEMBER) return false; 2488 if ((callee->flags & 1) || !callee->right || !callee->right->str) return false; 2489 if (is_ident_name(callee->left, "super")) return false; 2490 if (!is_ident_str(callee->right->str, callee->right->len, "isPrototypeOf", 13)) 2491 return false; 2492 2493 compile_expr(c, callee->left); 2494 compile_receiver_property_get(c, callee); 2495 compile_expr(c, node->args.items[0]); 2496 emit_op(c, OP_CALL_IS_PROTO); 2497 emit_u16(c, alloc_ic_idx(c)); 2498 return true; 2499} 2500 2501static bool compile_call_array_includes_intrinsic( 2502 sv_compiler_t *c, sv_ast_t *node, bool has_spread 2503) { 2504 if (!node || has_spread || node->args.count > UINT16_MAX) return false; 2505 sv_ast_t *callee = node->left; 2506 2507 if (!callee || callee->type != N_MEMBER) return false; 2508 if ((callee->flags & 1) || !callee->right || !callee->right->str) return false; 2509 if (is_ident_name(callee->left, "super")) return false; 2510 if (!is_ident_str(callee->right->str, callee->right->len, "includes", 8)) 2511 return false; 2512 2513 compile_expr(c, callee->left); 2514 compile_receiver_property_get(c, callee); 2515 for (int i = 0; i < node->args.count; i++) 2516 compile_expr(c, node->args.items[i]); 2517 emit_op(c, OP_CALL_ARRAY_INCLUDES); 2518 emit_u16(c, (uint16_t)node->args.count); 2519 2520 return true; 2521} 2522 2523static bool compile_regexp_exec_truthy_intrinsic( 2524 sv_compiler_t *c, sv_ast_t *node 2525) { 2526 if (!node || node->type != N_CALL || call_has_spread_arg(node) || node->args.count != 1) 2527 return false; 2528 2529 sv_ast_t *callee = node->left; 2530 if (!callee || callee->type != N_MEMBER) return false; 2531 if ((callee->flags & 1) || !callee->right || !callee->right->str) return false; 2532 if (is_ident_name(callee->left, "super")) return false; 2533 if (!is_ident_str(callee->right->str, callee->right->len, "exec", 4)) 2534 return false; 2535 2536 compile_expr(c, callee->left); 2537 compile_receiver_property_get(c, callee); 2538 compile_expr(c, node->args.items[0]); 2539 emit_op(c, OP_RE_EXEC_TRUTHY); 2540 2541 return true; 2542} 2543 2544static void compile_truthy_test_expr(sv_compiler_t *c, sv_ast_t *node) { 2545 if (compile_regexp_exec_truthy_intrinsic(c, node)) return; 2546 compile_expr(c, node); 2547} 2548 2549static void compile_optional_call_after_setup( 2550 sv_compiler_t *c, sv_ast_t *call_node, 2551 sv_call_kind_t kind, bool has_spread 2552) { 2553 emit_op(c, OP_DUP); 2554 emit_op(c, OP_IS_UNDEF_OR_NULL); 2555 int j_do_call = emit_jump(c, OP_JMP_FALSE); 2556 emit_op(c, OP_POP); 2557 if (sv_call_kind_has_receiver(kind)) 2558 emit_op(c, OP_POP); 2559 emit_op(c, OP_UNDEF); 2560 int j_end = emit_jump(c, OP_JMP); 2561 patch_jump(c, j_do_call); 2562 compile_call_emit_invoke(c, call_node, kind, has_spread); 2563 patch_jump(c, j_end); 2564} 2565 2566static void compile_call_optional( 2567 sv_compiler_t *c, sv_ast_t *node, 2568 sv_ast_t *opt_callee, bool has_spread 2569) { 2570 if (opt_callee->right) { 2571 compile_expr(c, opt_callee->left); 2572 emit_op(c, OP_DUP); 2573 emit_op(c, OP_IS_UNDEF_OR_NULL); 2574 int j_have_obj = emit_jump(c, OP_JMP_FALSE); 2575 emit_op(c, OP_POP); 2576 emit_op(c, OP_UNDEF); 2577 int j_end = emit_jump(c, OP_JMP); 2578 patch_jump(c, j_have_obj); 2579 2580 compile_receiver_property_get(c, opt_callee); 2581 compile_call_emit_invoke(c, node, SV_CALL_METHOD, has_spread); 2582 patch_jump(c, j_end); 2583 2584 return; 2585 } 2586 2587 sv_ast_t *target = opt_callee->left; 2588 if (target && target->type == N_OPTIONAL && target->right) { 2589 compile_expr(c, target->left); 2590 emit_op(c, OP_DUP); 2591 emit_op(c, OP_IS_UNDEF_OR_NULL); 2592 int j_have_obj = emit_jump(c, OP_JMP_FALSE); 2593 emit_op(c, OP_POP); 2594 emit_op(c, OP_UNDEF); 2595 int j_end = emit_jump(c, OP_JMP); 2596 patch_jump(c, j_have_obj); 2597 2598 compile_receiver_property_get(c, target); 2599 compile_optional_call_after_setup(c, node, SV_CALL_METHOD, has_spread); 2600 patch_jump(c, j_end); 2601 return; 2602 } 2603 2604 sv_call_kind_t kind = compile_call_setup_non_optional(c, target); 2605 compile_optional_call_after_setup(c, node, kind, has_spread); 2606} 2607 2608void compile_call(sv_compiler_t *c, sv_ast_t *node) { 2609 sv_ast_t *callee = node->left; 2610 bool has_spread = call_has_spread_arg(node); 2611 2612 if (callee->type == N_OPTIONAL) { 2613 compile_call_optional(c, node, callee, has_spread); 2614 return; 2615 } 2616 2617 if (compile_call_is_proto_intrinsic(c, node, has_spread)) 2618 return; 2619 2620 if (compile_call_array_includes_intrinsic(c, node, has_spread)) 2621 return; 2622 2623 if ( 2624 !has_spread && node->args.count >= 2 && 2625 callee->type == N_MEMBER && 2626 is_ident_name(callee->left, "Ant") && 2627 resolve_local(c, "Ant", 3) == -1 && 2628 callee->right && callee->right->type == N_IDENT && 2629 callee->right->len == 5 && memcmp(callee->right->str, "match", 5) == 0 && 2630 node->args.items[1]->type == N_OBJECT 2631 ) { 2632 sv_ast_t *obj = node->args.items[1]; 2633 sv_ast_t *param = sv_ast_new(N_IDENT); 2634 2635 param->str = "$"; param->len = 1; 2636 sv_ast_t *arrow = sv_ast_new(N_FUNC); 2637 2638 arrow->flags = FN_ARROW; 2639 arrow->body = obj; 2640 arrow->line = obj->line; arrow->col = obj->col; 2641 arrow->src_off = obj->src_off; arrow->src_end = obj->src_end; 2642 2643 sv_ast_list_push(&arrow->args, param); 2644 node->args.items[1] = arrow; 2645 } 2646 2647 if (!has_spread && is_ident_name(callee, "eval")) { 2648 if (node->args.count > 0) 2649 compile_expr(c, node->args.items[0]); 2650 else 2651 emit_op(c, OP_UNDEF); 2652 for (int i = 1; i < node->args.count; i++) { 2653 compile_expr(c, node->args.items[i]); 2654 emit_op(c, OP_POP); 2655 } 2656 2657 emit_op(c, OP_EVAL); 2658 emit_u32(c, 0); 2659 2660 return; 2661 } 2662 2663 if (callee->type == N_MEMBER && sv_node_has_optional_base(callee->left)) { 2664 compile_expr(c, callee->left); 2665 int ok_jump = emit_jump(c, OP_JMP_NOT_NULLISH); 2666 emit_op(c, OP_POP); 2667 emit_op(c, OP_UNDEF); 2668 int end_jump = emit_jump(c, OP_JMP); 2669 patch_jump(c, ok_jump); 2670 compile_receiver_property_get(c, callee); 2671 compile_call_emit_invoke(c, node, SV_CALL_METHOD, has_spread); 2672 patch_jump(c, end_jump); 2673 return; 2674 } 2675 2676 sv_call_kind_t kind = compile_call_setup_non_optional(c, callee); 2677 compile_call_emit_invoke(c, node, kind, has_spread); 2678} 2679 2680void compile_new(sv_compiler_t *c, sv_ast_t *node) { 2681 compile_expr(c, node->left); 2682 emit_op(c, OP_DUP); 2683 if (call_has_spread_arg(node)) { 2684 compile_call_args_array(c, node); 2685 emit_op(c, OP_NEW_APPLY); 2686 emit_u16(c, 1); 2687 } else { 2688 int argc = node->args.count; 2689 for (int i = 0; i < argc; i++) 2690 compile_expr(c, node->args.items[i]); 2691 emit_op(c, OP_NEW); 2692 emit_u16(c, (uint16_t)argc); 2693 } 2694} 2695 2696void compile_member(sv_compiler_t *c, sv_ast_t *node) { 2697 if (is_ident_name(node->left, "super")) { 2698 if (!(node->flags & 1) && is_private_name_node(node->right)) { 2699 js_mkerr_typed(c->js, JS_ERR_SYNTAX, "Cannot access private member through super"); 2700 emit_op(c, OP_UNDEF); 2701 return; 2702 } 2703 emit_op(c, OP_THIS); 2704 emit_get_var(c, "super", 5); 2705 if (node->flags & 1) 2706 compile_expr(c, node->right); 2707 else 2708 emit_constant(c, js_mkstr_permanent(c->js, node->right->str, node->right->len)); 2709 emit_op(c, OP_GET_SUPER_VAL); 2710 return; 2711 } 2712 2713 compile_expr(c, node->left); 2714 2715 int ok_jump = -1, end_jump = -1; 2716 if (sv_node_has_optional_base(node->left)) { 2717 ok_jump = emit_jump(c, OP_JMP_NOT_NULLISH); 2718 end_jump = emit_jump(c, OP_JMP); 2719 patch_jump(c, ok_jump); 2720 } 2721 2722 if (node->flags & 1) { 2723 compile_expr(c, node->right); 2724 emit_op(c, OP_GET_ELEM); 2725 } else if (is_private_name_node(node->right)) { 2726 emit_private_token(c, node->right); 2727 emit_op(c, OP_GET_PRIVATE); 2728 } else { 2729 if (node->right->len == 6 && memcmp(node->right->str, "length", 6) == 0) 2730 emit_op(c, OP_GET_LENGTH); 2731 else { 2732 emit_srcpos(c, node->right); 2733 emit_atom_op(c, OP_GET_FIELD, node->right->str, node->right->len); 2734 } 2735 } 2736 2737 if (end_jump >= 0) patch_jump(c, end_jump); 2738} 2739 2740void compile_optional_get(sv_compiler_t *c, sv_ast_t *node) { 2741 if (node->flags & 1) { 2742 compile_expr(c, node->right); 2743 emit_op(c, OP_GET_ELEM_OPT); 2744 } else if (is_private_name_node(node->right)) { 2745 emit_private_token(c, node->right); 2746 emit_op(c, OP_GET_PRIVATE_OPT); 2747 } else { 2748 emit_srcpos(c, node->right); 2749 emit_atom_op(c, OP_GET_FIELD_OPT, node->right->str, node->right->len); 2750 } 2751} 2752 2753void compile_optional(sv_compiler_t *c, sv_ast_t *node) { 2754 compile_expr(c, node->left); 2755 compile_optional_get(c, node); 2756} 2757 2758void compile_array(sv_compiler_t *c, sv_ast_t *node) { 2759 int count = node->args.count; 2760 bool has_spread = false; 2761 for (int i = 0; i < count; i++) { 2762 sv_ast_t *elem = node->args.items[i]; 2763 if (elem && elem->type == N_SPREAD) { 2764 has_spread = true; 2765 break; 2766 } 2767 } 2768 2769 if (!has_spread) { 2770 for (int i = 0; i < count; i++) { 2771 sv_ast_t *elem = node->args.items[i]; 2772 if (elem && elem->type == N_EMPTY) 2773 emit_op(c, OP_EMPTY); 2774 else 2775 compile_expr(c, elem); 2776 } 2777 emit_op(c, OP_ARRAY); 2778 emit_u16(c, (uint16_t)count); 2779 return; 2780 } 2781 2782 emit_op(c, OP_ARRAY); 2783 emit_u16(c, 0); 2784 for (int i = 0; i < count; i++) { 2785 sv_ast_t *elem = node->args.items[i]; 2786 if (elem && elem->type == N_SPREAD) compile_concat_spread_to_array(c, elem); 2787 else compile_push_arg_to_array(c, elem); 2788 } 2789} 2790 2791void compile_object(sv_compiler_t *c, sv_ast_t *node) { 2792 emit_op(c, OP_OBJECT); 2793 for (int i = 0; i < node->args.count; i++) { 2794 sv_ast_t *prop = node->args.items[i]; 2795 if (prop->type == N_SPREAD) { 2796 compile_expr(c, prop->right); 2797 emit_op(c, OP_COPY_DATA_PROPS); 2798 emit(c, 0); 2799 emit_op(c, OP_POP); 2800 continue; 2801 } 2802 2803 if (prop->type != N_PROPERTY) continue; 2804 if (prop->flags & FN_GETTER || prop->flags & FN_SETTER) { 2805 compile_expr(c, prop->right); 2806 uint8_t flags = 0; 2807 if (prop->flags & FN_GETTER) flags |= SV_DEFINE_METHOD_GETTER; 2808 if (prop->flags & FN_SETTER) flags |= SV_DEFINE_METHOD_SETTER; 2809 flags |= SV_DEFINE_METHOD_SET_NAME; 2810 if (prop->flags & FN_COMPUTED) compile_expr(c, prop->left); 2811 else compile_static_property_key(c, prop->left); 2812 emit_op(c, OP_SWAP); 2813 emit_op(c, OP_DEFINE_METHOD_COMP); 2814 emit(c, flags); 2815 } else if (prop->flags & FN_COMPUTED) { 2816 compile_expr(c, prop->left); 2817 compile_expr(c, prop->right); 2818 emit_op(c, OP_DEFINE_METHOD_COMP); 2819 emit(c, node_needs_inferred_function_name(prop->right) ? SV_DEFINE_METHOD_SET_NAME : 0); 2820 } else { 2821 if (prop->left && prop->left->type == N_IDENT && !is_quoted_ident_key(prop->left)) 2822 compile_expr_with_inferred_name(c, prop->right, prop->left->str, prop->left->len); 2823 else compile_expr(c, prop->right); 2824 if ((prop->flags & FN_COLON) && 2825 prop->left->type == N_IDENT && !is_quoted_ident_key(prop->left) && 2826 is_ident_str(prop->left->str, prop->left->len, "__proto__", 9)) { 2827 emit_op(c, OP_SET_PROTO); 2828 continue; 2829 } 2830 if (prop->left->type == N_IDENT && !is_quoted_ident_key(prop->left)) { 2831 emit_atom_op(c, OP_DEFINE_FIELD, prop->left->str, prop->left->len); 2832 } else if (is_quoted_ident_key(prop->left)) { 2833 emit_atom_op(c, OP_DEFINE_FIELD, prop->left->str + 1, prop->left->len - 2); 2834 } else if (prop->left->type == N_STRING) { 2835 emit_atom_op(c, OP_DEFINE_FIELD, prop->left->str ? prop->left->str : "", prop->left->len); 2836 } else if (prop->left->type == N_NUMBER) { 2837 char buf[32]; 2838 int n = snprintf(buf, sizeof(buf), "%g", prop->left->num); 2839 emit_atom_op(c, OP_DEFINE_FIELD, buf, (uint32_t)n); 2840 } else emit_atom_op(c, OP_DEFINE_FIELD, prop->left->str, prop->left->len); 2841 } 2842 } 2843} 2844 2845void compile_func_expr(sv_compiler_t *c, sv_ast_t *node) { 2846 bool has_name = node->str && node->len > 0 && !(node->flags & FN_ARROW); 2847 int name_local = -1; 2848 2849 if (has_name) { 2850 begin_scope(c); 2851 name_local = add_local(c, node->str, node->len, true, c->scope_depth); 2852 emit_op(c, OP_UNDEF); 2853 emit_put_local(c, name_local); 2854 } 2855 2856 sv_func_t *fn = compile_function_body(c, node, SV_COMPILE_SCRIPT); 2857 if (!fn) { 2858 emit_op(c, OP_UNDEF); 2859 if (has_name) end_scope(c); 2860 return; 2861 } 2862 2863 int idx = add_constant(c, mkval(T_NTARG, (uintptr_t)fn)); 2864 emit_op(c, OP_CLOSURE); 2865 emit_u32(c, (uint32_t)idx); 2866 2867 if (node->str && node->len > 0) { 2868 emit_set_function_name(c, node->str, node->len); 2869 } else if (c->inferred_name) { 2870 emit_set_function_name(c, c->inferred_name, c->inferred_name_len); 2871 c->inferred_name = NULL; 2872 c->inferred_name_len = 0; 2873 } else { 2874 emit_set_function_name(c, NULL, 0); 2875 } 2876 2877 if (has_name) { 2878 emit_op(c, OP_DUP); 2879 emit_put_local(c, name_local); 2880 end_scope(c); 2881 } 2882} 2883 2884typedef enum { 2885 DESTRUCTURE_ASSIGN = 0, 2886 DESTRUCTURE_BIND = 1, 2887} sv_destructure_mode_t; 2888 2889static void emit_build_object_rest(sv_compiler_t *c) { 2890 emit_op(c, OP_DUP); 2891 emit_op(c, OP_OBJECT); 2892 emit_op(c, OP_SWAP); 2893 emit_op(c, OP_COPY_DATA_PROPS); 2894 emit(c, 0); 2895 emit_op(c, OP_POP); 2896} 2897 2898static void emit_delete_rest_key(sv_compiler_t *c, sv_ast_t *key) { 2899 emit_op(c, OP_DUP); 2900 if (key->type == N_IDENT) { 2901 emit_constant(c, js_mkstr_permanent(c->js, key->str, key->len)); 2902 } else if (key->type == N_STRING) { 2903 emit_constant(c, ast_string_const(c, key)); 2904 } else if (key->type == N_NUMBER) { 2905 emit_number(c, key->num); 2906 } else { 2907 compile_expr(c, key); 2908 } 2909 emit_op(c, OP_DELETE); 2910 emit_op(c, OP_POP); 2911} 2912 2913static bool is_destructure_pattern_node(sv_ast_t *node) { 2914 return node && (node->type == N_ARRAY_PAT || node->type == N_ARRAY || 2915 node->type == N_OBJECT_PAT || node->type == N_OBJECT); 2916} 2917 2918static void compile_destructure_pattern(sv_compiler_t *c, sv_ast_t *pat, 2919 bool keep, bool consume_source, 2920 sv_destructure_mode_t mode, 2921 sv_var_kind_t kind); 2922 2923static void compile_destructure_store(sv_compiler_t *c, sv_ast_t *target, 2924 sv_destructure_mode_t mode, 2925 sv_var_kind_t kind) { 2926 if (!target) return; 2927 2928 if (mode == DESTRUCTURE_ASSIGN) { 2929 compile_lhs_set(c, target, false); 2930 return; 2931 } 2932 2933 if (target->type == N_IDENT) { 2934 bool is_const = (kind == SV_VAR_CONST); 2935 int idx = ensure_local_at_depth(c, target->str, target->len, 2936 is_const, c->scope_depth); 2937 emit_put_local(c, idx); 2938 return; 2939 } 2940 2941 if (is_destructure_pattern_node(target)) { 2942 compile_destructure_pattern(c, target, false, true, mode, kind); 2943 return; 2944 } 2945 2946 compile_lhs_set(c, target, false); 2947} 2948 2949static void compile_destructure_pattern( 2950 sv_compiler_t *c, sv_ast_t *pat, 2951 bool keep, bool consume_source, 2952 sv_destructure_mode_t mode, 2953 sv_var_kind_t kind 2954) { 2955 if (!pat) return; 2956 if (keep) emit_op(c, OP_DUP); 2957 2958 if (pat->type == N_ARRAY_PAT || pat->type == N_ARRAY) { 2959 if (!consume_source && !keep) emit_op(c, OP_DUP); 2960 emit_op(c, OP_DESTRUCTURE_INIT); 2961 2962 int err_local = add_local(c, "", 0, false, c->scope_depth); 2963 int try_jump = emit_jump(c, OP_TRY_PUSH); 2964 c->try_depth++; 2965 2966 for (int i = 0; i < pat->args.count; i++) { 2967 sv_ast_t *elem = pat->args.items[i]; 2968 if (!elem || elem->type == N_EMPTY) { 2969 emit_op(c, OP_DESTRUCTURE_NEXT); 2970 emit_op(c, OP_POP); 2971 continue; 2972 } 2973 2974 if (elem->type == N_REST || elem->type == N_SPREAD) { 2975 emit_op(c, OP_DESTRUCTURE_REST); 2976 compile_destructure_store(c, elem->right, mode, kind); 2977 continue; 2978 } 2979 2980 sv_ast_t *target = elem; 2981 sv_ast_t *default_val = NULL; 2982 if (elem->type == N_ASSIGN_PAT || 2983 (elem->type == N_ASSIGN && elem->op == TOK_ASSIGN)) { 2984 target = elem->left; 2985 default_val = elem->right; 2986 } 2987 2988 emit_op(c, OP_DESTRUCTURE_NEXT); 2989 2990 if (default_val) { 2991 emit_op(c, OP_DUP); 2992 emit_op(c, OP_IS_UNDEF); 2993 int skip = emit_jump(c, OP_JMP_FALSE); 2994 emit_op(c, OP_POP); 2995 compile_expr(c, default_val); 2996 patch_jump(c, skip); 2997 } 2998 2999 compile_destructure_store(c, target, mode, kind); 3000 } 3001 3002 emit_op(c, OP_TRY_POP); 3003 emit_op(c, OP_DESTRUCTURE_CLOSE); 3004 int end_jump = emit_jump(c, OP_JMP); 3005 3006 patch_jump(c, try_jump); 3007 int catch_tag = emit_jump(c, OP_CATCH); 3008 3009 emit_put_local(c, err_local); 3010 emit_op(c, OP_DESTRUCTURE_CLOSE); 3011 emit_get_local(c, err_local); 3012 emit_op(c, OP_THROW); 3013 patch_jump(c, catch_tag); 3014 patch_jump(c, end_jump); 3015 c->try_depth--; 3016 3017 return; 3018 } else if (pat->type == N_OBJECT_PAT || pat->type == N_OBJECT) { 3019 for (int i = 0; i < pat->args.count; i++) { 3020 sv_ast_t *prop = pat->args.items[i]; 3021 if (!prop) continue; 3022 3023 if (prop->type == N_REST || prop->type == N_SPREAD) { 3024 emit_build_object_rest(c); 3025 for (int j = 0; j < i; j++) { 3026 sv_ast_t *prev = pat->args.items[j]; 3027 if (!prev || prev->type != N_PROPERTY || !prev->left) continue; 3028 emit_delete_rest_key(c, prev->left); 3029 } 3030 compile_destructure_store(c, prop->right, mode, kind); 3031 continue; 3032 } 3033 if (prop->type != N_PROPERTY) continue; 3034 3035 sv_ast_t *key = prop->left; 3036 sv_ast_t *value = prop->right; 3037 sv_ast_t *default_val = NULL; 3038 if (value && (value->type == N_ASSIGN_PAT || 3039 (value->type == N_ASSIGN && value->op == TOK_ASSIGN))) { 3040 default_val = value->right; 3041 value = value->left; 3042 } 3043 3044 emit_op(c, OP_DUP); 3045 if ((prop->flags & FN_COMPUTED)) { 3046 compile_expr(c, key); 3047 emit_op(c, OP_GET_ELEM); 3048 } else if (key->type == N_IDENT) { 3049 emit_atom_op(c, OP_GET_FIELD, key->str, key->len); 3050 } else { 3051 compile_expr(c, key); 3052 emit_op(c, OP_GET_ELEM); 3053 } 3054 3055 if (default_val) { 3056 emit_op(c, OP_DUP); 3057 emit_op(c, OP_IS_UNDEF); 3058 int skip = emit_jump(c, OP_JMP_FALSE); 3059 emit_op(c, OP_POP); 3060 compile_expr(c, default_val); 3061 patch_jump(c, skip); 3062 } 3063 3064 compile_destructure_store(c, value, mode, kind); 3065 } 3066 } 3067 3068 if (consume_source) emit_op(c, OP_POP); 3069} 3070 3071void compile_array_destructure(sv_compiler_t *c, sv_ast_t *pat, bool keep) { 3072 compile_destructure_pattern(c, pat, keep, true, DESTRUCTURE_ASSIGN, SV_VAR_LET); 3073} 3074 3075void compile_object_destructure(sv_compiler_t *c, sv_ast_t *pat, bool keep) { 3076 compile_destructure_pattern(c, pat, keep, true, DESTRUCTURE_ASSIGN, SV_VAR_LET); 3077} 3078 3079static bool is_tail_callable(sv_compiler_t *c, sv_ast_t *node) { 3080 if (c->try_depth > 0) return false; 3081 if (c->using_cleanup_count > 0) return false; 3082 if (node->type != N_CALL) return false; 3083 if (call_has_spread_arg(node)) return false; 3084 3085 sv_ast_t *callee = node->left; 3086 if ( 3087 callee->type == N_IDENT && 3088 callee->len == 5 && memcmp(callee->str, "super", 5) == 0 3089 ) return false; 3090 3091 return true; 3092} 3093 3094static void emit_using_dispose_call( 3095 sv_compiler_t *c, 3096 int stack_local, 3097 int completion_local, 3098 bool is_async, 3099 bool suppressed_completion 3100) { 3101 emit_get_local(c, stack_local); 3102 if (suppressed_completion) { 3103 emit_get_local(c, completion_local); 3104 } 3105 if (is_async && suppressed_completion) emit_op(c, OP_USING_DISPOSE_ASYNC_SUPPRESSED); 3106 else if (is_async) emit_op(c, OP_USING_DISPOSE_ASYNC); 3107 else if (suppressed_completion) emit_op(c, OP_USING_DISPOSE_SUPPRESSED); 3108 else emit_op(c, OP_USING_DISPOSE); 3109 if (is_async) emit_op(c, OP_AWAIT); 3110} 3111 3112static void emit_using_cleanups_to_depth(sv_compiler_t *c, int target_depth) { 3113for (int i = c->using_cleanup_count - 1; i >= 0; i--) { 3114 sv_using_cleanup_t *cleanup = &c->using_cleanups[i]; 3115 if (cleanup->scope_depth <= target_depth) break; 3116 emit_using_dispose_call(c, cleanup->stack_local, -1, cleanup->is_async, false); 3117 emit_op(c, OP_POP); 3118}} 3119 3120static void emit_return_from_stack(sv_compiler_t *c) { 3121 emit_using_cleanups_to_depth(c, -1); 3122 emit_close_upvals(c); 3123 emit_op(c, OP_RETURN); 3124} 3125 3126static void compile_tail_call(sv_compiler_t *c, sv_ast_t *node) { 3127 sv_ast_t *callee = node->left; 3128 3129 if (callee->type == N_OPTIONAL) { 3130 compile_call(c, node); 3131 emit_return_from_stack(c); 3132 return; 3133 } 3134 3135 sv_call_kind_t kind = compile_call_setup_non_optional(c, callee); 3136 int argc = node->args.count; 3137 for (int i = 0; i < argc; i++) 3138 compile_expr(c, node->args.items[i]); 3139 3140 emit_close_upvals(c); 3141 emit_op(c, kind == SV_CALL_METHOD ? OP_TAIL_CALL_METHOD : OP_TAIL_CALL); 3142 emit_u16(c, (uint16_t)argc); 3143} 3144 3145void compile_tail_return_expr(sv_compiler_t *c, sv_ast_t *expr) { 3146 if (expr->type == N_TERNARY) { 3147 compile_truthy_test_expr(c, expr->cond); 3148 int else_jump = emit_jump(c, OP_JMP_FALSE); 3149 compile_tail_return_expr(c, expr->left); 3150 patch_jump(c, else_jump); 3151 compile_tail_return_expr(c, expr->right); 3152 return; 3153 } 3154 3155 if (expr->type == N_AWAIT && c->is_async && c->try_depth == 0 && !c->is_tla && 3156 c->using_cleanup_count == 0) { 3157 compile_expr(c, expr->right); 3158 emit_return_from_stack(c); 3159 return; 3160 } 3161 3162 if (is_tail_callable(c, expr)) { 3163 compile_tail_call(c, expr); 3164 return; 3165 } 3166 3167 compile_expr(c, expr); 3168 emit_return_from_stack(c); 3169} 3170 3171void compile_stmts(sv_compiler_t *c, sv_ast_list_t *list) { 3172 for (int i = 0; i < list->count; i++) compile_stmt(c, list->items[i]); 3173} 3174 3175static bool stmt_list_has_using_decl(sv_ast_list_t *list, bool *has_await_using) { 3176 bool found = false; 3177 for (int i = 0; i < list->count; i++) { 3178 sv_ast_t *node = list->items[i]; 3179 if (!node) continue; 3180 3181 sv_ast_t *decl = (node->type == N_EXPORT) ? node->left : node; 3182 if (!decl || decl->type != N_VAR) continue; 3183 3184 if (decl->var_kind == SV_VAR_USING || decl->var_kind == SV_VAR_AWAIT_USING) { 3185 if (decl->var_kind == SV_VAR_AWAIT_USING && has_await_using) *has_await_using = true; 3186 found = true; 3187 } 3188 } 3189 3190 return found; 3191} 3192 3193static void emit_empty_disposal_stack(sv_compiler_t *c) { 3194 emit_op(c, OP_ARRAY); 3195 emit_u16(c, 0); 3196} 3197 3198static void emit_using_push(sv_compiler_t *c, bool is_async) { 3199 emit_op(c, is_async ? OP_USING_PUSH_ASYNC : OP_USING_PUSH); 3200} 3201 3202static void pop_using_cleanup(sv_compiler_t *c) { 3203 if (c->using_cleanup_count > 0) c->using_cleanup_count--; 3204} 3205 3206static void emit_dispose_resource(sv_compiler_t *c, bool is_async) { 3207 emit_op(c, is_async ? OP_DISPOSE_RESOURCE_ASYNC : OP_DISPOSE_RESOURCE); 3208 if (is_async) emit_op(c, OP_AWAIT); 3209} 3210 3211static void push_using_cleanup( 3212 sv_compiler_t *c, 3213 int stack_local, 3214 int scope_depth, 3215 bool is_async 3216) { 3217 if (c->using_cleanup_count >= c->using_cleanup_cap) { 3218 int cap = c->using_cleanup_cap ? c->using_cleanup_cap * 2 : 4; 3219 c->using_cleanups = realloc(c->using_cleanups, (size_t)cap * sizeof(sv_using_cleanup_t)); 3220 c->using_cleanup_cap = cap; 3221 } 3222 3223 c->using_cleanups[c->using_cleanup_count++] = (sv_using_cleanup_t){ 3224 .stack_local = stack_local, 3225 .scope_depth = scope_depth, 3226 .is_async = is_async, 3227 }; 3228} 3229 3230static void compile_block_with_using(sv_compiler_t *c, sv_ast_t *node) { 3231 bool has_await_using = false; 3232 bool has_using = stmt_list_has_using_decl(&node->args, &has_await_using); 3233 3234 begin_scope(c); 3235 hoist_lexical_decls(c, &node->args); 3236 hoist_func_decls(c, &node->args); 3237 3238 if (!has_using) { 3239 compile_stmts(c, &node->args); 3240 end_scope(c); 3241 return; 3242 } 3243 3244 emit_empty_disposal_stack(c); 3245 int stack_local = add_local(c, "", 0, false, c->scope_depth); 3246 3247 emit_put_local(c, stack_local); 3248 int err_local = add_local(c, "", 0, false, c->scope_depth); 3249 3250 int old_using_stack = c->using_stack_local; 3251 bool old_using_async = c->using_stack_async; 3252 3253 c->using_stack_local = stack_local; 3254 c->using_stack_async = has_await_using; 3255 push_using_cleanup(c, stack_local, c->scope_depth, has_await_using); 3256 3257 c->try_depth++; 3258 int try_jump = emit_jump(c, OP_TRY_PUSH); 3259 compile_stmts(c, &node->args); 3260 emit_op(c, OP_TRY_POP); 3261 c->try_depth--; 3262 3263 emit_using_dispose_call(c, stack_local, -1, has_await_using, false); 3264 emit_op(c, OP_POP); 3265 int end_jump = emit_jump(c, OP_JMP); 3266 3267 patch_jump(c, try_jump); 3268 int catch_tag = emit_jump(c, OP_CATCH); 3269 3270 emit_put_local(c, err_local); 3271 emit_using_dispose_call(c, stack_local, err_local, has_await_using, true); 3272 3273 if (!has_await_using) emit_op(c, OP_THROW); 3274 patch_jump(c, catch_tag); 3275 patch_jump(c, end_jump); 3276 3277 c->using_stack_local = old_using_stack; 3278 c->using_stack_async = old_using_async; 3279 3280 pop_using_cleanup(c); 3281 end_scope(c); 3282} 3283 3284void compile_stmt(sv_compiler_t *c, sv_ast_t *node) { 3285 if (!node) return; 3286 emit_srcpos(c, node); 3287 3288 switch (node->type) { 3289 case N_EMPTY: 3290 case N_DEBUGGER: 3291 break; 3292 3293 case N_BLOCK: 3294 compile_block_with_using(c, node); 3295 break; 3296 3297 case N_VAR: 3298 compile_var_decl(c, node); 3299 break; 3300 3301 case N_IMPORT_DECL: 3302 compile_import_decl(c, node); 3303 break; 3304 3305 case N_EXPORT: 3306 compile_export_decl(c, node); 3307 break; 3308 3309 case N_IF: 3310 compile_if(c, node); 3311 break; 3312 3313 case N_WHILE: 3314 compile_while(c, node); 3315 break; 3316 3317 case N_DO_WHILE: 3318 compile_do_while(c, node); 3319 break; 3320 3321 case N_FOR: 3322 compile_for(c, node); 3323 break; 3324 3325 case N_FOR_IN: 3326 compile_for_in(c, node); 3327 break; 3328 3329 case N_FOR_OF: 3330 compile_for_of(c, node); 3331 break; 3332 3333 case N_FOR_AWAIT_OF: 3334 if (c->enclosing && !c->enclosing->enclosing) c->is_tla = true; 3335 compile_for_of(c, node); 3336 break; 3337 3338 case N_RETURN: 3339 if (node->right) { 3340 compile_tail_return_expr(c, node->right); 3341 } else { 3342 emit_op(c, OP_UNDEF); 3343 emit_return_from_stack(c); 3344 } 3345 break; 3346 3347 case N_THROW: 3348 compile_expr(c, node->right); 3349 emit_op(c, OP_THROW); 3350 break; 3351 3352 case N_BREAK: 3353 compile_break(c, node); 3354 break; 3355 3356 case N_CONTINUE: 3357 compile_continue(c, node); 3358 break; 3359 3360 case N_TRY: 3361 compile_try(c, node); 3362 break; 3363 3364 case N_SWITCH: 3365 compile_switch(c, node); 3366 break; 3367 3368 case N_LABEL: 3369 compile_label(c, node); 3370 break; 3371 3372 case N_ASSIGN: 3373 if (!has_completion_accumulator(c) && compile_self_append_stmt(c, node)) break; 3374 compile_expr(c, node); 3375 emit_set_completion_from_stack(c); 3376 break; 3377 3378 case N_FUNC: 3379 if (node->str && !(node->flags & (FN_ARROW | FN_PAREN))) break; 3380 compile_expr(c, node); 3381 emit_set_completion_from_stack(c); 3382 break; 3383 3384 case N_CLASS: 3385 compile_class(c, node); 3386 if (node->flags & FN_PAREN) emit_set_completion_from_stack(c); 3387 else emit_op(c, OP_POP); 3388 break; 3389 3390 case N_WITH: 3391 emit_set_completion_undefined(c); 3392 compile_expr(c, node->left); 3393 emit_op(c, OP_ENTER_WITH); 3394 c->with_depth++; 3395 compile_stmt(c, node->body); 3396 c->with_depth--; 3397 emit_op(c, OP_EXIT_WITH); 3398 break; 3399 3400 default: 3401 compile_expr(c, node); 3402 emit_set_completion_from_stack(c); 3403 break; 3404 } 3405} 3406 3407enum { 3408 IMPORT_BIND_DEFAULT = 1 << 0, 3409 IMPORT_BIND_NAMESPACE = 1 << 1, 3410}; 3411 3412void compile_import_decl(sv_compiler_t *c, sv_ast_t *node) { 3413 if (!node->right) return; 3414 bool repl_top = is_repl_top_level(c); 3415 3416 compile_expr(c, node->right); 3417 emit_op(c, OP_IMPORT_SYNC); 3418 3419 if (node->args.count == 0) { 3420 emit_op(c, OP_POP); 3421 return; 3422 } 3423 3424 int ns_local = add_local(c, "", 0, false, c->scope_depth); 3425 emit_put_local(c, ns_local); 3426 3427 for (int i = 0; i < node->args.count; i++) { 3428 sv_ast_t *spec = node->args.items[i]; 3429 if (!spec || spec->type != N_IMPORT_SPEC || 3430 !spec->right || spec->right->type != N_IDENT) 3431 continue; 3432 3433 emit_get_local(c, ns_local); 3434 3435 if (!(spec->flags & IMPORT_BIND_NAMESPACE)) { 3436 if ((spec->flags & IMPORT_BIND_DEFAULT) || 3437 !spec->left || spec->left->type != N_IDENT) { 3438 emit_op(c, OP_IMPORT_DEFAULT); 3439 } else { 3440 emit_atom_op(c, OP_IMPORT_NAMED, spec->left->str, spec->left->len); 3441 } 3442 } 3443 3444 if (repl_top) { 3445 emit_atom_op(c, OP_PUT_GLOBAL, spec->right->str, spec->right->len); 3446 } else { 3447 int idx = ensure_local_at_depth(c, spec->right->str, spec->right->len, 3448 true, c->scope_depth); 3449 emit_put_local(c, idx); 3450 } 3451 } 3452} 3453 3454static void compile_export_emit(sv_compiler_t *c, const char *name, uint32_t len) { 3455 emit_get_var(c, name, len); 3456 emit_atom_op(c, OP_EXPORT, name, len); 3457} 3458 3459static void defer_export(sv_compiler_t *c, const char *name, uint32_t len) { 3460 if (c->deferred_export_count >= c->deferred_export_cap) { 3461 int cap = c->deferred_export_cap ? c->deferred_export_cap * 2 : 8; 3462 c->deferred_exports = realloc(c->deferred_exports, cap * sizeof(sv_deferred_export_t)); 3463 c->deferred_export_cap = cap; 3464 } 3465 c->deferred_exports[c->deferred_export_count++] = 3466 (sv_deferred_export_t){ .name = name, .len = len }; 3467} 3468 3469static void defer_export_pattern(sv_compiler_t *c, sv_ast_t *pat) { 3470 if (!pat) return; 3471 switch (pat->type) { 3472 case N_IDENT: 3473 defer_export(c, pat->str, pat->len); 3474 break; 3475 case N_ASSIGN_PAT: 3476 defer_export_pattern(c, pat->left); 3477 break; 3478 case N_REST: 3479 case N_SPREAD: 3480 defer_export_pattern(c, pat->right); 3481 break; 3482 case N_ARRAY: 3483 case N_ARRAY_PAT: 3484 for (int i = 0; i < pat->args.count; i++) 3485 defer_export_pattern(c, pat->args.items[i]); 3486 break; 3487 case N_OBJECT: 3488 case N_OBJECT_PAT: 3489 for (int i = 0; i < pat->args.count; i++) { 3490 sv_ast_t *prop = pat->args.items[i]; 3491 if (!prop) continue; 3492 if (prop->type == N_PROPERTY) defer_export_pattern(c, prop->right); 3493 else defer_export_pattern(c, prop); 3494 } 3495 break; 3496 default: 3497 break; 3498 } 3499} 3500 3501static void compile_export_pattern(sv_compiler_t *c, sv_ast_t *pat) { 3502 if (!pat) return; 3503 switch (pat->type) { 3504 case N_IDENT: 3505 compile_export_emit(c, pat->str, pat->len); 3506 break; 3507 case N_ASSIGN_PAT: 3508 compile_export_pattern(c, pat->left); 3509 break; 3510 case N_REST: 3511 case N_SPREAD: 3512 compile_export_pattern(c, pat->right); 3513 break; 3514 case N_ARRAY: 3515 case N_ARRAY_PAT: 3516 for (int i = 0; i < pat->args.count; i++) 3517 compile_export_pattern(c, pat->args.items[i]); 3518 break; 3519 case N_OBJECT: 3520 case N_OBJECT_PAT: 3521 for (int i = 0; i < pat->args.count; i++) { 3522 sv_ast_t *prop = pat->args.items[i]; 3523 if (!prop) continue; 3524 if (prop->type == N_PROPERTY) compile_export_pattern(c, prop->right); 3525 else compile_export_pattern(c, prop); 3526 } 3527 break; 3528 default: 3529 break; 3530 } 3531} 3532 3533void compile_export_decl(sv_compiler_t *c, sv_ast_t *node) { 3534 if (!node) return; 3535 3536 if (node->flags & EX_DEFAULT) { 3537 if (node->left) compile_expr(c, node->left); 3538 else emit_op(c, OP_UNDEF); 3539 emit_atom_op(c, OP_EXPORT, "default", 7); 3540 return; 3541 } 3542 3543 if ((node->flags & EX_DECL) && node->left) { 3544 sv_ast_t *decl = node->left; 3545 if (decl->type == N_VAR) { 3546 compile_var_decl(c, decl); 3547 bool is_var = decl->var_kind == SV_VAR_VAR; 3548 for (int i = 0; i < decl->args.count; i++) { 3549 sv_ast_t *var = decl->args.items[i]; 3550 if (!var || var->type != N_VARDECL) continue; 3551 if (is_var && c->mode == SV_COMPILE_MODULE) 3552 defer_export_pattern(c, var->left); 3553 else 3554 compile_export_pattern(c, var->left); 3555 } 3556 return; 3557 } 3558 3559 compile_stmt(c, decl); 3560 if ((decl->type == N_FUNC || decl->type == N_CLASS) && 3561 decl->str && decl->len > 0) { 3562 compile_export_emit(c, decl->str, decl->len); 3563 } 3564 return; 3565 } 3566 3567 if ((node->flags & EX_STAR) && (node->flags & EX_FROM) && node->right) { 3568 compile_expr(c, node->right); 3569 emit_op(c, OP_IMPORT_SYNC); 3570 3571 if (node->flags & EX_NAMESPACE) { 3572 if (node->args.count > 0) { 3573 sv_ast_t *spec = node->args.items[0]; 3574 if (spec && spec->type == N_IMPORT_SPEC && 3575 spec->right && spec->right->type == N_IDENT) { 3576 emit_atom_op(c, OP_EXPORT, spec->right->str, spec->right->len); 3577 return; 3578 } 3579 } 3580 emit_op(c, OP_POP); 3581 return; 3582 } 3583 3584 emit_op(c, OP_EXPORT_ALL); 3585 return; 3586 } 3587 3588 if (!(node->flags & EX_NAMED) || node->args.count == 0) return; 3589 3590 int ns_local = -1; 3591 if (node->flags & EX_FROM) { 3592 if (!node->right) return; 3593 compile_expr(c, node->right); 3594 emit_op(c, OP_IMPORT_SYNC); 3595 ns_local = add_local(c, "", 0, false, c->scope_depth); 3596 emit_put_local(c, ns_local); 3597 } 3598 3599 for (int i = 0; i < node->args.count; i++) { 3600 sv_ast_t *spec = node->args.items[i]; 3601 if (!spec || spec->type != N_IMPORT_SPEC || !spec->left || !spec->right || 3602 spec->left->type != N_IDENT || spec->right->type != N_IDENT) 3603 continue; 3604 3605 if (node->flags & EX_FROM) { 3606 emit_get_local(c, ns_local); 3607 if (spec->left->len == 7 && memcmp(spec->left->str, "default", 7) == 0) 3608 emit_op(c, OP_IMPORT_DEFAULT); 3609 else 3610 emit_atom_op(c, OP_IMPORT_NAMED, spec->left->str, spec->left->len); 3611 emit_atom_op(c, OP_EXPORT, spec->right->str, spec->right->len); 3612 } else { 3613 emit_get_var(c, spec->left->str, spec->left->len); 3614 emit_atom_op(c, OP_EXPORT, spec->right->str, spec->right->len); 3615 } 3616 } 3617} 3618 3619void compile_var_decl(sv_compiler_t *c, sv_ast_t *node) { 3620 sv_var_kind_t kind = node->var_kind; 3621 3622 bool is_using = (kind == SV_VAR_USING || kind == SV_VAR_AWAIT_USING); 3623 bool is_await_using = (kind == SV_VAR_AWAIT_USING); 3624 bool is_const = (kind == SV_VAR_CONST || is_using); 3625 bool repl_top = is_repl_top_level(c); 3626 3627 for (int i = 0; i < node->args.count; i++) { 3628 sv_ast_t *decl = node->args.items[i]; 3629 if (decl->type != N_VARDECL) continue; 3630 sv_ast_t *target = decl->left; 3631 3632 if (repl_top) { 3633 if (!decl->right && kind == SV_VAR_VAR) continue; 3634 if (decl->right) { 3635 if (target->type == N_IDENT) 3636 compile_expr_with_inferred_name(c, decl->right, target->str, target->len); 3637 else compile_expr(c, decl->right); 3638 } else emit_op(c, OP_UNDEF); 3639 if (target->type == N_IDENT) { 3640 emit_atom_op(c, OP_PUT_GLOBAL, target->str, target->len); 3641 } else compile_destructure_pattern(c, target, false, true, DESTRUCTURE_ASSIGN, kind); 3642 } else if (kind == SV_VAR_VAR) { 3643 if (decl->right) { 3644 uint8_t init_type = infer_expr_type(c, decl->right); 3645 if (target->type == N_IDENT) 3646 compile_expr_with_inferred_name(c, decl->right, target->str, target->len); 3647 else compile_expr(c, decl->right); 3648 if (target->type == N_IDENT) { 3649 int idx = resolve_local(c, target->str, target->len); 3650 if (idx >= 0 && c->locals[idx].depth != -1) 3651 emit_put_local_typed(c, idx, init_type); 3652 else compile_lhs_set(c, target, false); 3653 } else compile_lhs_set(c, target, false); 3654 } 3655 } else { 3656 if (target->type == N_IDENT) { 3657 int idx = ensure_local_at_depth(c, target->str, target->len, is_const, c->scope_depth); 3658 uint8_t init_type = SV_TI_UNKNOWN; 3659 if (decl->right) { 3660 init_type = infer_expr_type(c, decl->right); 3661 compile_expr_with_inferred_name(c, decl->right, target->str, target->len); 3662 } else if (!is_const) { 3663 emit_op(c, OP_UNDEF); 3664 init_type = SV_TI_UNDEF; 3665 } 3666 if (decl->right || !is_const) { 3667 emit_put_local_typed(c, idx, init_type); 3668 c->locals[idx].is_tdz = false; 3669 if (is_using) { 3670 if (c->using_stack_local >= 0) { 3671 emit_get_local(c, c->using_stack_local); 3672 emit_get_local(c, idx); 3673 emit_using_push(c, is_await_using); 3674 } else { 3675 emit_get_local(c, idx); 3676 emit_dispose_resource(c, is_await_using); 3677 } 3678 emit_op(c, OP_POP); 3679 } 3680 } 3681 } else { 3682 if (decl->right) { 3683 compile_expr(c, decl->right); 3684 compile_destructure_binding(c, target, kind); 3685 emit_op(c, OP_POP); 3686 } 3687 } 3688 } 3689 } 3690} 3691 3692void compile_destructure_binding(sv_compiler_t *c, sv_ast_t *pat, sv_var_kind_t kind) { 3693 compile_destructure_pattern(c, pat, false, false, DESTRUCTURE_BIND, kind); 3694} 3695 3696static bool fold_static_typeof_compare( 3697 sv_compiler_t *c, sv_ast_t *cond, bool *out_truth 3698) { 3699 if (!cond || cond->type != N_BINARY) return false; 3700 if (!(cond->op == TOK_SEQ || cond->op == TOK_SNE || 3701 cond->op == TOK_EQ || cond->op == TOK_NE)) 3702 return false; 3703 3704 sv_ast_t *typeof_node = NULL; 3705 sv_ast_t *str_node = NULL; 3706 if (cond->left && cond->left->type == N_TYPEOF && 3707 cond->right && cond->right->type == N_STRING) { 3708 typeof_node = cond->left; 3709 str_node = cond->right; 3710 } else if (cond->right && cond->right->type == N_TYPEOF && 3711 cond->left && cond->left->type == N_STRING) { 3712 typeof_node = cond->right; 3713 str_node = cond->left; 3714 } else return false; 3715 3716 if (!typeof_node->right || typeof_node->right->type != N_IDENT) return false; 3717 sv_ast_t *ident = typeof_node->right; 3718 int local = resolve_local(c, ident->str, ident->len); 3719 if (local < 0) return false; 3720 const char *known = typeof_name_for_type(get_local_inferred_type(c, local)); 3721 if (!known) return false; 3722 3723 bool is_equal = (strlen(known) == str_node->len && 3724 memcmp(known, str_node->str, str_node->len) == 0); 3725 bool truth = (cond->op == TOK_SEQ || cond->op == TOK_EQ) ? is_equal : !is_equal; 3726 *out_truth = truth; 3727 return true; 3728} 3729 3730void compile_if(sv_compiler_t *c, sv_ast_t *node) { 3731 emit_set_completion_undefined(c); 3732 3733 bool folded_truth = false; 3734 if (fold_static_typeof_compare(c, node->cond, &folded_truth)) { 3735 if (folded_truth) compile_stmt(c, node->left); 3736 else if (node->right) compile_stmt(c, node->right); 3737 return; 3738 } 3739 3740 compile_truthy_test_expr(c, node->cond); 3741 int else_jump = emit_jump(c, OP_JMP_FALSE); 3742 compile_stmt(c, node->left); 3743 if (node->right) { 3744 int end_jump = emit_jump(c, OP_JMP); 3745 patch_jump(c, else_jump); 3746 compile_stmt(c, node->right); 3747 patch_jump(c, end_jump); 3748 } else { 3749 patch_jump(c, else_jump); 3750 } 3751} 3752 3753void compile_while(sv_compiler_t *c, sv_ast_t *node) { 3754 emit_set_completion_undefined(c); 3755 3756 int loop_start = c->code_len; 3757 push_loop(c, loop_start, NULL, 0, false); 3758 3759 compile_truthy_test_expr(c, node->cond); 3760 int exit_jump = emit_jump(c, OP_JMP_FALSE); 3761 compile_stmt(c, node->body); 3762 3763 sv_loop_t *loop = &c->loops[c->loop_count - 1]; 3764 for (int i = 0; i < loop->continues.count; i++) 3765 patch_jump(c, loop->continues.offsets[i]); 3766 3767 emit_loop(c, loop_start); 3768 patch_jump(c, exit_jump); 3769 pop_loop(c); 3770} 3771 3772void compile_do_while(sv_compiler_t *c, sv_ast_t *node) { 3773 emit_set_completion_undefined(c); 3774 3775 int loop_start = c->code_len; 3776 push_loop(c, loop_start, NULL, 0, false); 3777 compile_stmt(c, node->body); 3778 3779 sv_loop_t *loop = &c->loops[c->loop_count - 1]; 3780 for (int i = 0; i < loop->continues.count; i++) 3781 patch_jump(c, loop->continues.offsets[i]); 3782 3783 compile_truthy_test_expr(c, node->cond); 3784 int exit_jump = emit_jump(c, OP_JMP_FALSE); 3785 emit_loop(c, loop_start); 3786 patch_jump(c, exit_jump); 3787 pop_loop(c); 3788} 3789 3790static void for_add_slot_unique(int **slots, int *count, int *cap, int slot) { 3791 if (slot < 0) return; 3792 for (int i = 0; i < *count; i++) { 3793 if ((*slots)[i] == slot) return; 3794 } 3795 if (*count >= *cap) { 3796 int new_cap = (*cap > 0) ? (*cap * 2) : 8; 3797 int *new_slots = realloc(*slots, (size_t)new_cap * sizeof(int)); 3798 if (!new_slots) return; 3799 *slots = new_slots; 3800 *cap = new_cap; 3801 } 3802 (*slots)[(*count)++] = slot; 3803} 3804 3805static void for_collect_pattern_slots(sv_compiler_t *c, sv_ast_t *pat, int **slots, int *count, int *cap) { 3806 if (!pat) return; 3807 switch (pat->type) { 3808 case N_IDENT: { 3809 int slot = resolve_local(c, pat->str, pat->len); 3810 for_add_slot_unique(slots, count, cap, slot); 3811 break; 3812 } 3813 case N_ASSIGN_PAT: 3814 case N_ASSIGN: 3815 for_collect_pattern_slots(c, pat->left, slots, count, cap); 3816 break; 3817 case N_REST: 3818 case N_SPREAD: 3819 for_collect_pattern_slots(c, pat->right, slots, count, cap); 3820 break; 3821 case N_ARRAY: 3822 case N_ARRAY_PAT: 3823 for (int i = 0; i < pat->args.count; i++) 3824 for_collect_pattern_slots(c, pat->args.items[i], slots, count, cap); 3825 break; 3826 case N_OBJECT: 3827 case N_OBJECT_PAT: 3828 for (int i = 0; i < pat->args.count; i++) { 3829 sv_ast_t *prop = pat->args.items[i]; 3830 if (!prop) continue; 3831 if (prop->type == N_PROPERTY) 3832 for_collect_pattern_slots(c, prop->right, slots, count, cap); 3833 else 3834 for_collect_pattern_slots(c, prop, slots, count, cap); 3835 } 3836 break; 3837 default: 3838 break; 3839 } 3840} 3841 3842static void for_collect_var_decl_slots(sv_compiler_t *c, sv_ast_t *init_var, int **slots, int *count, int *cap) { 3843 if (!init_var || init_var->type != N_VAR) return; 3844 for (int i = 0; i < init_var->args.count; i++) { 3845 sv_ast_t *decl = init_var->args.items[i]; 3846 if (!decl || decl->type != N_VARDECL || !decl->left) continue; 3847 for_collect_pattern_slots(c, decl->left, slots, count, cap); 3848 } 3849} 3850 3851void compile_for(sv_compiler_t *c, sv_ast_t *node) { 3852 emit_set_completion_undefined(c); 3853 begin_scope(c); 3854 3855 int *iter_slots = NULL; 3856 int iter_count = 0; 3857 int iter_cap = 0; 3858 3859 if (node->init) { 3860 if (node->init->type == N_VAR) { 3861 sv_var_kind_t kind = node->init->var_kind; 3862 compile_var_decl(c, node->init); 3863 if (kind == SV_VAR_LET || kind == SV_VAR_CONST) 3864 for_collect_var_decl_slots(c, node->init, &iter_slots, &iter_count, &iter_cap); 3865 } else { 3866 compile_expr(c, node->init); 3867 emit_op(c, OP_POP); 3868 } 3869 } 3870 3871 int loop_start = c->code_len; 3872 push_loop(c, loop_start, NULL, 0, false); 3873 3874 int exit_jump = -1; 3875 if (node->cond) { 3876 compile_truthy_test_expr(c, node->cond); 3877 exit_jump = emit_jump(c, OP_JMP_FALSE); 3878 } 3879 3880 int iter_inner_start = -1; 3881 if (iter_count > 0) { 3882 begin_scope(c); 3883 iter_inner_start = c->local_count; 3884 for (int i = 0; i < iter_count; i++) { 3885 int outer_idx = iter_slots[i]; 3886 sv_local_t outer = c->locals[outer_idx]; 3887 emit_get_local(c, outer_idx); 3888 int inner_idx = add_local(c, outer.name, outer.name_len, outer.is_const, c->scope_depth); 3889 emit_put_local(c, inner_idx); 3890 }} 3891 3892 compile_stmt(c, node->body); 3893 sv_loop_t *loop = &c->loops[c->loop_count - 1]; 3894 for (int i = 0; i < loop->continues.count; i++) 3895 patch_jump(c, loop->continues.offsets[i]); 3896 3897 int break_close_slot = -1; 3898 if (iter_count > 0) { 3899 for (int i = 0; i < iter_count; i++) { 3900 int inner_idx = iter_inner_start + i; 3901 if (!c->locals[inner_idx].captured) continue; 3902 int slot = local_to_frame_slot(c, inner_idx); 3903 if (break_close_slot < 0 || slot < break_close_slot) 3904 break_close_slot = slot; 3905 } 3906 3907 for (int i = 0; i < iter_count; i++) { 3908 emit_get_local(c, iter_inner_start + i); 3909 emit_put_local(c, iter_slots[i]); 3910 } 3911 end_scope(c); 3912 } 3913 3914 if (node->update) { 3915 sv_ast_t *upd = node->update; 3916 int slot; 3917 if (upd->type == N_UPDATE && upd->right && upd->right->type == N_IDENT && 3918 (slot = resolve_local_slot(c, upd->right->str, upd->right->len)) >= 0) { 3919 emit_op(c, upd->op == TOK_POSTINC ? OP_INC_LOCAL : OP_DEC_LOCAL); 3920 emit(c, (uint8_t)slot); 3921 set_local_inferred_type(c, c->param_locals + slot, SV_TI_UNKNOWN); 3922 } else { 3923 compile_expr(c, upd); 3924 emit_op(c, OP_POP); 3925 } 3926 } 3927 3928 emit_loop(c, loop_start); 3929 if (exit_jump >= 0) patch_jump(c, exit_jump); 3930 3931 int skip_break_cleanup = -1; 3932 if (break_close_slot >= 0) 3933 skip_break_cleanup = emit_jump(c, OP_JMP); 3934 3935 pop_loop(c); 3936 3937 if (break_close_slot >= 0) { 3938 emit_op(c, OP_CLOSE_UPVAL); 3939 emit_u16(c, (uint16_t)break_close_slot); 3940 patch_jump(c, skip_break_cleanup); 3941 } 3942 3943 free(iter_slots); 3944 end_scope(c); 3945} 3946 3947 3948static void compile_for_each(sv_compiler_t *c, sv_ast_t *node, bool is_for_of); 3949 3950void compile_for_in(sv_compiler_t *c, sv_ast_t *node) { 3951 compile_for_each(c, node, false); 3952} 3953 3954 3955void compile_for_of(sv_compiler_t *c, sv_ast_t *node) { 3956 compile_for_each(c, node, true); 3957} 3958 3959static void compile_for_each_assign_target(sv_compiler_t *c, sv_ast_t *lhs) { 3960 if (!lhs) return; 3961 if (lhs->type == N_VAR && lhs->args.count > 0) { 3962 sv_ast_t *decl = lhs->args.items[0]; 3963 sv_ast_t *target = decl->left ? decl->left : decl; 3964 if (target->type == N_IDENT) { 3965 int loc = resolve_local(c, target->str, target->len); 3966 if (loc == -1) { 3967 bool is_const = (lhs->var_kind == SV_VAR_CONST || 3968 lhs->var_kind == SV_VAR_USING || 3969 lhs->var_kind == SV_VAR_AWAIT_USING); 3970 loc = add_local(c, target->str, target->len, is_const, c->scope_depth); 3971 } 3972 emit_put_local(c, loc); 3973 } else { 3974 if (lhs->var_kind == SV_VAR_VAR) { 3975 compile_lhs_set(c, target, false); 3976 } else { 3977 compile_destructure_binding(c, target, lhs->var_kind); 3978 emit_op(c, OP_POP); 3979 } 3980 } 3981 return; 3982 } 3983 if (lhs->type == N_IDENT) { 3984 emit_set_var(c, lhs->str, lhs->len, false); 3985 return; 3986 } 3987 compile_lhs_set(c, lhs, false); 3988} 3989 3990static void compile_using_dispose_target(sv_compiler_t *c, sv_ast_t *lhs) { 3991 if (!lhs || lhs->type != N_VAR) return; 3992 bool is_await_using = lhs->var_kind == SV_VAR_AWAIT_USING; 3993 if (lhs->var_kind != SV_VAR_USING && !is_await_using) return; 3994 if (lhs->args.count == 0) return; 3995 3996 sv_ast_t *decl = lhs->args.items[0]; 3997 if (!decl || decl->type != N_VARDECL || !decl->left || decl->left->type != N_IDENT) return; 3998 3999 emit_get_var(c, decl->left->str, decl->left->len); 4000 emit_dispose_resource(c, is_await_using); 4001 emit_op(c, OP_POP); 4002} 4003 4004static bool compile_using_push_target(sv_compiler_t *c, sv_ast_t *lhs, int stack_local) { 4005 if (!lhs || lhs->type != N_VAR) return false; 4006 bool is_await_using = lhs->var_kind == SV_VAR_AWAIT_USING; 4007 if (lhs->var_kind != SV_VAR_USING && !is_await_using) return false; 4008 if (lhs->args.count == 0) return false; 4009 4010 sv_ast_t *decl = lhs->args.items[0]; 4011 if (!decl || decl->type != N_VARDECL || !decl->left || decl->left->type != N_IDENT) return false; 4012 4013 emit_get_local(c, stack_local); 4014 emit_get_var(c, decl->left->str, decl->left->len); 4015 emit_using_push(c, is_await_using); 4016 emit_op(c, OP_POP); 4017 4018 return true; 4019} 4020 4021static void compile_for_each(sv_compiler_t *c, sv_ast_t *node, bool is_for_of) { 4022 emit_set_completion_undefined(c); 4023 begin_scope(c); 4024 4025 int *iter_slots = NULL; 4026 int iter_count = 0; 4027 int iter_cap = 0; 4028 4029 if (node->left && node->left->type == N_VAR && 4030 node->left->var_kind != SV_VAR_VAR) { 4031 bool is_const = 4032 (node->left->var_kind == SV_VAR_CONST || 4033 node->left->var_kind == SV_VAR_USING || 4034 node->left->var_kind == SV_VAR_AWAIT_USING); 4035 int lb = c->local_count; 4036 for (int i = 0; i < node->left->args.count; i++) { 4037 sv_ast_t *decl = node->left->args.items[i]; 4038 if (!decl || decl->type != N_VARDECL || !decl->left) continue; 4039 hoist_lexical_pattern(c, decl->left, is_const); 4040 } 4041 for (int i = lb; i < c->local_count; i++) { 4042 c->locals[i].is_tdz = true; 4043 set_local_inferred_type(c, i, SV_TI_UNKNOWN); 4044 int slot = i - c->param_locals; 4045 emit_op(c, OP_SET_LOCAL_UNDEF); 4046 emit_u16(c, (uint16_t)slot); 4047 } 4048 for_collect_var_decl_slots(c, node->left, &iter_slots, &iter_count, &iter_cap); 4049 } 4050 4051 if (!is_for_of && node->left && node->left->type == N_VAR && 4052 node->left->var_kind == SV_VAR_VAR && node->left->args.count > 0) { 4053 sv_ast_t *decl = node->left->args.items[0]; 4054 if (decl && decl->right) { 4055 compile_expr(c, decl->right); 4056 sv_ast_t *target = decl->left ? decl->left : decl; 4057 if (target->type == N_IDENT) { 4058 int loc = resolve_local(c, target->str, target->len); 4059 if (loc == -1) 4060 loc = add_local(c, target->str, target->len, false, c->scope_depth); 4061 emit_put_local(c, loc); 4062 } else { 4063 compile_lhs_set(c, target, false); 4064 } 4065 } 4066 } 4067 4068 int iter_local = -1; 4069 int idx_local = -1; 4070 int exit_jump = -1; 4071 int try_jump_for_of = -1; 4072 int iter_err_local = -1; 4073 int break_close_slot = -1; 4074 int iter_inner_start = -1; 4075 int using_stack_local = -1; 4076 4077 bool is_for_await = (node->type == N_FOR_AWAIT_OF); 4078 bool is_using_loop = node->left && node->left->type == N_VAR && 4079 (node->left->var_kind == SV_VAR_USING || node->left->var_kind == SV_VAR_AWAIT_USING); 4080 bool is_await_using_loop = is_using_loop && node->left->var_kind == SV_VAR_AWAIT_USING; 4081 int old_using_stack = c->using_stack_local; 4082 bool old_using_async = c->using_stack_async; 4083 uint8_t iter_hint = 0; 4084 if (is_for_of && !is_for_await) 4085 iter_hint = iter_hint_for_type(infer_expr_type(c, node->right)); 4086 4087 if (is_using_loop) { 4088 emit_empty_disposal_stack(c); 4089 using_stack_local = add_local(c, "", 0, false, c->scope_depth); 4090 emit_put_local(c, using_stack_local); 4091 } 4092 4093 compile_expr(c, node->right); 4094 if (is_for_of) { 4095 emit_op(c, is_for_await ? OP_FOR_AWAIT_OF : OP_FOR_OF); 4096 iter_err_local = add_local(c, "", 0, false, c->scope_depth); 4097 try_jump_for_of = emit_jump(c, OP_TRY_PUSH); 4098 c->try_depth++; 4099 } else { 4100 emit_op(c, OP_FOR_IN); 4101 iter_local = add_local(c, "", 0, false, c->scope_depth); 4102 emit_put_local(c, iter_local); 4103 4104 emit_number(c, 0); 4105 idx_local = add_local(c, "", 0, false, c->scope_depth); 4106 emit_put_local(c, idx_local); 4107 } 4108 4109 int loop_start = c->code_len; 4110 push_loop(c, loop_start, NULL, 0, false); 4111 4112 if (is_using_loop) { 4113 emit_empty_disposal_stack(c); 4114 emit_put_local(c, using_stack_local); 4115 } 4116 4117 if (is_for_of) { 4118 if (is_for_await) { 4119 emit_op(c, OP_AWAIT_ITER_NEXT); 4120 } else { 4121 emit_op(c, OP_ITER_NEXT); 4122 emit(c, iter_hint); 4123 } 4124 exit_jump = emit_jump(c, OP_JMP_TRUE); 4125 } else { 4126 emit_get_local(c, idx_local); 4127 emit_get_local(c, iter_local); 4128 emit_op(c, OP_GET_LENGTH); 4129 emit_op(c, OP_LT); 4130 exit_jump = emit_jump(c, OP_JMP_FALSE); 4131 4132 emit_get_local(c, iter_local); 4133 emit_get_local(c, idx_local); 4134 emit_op(c, OP_GET_ELEM); 4135 } 4136 4137 compile_for_each_assign_target(c, node->left); 4138 4139 if (iter_count > 0) { 4140 begin_scope(c); 4141 iter_inner_start = c->local_count; 4142 for (int i = 0; i < iter_count; i++) { 4143 int outer_idx = iter_slots[i]; 4144 sv_local_t outer = c->locals[outer_idx]; 4145 emit_get_local(c, outer_idx); 4146 int inner_idx = add_local(c, outer.name, outer.name_len, 4147 outer.is_const, c->scope_depth); 4148 emit_put_local(c, inner_idx); 4149 } 4150 } 4151 4152 if (is_using_loop) { 4153 c->using_stack_local = using_stack_local; 4154 c->using_stack_async = is_await_using_loop; 4155 push_using_cleanup(c, using_stack_local, c->scope_depth, is_await_using_loop); 4156 compile_using_push_target(c, node->left, using_stack_local); 4157 } 4158 4159 compile_stmt(c, node->body); 4160 sv_loop_t *loop = &c->loops[c->loop_count - 1]; 4161 for (int i = 0; i < loop->continues.count; i++) 4162 patch_jump(c, loop->continues.offsets[i]); 4163 4164 if (is_using_loop) { 4165 emit_using_dispose_call(c, using_stack_local, -1, is_await_using_loop, false); 4166 emit_op(c, OP_POP); 4167 4168 c->using_stack_local = old_using_stack; 4169 c->using_stack_async = old_using_async; 4170 pop_using_cleanup(c); 4171 } else compile_using_dispose_target(c, node->left); 4172 4173 if (iter_count > 0) { 4174 for (int i = 0; i < iter_count; i++) { 4175 int inner_idx = iter_inner_start + i; 4176 if (!c->locals[inner_idx].captured) continue; 4177 int slot = local_to_frame_slot(c, inner_idx); 4178 if (break_close_slot < 0 || slot < break_close_slot) 4179 break_close_slot = slot; 4180 } 4181 end_scope(c); 4182 } 4183 4184 if (!is_for_of) { 4185 emit_get_local(c, idx_local); 4186 emit_op(c, OP_INC); 4187 emit_put_local(c, idx_local); 4188 } 4189 4190 emit_loop(c, loop_start); 4191 patch_jump(c, exit_jump); 4192 4193 if (is_for_of) { 4194 emit_op(c, OP_POP); 4195 emit_op(c, OP_TRY_POP); 4196 4197 int skip_break_cleanup = -1; 4198 if (break_close_slot >= 0) 4199 skip_break_cleanup = emit_jump(c, OP_JMP); 4200 4201 pop_loop(c); 4202 if (break_close_slot >= 0) { 4203 emit_op(c, OP_CLOSE_UPVAL); 4204 emit_u16(c, (uint16_t)break_close_slot); 4205 patch_jump(c, skip_break_cleanup); 4206 } 4207 emit_op(c, OP_TRY_POP); 4208 emit_op(c, OP_ITER_CLOSE); 4209 int end_jump = emit_jump(c, OP_JMP); 4210 4211 patch_jump(c, try_jump_for_of); 4212 int catch_tag = emit_jump(c, OP_CATCH); 4213 emit_put_local(c, iter_err_local); 4214 4215 if (is_using_loop) { 4216 emit_using_dispose_call(c, using_stack_local, iter_err_local, is_await_using_loop, true); 4217 emit_put_local(c, iter_err_local); 4218 } 4219 4220 emit_op(c, OP_ITER_CLOSE); 4221 emit_get_local(c, iter_err_local); 4222 emit_op(c, OP_THROW); 4223 patch_jump(c, catch_tag); 4224 4225 patch_jump(c, end_jump); 4226 c->try_depth--; 4227 } else { 4228 int skip_break_cleanup = -1; 4229 if (break_close_slot >= 0) 4230 skip_break_cleanup = emit_jump(c, OP_JMP); 4231 4232 pop_loop(c); 4233 if (break_close_slot >= 0) { 4234 emit_op(c, OP_CLOSE_UPVAL); 4235 emit_u16(c, (uint16_t)break_close_slot); 4236 patch_jump(c, skip_break_cleanup); 4237 } 4238 } 4239 4240 free(iter_slots); 4241 end_scope(c); 4242} 4243 4244 4245static void emit_close_upvals_to_depth(sv_compiler_t *c, int target_depth) { 4246for (int i = c->local_count - 1; i >= 0; i--) { 4247 if (c->locals[i].depth <= target_depth) break; 4248 if (c->locals[i].captured) { 4249 int frame_slot = local_to_frame_slot(c, i); 4250 emit_op(c, OP_CLOSE_UPVAL); 4251 emit_u16(c, (uint16_t)frame_slot); 4252 } 4253}} 4254 4255void compile_break(sv_compiler_t *c, sv_ast_t *node) { 4256 if (c->loop_count == 0) return; 4257 4258 int target = c->loop_count - 1; 4259 if (node->str) for (int i = c->loop_count - 1; i >= 0; i--) if ( 4260 c->loops[i].label && 4261 c->loops[i].label_len == node->len && 4262 memcmp(c->loops[i].label, node->str, node->len) == 0 4263 ) { target = i; break; } 4264 4265 emit_close_upvals_to_depth(c, c->loops[target].scope_depth); 4266 emit_using_cleanups_to_depth(c, c->loops[target].scope_depth); 4267 4268 int offset = emit_jump(c, OP_JMP); 4269 patch_list_add(&c->loops[target].breaks, offset); 4270} 4271 4272 4273void compile_continue(sv_compiler_t *c, sv_ast_t *node) { 4274 for (int i = c->loop_count - 1; i >= 0; i--) if (node->str) { 4275 if ( 4276 c->loops[i].label && 4277 c->loops[i].label_len == node->len && 4278 memcmp(c->loops[i].label, node->str, node->len) == 0 4279 ) { 4280 emit_close_upvals_to_depth(c, c->loops[i].scope_depth); 4281 emit_using_cleanups_to_depth(c, c->loops[i].scope_depth); 4282 patch_list_add(&c->loops[i].continues, emit_jump(c, OP_JMP)); 4283 return; 4284 } 4285 } else if (!c->loops[i].is_switch) { 4286 emit_close_upvals_to_depth(c, c->loops[i].scope_depth); 4287 emit_using_cleanups_to_depth(c, c->loops[i].scope_depth); 4288 patch_list_add(&c->loops[i].continues, emit_jump(c, OP_JMP)); 4289 return; 4290 } 4291} 4292 4293static void compile_finally_block(sv_compiler_t *c, sv_ast_t *finally_body) { 4294 int finally_jump = emit_jump(c, OP_FINALLY); 4295 compile_stmt(c, finally_body); 4296 emit_op(c, OP_FINALLY_RET); 4297 patch_jump(c, finally_jump); 4298} 4299 4300static void compile_catch_body(sv_compiler_t *c, sv_ast_t *node) { 4301 begin_scope(c); 4302 if (node->catch_param && node->catch_param->type == N_IDENT) { 4303 int loc = add_local(c, node->catch_param->str, node->catch_param->len, false, c->scope_depth); 4304 emit_put_local(c, loc); 4305 } else if (node->catch_param && is_destructure_pattern_node(node->catch_param)) { 4306 compile_destructure_binding(c, node->catch_param, SV_VAR_LET); 4307 emit_op(c, OP_POP); 4308 } else emit_op(c, OP_POP); 4309 4310 compile_stmt(c, node->catch_body); 4311 end_scope(c); 4312} 4313 4314void compile_try(sv_compiler_t *c, sv_ast_t *node) { 4315 emit_set_completion_undefined(c); 4316 4317 c->try_depth++; 4318 int try_jump = emit_jump(c, OP_TRY_PUSH); 4319 4320 compile_stmt(c, node->body); 4321 emit_op(c, OP_TRY_POP); 4322 4323 bool has_catch = (node->catch_body != NULL); 4324 bool has_finally = (node->finally_body != NULL); 4325 4326 if (!has_finally) { 4327 int end_jump = emit_jump(c, OP_JMP); 4328 patch_jump(c, try_jump); 4329 int catch_tag = emit_jump(c, OP_CATCH); 4330 if (has_catch) 4331 compile_catch_body(c, node); 4332 else 4333 emit_op(c, OP_POP); 4334 patch_jump(c, catch_tag); 4335 patch_jump(c, end_jump); 4336 c->try_depth--; 4337 return; 4338 } 4339 4340 int to_finally_from_try = emit_jump(c, OP_JMP); 4341 int to_finally_from_catch = -1; 4342 int to_finally_from_throw = -1; 4343 4344 patch_jump(c, try_jump); 4345 4346 if (has_catch) { 4347 int catch_tag = emit_jump(c, OP_CATCH); 4348 int catch_throw_jump = emit_jump(c, OP_TRY_PUSH); 4349 4350 compile_catch_body(c, node); 4351 emit_op(c, OP_TRY_POP); 4352 to_finally_from_catch = emit_jump(c, OP_JMP); 4353 4354 patch_jump(c, catch_throw_jump); 4355 emit_op(c, OP_POP); 4356 to_finally_from_throw = emit_jump(c, OP_JMP); 4357 4358 patch_jump(c, catch_tag); 4359 } else { 4360 emit_op(c, OP_POP); 4361 to_finally_from_throw = emit_jump(c, OP_JMP); 4362 } 4363 4364 patch_jump(c, to_finally_from_try); 4365 if (to_finally_from_catch >= 0) patch_jump(c, to_finally_from_catch); 4366 if (to_finally_from_throw >= 0) patch_jump(c, to_finally_from_throw); 4367 4368 compile_finally_block(c, node->finally_body); 4369 4370 c->try_depth--; 4371} 4372 4373 4374void compile_switch(sv_compiler_t *c, sv_ast_t *node) { 4375 emit_set_completion_undefined(c); 4376 4377 int case_count = node->args.count; 4378 int default_case = -1; 4379 int *match_to_stub = NULL; 4380 int *stub_to_body = NULL; 4381 4382 if (case_count > 0) { 4383 match_to_stub = calloc((size_t)case_count, sizeof(int)); 4384 stub_to_body = calloc((size_t)case_count, sizeof(int)); 4385 for (int i = 0; i < case_count; i++) { 4386 match_to_stub[i] = -1; 4387 stub_to_body[i] = -1; 4388 } 4389 } 4390 4391 compile_expr(c, node->cond); 4392 begin_scope(c); 4393 push_loop(c, c->code_len, NULL, 0, true); 4394 4395 for (int i = 0; i < case_count; i++) { 4396 sv_ast_t *cas = node->args.items[i]; 4397 if (!cas->left) { 4398 default_case = i; 4399 continue; 4400 } 4401 emit_op(c, OP_DUP); 4402 compile_expr(c, cas->left); 4403 emit_op(c, OP_SEQ); 4404 match_to_stub[i] = emit_jump(c, OP_JMP_TRUE); 4405 } 4406 4407 int miss_jump = emit_jump(c, OP_JMP); 4408 int default_to_body = -1; 4409 int miss_to_end = -1; 4410 4411 for (int i = 0; i < case_count; i++) { 4412 if (match_to_stub[i] < 0) continue; 4413 patch_jump(c, match_to_stub[i]); 4414 emit_op(c, OP_POP); 4415 stub_to_body[i] = emit_jump(c, OP_JMP); 4416 } 4417 4418 patch_jump(c, miss_jump); 4419 emit_op(c, OP_POP); 4420 if (default_case >= 0) 4421 default_to_body = emit_jump(c, OP_JMP); 4422 else 4423 miss_to_end = emit_jump(c, OP_JMP); 4424 4425 for (int i = 0; i < case_count; i++) { 4426 if (i == default_case && default_to_body >= 0) 4427 patch_jump(c, default_to_body); 4428 if (stub_to_body[i] >= 0) 4429 patch_jump(c, stub_to_body[i]); 4430 4431 sv_ast_t *cas = node->args.items[i]; 4432 compile_stmts(c, &cas->args); 4433 } 4434 4435 if (miss_to_end >= 0) 4436 patch_jump(c, miss_to_end); 4437 4438 free(match_to_stub); 4439 free(stub_to_body); 4440 pop_loop(c); 4441 end_scope(c); 4442} 4443 4444 4445static inline bool is_loop_node(sv_ast_t *n) { 4446 return n && 4447 (n->type == N_WHILE || n->type == N_DO_WHILE || 4448 n->type == N_FOR || n->type == N_FOR_IN || 4449 n->type == N_FOR_OF || n->type == N_FOR_AWAIT_OF); 4450} 4451 4452void compile_label(sv_compiler_t *c, sv_ast_t *node) { 4453 if (is_loop_node(node->body)) { 4454 c->pending_label = node->str; 4455 c->pending_label_len = node->len; 4456 compile_stmt(c, node->body); 4457 c->pending_label = NULL; 4458 c->pending_label_len = 0; 4459 } else { 4460 push_loop(c, c->code_len, node->str, node->len, false); 4461 compile_stmt(c, node->body); 4462 pop_loop(c); 4463 } 4464} 4465 4466static inline bool is_class_method_def(const sv_ast_t *m); 4467static void emit_field_inits(sv_compiler_t *c, sv_ast_t **fields, int count) { 4468 sv_compiler_t *enc = c->enclosing; 4469 for (int i = 0; i < count; i++) { 4470 sv_ast_t *m = fields[i]; 4471 bool is_fn = is_class_method_def(m); 4472 if (is_private_name_node(m->left)) { 4473 emit_op(c, OP_THIS); 4474 emit_private_token(c, m->left); 4475 if (is_fn) compile_func_expr(c, m->right); 4476 else if (m->right) compile_expr(c, m->right); 4477 else emit_op(c, OP_UNDEF); 4478 emit_op(c, OP_DEF_PRIVATE); 4479 if (m->flags & FN_GETTER) emit(c, SV_COMP_PRIVATE_GETTER); 4480 else if (m->flags & FN_SETTER) emit(c, SV_COMP_PRIVATE_SETTER); 4481 else emit(c, is_fn ? SV_COMP_PRIVATE_METHOD : SV_COMP_PRIVATE_FIELD); 4482 emit_op(c, OP_POP); 4483 continue; 4484 } 4485 4486 emit_op(c, OP_THIS); 4487 if (m->right) compile_expr(c, m->right); 4488 else emit_op(c, OP_UNDEF); 4489 if (m->flags & FN_COMPUTED) { 4490 int key_local = enc->computed_key_locals[i]; 4491 enc->locals[key_local].captured = true; 4492 uint16_t slot = (uint16_t)local_to_frame_slot(enc, key_local); 4493 int uv = add_upvalue(c, slot, true, false); 4494 emit_op(c, OP_GET_UPVAL); 4495 emit_u16(c, (uint16_t)uv); 4496 } else { 4497 compile_static_property_key(c, m->left); 4498 } 4499 emit_op(c, OP_SWAP); 4500 emit_op(c, OP_DEFINE_METHOD_COMP); 4501 emit(c, 0); 4502 emit_op(c, OP_POP); 4503 } 4504} 4505 4506 4507static sv_ast_t *find_class_constructor(sv_ast_t *node) { 4508 for (int i = 0; i < node->args.count; i++) { 4509 sv_ast_t *m = node->args.items[i]; 4510 if (m->type == N_METHOD && m->left && m->left->type == N_IDENT && 4511 m->left->len == 11 && 4512 memcmp(m->left->str, "constructor", 11) == 0) { 4513 return m; 4514 } 4515 } 4516 return NULL; 4517} 4518 4519static inline bool is_class_method_def(const sv_ast_t *m) { 4520 return 4521 m && m->right && m->right->type == N_FUNC && 4522 (m->right->flags & FN_METHOD); 4523} 4524 4525static void compile_class_method( 4526 sv_compiler_t *c, sv_ast_t *m, 4527 int ctor_local, int proto_local, 4528 int preeval_key 4529) { 4530 bool is_static = !!(m->flags & FN_STATIC); 4531 int home_local = is_static ? ctor_local : proto_local; 4532 bool is_fn = is_class_method_def(m); 4533 4534 if (is_fn) { 4535 if (is_static) m->right->flags |= FN_STATIC; 4536 compile_func_expr(c, m->right); 4537 emit_get_local(c, home_local); 4538 emit_op(c, OP_SET_HOME_OBJ); 4539 emit_op(c, OP_SWAP); 4540 } else { 4541 emit_get_local(c, home_local); 4542 if (m->right) compile_expr(c, m->right); 4543 else emit_op(c, OP_UNDEF); 4544 } 4545 4546 uint8_t method_flags = 0; 4547 if (m->flags & FN_GETTER) method_flags |= SV_DEFINE_METHOD_GETTER; 4548 if (m->flags & FN_SETTER) method_flags |= SV_DEFINE_METHOD_SETTER; 4549 if (is_fn) method_flags |= SV_DEFINE_METHOD_SET_NAME; 4550 4551 if (m->flags & FN_COMPUTED) { 4552 if (preeval_key >= 0) emit_get_local(c, preeval_key); 4553 else compile_expr(c, m->left); 4554 } else compile_static_property_key(c, m->left); 4555 4556 emit_op(c, OP_SWAP); 4557 emit_op(c, OP_DEFINE_METHOD_COMP); 4558 emit(c, method_flags); 4559 emit_op(c, OP_POP); 4560} 4561 4562static void compile_private_static_element(sv_compiler_t *c, sv_ast_t *m, int ctor_local) { 4563 bool is_fn = is_class_method_def(m); 4564 emit_get_local(c, ctor_local); 4565 emit_private_token(c, m->left); 4566 if (is_fn) { 4567 if (m->flags & FN_STATIC) m->right->flags |= FN_STATIC; 4568 compile_func_expr(c, m->right); 4569 } else if (m->right) compile_expr(c, m->right); 4570 else emit_op(c, OP_UNDEF); 4571 4572 emit_op(c, OP_DEF_PRIVATE); 4573 if (m->flags & FN_GETTER) emit(c, SV_COMP_PRIVATE_GETTER); 4574 else if (m->flags & FN_SETTER) emit(c, SV_COMP_PRIVATE_SETTER); 4575 else emit(c, is_fn ? SV_COMP_PRIVATE_METHOD : SV_COMP_PRIVATE_FIELD); 4576 emit_op(c, OP_POP); 4577} 4578 4579static inline int compile_class_precompute_key(sv_compiler_t *c, sv_ast_t *key_expr) { 4580 compile_expr(c, key_expr); 4581 int loc = add_local(c, "", 0, false, c->scope_depth); 4582 emit_put_local(c, loc); 4583 return loc; 4584} 4585 4586void compile_class(sv_compiler_t *c, sv_ast_t *node) { 4587 int outer_name_local = -1; 4588 bool class_repl_top = is_repl_top_level(c); 4589 4590 sv_ast_t *ctor_method = NULL; 4591 bool has_static_name = false; 4592 4593 int field_count = 0; 4594 int computed_method_count = 0; 4595 4596 if (node->str) outer_name_local = resolve_local(c, node->str, node->len); 4597 if (node->left) compile_expr(c, node->left); 4598 else emit_op(c, OP_UNDEF); 4599 4600 sv_private_scope_t private_scope = { .parent = c->private_scope }; 4601 sv_private_scope_t *saved_private_scope = c->private_scope; 4602 c->private_scope = &private_scope; 4603 4604 for (int i = 0; i < node->args.count; i++) { 4605 sv_ast_t *m = node->args.items[i]; 4606 if (m->type != N_METHOD) continue; 4607 bool is_fn = is_class_method_def(m); 4608 bool is_private = is_private_name_node(m->left); 4609 4610 if (is_private) { 4611 uint8_t private_kind = (m->flags & FN_GETTER) ? SV_COMP_PRIVATE_GETTER : 4612 (m->flags & FN_SETTER) ? SV_COMP_PRIVATE_SETTER : 4613 is_fn ? SV_COMP_PRIVATE_METHOD : SV_COMP_PRIVATE_FIELD; 4614 if (!private_scope_add(c, &private_scope, m->left, private_kind, !!(m->flags & FN_STATIC))) { 4615 c->private_scope = saved_private_scope; 4616 free(private_scope.names); 4617 emit_op(c, OP_UNDEF); 4618 return; 4619 } 4620 } 4621 4622 if ( 4623 !(m->flags & FN_STATIC) && 4624 !(m->flags & FN_COMPUTED) && 4625 m->left && m->left->type == N_IDENT && 4626 m->left->len == 11 && 4627 memcmp(m->left->str, "constructor", 11) == 0 4628 ) { ctor_method = m; continue; } 4629 4630 if ( 4631 (m->flags & FN_STATIC) && 4632 !(m->flags & FN_COMPUTED) && 4633 m->left && m->left->str && 4634 m->left->len == 4 && 4635 memcmp(m->left->str, "name", 4) == 0 4636 ) has_static_name = true; 4637 4638 if (!(m->flags & FN_STATIC) && (is_private || !is_fn)) field_count++; 4639 if (!is_private && node->str && (m->flags & FN_COMPUTED) && (is_fn || (m->flags & FN_STATIC))) computed_method_count++; 4640 } 4641 4642 sv_ast_t **field_inits = NULL; 4643 int *computed_key_locals = NULL; 4644 int *method_comp_keys = NULL; 4645 if (field_count > 0) { 4646 field_inits = malloc(sizeof(sv_ast_t *) * field_count); 4647 computed_key_locals = malloc(sizeof(int) * field_count); 4648 } 4649 if (computed_method_count > 0) { 4650 method_comp_keys = malloc(sizeof(int) * node->args.count); 4651 for (int i = 0; i < node->args.count; i++) method_comp_keys[i] = -1; 4652 } 4653 4654 if (field_count > 0 || method_comp_keys) { 4655 int fi = 0; 4656 for (int i = 0; i < node->args.count; i++) { 4657 sv_ast_t *m = node->args.items[i]; 4658 if (m->type != N_METHOD || m == ctor_method) continue; 4659 4660 bool is_fn = is_class_method_def(m); 4661 bool is_private = is_private_name_node(m->left); 4662 bool needs_instance_init = !(m->flags & FN_STATIC) && (is_private || !is_fn); 4663 4664 if (needs_instance_init) { 4665 if (field_inits) field_inits[fi] = m; 4666 if (computed_key_locals) computed_key_locals[fi] = (!is_private && (m->flags & FN_COMPUTED)) 4667 ? compile_class_precompute_key(c, m->left) : -1; 4668 fi++; 4669 continue; 4670 } 4671 4672 if (is_private || !method_comp_keys || !(m->flags & FN_COMPUTED)) continue; 4673 method_comp_keys[i] = compile_class_precompute_key(c, m->left); 4674 }} 4675 4676 int inner_name_local = -1; 4677 bool has_class_scope = node->str || private_scope.count > 0; 4678 if (has_class_scope) { 4679 begin_scope(c); 4680 if (node->str) 4681 inner_name_local = add_local(c, node->str, node->len, true, c->scope_depth); 4682 for (int i = 0; i < private_scope.count; i++) { 4683 sv_private_name_t *p = &private_scope.names[i]; 4684 p->owner = c; 4685 p->local = add_local(c, "", 0, true, c->scope_depth); 4686 emit_op(c, OP_PRIVATE_TOKEN); 4687 emit_u32(c, p->hash); 4688 emit_put_local(c, p->local); 4689 } 4690 } 4691 4692 if (ctor_method && ctor_method->right) { 4693 c->field_inits = field_inits; 4694 c->field_init_count = field_count; 4695 c->computed_key_locals = computed_key_locals; 4696 compile_func_expr(c, ctor_method->right); 4697 c->field_inits = NULL; 4698 c->field_init_count = 0; 4699 c->computed_key_locals = NULL; 4700 } else if (field_count > 0) { 4701 c->computed_key_locals = computed_key_locals; 4702 sv_compiler_t comp; 4703 sv_compile_ctx_init_child(&comp, c, NULL, c->mode); 4704 4705 if (node->left) { 4706 emit_op(&comp, OP_THIS); 4707 emit_op(&comp, OP_SPECIAL_OBJ); 4708 emit(&comp, 2); 4709 emit_op(&comp, OP_SWAP); 4710 emit_op(&comp, OP_SPECIAL_OBJ); 4711 emit(&comp, 0); 4712 emit_op(&comp, OP_SUPER_APPLY); 4713 emit_u16(&comp, 1); 4714 emit_op(&comp, OP_POP); 4715 } 4716 4717 emit_field_inits(&comp, field_inits, field_count); 4718 emit_op(&comp, OP_RETURN_UNDEF); 4719 4720 sv_func_t *fn = code_arena_bump(sizeof(sv_func_t)); 4721 memset(fn, 0, sizeof(sv_func_t)); 4722 fn->code = code_arena_bump((size_t)comp.code_len); 4723 memcpy(fn->code, comp.code, (size_t)comp.code_len); 4724 fn->code_len = comp.code_len; 4725 sv_func_init_obj_sites(fn); 4726 if (comp.const_count > 0) { 4727 fn->constants = code_arena_bump((size_t)comp.const_count * sizeof(ant_value_t)); 4728 memcpy(fn->constants, comp.constants, (size_t)comp.const_count * sizeof(ant_value_t)); 4729 fn->const_count = comp.const_count; 4730 build_gc_const_tables(fn); 4731 } 4732 if (comp.atom_count > 0) { 4733 fn->atoms = code_arena_bump((size_t)comp.atom_count * sizeof(sv_atom_t)); 4734 memcpy(fn->atoms, comp.atoms, (size_t)comp.atom_count * sizeof(sv_atom_t)); 4735 fn->atom_count = comp.atom_count; 4736 } 4737 fn->ic_count = (uint16_t)comp.ic_count; 4738 if (fn->ic_count > 0) { 4739 fn->ic_slots = code_arena_bump((size_t)fn->ic_count * sizeof(sv_ic_entry_t)); 4740 memset(fn->ic_slots, 0, (size_t)fn->ic_count * sizeof(sv_ic_entry_t)); 4741 } 4742 if (comp.upvalue_count > 0) { 4743 fn->upval_descs = code_arena_bump( 4744 (size_t)comp.upvalue_count * sizeof(sv_upval_desc_t)); 4745 memcpy(fn->upval_descs, comp.upval_descs, 4746 (size_t)comp.upvalue_count * sizeof(sv_upval_desc_t)); 4747 fn->upvalue_count = comp.upvalue_count; 4748 } 4749 fn->max_locals = comp.max_local_count; 4750 fn->max_stack = fn->max_locals + 64; 4751 fn->local_type_count = fn->max_locals; 4752 if (fn->max_locals > 0) { 4753 fn->local_types = code_arena_bump((size_t)fn->max_locals * sizeof(sv_type_info_t)); 4754 memset(fn->local_types, 0, (size_t)fn->max_locals * sizeof(sv_type_info_t)); 4755 if (comp.slot_types) { 4756 int ncopy = fn->max_locals < comp.slot_type_cap ? fn->max_locals : comp.slot_type_cap; 4757 memcpy(fn->local_types, comp.slot_types, (size_t)ncopy * sizeof(sv_type_info_t)); 4758 } 4759 } 4760 4761 fn->param_count = (uint16_t)comp.param_count; 4762 fn->function_length = (uint16_t)comp.param_count; 4763 fn->is_strict = comp.is_strict; 4764 fn->filename = c->js->filename; 4765 fn->source_line = (int)node->line; 4766 4767 if (node->str && node->len > 0) { 4768 char *name = code_arena_bump(node->len + 1); 4769 memcpy(name, node->str, node->len); 4770 name[node->len] = '\0'; 4771 fn->name = name; 4772 } 4773 4774 sv_compile_ctx_cleanup(&comp); 4775 int idx = add_constant(c, mkval(T_NTARG, (uintptr_t)fn)); 4776 emit_op(c, OP_CLOSURE); 4777 emit_u32(c, (uint32_t)idx); 4778 } else emit_op(c, OP_UNDEF); 4779 4780 free(field_inits); 4781 free(computed_key_locals); 4782 c->computed_key_locals = NULL; 4783 4784 const char *class_name = node->str; 4785 uint32_t class_name_len = node->len; 4786 bool consumed_inferred_name = false; 4787 4788 if (!class_name && c->inferred_name) { 4789 class_name = c->inferred_name; 4790 class_name_len = c->inferred_name_len; 4791 consumed_inferred_name = true; 4792 } 4793 4794 if (!has_static_name) { 4795 int atom = class_name 4796 ? add_atom(c, class_name, class_name_len) 4797 : add_atom(c, "", 0); 4798 emit_op(c, OP_DEFINE_CLASS); 4799 emit_u32(c, (uint32_t)atom); 4800 emit(c, 1); 4801 } else { 4802 emit_op(c, OP_DEFINE_CLASS); 4803 emit_u32(c, 0); 4804 emit(c, 0); 4805 } 4806 4807 if (consumed_inferred_name) { 4808 c->inferred_name = NULL; 4809 c->inferred_name_len = 0; 4810 } 4811 4812 emit_u32(c, node->src_off); 4813 emit_u32(c, node->src_end); 4814 4815 int proto_local = add_local(c, "", 0, false, c->scope_depth); 4816 int ctor_local = add_local(c, "", 0, false, c->scope_depth); 4817 emit_put_local(c, proto_local); 4818 emit_put_local(c, ctor_local); 4819 4820 if (inner_name_local >= 0) { 4821 emit_get_local(c, ctor_local); 4822 emit_put_local(c, inner_name_local); 4823 } 4824 4825 for (int i = 0; i < node->args.count; i++) { 4826 sv_ast_t *m = node->args.items[i]; 4827 if (m->type == N_STATIC_BLOCK) { 4828 begin_scope(c); 4829 int saved_completion_local = c->completion_local; 4830 c->completion_local = -1; 4831 compile_stmts(c, &m->args); 4832 c->completion_local = saved_completion_local; 4833 end_scope(c); 4834 continue; 4835 } 4836 4837 if (m->type != N_METHOD) continue; 4838 if (m == ctor_method) continue; 4839 if (is_private_name_node(m->left)) { 4840 if (m->flags & FN_STATIC) compile_private_static_element(c, m, ctor_local); 4841 continue; 4842 } 4843 4844 bool is_fn = is_class_method_def(m); 4845 if (!is_fn && !(m->flags & FN_STATIC)) continue; 4846 4847 compile_class_method( 4848 c, m, ctor_local, proto_local, 4849 method_comp_keys ? method_comp_keys[i] : -1 4850 ); 4851 } 4852 4853 free(method_comp_keys); 4854 emit_get_local(c, ctor_local); 4855 4856 if (class_repl_top && node->str) { 4857 emit_op(c, OP_DUP); 4858 emit_atom_op(c, OP_PUT_GLOBAL, node->str, node->len); 4859 } else if (outer_name_local >= 0) { 4860 emit_op(c, OP_DUP); 4861 emit_put_local(c, outer_name_local); 4862 c->locals[outer_name_local].is_tdz = false; 4863 } 4864 4865 if (has_class_scope) end_scope(c); 4866 c->private_scope = saved_private_scope; 4867 free(private_scope.names); 4868} 4869 4870static bool ast_contains_await_expr(const sv_ast_t *node) { 4871 if (!node) return false; 4872 4873 if (node->type == N_AWAIT) return true; 4874 if (node->type == N_FUNC) return false; 4875 4876 if (ast_contains_await_expr(node->left)) return true; 4877 if (ast_contains_await_expr(node->right)) return true; 4878 if (ast_contains_await_expr(node->cond)) return true; 4879 if (ast_contains_await_expr(node->body)) return true; 4880 if (ast_contains_await_expr(node->catch_body)) return true; 4881 if (ast_contains_await_expr(node->finally_body)) return true; 4882 if (ast_contains_await_expr(node->catch_param)) return true; 4883 if (ast_contains_await_expr(node->init)) return true; 4884 if (ast_contains_await_expr(node->update)) return true; 4885 4886 for (int i = 0; i < node->args.count; i++) { 4887 if (ast_contains_await_expr(node->args.items[i])) return true; 4888 } 4889 4890 return false; 4891} 4892 4893static bool func_params_contain_await(const sv_ast_t *node) { 4894 if (!node) return false; 4895 for (int i = 0; i < node->args.count; i++) { 4896 if (ast_contains_await_expr(node->args.items[i])) return true; 4897 } 4898 return false; 4899} 4900 4901static uint16_t function_length_from_params(const sv_ast_t *node) { 4902 if (!node) return 0; 4903 uint16_t length = 0; 4904 for (int i = 0; i < node->args.count; i++) { 4905 sv_ast_t *param = node->args.items[i]; 4906 if (!param || param->type == N_REST || param->type == N_ASSIGN_PAT) break; 4907 length++; 4908 } 4909 return length; 4910} 4911 4912sv_func_t *compile_function_body( 4913 sv_compiler_t *enclosing, 4914 sv_ast_t *node, 4915 sv_compile_mode_t mode 4916) { 4917 if (node->args.count > UINT16_MAX) { 4918 js_mkerr_typed( 4919 enclosing->js, JS_ERR_SYNTAX, 4920 "too many function parameters"); 4921 return NULL; 4922 } 4923 4924 if ((node->flags & FN_ASYNC) && func_params_contain_await(node)) { 4925 js_mkerr_typed( 4926 enclosing->js, JS_ERR_SYNTAX, 4927 "await is not allowed in async function parameters"); 4928 return NULL; 4929 } 4930 4931 sv_compiler_t comp; 4932 sv_compile_ctx_init_child(&comp, enclosing, node, mode); 4933 4934 for (int i = 0; i < node->args.count; i++) { 4935 sv_ast_t *p = node->args.items[i]; 4936 if (p->type == N_IDENT) { 4937 add_local(&comp, p->str, p->len, false, -1); 4938 } else if (p->type == N_REST && p->right && p->right->type == N_IDENT) { 4939 add_local(&comp, p->right->str, p->right->len, false, -1); 4940 } else if (p->type == N_ASSIGN_PAT && p->left && p->left->type == N_IDENT) { 4941 add_local(&comp, p->left->str, p->left->len, false, -1); 4942 } else add_local(&comp, "", 0, false, -1); 4943 } 4944 4945 comp.param_locals = comp.local_count; 4946 4947 bool has_own_use_strict = false; 4948 if (node->body && node->body->type == N_BLOCK) for (int i = 0; i < node->body->args.count; i++) { 4949 sv_ast_t *stmt = node->body->args.items[i]; 4950 if (!stmt || stmt->type == N_EMPTY) continue; 4951 if (stmt->type != N_STRING) break; 4952 if (sv_ast_is_use_strict(comp.js, stmt)) { 4953 has_own_use_strict = true; 4954 comp.is_strict = true; 4955 } 4956 } 4957 4958 if (comp.is_strict) { 4959 const char *param_names[256]; 4960 uint32_t param_lens[256]; 4961 int param_name_count = 0; 4962 4963 for (int i = 0; i < node->args.count; i++) { 4964 sv_ast_t *p = node->args.items[i]; 4965 const char *pname = NULL; 4966 uint32_t plen = 0; 4967 4968 if (p && p->type == N_IDENT) { 4969 pname = p->str; plen = p->len; 4970 } else if (p && p->type == N_REST && p->right && p->right->type == N_IDENT) { 4971 pname = p->right->str; plen = p->right->len; 4972 } else if (p && p->type == N_ASSIGN_PAT && p->left && p->left->type == N_IDENT) { 4973 pname = p->left->str; plen = p->left->len; 4974 } 4975 4976 if (!pname || plen == 0) continue; 4977 4978 if (is_strict_restricted_ident(pname, plen)) { 4979 js_mkerr_typed( 4980 comp.js, JS_ERR_SYNTAX, 4981 "strict mode forbids '%.*s' as a parameter name", 4982 (int)plen, pname); 4983 return NULL; 4984 } 4985 4986 for (int j = 0; j < param_name_count; j++) { 4987 if (param_lens[j] == plen && 4988 memcmp(param_names[j], pname, plen) == 0) { 4989 js_mkerr_typed( 4990 comp.js, JS_ERR_SYNTAX, 4991 "duplicate parameter name '%.*s' in strict mode", 4992 (int)plen, pname); 4993 return NULL; 4994 } 4995 } 4996 4997 if (param_name_count < (int)(sizeof(param_names) / sizeof(param_names[0]))) { 4998 param_names[param_name_count] = pname; 4999 param_lens[param_name_count] = plen; 5000 param_name_count++; 5001 } 5002 } 5003 } 5004 5005 bool has_non_simple_params = false; 5006 for (int i = 0; i < node->args.count; i++) { 5007 sv_ast_t *p = node->args.items[i]; 5008 if (p->type != N_IDENT) { has_non_simple_params = true; break; } 5009 } 5010 5011 if (has_own_use_strict && has_non_simple_params) { 5012 js_mkerr_typed( 5013 comp.js, JS_ERR_SYNTAX, 5014 "Illegal 'use strict' directive in function with non-simple parameter list"); 5015 return NULL; 5016 } 5017 5018 bool repl_top = is_repl_top_level(&comp); 5019 if (!has_non_simple_params && node->body) { 5020 if (node->body->type == N_BLOCK) { 5021 if (!repl_top) { 5022 for (int i = 0; i < node->body->args.count; i++) 5023 hoist_var_decls(&comp, node->body->args.items[i]); 5024 hoist_lexical_decls(&comp, &node->body->args); 5025 } 5026 hoist_func_decls(&comp, &node->body->args); 5027 } else if (!repl_top) hoist_var_decls(&comp, node->body); 5028 } 5029 5030 if (!has_non_simple_params) { 5031 for (int i = 0; i < node->args.count; i++) { 5032 sv_ast_t *p = node->args.items[i]; 5033 if (p->type == N_ASSIGN_PAT) { 5034 emit_op(&comp, OP_GET_ARG); 5035 emit_u16(&comp, (uint16_t)i); 5036 emit_op(&comp, OP_DUP); 5037 emit_op(&comp, OP_IS_UNDEF); 5038 int skip = emit_jump(&comp, OP_JMP_FALSE); 5039 emit_op(&comp, OP_POP); 5040 compile_expr(&comp, p->right); 5041 patch_jump(&comp, skip); 5042 if (p->left && p->left->type == N_IDENT) { 5043 emit_op(&comp, OP_PUT_ARG); 5044 emit_u16(&comp, (uint16_t)i); 5045 } else if (p->left) { 5046 compile_destructure_binding(&comp, p->left, SV_VAR_LET); 5047 emit_op(&comp, OP_POP); 5048 } else emit_op(&comp, OP_POP); 5049 } else if ( 5050 p->type == N_ARRAY_PAT || p->type == N_ARRAY || 5051 p->type == N_OBJECT_PAT || p->type == N_OBJECT) { 5052 emit_op(&comp, OP_GET_ARG); 5053 emit_u16(&comp, (uint16_t)i); 5054 compile_destructure_binding(&comp, p, SV_VAR_LET); 5055 emit_op(&comp, OP_POP); 5056 } else if (p->type == N_REST && p->right && p->right->type == N_IDENT) { 5057 emit_op(&comp, OP_REST); 5058 emit_u16(&comp, (uint16_t)i); 5059 int loc = resolve_local(&comp, p->right->str, p->right->len); 5060 if (loc >= 0) { 5061 emit_op(&comp, OP_PUT_ARG); 5062 emit_u16(&comp, (uint16_t)loc); 5063 } 5064 } else if (p->type == N_REST && p->right) { 5065 emit_op(&comp, OP_REST); 5066 emit_u16(&comp, (uint16_t)i); 5067 compile_destructure_binding(&comp, p->right, SV_VAR_LET); 5068 emit_op(&comp, OP_POP); 5069 } 5070 } 5071 } else { 5072 int *param_bind_locals = NULL; 5073 int param_bind_count = 0; 5074 int param_bind_cap = 0; 5075 5076 for (int i = 0; i < node->args.count; i++) { 5077 sv_ast_t *p = node->args.items[i]; 5078 const char *pname = NULL; 5079 uint32_t plen = 0; 5080 if (p->type == N_IDENT) { 5081 pname = p->str; plen = p->len; 5082 } else if (( 5083 p->type == N_ASSIGN_PAT) && p->left && 5084 p->left->type == N_IDENT) { 5085 pname = p->left->str; plen = p->left->len; 5086 } else if ( 5087 p->type == N_REST && p->right && 5088 p->right->type == N_IDENT) { 5089 pname = p->right->str; plen = p->right->len; 5090 } 5091 5092 int lb = comp.local_count; 5093 if (pname && plen) { 5094 int loc = add_local(&comp, pname, plen, false, 0); 5095 comp.locals[loc].is_tdz = true; 5096 set_local_inferred_type(&comp, loc, SV_TI_UNKNOWN); 5097 int slot = loc - comp.param_locals; 5098 emit_op(&comp, OP_SET_LOCAL_UNDEF); 5099 emit_u16(&comp, (uint16_t)slot); 5100 } 5101 5102 if (param_bind_count >= param_bind_cap) { 5103 param_bind_cap = param_bind_cap ? param_bind_cap * 2 : 8; 5104 param_bind_locals = realloc( 5105 param_bind_locals, 5106 (size_t)param_bind_cap * sizeof(int)); 5107 } 5108 param_bind_locals[param_bind_count++] = lb; 5109 } 5110 5111 for (int i = 0; i < node->args.count; i++) { 5112 sv_ast_t *p = node->args.items[i]; 5113 int bind_lb = param_bind_locals[i]; 5114 5115 if (p->type == N_IDENT) { 5116 if (bind_lb < comp.local_count) { 5117 emit_op(&comp, OP_GET_ARG); 5118 emit_u16(&comp, (uint16_t)i); 5119 int slot = bind_lb - comp.param_locals; 5120 comp.locals[bind_lb].is_tdz = false; 5121 if (slot <= 255) { emit_op(&comp, OP_PUT_LOCAL8); emit(&comp, (uint8_t)slot); } 5122 else { emit_op(&comp, OP_PUT_LOCAL); emit_u16(&comp, (uint16_t)slot); } 5123 set_local_inferred_type(&comp, bind_lb, SV_TI_UNKNOWN); 5124 } 5125 } else if (p->type == N_ASSIGN_PAT) { 5126 emit_op(&comp, OP_GET_ARG); 5127 emit_u16(&comp, (uint16_t)i); 5128 emit_op(&comp, OP_DUP); 5129 emit_op(&comp, OP_IS_UNDEF); 5130 int skip = emit_jump(&comp, OP_JMP_FALSE); 5131 emit_op(&comp, OP_POP); 5132 compile_expr(&comp, p->right); 5133 patch_jump(&comp, skip); 5134 if (p->left && p->left->type == N_IDENT && bind_lb < comp.local_count) { 5135 int slot = bind_lb - comp.param_locals; 5136 comp.locals[bind_lb].is_tdz = false; 5137 if (slot <= 255) { emit_op(&comp, OP_PUT_LOCAL8); emit(&comp, (uint8_t)slot); } 5138 else { emit_op(&comp, OP_PUT_LOCAL); emit_u16(&comp, (uint16_t)slot); } 5139 set_local_inferred_type(&comp, bind_lb, SV_TI_UNKNOWN); 5140 } else if (p->left) { 5141 compile_destructure_binding(&comp, p->left, SV_VAR_LET); 5142 emit_op(&comp, OP_POP); 5143 } else { 5144 emit_op(&comp, OP_POP); 5145 } 5146 } else if ( 5147 p->type == N_ARRAY_PAT || p->type == N_ARRAY || 5148 p->type == N_OBJECT_PAT || p->type == N_OBJECT) { 5149 emit_op(&comp, OP_GET_ARG); 5150 emit_u16(&comp, (uint16_t)i); 5151 compile_destructure_binding(&comp, p, SV_VAR_LET); 5152 emit_op(&comp, OP_POP); 5153 } else if ( 5154 p->type == N_REST && p->right && p->right->type == N_IDENT && 5155 bind_lb < comp.local_count) { 5156 emit_op(&comp, OP_REST); 5157 emit_u16(&comp, (uint16_t)i); 5158 int slot = bind_lb - comp.param_locals; 5159 comp.locals[bind_lb].is_tdz = false; 5160 if (slot <= 255) { emit_op(&comp, OP_PUT_LOCAL8); emit(&comp, (uint8_t)slot); } 5161 else { emit_op(&comp, OP_PUT_LOCAL); emit_u16(&comp, (uint16_t)slot); } 5162 set_local_inferred_type(&comp, bind_lb, SV_TI_UNKNOWN); 5163 } else if (p->type == N_REST && p->right) { 5164 emit_op(&comp, OP_REST); 5165 emit_u16(&comp, (uint16_t)i); 5166 compile_destructure_binding(&comp, p->right, SV_VAR_LET); 5167 emit_op(&comp, OP_POP); 5168 } 5169 } 5170 5171 free(param_bind_locals); 5172 sv_ast_t *body = node->body; 5173 5174 if (body && body->type != N_BLOCK) { 5175 if (!repl_top) hoist_var_decls(&comp, body); 5176 } else if (body) { 5177 if (!repl_top) { 5178 for (int i = 0; i < body->args.count; i++) 5179 hoist_var_decls(&comp, body->args.items[i]); 5180 hoist_lexical_decls(&comp, &body->args); 5181 } 5182 hoist_func_decls(&comp, &body->args); 5183 } 5184 } 5185 5186 if (!comp.is_arrow && has_implicit_arguments_obj(&comp) && (node->flags & FN_USES_ARGS)) { 5187 static const char args_name[] = "\x01arguments"; 5188 comp.strict_args_local = add_local(&comp, args_name, sizeof(args_name) - 1, false, comp.scope_depth); 5189 emit_op(&comp, OP_SPECIAL_OBJ); 5190 emit(&comp, 0); 5191 emit_put_local(&comp, comp.strict_args_local); 5192 } 5193 5194 if (!comp.is_arrow && comp.enclosing && (node->flags & FN_USES_NEW_TARGET)) { 5195 static const char nt_name[] = "\x01new.target"; 5196 comp.new_target_local = add_local(&comp, nt_name, sizeof(nt_name) - 1, false, comp.scope_depth); 5197 emit_op(&comp, OP_SPECIAL_OBJ); 5198 emit(&comp, 1); 5199 emit_put_local(&comp, comp.new_target_local); 5200 } 5201 5202 if (!comp.is_arrow && comp.enclosing && (node->flags & (FN_METHOD | FN_GETTER | FN_SETTER | FN_STATIC))) { 5203 static const char sv_name[] = "\x01super"; 5204 comp.super_local = add_local(&comp, sv_name, sizeof(sv_name) - 1, false, comp.scope_depth); 5205 emit_op(&comp, OP_SPECIAL_OBJ); 5206 emit(&comp, 2); 5207 emit_put_local(&comp, comp.super_local); 5208 } 5209 5210 if (enclosing->field_init_count > 0) { 5211 emit_field_inits(&comp, enclosing->field_inits, enclosing->field_init_count); 5212 } 5213 5214 bool body_has_await_using = false; 5215 bool body_has_using = node->body && node->body->type == N_BLOCK && 5216 stmt_list_has_using_decl(&node->body->args, &body_has_await_using); 5217 int body_using_try_jump = -1; 5218 int body_using_err_local = -1; 5219 int old_using_stack = comp.using_stack_local; 5220 bool old_using_async = comp.using_stack_async; 5221 5222 if (body_has_using) { 5223 emit_empty_disposal_stack(&comp); 5224 int body_using_stack = add_local(&comp, "", 0, false, comp.scope_depth); 5225 emit_put_local(&comp, body_using_stack); 5226 body_using_err_local = add_local(&comp, "", 0, false, comp.scope_depth); 5227 5228 comp.using_stack_local = body_using_stack; 5229 comp.using_stack_async = body_has_await_using; 5230 push_using_cleanup(&comp, body_using_stack, comp.scope_depth, body_has_await_using); 5231 5232 comp.try_depth++; 5233 body_using_try_jump = emit_jump(&comp, OP_TRY_PUSH); 5234 } 5235 5236 bool completion_top = is_completion_top_level(&comp); 5237 if (completion_top) { 5238 emit_op(&comp, OP_UNDEF); 5239 comp.completion_local = add_local(&comp, "", 0, false, comp.scope_depth); 5240 emit_put_local(&comp, comp.completion_local); 5241 } 5242 5243 if (node->body) { 5244 if (node->body->type == N_BLOCK) { 5245 for (int i = 0; i < node->body->args.count; i++) 5246 compile_stmt(&comp, node->body->args.items[i]); 5247 } else compile_tail_return_expr(&comp, node->body); 5248 } 5249 5250 for (int i = 0; i < comp.deferred_export_count; i++) { 5251 sv_deferred_export_t *e = &comp.deferred_exports[i]; 5252 compile_export_emit(&comp, e->name, e->len); 5253 } 5254 5255 if (body_has_using) { 5256 emit_op(&comp, OP_TRY_POP); 5257 comp.try_depth--; 5258 5259 emit_using_dispose_call(&comp, comp.using_stack_local, -1, body_has_await_using, false); 5260 emit_op(&comp, OP_POP); 5261 int end_jump = emit_jump(&comp, OP_JMP); 5262 5263 patch_jump(&comp, body_using_try_jump); 5264 int catch_tag = emit_jump(&comp, OP_CATCH); 5265 emit_put_local(&comp, body_using_err_local); 5266 emit_using_dispose_call(&comp, comp.using_stack_local, body_using_err_local, body_has_await_using, true); 5267 if (!body_has_await_using) emit_op(&comp, OP_THROW); 5268 patch_jump(&comp, catch_tag); 5269 patch_jump(&comp, end_jump); 5270 5271 pop_using_cleanup(&comp); 5272 comp.using_stack_local = old_using_stack; 5273 comp.using_stack_async = old_using_async; 5274 } 5275 5276 if (completion_top) { 5277 emit_get_local(&comp, comp.completion_local); 5278 emit_return_from_stack(&comp); 5279 } 5280 5281 emit_using_cleanups_to_depth(&comp, -1); 5282 emit_close_upvals(&comp); 5283 emit_op(&comp, OP_RETURN_UNDEF); 5284 5285 int max_locals = comp.max_local_count - comp.param_locals; 5286 sv_func_t *func = code_arena_bump(sizeof(sv_func_t)); 5287 memset(func, 0, sizeof(sv_func_t)); 5288 5289 func->code = code_arena_bump((size_t)comp.code_len); 5290 memcpy(func->code, comp.code, (size_t)comp.code_len); 5291 func->code_len = comp.code_len; 5292 sv_func_init_obj_sites(func); 5293 5294 if (comp.const_count > 0) { 5295 func->constants = code_arena_bump((size_t)comp.const_count * sizeof(ant_value_t)); 5296 memcpy(func->constants, comp.constants, (size_t)comp.const_count * sizeof(ant_value_t)); 5297 func->const_count = comp.const_count; 5298 build_gc_const_tables(func); 5299 } 5300 5301 if (comp.atom_count > 0) { 5302 func->atoms = code_arena_bump((size_t)comp.atom_count * sizeof(sv_atom_t)); 5303 memcpy(func->atoms, comp.atoms, (size_t)comp.atom_count * sizeof(sv_atom_t)); 5304 func->atom_count = comp.atom_count; 5305 } 5306 5307 func->ic_count = (uint16_t)comp.ic_count; 5308 if (func->ic_count > 0) { 5309 func->ic_slots = code_arena_bump((size_t)func->ic_count * sizeof(sv_ic_entry_t)); 5310 memset(func->ic_slots, 0, (size_t)func->ic_count * sizeof(sv_ic_entry_t)); 5311 } 5312 5313 if (comp.upvalue_count > 0) { 5314 func->upval_descs = code_arena_bump( 5315 (size_t)comp.upvalue_count * sizeof(sv_upval_desc_t)); 5316 memcpy(func->upval_descs, comp.upval_descs, 5317 (size_t)comp.upvalue_count * sizeof(sv_upval_desc_t)); 5318 func->upvalue_count = comp.upvalue_count; 5319 } 5320 5321 if (comp.srcpos_count > 0) { 5322 func->srcpos = code_arena_bump((size_t)comp.srcpos_count * sizeof(sv_srcpos_t)); 5323 memcpy(func->srcpos, comp.srcpos, (size_t)comp.srcpos_count * sizeof(sv_srcpos_t)); 5324 func->srcpos_count = comp.srcpos_count; 5325 } 5326 5327 if (enclosing->source && enclosing->source_len > 0) { 5328 func->source = enclosing->source; 5329 func->source_len = (int)enclosing->source_len; 5330 func->source_start = (int)node->src_off; 5331 func->source_end = (node->src_end > node->src_off) 5332 ? (int)node->src_end : func->source_len; 5333 } 5334 5335 func->max_locals = max_locals; 5336 func->max_stack = max_locals + 64; 5337 func->local_type_count = max_locals; 5338 if (max_locals > 0) { 5339 func->local_types = code_arena_bump((size_t)max_locals * sizeof(sv_type_info_t)); 5340 memset(func->local_types, 0, (size_t)max_locals * sizeof(sv_type_info_t)); 5341 if (comp.slot_types) { 5342 int ncopy = max_locals < comp.slot_type_cap ? max_locals : comp.slot_type_cap; 5343 memcpy(func->local_types, comp.slot_types, (size_t)ncopy * sizeof(sv_type_info_t)); 5344 } 5345 } 5346 5347 func->param_count = (uint16_t)comp.param_count; 5348 func->function_length = function_length_from_params(node); 5349 func->is_strict = comp.is_strict; 5350 func->is_arrow = comp.is_arrow; 5351 5352 func->is_async = !!(node->flags & FN_ASYNC); 5353 func->has_await = false; 5354 func->is_generator = !!(node->flags & FN_GENERATOR); 5355 func->is_method = !!(node->flags & FN_METHOD); 5356 func->is_static = !!(node->flags & FN_STATIC); 5357 func->is_tla = comp.is_tla; 5358 func->filename = enclosing->filename ? enclosing->filename : enclosing->js->filename; 5359 func->source_line = (int)node->line; 5360 5361 if (node->str && node->len > 0) { 5362 char *name = code_arena_bump(node->len + 1); 5363 memcpy(name, node->str, node->len); 5364 name[node->len] = '\0'; 5365 func->name = name; 5366 } else if (enclosing->inferred_name && enclosing->inferred_name_len > 0) { 5367 char *name = code_arena_bump(enclosing->inferred_name_len + 1); 5368 memcpy(name, enclosing->inferred_name, enclosing->inferred_name_len); 5369 name[enclosing->inferred_name_len] = '\0'; 5370 func->name = name; 5371 } 5372 5373 if (func->is_async || func->is_tla) { 5374 const uint8_t *ip = func->code; 5375 const uint8_t *end = func->code + func->code_len; 5376 while (ip < end) { 5377 sv_op_t op = (sv_op_t)*ip; 5378 if (op == OP_AWAIT || op == OP_FOR_AWAIT_OF || op == OP_AWAIT_ITER_NEXT) { 5379 func->has_await = true; 5380 break; 5381 } 5382 int sz = sv_op_size[op]; 5383 if (sz <= 0) break; 5384 ip += sz; 5385 }} 5386 5387 sv_compile_ctx_cleanup(&comp); 5388 return func; 5389} 5390 5391const char *const sv_op_names[OP__COUNT] = { 5392#define OP_DEF(name, size, n_pop, n_push, f) [OP_##name] = #name, 5393#include "silver/opcode.h" 5394}; 5395 5396enum { 5397 SVF_none, SVF_u8, SVF_i8, SVF_u16, SVF_i16, SVF_u32, SVF_i32, 5398 SVF_atom, SVF_atom_u8, SVF_label, SVF_label8, SVF_loc, SVF_loc8, 5399 SVF_loc_atom, SVF_arg, SVF_const, SVF_const8, SVF_npop, SVF_var_ref, 5400}; 5401 5402static const uint8_t sv_op_fmts[OP__COUNT] = { 5403#define OP_DEF(name, size, n_pop, n_push, f) [OP_##name] = SVF_##f, 5404#include "silver/opcode.h" 5405}; 5406 5407void sv_disasm(ant_t *js, sv_func_t *func, const char *label) { 5408 const char *fname = func->name ? func->name : ""; 5409 5410 fprintf(stderr, "[generated bytecode for function: %s (%p <SharedFunctionInfo %s>)]\n", 5411 fname, (void *)func, fname); 5412 fprintf(stderr, "Bytecode length: %d\n", func->code_len); 5413 fprintf(stderr, "Parameter count %d\n", func->param_count); 5414 fprintf(stderr, "Register count %d\n", func->max_locals); 5415 fprintf(stderr, "Frame size %d\n", func->max_locals * (int)sizeof(ant_value_t)); 5416 5417 int pc = 0; 5418 while (pc < func->code_len) { 5419 uint8_t op = func->code[pc]; 5420 const char *name = (op < OP__COUNT) ? sv_op_names[op] : "???"; 5421 uint8_t size = (op < OP__COUNT) ? sv_op_size[op] : 1; 5422 uint8_t fmt = (op < OP__COUNT) ? sv_op_fmts[op] : SVF_none; 5423 5424 uint32_t line, col; 5425 if (sv_lookup_srcpos(func, pc, &line, &col)) 5426 fprintf(stderr, "%5u S> ", line); 5427 else 5428 fprintf(stderr, " "); 5429 5430 fprintf(stderr, "%p @ %4d : ", (void *)(func->code + pc), pc); 5431 5432 char hex[32]; 5433 int hlen = 0; 5434 for (int i = 0; i < size && i < 8; i++) 5435 hlen += snprintf(hex + hlen, sizeof(hex) - hlen, "%02x ", func->code[pc + i]); 5436 5437 fprintf(stderr, "%-18s", hex); 5438 fprintf(stderr, "%s", name ? name : "???"); 5439 5440 switch (fmt) { 5441 case SVF_u8: 5442 fprintf(stderr, " [%d]", func->code[pc + 1]); 5443 break; 5444 case SVF_i8: 5445 fprintf(stderr, " [%d]", (int8_t)func->code[pc + 1]); 5446 break; 5447 case SVF_u16: 5448 fprintf(stderr, " [%d]", sv_get_u16(func->code + pc + 1)); 5449 break; 5450 case SVF_i16: 5451 fprintf(stderr, " [%d]", (int16_t)sv_get_u16(func->code + pc + 1)); 5452 break; 5453 case SVF_u32: 5454 fprintf(stderr, " [%d]", (int)sv_get_u32(func->code + pc + 1)); 5455 break; 5456 case SVF_i32: 5457 fprintf(stderr, " [%d]", (int32_t)sv_get_u32(func->code + pc + 1)); 5458 break; 5459 case SVF_atom: { 5460 uint32_t idx = sv_get_u32(func->code + pc + 1); 5461 if (idx < (uint32_t)func->atom_count) 5462 fprintf(stderr, " [%.*s]", (int)func->atoms[idx].len, func->atoms[idx].str); 5463 else 5464 fprintf(stderr, " a%u", idx); 5465 if ((op == OP_GET_GLOBAL || op == OP_GET_GLOBAL_UNDEF || 5466 op == OP_GET_FIELD || op == OP_GET_FIELD2 || op == OP_PUT_FIELD) && size >= 7) 5467 fprintf(stderr, " ic[%u]", sv_get_u16(func->code + pc + 5)); 5468 break; 5469 } 5470 case SVF_atom_u8: { 5471 uint32_t idx = sv_get_u32(func->code + pc + 1); 5472 uint8_t extra = func->code[pc + 5]; 5473 if (idx < (uint32_t)func->atom_count) 5474 fprintf(stderr, " [%.*s], [%d]", (int)func->atoms[idx].len, func->atoms[idx].str, extra); 5475 else 5476 fprintf(stderr, " a%u, [%d]", idx, extra); 5477 break; 5478 } 5479 case SVF_label: { 5480 int32_t off = (int32_t)sv_get_u32(func->code + pc + 1); 5481 fprintf(stderr, " [%d] (%d)", off, pc + size + off); 5482 break; 5483 } 5484 case SVF_label8: { 5485 int8_t off = (int8_t)func->code[pc + 1]; 5486 fprintf(stderr, " [%d] (%d)", off, pc + size + off); 5487 break; 5488 } 5489 case SVF_loc: 5490 fprintf(stderr, " r%d", sv_get_u16(func->code + pc + 1)); 5491 break; 5492 case SVF_loc8: 5493 fprintf(stderr, " r%d", func->code[pc + 1]); 5494 break; 5495 case SVF_loc_atom: { 5496 uint16_t slot = sv_get_u16(func->code + pc + 1); 5497 uint32_t aidx = sv_get_u32(func->code + pc + 3); 5498 fprintf(stderr, " r%d", slot); 5499 if (aidx < (uint32_t)func->atom_count) 5500 fprintf(stderr, ", [%.*s]", (int)func->atoms[aidx].len, func->atoms[aidx].str); 5501 else 5502 fprintf(stderr, ", a%u", aidx); 5503 break; 5504 } 5505 case SVF_arg: 5506 fprintf(stderr, " a%d", sv_get_u16(func->code + pc + 1)); 5507 break; 5508 case SVF_const: { 5509 uint32_t idx = sv_get_u32(func->code + pc + 1); 5510 fprintf(stderr, " [%u]", idx); 5511 break; 5512 } 5513 case SVF_const8: 5514 fprintf(stderr, " [%d]", func->code[pc + 1]); 5515 break; 5516 case SVF_npop: 5517 fprintf(stderr, " %d", sv_get_u16(func->code + pc + 1)); 5518 break; 5519 case SVF_var_ref: 5520 fprintf(stderr, " [%d]", sv_get_u16(func->code + pc + 1)); 5521 break; 5522 default: 5523 break; 5524 } 5525 5526 fprintf(stderr, "\n"); 5527 pc += size; 5528 } 5529 5530 fprintf(stderr, "Constant pool (size = %d)\n", func->const_count); 5531 for (int i = 0; i < func->const_count; i++) { 5532 ant_value_t v = func->constants[i]; 5533 uint8_t t = vtype(v); 5534 if (t == T_STR) { 5535 ant_offset_t slen; 5536 ant_offset_t soff = vstr(js, v, &slen); 5537 fprintf(stderr, " %d: <String[%d]: #%.*s>\n", i, (int)slen, (int)slen, (const char *)(uintptr_t)soff); 5538 } else if (t == T_NUM) { 5539 fprintf(stderr, " %d: <Number [%g]>\n", i, tod(v)); 5540 } else if (t == T_CFUNC) { 5541 sv_func_t *child = (sv_func_t *)(uintptr_t)vdata(v); 5542 const char *cname = child->name ? child->name : ""; 5543 fprintf(stderr, " %d: <SharedFunctionInfo %s>\n", i, cname); 5544 } else fprintf(stderr, " %d: <Unknown type=%d>\n", i, t); 5545 } 5546 5547 if (func->atom_count > 0) { 5548 fprintf(stderr, "Atom table (size = %d)\n", func->atom_count); 5549 for (int i = 0; i < func->atom_count; i++) 5550 fprintf(stderr, " %d: <String[%d]: #%.*s>\n", 5551 i, (int)func->atoms[i].len, (int)func->atoms[i].len, func->atoms[i].str); 5552 } 5553 5554 fprintf(stderr, "Handler Table (size = 0)\n"); 5555 fprintf(stderr, "Source Position Table (size = %d)\n", func->srcpos_count); 5556 fprintf(stderr, "\n"); 5557 5558 for (int i = 0; i < func->const_count; i++) { 5559 if (vtype(func->constants[i]) == T_NTARG) { 5560 sv_func_t *child = (sv_func_t *)(uintptr_t)vdata(func->constants[i]); 5561 char child_label[256]; 5562 snprintf(child_label, sizeof(child_label), "%s/closure[%d]", label, i); 5563 sv_disasm(js, child, child_label); 5564 }} 5565} 5566 5567sv_func_t *sv_compile(ant_t *js, sv_ast_t *program, sv_compile_mode_t mode, const char *source, ant_offset_t source_len) { 5568 if (!program || program->type != N_PROGRAM) return NULL; 5569 if (sv_compile_trace_unlikely) fprintf( 5570 stderr, "[compile] start kind=program mode=%d len=%u body=%d strict=%d\n", 5571 (int)mode, (unsigned)source_len, 5572 program->args.count, (program->flags & FN_PARSE_STRICT) != 0 ? 1 : 0 5573 ); 5574 5575 static const char *k_top_name_script = "<script>"; 5576 static const char *k_top_name_module = "<module>"; 5577 static const char *k_top_name_eval = "<eval>"; 5578 static const char *k_top_name_repl = "<repl>"; 5579 const char *top_name = k_top_name_script; 5580 5581 switch (mode) { 5582 case SV_COMPILE_MODULE: top_name = k_top_name_module; break; 5583 case SV_COMPILE_EVAL: top_name = k_top_name_eval; break; 5584 case SV_COMPILE_REPL: top_name = k_top_name_repl; break; 5585 case SV_COMPILE_SCRIPT: 5586 default: top_name = k_top_name_script; break; 5587 } 5588 5589 sv_ast_t top_fn; 5590 memset(&top_fn, 0, sizeof(top_fn)); 5591 5592 top_fn.type = N_FUNC; 5593 top_fn.line = 1; 5594 top_fn.str = top_name; 5595 top_fn.len = (uint32_t)strlen(top_name); 5596 top_fn.src_off = 0; 5597 top_fn.src_end = (source_len > 0) ? (uint32_t)source_len : 0; 5598 top_fn.body = sv_ast_new(N_BLOCK); 5599 top_fn.body->args = program->args; 5600 5601 sv_compiler_t root; 5602 sv_compile_ctx_init_root( 5603 &root, js, js->filename, 5604 pin_source_text(source, source_len), 5605 source_len, mode, 5606 (program->flags & FN_PARSE_STRICT) != 0, NULL 5607 ); 5608 5609 root.line_table = sv_compile_ctx_build_line_table(root.source, source_len); 5610 sv_func_t *func = compile_function_body(&root, &top_fn, mode); 5611 sv_compile_ctx_free_line_table(root.line_table); 5612 5613 if (sv_compile_trace_unlikely) fprintf( 5614 stderr, "[compile] end kind=program mode=%d thrown=%d func=%p\n", 5615 (int)mode, js->thrown_exists ? 1 : 0, (void *)func 5616 ); 5617 5618 if (js->thrown_exists || !func) return NULL; 5619 return func; 5620} 5621 5622sv_func_t *sv_compile_function(ant_t *js, const char *source, size_t len, bool is_async, bool is_generator) { 5623 if (sv_compile_trace_unlikely) fprintf( 5624 stderr, "[compile] start kind=function len=%u async=%d generator=%d\n", 5625 (unsigned)len, is_async ? 1 : 0, is_generator ? 1 : 0 5626 ); 5627 5628 const char *prefix = is_async 5629 ? (is_generator ? "(async function*" : "(async function") 5630 : (is_generator ? "(function*" : "(function"); 5631 5632 size_t prefix_len = strlen(prefix); 5633 size_t wrapped_len = prefix_len + len + 1; 5634 5635 char *wrapped = malloc(wrapped_len + 1); 5636 if (!wrapped) return NULL; 5637 5638 memcpy(wrapped, prefix, prefix_len); 5639 memcpy(wrapped + prefix_len, source, len); 5640 wrapped[prefix_len + len] = ')'; 5641 wrapped[wrapped_len] = '\0'; 5642 5643 bool parse_strict = sv_vm_is_strict(js->vm); 5644 code_arena_mark_t parse_mark = parse_arena_mark(); 5645 sv_ast_t *program = sv_parse(js, wrapped, (ant_offset_t)wrapped_len, parse_strict); 5646 5647 if (!program) { 5648 parse_arena_rewind(parse_mark); 5649 free(wrapped); 5650 return NULL; 5651 } 5652 5653 sv_ast_t *func_node = NULL; 5654 if (program->args.count > 0) { 5655 sv_ast_t *stmt = program->args.items[0]; 5656 if (stmt && stmt->type == N_FUNC) func_node = stmt; 5657 else if (stmt && stmt->left && stmt->left->type == N_FUNC) func_node = stmt->left; 5658 } 5659 5660 if (!func_node) { 5661 parse_arena_rewind(parse_mark); 5662 free(wrapped); 5663 return NULL; 5664 } 5665 5666 sv_compiler_t root; 5667 sv_compile_ctx_init_root( 5668 &root, js, js->filename, 5669 pin_source_text(wrapped, (ant_offset_t)wrapped_len), 5670 (ant_offset_t)wrapped_len, SV_COMPILE_SCRIPT, 5671 (program->flags & FN_PARSE_STRICT) != 0, NULL 5672 ); 5673 5674 root.line_table = sv_compile_ctx_build_line_table(root.source, (ant_offset_t)wrapped_len); 5675 sv_func_t *func = compile_function_body(&root, func_node, SV_COMPILE_SCRIPT); 5676 5677 sv_compile_ctx_free_line_table(root.line_table); 5678 parse_arena_rewind(parse_mark); 5679 free(wrapped); 5680 5681 if (sv_compile_trace_unlikely) fprintf( 5682 stderr, "[compile] end kind=function thrown=%d func=%p\n", 5683 js->thrown_exists ? 1 : 0, (void *)func 5684 ); 5685 5686 if (js->thrown_exists || !func) return NULL; 5687 return func; 5688} 5689 5690sv_func_t *sv_compile_function_with_params( 5691 ant_t *js, 5692 const sv_param_t *params, 5693 int param_count, 5694 const char *body, 5695 size_t body_len, 5696 bool is_async 5697) { 5698 if (sv_compile_trace_unlikely) fprintf( 5699 stderr, "[compile] start kind=function-with-params len=%u params=%d async=%d\n", 5700 (unsigned)body_len, param_count, is_async ? 1 : 0 5701 ); 5702 5703 if (!body) { 5704 body = ""; 5705 body_len = 0; 5706 } 5707 5708 bool parse_strict = sv_vm_is_strict(js->vm); 5709 code_arena_mark_t parse_mark = parse_arena_mark(); 5710 sv_ast_t *program = sv_parse(js, body, (ant_offset_t)body_len, parse_strict); 5711 5712 if (!program) { 5713 parse_arena_rewind(parse_mark); 5714 return NULL; 5715 } 5716 5717 static const char *k_top_name_function = "<function>"; 5718 static const char *k_top_name_async_function = "<async function>"; 5719 const char *top_name = is_async ? k_top_name_async_function : k_top_name_function; 5720 5721 sv_ast_t top_fn; 5722 memset(&top_fn, 0, sizeof(top_fn)); 5723 5724 top_fn.type = N_FUNC; 5725 top_fn.line = 1; 5726 top_fn.str = top_name; 5727 top_fn.len = (uint32_t)strlen(top_name); 5728 top_fn.src_off = 0; 5729 top_fn.src_end = (body_len > 0) ? (uint32_t)body_len : 0; 5730 if (is_async) top_fn.flags |= FN_ASYNC; 5731 5732 for (int i = 0; i < param_count; i++) { 5733 const char *name = (params && params[i].name) ? params[i].name : ""; 5734 size_t name_len = 0; 5735 if (params && params[i].name) { 5736 name_len = params[i].len ? params[i].len : strlen(name); 5737 } 5738 5739 sv_ast_t *ident = sv_ast_new(N_IDENT); 5740 if (!ident) { 5741 parse_arena_rewind(parse_mark); 5742 return NULL; 5743 } 5744 5745 ident->str = name; 5746 ident->len = (uint32_t)name_len; 5747 ident->line = 1; 5748 ident->col = 1; 5749 sv_ast_list_push(&top_fn.args, ident); 5750 } 5751 5752 top_fn.body = sv_ast_new(N_BLOCK); 5753 if (!top_fn.body) { 5754 parse_arena_rewind(parse_mark); 5755 return NULL; 5756 } 5757 5758 top_fn.body->args = program->args; 5759 sv_compiler_t root; 5760 5761 sv_compile_ctx_init_root( 5762 &root, js, js->filename, 5763 pin_source_text(body, (ant_offset_t)body_len), 5764 (ant_offset_t)body_len, SV_COMPILE_SCRIPT, 5765 (program->flags & FN_PARSE_STRICT) != 0, NULL 5766 ); 5767 5768 root.line_table = sv_compile_ctx_build_line_table(root.source, (ant_offset_t)body_len); 5769 sv_func_t *func = compile_function_body(&root, &top_fn, SV_COMPILE_SCRIPT); 5770 5771 sv_compile_ctx_free_line_table(root.line_table); 5772 parse_arena_rewind(parse_mark); 5773 5774 if (sv_compile_trace_unlikely) fprintf( 5775 stderr, "[compile] end kind=function-with-params thrown=%d func=%p\n", 5776 js->thrown_exists ? 1 : 0, (void *)func 5777 ); 5778 5779 if (js->thrown_exists || !func) return NULL; 5780 return func; 5781}