parser.c (65677B)
1 #include <stddef.h> 2 #include <stdint.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 #include "internal.h" 7 8 /* Public CG API coverage goals for this frontend are tracked in 9 * doc/toy-todo.md. Keep this file aligned with include/kit/cg.h rather than 10 * private CG implementation details. */ 11 12 /* ============================================================ 13 * Parser (single-pass parse -> codegen) 14 * ============================================================ */ 15 16 static int toy_parse_stmt(ToyParser* p); 17 18 int toy_parse_block(ToyParser* p) { 19 size_t saved_nvars = p->nvars; 20 if (!toy_parser_expect(p, TOK_LBRACE)) { 21 toy_error(p, p->cur.loc, "expected '{'"); 22 return 0; 23 } 24 while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) { 25 if (!toy_parse_stmt(p)) return 0; 26 } 27 if (!toy_parser_expect(p, TOK_RBRACE)) { 28 toy_error(p, p->cur.loc, "expected '}'"); 29 return 0; 30 } 31 p->nvars = saved_nvars; 32 return 1; 33 } 34 35 /* Pushes [base_ptr, index] for kit_cg_elem: the array local is decayed to a 36 * pointer to its element type (its address, bitcast to *elem), then the index 37 * value is pushed on top. The following kit_cg_elem(0) yields the element 38 * PLACE. */ 39 static void toy_push_local_indexed(ToyParser* p, KitCgLocal slot, 40 KitCgTypeId elem_ty, uint64_t index) { 41 kit_cg_push_local(p->cg, slot); 42 kit_cg_addr(p->cg); 43 kit_cg_bitcast(p->cg, kit_cg_type_ptr(p->c, elem_ty, 0)); 44 kit_cg_push_int(p->cg, index, p->size_type); 45 } 46 47 static int toy_check_source_value(ToyParser* p, KitCgTypeId expected_cg, 48 ToyTypeId expected_toy, KitCgTypeId actual_cg, 49 ToyTypeId actual_toy, const char* message) { 50 if (expected_toy != TOY_TYPE_NONE) { 51 if (!toy_type_accepts_type(p, expected_toy, actual_toy)) { 52 toy_error(p, p->cur.loc, message); 53 return 0; 54 } 55 return 1; 56 } 57 if (!toy_type_can_implicitly_cast(p, actual_cg, expected_cg)) { 58 toy_error(p, p->cur.loc, message); 59 return 0; 60 } 61 return 1; 62 } 63 64 static int toy_records_have_matching_storage(ToyParser* p, KitCgTypeId expected, 65 KitCgTypeId actual) { 66 uint32_t i; 67 const KitCgRecordLayout* el; 68 const KitCgRecordLayout* al; 69 if (kit_cg_type_kind(p->c, expected) != KIT_CG_TYPE_RECORD || 70 kit_cg_type_kind(p->c, actual) != KIT_CG_TYPE_RECORD) { 71 return 0; 72 } 73 el = kit_cg_type_record_layout(p->c, expected); 74 al = kit_cg_type_record_layout(p->c, actual); 75 if (!el || !al) return 0; 76 if (el->nfields != al->nfields) return 0; 77 for (i = 0; i < el->nfields; ++i) { 78 if (el->fields[i].name != al->fields[i].name || 79 el->fields[i].type != al->fields[i].type) { 80 return 0; 81 } 82 } 83 return 1; 84 } 85 86 static int toy_copy_record_lvalue_to_local(ToyParser* p, KitCgTypeId src_ty, 87 KitCgLocal dst_slot, 88 KitCgTypeId dst_ty) { 89 uint32_t i; 90 const KitCgRecordLayout* L; 91 if (!toy_records_have_matching_storage(p, dst_ty, src_ty)) { 92 toy_error(p, p->cur.loc, "record storage mismatch"); 93 return 0; 94 } 95 L = kit_cg_type_record_layout(p->c, dst_ty); 96 if (!L) return 0; 97 for (i = 0; i < L->nfields; ++i) { 98 const KitCgFieldLayout* field = &L->fields[i]; 99 uint64_t offset = field->offset; 100 kit_cg_dup(p->cg); 101 kit_cg_deref(p->cg, (int64_t)offset); 102 kit_cg_load(p->cg, toy_mem_access(p, field->type)); 103 kit_cg_push_local(p->cg, dst_slot); 104 kit_cg_addr(p->cg); 105 kit_cg_deref(p->cg, (int64_t)offset); 106 kit_cg_swap(p->cg); 107 kit_cg_store(p->cg, toy_mem_access(p, field->type)); 108 } 109 kit_cg_drop(p->cg); 110 return 1; 111 } 112 113 static int toy_copy_record_lvalue_to_var(ToyParser* p, KitCgTypeId src_ty, 114 const ToyVar* dst_var, 115 const ToyGlobal* dst_global) { 116 KitCgTypeId dst_ty = dst_var ? dst_var->type : dst_global->type; 117 uint32_t i; 118 const KitCgRecordLayout* L; 119 if (!toy_records_have_matching_storage(p, dst_ty, src_ty)) { 120 toy_error(p, p->cur.loc, "record storage mismatch"); 121 return 0; 122 } 123 L = kit_cg_type_record_layout(p->c, dst_ty); 124 if (!L) return 0; 125 for (i = 0; i < L->nfields; ++i) { 126 const KitCgFieldLayout* field = &L->fields[i]; 127 uint64_t offset = field->offset; 128 kit_cg_dup(p->cg); 129 kit_cg_deref(p->cg, (int64_t)offset); 130 kit_cg_load(p->cg, toy_mem_access(p, field->type)); 131 if (dst_var) { 132 toy_push_var_lvalue(p, dst_var); 133 } else { 134 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, dst_global), 0); 135 } 136 kit_cg_deref(p->cg, (int64_t)offset); 137 kit_cg_swap(p->cg); 138 kit_cg_store(p->cg, toy_mem_access(p, field->type)); 139 } 140 kit_cg_drop(p->cg); 141 return 1; 142 } 143 144 static int toy_parse_array_initializer(ToyParser* p, KitCgLocal slot, 145 KitCgTypeId arr_ty, 146 ToyTypeId arr_toy_type) { 147 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, arr_ty); 148 ToyTypeId elem_toy_type = toy_type_array_elem(p, arr_toy_type); 149 uint64_t count = kit_cg_type_array_count(p->c, arr_ty); 150 uint64_t index = 0; 151 152 if (!toy_parser_expect(p, TOK_LBRACKET)) { 153 toy_error(p, p->cur.loc, "expected array literal"); 154 return 0; 155 } 156 while (p->cur.kind != TOK_RBRACKET && p->cur.kind != TOK_EOF) { 157 KitCgTypeId expr_ty; 158 if (index >= count) { 159 toy_error(p, p->cur.loc, "too many array elements"); 160 return 0; 161 } 162 toy_push_local_indexed(p, slot, elem_ty, index); 163 kit_cg_elem(p->cg, 0); 164 expr_ty = toy_parse_expr(p); 165 if (expr_ty == KIT_CG_TYPE_NONE) return 0; 166 if (!toy_check_source_value(p, elem_ty, elem_toy_type, expr_ty, 167 p->last_type, "array element type mismatch")) { 168 return 0; 169 } 170 if (expr_ty != elem_ty && !toy_emit_checked_cast(p, expr_ty, elem_ty)) 171 return 0; 172 kit_cg_store(p->cg, toy_mem_access(p, elem_ty)); 173 index++; 174 if (!toy_parser_match(p, TOK_COMMA)) break; 175 } 176 if (!toy_parser_expect(p, TOK_RBRACKET)) { 177 toy_error(p, p->cur.loc, "expected ']' after array literal"); 178 return 0; 179 } 180 while (index < count) { 181 toy_push_local_indexed(p, slot, elem_ty, index); 182 kit_cg_elem(p->cg, 0); 183 kit_cg_push_int(p->cg, 0, elem_ty); 184 kit_cg_store(p->cg, toy_mem_access(p, elem_ty)); 185 index++; 186 } 187 return 1; 188 } 189 190 static int toy_parse_record_initializer(ToyParser* p, KitCgLocal slot, 191 KitCgTypeId record_ty, 192 ToyTypeId record_toy_type) { 193 uint32_t i; 194 const KitCgRecordLayout* L = kit_cg_type_record_layout(p->c, record_ty); 195 uint32_t nfields = L ? L->nfields : 0; 196 ToyNamedType* named = toy_find_named_type_by_type(p, record_ty); 197 int positional = named && named->kind == TOY_NAMED_TUPLE; 198 (void)record_toy_type; 199 if (!L) return 0; 200 if (p->cur.kind == TOK_IDENT) toy_parser_advance(p); 201 if (!toy_parser_expect(p, TOK_LBRACE)) { 202 toy_error(p, p->cur.loc, "expected record literal"); 203 return 0; 204 } 205 206 for (i = 0; i < nfields; ++i) { 207 const KitCgFieldLayout* field = &L->fields[i]; 208 uint64_t foff = field->offset; 209 kit_cg_push_local(p->cg, slot); 210 kit_cg_addr(p->cg); 211 kit_cg_deref(p->cg, (int64_t)foff); 212 kit_cg_push_int(p->cg, 0, field->type); 213 kit_cg_store(p->cg, toy_mem_access(p, field->type)); 214 } 215 216 if (positional) { 217 uint32_t field_index = 0; 218 while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) { 219 const KitCgFieldLayout* field; 220 KitCgTypeId expr_ty; 221 uint64_t foff; 222 if (field_index >= nfields) { 223 toy_error(p, p->cur.loc, "too many tuple fields"); 224 return 0; 225 } 226 field = &L->fields[field_index]; 227 foff = field->offset; 228 kit_cg_push_local(p->cg, slot); 229 kit_cg_addr(p->cg); 230 kit_cg_deref(p->cg, (int64_t)foff); 231 expr_ty = toy_parse_expr(p); 232 if (expr_ty == KIT_CG_TYPE_NONE) return 0; 233 { 234 ToyTypeId expected = (named && field_index < named->nfields) 235 ? named->fields[field_index].toy_type 236 : TOY_TYPE_NONE; 237 if (!toy_check_source_value(p, field->type, expected, expr_ty, 238 p->last_type, 239 "tuple field type mismatch")) { 240 return 0; 241 } 242 } 243 if (expr_ty != field->type && 244 !toy_emit_checked_cast(p, expr_ty, field->type)) 245 return 0; 246 kit_cg_store(p->cg, toy_mem_access(p, field->type)); 247 field_index++; 248 if (!toy_parser_match(p, TOK_COMMA)) break; 249 } 250 if (!toy_parser_expect(p, TOK_RBRACE)) { 251 toy_error(p, p->cur.loc, "expected '}' after tuple literal"); 252 return 0; 253 } 254 return 1; 255 } 256 257 while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) { 258 KitSym field_name; 259 KitCgFieldLayout field; 260 uint32_t field_index; 261 KitCgTypeId expr_ty; 262 uint64_t foff = 0; 263 if (p->cur.kind != TOK_IDENT) { 264 toy_error(p, p->cur.loc, "expected field name"); 265 return 0; 266 } 267 field_name = toy_tok_sym(p, p->cur); 268 toy_parser_advance(p); 269 if (!toy_parser_expect(p, TOK_COLON)) { 270 toy_error(p, p->cur.loc, "expected ':' in record literal"); 271 return 0; 272 } 273 if (!toy_record_field_index(p, record_ty, field_name, &field_index, 274 &field)) { 275 toy_error(p, p->cur.loc, "unknown record field"); 276 return 0; 277 } 278 foff = field.offset; 279 kit_cg_push_local(p->cg, slot); 280 kit_cg_addr(p->cg); 281 kit_cg_deref(p->cg, (int64_t)foff); 282 expr_ty = toy_parse_expr(p); 283 if (expr_ty == KIT_CG_TYPE_NONE) return 0; 284 { 285 ToyTypeId expected = (named && field_index < named->nfields) 286 ? named->fields[field_index].toy_type 287 : TOY_TYPE_NONE; 288 if (!toy_check_source_value(p, field.type, expected, expr_ty, 289 p->last_type, "record field type mismatch")) { 290 return 0; 291 } 292 } 293 if (expr_ty != field.type && !toy_emit_checked_cast(p, expr_ty, field.type)) 294 return 0; 295 kit_cg_store(p->cg, toy_mem_access(p, field.type)); 296 if (!toy_parser_match(p, TOK_COMMA)) break; 297 } 298 if (!toy_parser_expect(p, TOK_RBRACE)) { 299 toy_error(p, p->cur.loc, "expected '}' after record literal"); 300 return 0; 301 } 302 return 1; 303 } 304 305 static int toy_parse_value_block_body_to_local(ToyParser* p, KitCgLocal slot, 306 KitCgTypeId result_ty, 307 ToyTypeId result_toy_type); 308 309 static int toy_parse_if_initializer(ToyParser* p, KitCgLocal slot, 310 KitCgTypeId result_ty, 311 ToyTypeId result_toy_type) { 312 KitCgTypeId cond_ty; 313 KitCgIf it; 314 if (!toy_parser_match(p, TOK_IF)) return 0; 315 cond_ty = toy_parse_expr(p); 316 if (cond_ty == KIT_CG_TYPE_NONE) return 0; 317 if (!toy_emit_truthy(p, cond_ty)) return 0; 318 it = kit_cg_if_begin(p->cg); 319 320 if (!toy_parser_expect(p, TOK_LBRACE)) { 321 toy_error(p, p->cur.loc, "expected '{' in if expression"); 322 return 0; 323 } 324 if (!toy_parse_value_block_body_to_local(p, slot, result_ty, result_toy_type)) 325 return 0; 326 327 kit_cg_if_else(p->cg, it); 328 329 if (!toy_parser_expect(p, TOK_ELSE) || !toy_parser_expect(p, TOK_LBRACE)) { 330 toy_error(p, p->cur.loc, "expected else block in if expression"); 331 return 0; 332 } 333 if (!toy_parse_value_block_body_to_local(p, slot, result_ty, result_toy_type)) 334 return 0; 335 336 kit_cg_if_end(p->cg, it); 337 return 1; 338 } 339 340 static int toy_parse_value_block_body_to_local(ToyParser* p, KitCgLocal slot, 341 KitCgTypeId result_ty, 342 ToyTypeId result_toy_type) { 343 size_t saved_nvars = p->nvars; 344 while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) { 345 KitCgTypeId arm_ty; 346 if (p->cur.kind == TOK_LET || p->cur.kind == TOK_VAR || 347 p->cur.kind == TOK_IF || p->cur.kind == TOK_WHILE || 348 p->cur.kind == TOK_SWITCH || p->cur.kind == TOK_LABEL || 349 p->cur.kind == TOK_GOTO || p->cur.kind == TOK_BREAK || 350 p->cur.kind == TOK_CONTINUE || p->cur.kind == TOK_RETURN || 351 p->cur.kind == TOK_LBRACE) { 352 if (!toy_parse_stmt(p)) { 353 p->nvars = saved_nvars; 354 return 0; 355 } 356 continue; 357 } 358 arm_ty = toy_parse_expr(p); 359 if (arm_ty == KIT_CG_TYPE_NONE) { 360 p->nvars = saved_nvars; 361 return 0; 362 } 363 if (toy_parser_match(p, TOK_SEMI)) { 364 if (arm_ty != toy_builtin_type(p, KIT_CG_BUILTIN_VOID)) 365 kit_cg_drop(p->cg); 366 continue; 367 } 368 if (!toy_check_source_value(p, result_ty, result_toy_type, arm_ty, 369 p->last_type, "block value type mismatch")) { 370 p->nvars = saved_nvars; 371 return 0; 372 } 373 if (arm_ty != result_ty && !toy_emit_checked_cast(p, arm_ty, result_ty)) { 374 p->nvars = saved_nvars; 375 return 0; 376 } 377 kit_cg_push_local(p->cg, slot); 378 kit_cg_swap(p->cg); 379 kit_cg_store(p->cg, toy_mem_access(p, result_ty)); 380 if (!toy_parser_expect(p, TOK_RBRACE)) { 381 toy_error(p, p->cur.loc, "expected '}' after value block"); 382 p->nvars = saved_nvars; 383 return 0; 384 } 385 p->nvars = saved_nvars; 386 return 1; 387 } 388 toy_error(p, p->cur.loc, "missing block value"); 389 p->nvars = saved_nvars; 390 return 0; 391 } 392 393 static int toy_parse_value_block_to_local(ToyParser* p, KitCgLocal slot, 394 KitCgTypeId result_ty, 395 ToyTypeId result_toy_type) { 396 if (!toy_parser_expect(p, TOK_LBRACE)) { 397 toy_error(p, p->cur.loc, "expected value block"); 398 return 0; 399 } 400 return toy_parse_value_block_body_to_local(p, slot, result_ty, 401 result_toy_type); 402 } 403 404 static int toy_parse_switch_strategy_hint(ToyParser* p, 405 KitCgSwitchHint* hint_out) { 406 *hint_out = KIT_CG_SWITCH_TARGET_DEFAULT; 407 if (p->cur.kind != TOK_AT || toy_lexer_peek(&p->lex).kind != TOK_LBRACKET) 408 return 1; 409 toy_parser_advance(p); 410 if (!toy_parser_expect(p, TOK_LBRACKET)) { 411 toy_error(p, p->cur.loc, "expected switch strategy list"); 412 return 0; 413 } 414 while (p->cur.kind != TOK_RBRACKET && p->cur.kind != TOK_EOF) { 415 KitSym name; 416 if (!toy_parse_attr_dot_name(p, &name)) return 0; 417 if (toy_sym_is(p, name, "branch_chain")) { 418 *hint_out = KIT_CG_SWITCH_BRANCH_CHAIN; 419 } else if (toy_sym_is(p, name, "jump_table")) { 420 *hint_out = KIT_CG_SWITCH_JUMP_TABLE; 421 } else { 422 toy_error(p, p->cur.loc, "unknown switch strategy"); 423 return 0; 424 } 425 if (!toy_parser_match(p, TOK_COMMA)) break; 426 } 427 if (!toy_parser_expect(p, TOK_RBRACKET)) { 428 toy_error(p, p->cur.loc, "expected ']' after switch strategy list"); 429 return 0; 430 } 431 return 1; 432 } 433 434 static int toy_parse_switch_initializer(ToyParser* p, KitCgLocal slot, 435 KitCgTypeId result_ty, 436 ToyTypeId result_toy_type) { 437 KitCgTypeId selector_ty; 438 KitCgLocal selector_slot; 439 KitCgLabel end_label; 440 KitCgLabel dispatch_label; 441 KitCgLabel default_arm_label = KIT_CG_LABEL_NONE; 442 KitCgLabel unreachable_label = KIT_CG_LABEL_NONE; 443 ToyNamedType* selector_enum; 444 unsigned char* enum_seen = NULL; 445 size_t enum_seen_size = 0; 446 int saw_default = 0; 447 size_t enum_seen_count = 0; 448 KitCgSwitchCase* cases = NULL; 449 size_t ncases = 0; 450 size_t cap_cases = 0; 451 KitCgSwitchHint hint; 452 KitCgSwitch sw; 453 454 if (!toy_parser_match(p, TOK_SWITCH)) return 0; 455 if (!toy_parse_switch_strategy_hint(p, &hint)) return 0; 456 selector_ty = toy_parse_expr(p); 457 if (selector_ty == KIT_CG_TYPE_NONE) return 0; 458 if (!toy_type_is_intlike(p, selector_ty)) { 459 toy_error(p, p->cur.loc, "switch selector must be integer-like"); 460 return 0; 461 } 462 selector_slot = kit_cg_local(p->cg, selector_ty, toy_slot_attrs(0)); 463 kit_cg_push_local(p->cg, selector_slot); 464 kit_cg_swap(p->cg); 465 kit_cg_store(p->cg, toy_mem_access(p, selector_ty)); 466 end_label = kit_cg_label_new(p->cg); 467 dispatch_label = kit_cg_label_new(p->cg); 468 /* Skip the arm bodies on entry; come back through the dispatch label. */ 469 kit_cg_jump(p->cg, dispatch_label); 470 selector_enum = toy_find_named_type_by_type(p, selector_ty); 471 if (!selector_enum || selector_enum->kind != TOY_NAMED_ENUM) 472 selector_enum = NULL; 473 if (selector_enum) { 474 enum_seen_size = 475 (selector_enum->nenum_values ? selector_enum->nenum_values : 1u) * 476 sizeof *enum_seen; 477 enum_seen = (unsigned char*)toy_parser_zalloc( 478 p, selector_enum->nenum_values ? selector_enum->nenum_values : 1u, 479 sizeof *enum_seen, "enum switch state"); 480 if (!enum_seen) return 0; 481 } 482 483 if (!toy_parser_expect(p, TOK_LBRACE)) { 484 toy_error(p, p->cur.loc, "expected '{' after switch selector"); 485 toy_parser_free_mem(p, enum_seen, enum_seen_size); 486 return 0; 487 } 488 while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) { 489 KitCgLabel arm_label = kit_cg_label_new(p->cg); 490 if (p->cur.kind == TOK_DEFAULT) { 491 saw_default = 1; 492 default_arm_label = arm_label; 493 toy_parser_advance(p); 494 } else { 495 for (;;) { 496 int64_t value; 497 size_t i; 498 if (!toy_parse_switch_label_value(p, selector_ty, &value)) { 499 toy_parser_free_mem(p, enum_seen, enum_seen_size); 500 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 501 return 0; 502 } 503 if (selector_enum) { 504 for (i = 0; i < selector_enum->nenum_values; ++i) { 505 if (selector_enum->enum_values[i].value == value) { 506 if (!enum_seen[i]) { 507 enum_seen[i] = 1; 508 enum_seen_count++; 509 } 510 break; 511 } 512 } 513 } 514 if (!toy_parser_reserve(p, (void**)&cases, &cap_cases, ncases + 1u, 515 sizeof *cases, "switch cases")) { 516 toy_parser_free_mem(p, enum_seen, enum_seen_size); 517 return 0; 518 } 519 cases[ncases].value = (uint64_t)value; 520 cases[ncases].label = arm_label; 521 ncases++; 522 if (!toy_parser_match(p, TOK_COMMA)) break; 523 } 524 } 525 kit_cg_label_place(p->cg, arm_label); 526 if (!toy_parse_value_block_to_local(p, slot, result_ty, result_toy_type)) { 527 toy_parser_free_mem(p, enum_seen, enum_seen_size); 528 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 529 return 0; 530 } 531 kit_cg_jump(p->cg, end_label); 532 } 533 if (!toy_parser_expect(p, TOK_RBRACE)) { 534 toy_error(p, p->cur.loc, "expected '}' after switch expression"); 535 toy_parser_free_mem(p, enum_seen, enum_seen_size); 536 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 537 return 0; 538 } 539 if (!saw_default && 540 (!selector_enum || enum_seen_count != selector_enum->nenum_values)) { 541 toy_error(p, p->cur.loc, "expression switch requires default"); 542 toy_parser_free_mem(p, enum_seen, enum_seen_size); 543 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 544 return 0; 545 } 546 kit_cg_label_place(p->cg, dispatch_label); 547 kit_cg_push_local(p->cg, selector_slot); 548 kit_cg_load(p->cg, toy_mem_access(p, selector_ty)); 549 if (saw_default) { 550 sw.default_label = default_arm_label; 551 } else { 552 /* Enum-exhaustive switch with no source default: any value outside the 553 * covered set is undefined behavior — emit an unreachable landing pad. */ 554 unreachable_label = kit_cg_label_new(p->cg); 555 sw.default_label = unreachable_label; 556 } 557 sw.selector_type = selector_ty; 558 sw.cases = cases; 559 sw.ncases = (uint32_t)ncases; 560 sw.hint = hint; 561 kit_cg_switch(p->cg, sw); 562 if (unreachable_label != KIT_CG_LABEL_NONE) { 563 kit_cg_label_place(p->cg, unreachable_label); 564 kit_cg_unreachable(p->cg); 565 } 566 kit_cg_label_place(p->cg, end_label); 567 toy_parser_free_mem(p, enum_seen, enum_seen_size); 568 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 569 return 1; 570 } 571 572 static int toy_parse_while_initializer_named(ToyParser* p, KitCgLocal slot, 573 KitCgTypeId result_ty, 574 ToyTypeId result_toy_type, 575 KitSym label_name) { 576 KitCgTypeId explicit_ty; 577 ToyTypeId explicit_toy_type; 578 KitCgTypeId cond_ty; 579 KitCgScope scope; 580 KitCgLabel else_label; 581 582 if (!toy_parser_match(p, TOK_WHILE)) return 0; 583 if (!toy_parser_expect(p, TOK_LT)) { 584 toy_error(p, p->cur.loc, "expected result type in while expression"); 585 return 0; 586 } 587 explicit_ty = toy_parse_type(p); 588 if (explicit_ty == KIT_CG_TYPE_NONE || !toy_parser_expect(p, TOK_GT)) 589 return 0; 590 explicit_toy_type = p->last_type; 591 if (!toy_check_source_value(p, result_ty, result_toy_type, explicit_ty, 592 explicit_toy_type, 593 "while result type mismatch")) { 594 return 0; 595 } 596 if (!toy_parser_reserve(p, (void**)&p->scopes, &p->cap_scopes, 597 p->nscopes + 1u, sizeof *p->scopes, "scopes")) { 598 return 0; 599 } 600 scope = kit_cg_scope_begin_value(p->cg, result_ty); 601 p->scopes[p->nscopes].name = label_name; 602 p->scopes[p->nscopes].kind = TOY_SCOPE_LOOP; 603 p->scopes[p->nscopes].cg_scope = scope; 604 p->scopes[p->nscopes].result_type = result_ty; 605 p->scopes[p->nscopes].result_toy_type = result_toy_type; 606 p->nscopes++; 607 else_label = kit_cg_label_new(p->cg); 608 609 cond_ty = toy_parse_expr(p); 610 if (cond_ty == KIT_CG_TYPE_NONE) { 611 p->nscopes--; 612 return 0; 613 } 614 if (!toy_emit_truthy(p, cond_ty)) { 615 p->nscopes--; 616 return 0; 617 } 618 kit_cg_branch_false(p->cg, else_label); 619 if (!toy_parse_block(p)) { 620 p->nscopes--; 621 return 0; 622 } 623 kit_cg_continue(p->cg, scope); 624 kit_cg_label_place(p->cg, else_label); 625 if (!toy_parser_expect(p, TOK_ELSE)) { 626 toy_error(p, p->cur.loc, "expected else in while expression"); 627 p->nscopes--; 628 return 0; 629 } 630 if (!toy_parser_expect(p, TOK_LBRACE)) { 631 toy_error(p, p->cur.loc, "expected else block in while expression"); 632 p->nscopes--; 633 return 0; 634 } 635 { 636 KitCgTypeId else_ty = toy_parse_expr(p); 637 if (else_ty == KIT_CG_TYPE_NONE) { 638 p->nscopes--; 639 return 0; 640 } 641 if (!toy_check_source_value(p, result_ty, result_toy_type, else_ty, 642 p->last_type, "while else type mismatch")) { 643 p->nscopes--; 644 return 0; 645 } 646 if (else_ty != result_ty && !toy_emit_checked_cast(p, else_ty, result_ty)) { 647 p->nscopes--; 648 return 0; 649 } 650 } 651 if (!toy_parser_expect(p, TOK_RBRACE)) { 652 toy_error(p, p->cur.loc, "expected '}' after while else"); 653 p->nscopes--; 654 return 0; 655 } 656 kit_cg_scope_end(p->cg, scope); 657 p->nscopes--; 658 kit_cg_push_local(p->cg, slot); 659 kit_cg_swap(p->cg); 660 kit_cg_store(p->cg, toy_mem_access(p, result_ty)); 661 return 1; 662 } 663 664 static int toy_parse_while_initializer(ToyParser* p, KitCgLocal slot, 665 KitCgTypeId result_ty, 666 ToyTypeId result_toy_type) { 667 return toy_parse_while_initializer_named(p, slot, result_ty, result_toy_type, 668 0); 669 } 670 671 static int toy_parse_let_stmt(ToyParser* p) { 672 KitSym name; 673 KitCgTypeId ty = KIT_CG_TYPE_NONE; 674 KitCgTypeId init_ty = KIT_CG_TYPE_NONE; 675 ToyTypeId toy_ty = TOY_TYPE_NONE; 676 ToyTypeId init_toy_type = TOY_TYPE_NONE; 677 KitCgLocal slot; 678 int has_init = 0; 679 int inferred = 0; 680 int is_var = p->cur.kind == TOK_VAR; 681 int is_static = 0; 682 int copy_record_init = 0; 683 toy_parser_advance(p); /* let/var */ 684 if (!toy_skip_attr_list_ex(p, &is_static)) return 0; 685 if (p->cur.kind != TOK_IDENT) { 686 toy_error(p, p->cur.loc, "expected identifier after 'let'"); 687 return 0; 688 } 689 name = toy_tok_sym(p, p->cur); 690 toy_parser_advance(p); 691 692 if (toy_parser_match(p, TOK_COLON)) { 693 ty = toy_parse_type(p); 694 if (ty == KIT_CG_TYPE_NONE) return 0; 695 toy_ty = p->last_type; 696 } else { 697 inferred = 1; 698 if (p->cur.kind != TOK_EQ) { 699 toy_error(p, p->cur.loc, "expected ':' or initializer after identifier"); 700 return 0; 701 } 702 } 703 704 if (is_static) { 705 KitCgDecl decl; 706 KitCgDataDefAttrs data_attrs; 707 KitCgSym sym; 708 KitSym linkage_name; 709 char sym_name[64]; 710 uint8_t buf[1024]; 711 size_t n = (size_t)kit_cg_type_size(p->c, ty); 712 int array_data_init = 0; 713 if (inferred) { 714 toy_error(p, p->cur.loc, "static local requires explicit type"); 715 return 0; 716 } 717 if (n > sizeof buf) { 718 toy_error(p, p->cur.loc, "static initializer too large"); 719 return 0; 720 } 721 memset(buf, 0, n); 722 if (toy_parser_match(p, TOK_EQ)) { 723 if (p->cur.kind == TOK_NUMBER && !p->cur.is_float) { 724 toy_emit_int_bytes(p, (uint64_t)p->cur.int_value, buf, n); 725 toy_parser_advance(p); 726 } else if (p->cur.kind == TOK_STRING && 727 kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY && 728 kit_cg_type_array_elem(p->c, ty) == 729 toy_builtin_type(p, KIT_CG_BUILTIN_I8)) { 730 size_t len = 0; 731 if (!toy_parse_string_bytes(p, buf, sizeof buf, &len)) return 0; 732 if (len > n) { 733 toy_error(p, p->cur.loc, "string initializer too large"); 734 return 0; 735 } 736 } else if (p->cur.kind == TOK_LBRACKET && 737 kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY && 738 toy_lexer_peek(&p->lex).kind == TOK_AT) { 739 array_data_init = 1; 740 } else { 741 toy_error(p, p->cur.loc, "expected constant static initializer"); 742 return 0; 743 } 744 } 745 snprintf(sym_name, sizeof sym_name, ".Ltoy_static_%u", 746 p->module->static_counter++); 747 linkage_name = kit_sym_intern(p->c, kit_slice_cstr(sym_name)); 748 memset(&decl, 0, sizeof decl); 749 decl.kind = KIT_CG_DECL_OBJECT; 750 decl.linkage_name = linkage_name; 751 decl.display_name = name; 752 decl.type = ty; 753 decl.sym.bind = KIT_SB_LOCAL; 754 decl.sym.visibility = KIT_CG_VIS_DEFAULT; 755 decl.as.object.tls_model = KIT_CG_TLS_AUTO; 756 if (!is_var) decl.as.object.flags |= KIT_CG_OBJ_READONLY; 757 sym = kit_cg_decl(p->cg, decl); 758 if (sym == KIT_CG_SYM_NONE) { 759 toy_error(p, p->cur.loc, "failed to declare static local"); 760 return 0; 761 } 762 if (!toy_add_static_local_typed(p, name, ty, toy_ty, sym, is_var)) return 0; 763 memset(&data_attrs, 0, sizeof data_attrs); 764 data_attrs.flags |= KIT_CG_DATADEF_FUNCTION_LOCAL; 765 if (!is_var) data_attrs.flags |= KIT_CG_DATADEF_READONLY; 766 kit_cg_data_begin(p->cg, sym, data_attrs); 767 if (array_data_init) { 768 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, ty); 769 uint64_t total_size = kit_cg_type_size(p->c, ty); 770 uint64_t pos = 0; 771 toy_parser_advance(p); /* '[' */ 772 while (p->cur.kind != TOK_RBRACKET && p->cur.kind != TOK_EOF) { 773 if (!toy_parse_data_array_builtin(p, elem_ty, total_size, &pos)) 774 return 0; 775 if (!toy_parser_match(p, TOK_COMMA)) break; 776 } 777 if (!toy_parser_expect(p, TOK_RBRACKET)) { 778 toy_error(p, p->cur.loc, "expected ']' after static initializer"); 779 return 0; 780 } 781 if (pos < total_size) kit_cg_data_zero(p->cg, total_size - pos); 782 } else { 783 kit_cg_data_bytes(p->cg, buf, n); 784 } 785 kit_cg_data_end(p->cg); 786 if (!toy_parser_expect(p, TOK_SEMI)) { 787 toy_error(p, p->cur.loc, "expected ';' after static local"); 788 return 0; 789 } 790 return 1; 791 } 792 793 if (!inferred && p->cur.kind == TOK_EQ && 794 ((kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY && 795 toy_lexer_peek(&p->lex).kind == TOK_LBRACKET) || 796 (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_RECORD && 797 !toy_type_is_slice(p, toy_ty) && 798 (toy_lexer_peek(&p->lex).kind == TOK_IDENT || 799 toy_lexer_peek(&p->lex).kind == TOK_LBRACE)))) { 800 toy_parser_advance(p); /* = */ 801 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 802 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 803 if (kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ARRAY) { 804 if (!toy_parse_array_initializer(p, slot, ty, toy_ty)) return 0; 805 } else { 806 if (!toy_parse_record_initializer(p, slot, ty, toy_ty)) return 0; 807 } 808 if (!toy_parser_expect(p, TOK_SEMI)) { 809 toy_error(p, p->cur.loc, "expected ';' after let"); 810 return 0; 811 } 812 return 1; 813 } 814 815 if (!inferred && kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_ENUM && 816 p->cur.kind == TOK_EQ && toy_lexer_peek(&p->lex).kind == TOK_DOT) { 817 ToyNamedType* named = toy_find_named_type_by_type(p, ty); 818 KitSym value_name; 819 size_t i; 820 int found = 0; 821 int64_t value = 0; 822 toy_parser_advance(p); /* = */ 823 toy_parser_advance(p); /* . */ 824 if (p->cur.kind != TOK_IDENT) { 825 toy_error(p, p->cur.loc, "expected enum value"); 826 return 0; 827 } 828 value_name = toy_tok_sym(p, p->cur); 829 toy_parser_advance(p); 830 if (!named || named->kind != TOY_NAMED_ENUM) { 831 toy_error(p, p->cur.loc, "unknown enum type"); 832 return 0; 833 } 834 for (i = 0; i < named->nenum_values; ++i) { 835 if (named->enum_values[i].name == value_name) { 836 found = 1; 837 value = named->enum_values[i].value; 838 break; 839 } 840 } 841 if (!found) { 842 toy_error(p, p->cur.loc, "unknown enum value"); 843 return 0; 844 } 845 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 846 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 847 kit_cg_push_local(p->cg, slot); 848 kit_cg_push_int(p->cg, (uint64_t)value, ty); 849 kit_cg_store(p->cg, toy_mem_access(p, ty)); 850 if (!toy_parser_expect(p, TOK_SEMI)) { 851 toy_error(p, p->cur.loc, "expected ';' after let"); 852 return 0; 853 } 854 return 1; 855 } 856 857 if (!inferred && p->cur.kind == TOK_EQ && 858 toy_lexer_peek(&p->lex).kind == TOK_IF) { 859 toy_parser_advance(p); /* = */ 860 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 861 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 862 if (!toy_parse_if_initializer(p, slot, ty, toy_ty)) return 0; 863 if (!toy_parser_expect(p, TOK_SEMI)) { 864 toy_error(p, p->cur.loc, "expected ';' after let"); 865 return 0; 866 } 867 return 1; 868 } 869 870 if (!inferred && p->cur.kind == TOK_EQ && 871 toy_lexer_peek(&p->lex).kind == TOK_SWITCH) { 872 toy_parser_advance(p); /* = */ 873 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 874 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 875 if (!toy_parse_switch_initializer(p, slot, ty, toy_ty)) return 0; 876 if (!toy_parser_expect(p, TOK_SEMI)) { 877 toy_error(p, p->cur.loc, "expected ';' after let"); 878 return 0; 879 } 880 return 1; 881 } 882 883 if (!inferred && p->cur.kind == TOK_EQ && 884 toy_lexer_peek(&p->lex).kind == TOK_WHILE) { 885 toy_parser_advance(p); /* = */ 886 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 887 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 888 if (!toy_parse_while_initializer(p, slot, ty, toy_ty)) return 0; 889 if (!toy_parser_expect(p, TOK_SEMI)) { 890 toy_error(p, p->cur.loc, "expected ';' after let"); 891 return 0; 892 } 893 return 1; 894 } 895 896 if (!inferred && p->cur.kind == TOK_EQ) { 897 ToyLexer tmp_lex = p->lex; 898 ToyToken label_tok = toy_lexer_next(&tmp_lex); 899 ToyToken colon_tok = toy_lexer_next(&tmp_lex); 900 ToyToken while_tok = toy_lexer_next(&tmp_lex); 901 if (label_tok.kind == TOK_IDENT && colon_tok.kind == TOK_COLON && 902 while_tok.kind == TOK_WHILE) { 903 KitSym loop_label; 904 toy_parser_advance(p); /* = */ 905 loop_label = toy_tok_sym(p, p->cur); 906 toy_parser_advance(p); /* label */ 907 if (!toy_parser_expect(p, TOK_COLON)) { 908 toy_error(p, p->cur.loc, "expected ':' after loop label"); 909 return 0; 910 } 911 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 912 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 913 if (!toy_parse_while_initializer_named(p, slot, ty, toy_ty, loop_label)) 914 return 0; 915 if (!toy_parser_expect(p, TOK_SEMI)) { 916 toy_error(p, p->cur.loc, "expected ';' after let"); 917 return 0; 918 } 919 return 1; 920 } 921 } 922 923 if (toy_parser_match(p, TOK_EQ)) { 924 has_init = 1; 925 if (!inferred && toy_type_is_ptr(p, ty) && p->cur.kind == TOK_IDENT && 926 toy_sym_is(p, toy_tok_sym(p, p->cur), "NULL") && 927 toy_lexer_peek(&p->lex).kind == TOK_SEMI) { 928 toy_parser_advance(p); 929 kit_cg_push_int(p->cg, 0, p->int_type); 930 kit_cg_int_to_ptr(p->cg, ty); 931 init_ty = ty; 932 init_toy_type = toy_ty; 933 } else { 934 init_ty = toy_parse_expr(p); 935 if (init_ty == KIT_CG_TYPE_NONE) return 0; 936 init_toy_type = p->last_type; 937 } 938 if (inferred) { 939 ty = init_ty; 940 toy_ty = init_toy_type; 941 } else { 942 if (!toy_check_source_value(p, ty, toy_ty, init_ty, init_toy_type, 943 "type mismatch in let initializer")) { 944 return 0; 945 } 946 if (init_ty != ty) { 947 if (toy_records_have_matching_storage(p, ty, init_ty)) { 948 copy_record_init = 1; 949 } else { 950 if (!toy_emit_checked_cast(p, init_ty, ty)) return 0; 951 } 952 } 953 } 954 } 955 956 slot = kit_cg_local(p->cg, ty, toy_slot_attrs(name)); 957 if (!toy_add_local_typed(p, name, ty, toy_ty, slot, is_var)) return 0; 958 959 if (has_init) { 960 if (toy_type_is_slice(p, init_toy_type)) { 961 if (!toy_copy_record_lvalue_to_local(p, init_ty, slot, ty)) return 0; 962 } else if (copy_record_init || 963 kit_cg_type_kind(p->c, ty) == KIT_CG_TYPE_RECORD) { 964 if (!toy_copy_record_lvalue_to_local(p, init_ty, slot, ty)) return 0; 965 } else { 966 kit_cg_push_local(p->cg, slot); 967 kit_cg_swap(p->cg); 968 kit_cg_store(p->cg, toy_mem_access(p, ty)); 969 } 970 } 971 if (!toy_parser_expect(p, TOK_SEMI)) { 972 toy_error(p, p->cur.loc, "expected ';' after let"); 973 return 0; 974 } 975 return 1; 976 } 977 978 static int toy_parse_if_stmt(ToyParser* p) { 979 KitCgIf it; 980 KitCgTypeId cond_ty; 981 toy_parser_advance(p); /* if */ 982 cond_ty = toy_parse_expr(p); 983 if (cond_ty == KIT_CG_TYPE_NONE) return 0; 984 if (!toy_emit_truthy(p, cond_ty)) return 0; 985 986 it = kit_cg_if_begin(p->cg); 987 988 if (!toy_parse_block(p)) return 0; 989 990 kit_cg_if_else(p->cg, it); 991 992 if (p->cur.kind == TOK_ELSE) { 993 toy_parser_advance(p); /* else */ 994 if (p->cur.kind == TOK_LBRACE) { 995 if (!toy_parse_block(p)) return 0; 996 } else { 997 if (!toy_parse_stmt(p)) return 0; 998 } 999 } 1000 1001 kit_cg_if_end(p->cg, it); 1002 return 1; 1003 } 1004 1005 static int toy_parse_while_stmt_named(ToyParser* p, KitSym label_name) { 1006 KitCgScope scope; 1007 KitCgTypeId cond_ty; 1008 1009 toy_parser_advance(p); /* while */ 1010 1011 if (!toy_parser_reserve(p, (void**)&p->scopes, &p->cap_scopes, 1012 p->nscopes + 1u, sizeof *p->scopes, "scopes")) { 1013 return 0; 1014 } 1015 scope = kit_cg_scope_begin(p->cg); 1016 p->scopes[p->nscopes].name = label_name; 1017 p->scopes[p->nscopes].kind = TOY_SCOPE_LOOP; 1018 p->scopes[p->nscopes].cg_scope = scope; 1019 p->scopes[p->nscopes].result_type = KIT_CG_TYPE_NONE; 1020 p->scopes[p->nscopes].result_toy_type = TOY_TYPE_NONE; 1021 p->nscopes++; 1022 1023 cond_ty = toy_parse_expr(p); 1024 if (cond_ty == KIT_CG_TYPE_NONE) { 1025 p->nscopes--; 1026 return 0; 1027 } 1028 if (!toy_emit_truthy(p, cond_ty)) { 1029 p->nscopes--; 1030 return 0; 1031 } 1032 kit_cg_break_false(p->cg, scope); 1033 1034 if (!toy_parse_block(p)) { 1035 p->nscopes--; 1036 return 0; 1037 } 1038 1039 kit_cg_continue(p->cg, scope); 1040 kit_cg_scope_end(p->cg, scope); 1041 p->nscopes--; 1042 return 1; 1043 } 1044 1045 static int toy_parse_while_stmt(ToyParser* p) { 1046 return toy_parse_while_stmt_named(p, 0); 1047 } 1048 1049 static int toy_parse_switch_stmt_named(ToyParser* p, KitSym label_name) { 1050 KitCgTypeId selector_ty; 1051 KitCgLocal selector_slot; 1052 KitCgLabel end_label; 1053 KitCgLabel dispatch_label; 1054 KitCgLabel default_arm_label = KIT_CG_LABEL_NONE; 1055 KitCgScope scope; 1056 KitCgSwitchCase* cases = NULL; 1057 size_t ncases = 0; 1058 size_t cap_cases = 0; 1059 KitCgSwitchHint hint; 1060 KitCgSwitch sw; 1061 1062 toy_parser_advance(p); /* switch */ 1063 if (!toy_parse_switch_strategy_hint(p, &hint)) return 0; 1064 selector_ty = toy_parse_expr(p); 1065 if (selector_ty == KIT_CG_TYPE_NONE) return 0; 1066 if (!toy_type_is_intlike(p, selector_ty)) { 1067 toy_error(p, p->cur.loc, "switch selector must be integer-like"); 1068 return 0; 1069 } 1070 selector_slot = kit_cg_local(p->cg, selector_ty, toy_slot_attrs(0)); 1071 kit_cg_push_local(p->cg, selector_slot); 1072 kit_cg_swap(p->cg); 1073 kit_cg_store(p->cg, toy_mem_access(p, selector_ty)); 1074 end_label = kit_cg_label_new(p->cg); 1075 dispatch_label = kit_cg_label_new(p->cg); 1076 if (!toy_parser_reserve(p, (void**)&p->scopes, &p->cap_scopes, 1077 p->nscopes + 1u, sizeof *p->scopes, "scopes")) { 1078 return 0; 1079 } 1080 /* scope_begin must precede the jump-to-dispatch so the scope's entry 1081 * block is reachable from the straight-line predecessor. With the 1082 * jump before scope_begin, opt's CFG sees the scope_begin block as 1083 * unreachable and prunes it; scope_end then can't find its handle. */ 1084 scope = kit_cg_scope_begin(p->cg); 1085 p->scopes[p->nscopes].name = label_name; 1086 p->scopes[p->nscopes].kind = TOY_SCOPE_SWITCH; 1087 p->scopes[p->nscopes].cg_scope = scope; 1088 p->scopes[p->nscopes].result_type = KIT_CG_TYPE_NONE; 1089 p->scopes[p->nscopes].result_toy_type = TOY_TYPE_NONE; 1090 p->nscopes++; 1091 /* Skip the arm bodies on entry; come back through the dispatch label. */ 1092 kit_cg_jump(p->cg, dispatch_label); 1093 if (!toy_parser_expect(p, TOK_LBRACE)) { 1094 toy_error(p, p->cur.loc, "expected '{' after switch selector"); 1095 p->nscopes--; 1096 return 0; 1097 } 1098 while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) { 1099 KitCgLabel arm_label = kit_cg_label_new(p->cg); 1100 if (p->cur.kind == TOK_DEFAULT) { 1101 default_arm_label = arm_label; 1102 toy_parser_advance(p); 1103 } else { 1104 for (;;) { 1105 int64_t value; 1106 if (!toy_parse_switch_label_value(p, selector_ty, &value)) { 1107 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 1108 p->nscopes--; 1109 return 0; 1110 } 1111 if (!toy_parser_reserve(p, (void**)&cases, &cap_cases, ncases + 1u, 1112 sizeof *cases, "switch cases")) { 1113 p->nscopes--; 1114 return 0; 1115 } 1116 cases[ncases].value = (uint64_t)value; 1117 cases[ncases].label = arm_label; 1118 ncases++; 1119 if (!toy_parser_match(p, TOK_COMMA)) break; 1120 } 1121 } 1122 kit_cg_label_place(p->cg, arm_label); 1123 if (!toy_parse_block(p)) { 1124 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 1125 p->nscopes--; 1126 return 0; 1127 } 1128 kit_cg_jump(p->cg, end_label); 1129 } 1130 if (!toy_parser_expect(p, TOK_RBRACE)) { 1131 toy_error(p, p->cur.loc, "expected '}' after switch"); 1132 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 1133 p->nscopes--; 1134 return 0; 1135 } 1136 kit_cg_label_place(p->cg, dispatch_label); 1137 kit_cg_push_local(p->cg, selector_slot); 1138 kit_cg_load(p->cg, toy_mem_access(p, selector_ty)); 1139 sw.selector_type = selector_ty; 1140 sw.default_label = 1141 default_arm_label != KIT_CG_LABEL_NONE ? default_arm_label : end_label; 1142 sw.cases = cases; 1143 sw.ncases = (uint32_t)ncases; 1144 sw.hint = hint; 1145 kit_cg_switch(p->cg, sw); 1146 kit_cg_label_place(p->cg, end_label); 1147 kit_cg_scope_end(p->cg, scope); 1148 p->nscopes--; 1149 toy_parser_free_mem(p, cases, cap_cases * sizeof *cases); 1150 return 1; 1151 } 1152 1153 static int toy_parse_switch_stmt(ToyParser* p) { 1154 return toy_parse_switch_stmt_named(p, 0); 1155 } 1156 1157 static int toy_add_goto_target(ToyParser* p, uint32_t* ntargets, 1158 KitCgLabel label) { 1159 if (!toy_parser_reserve(p, (void**)&p->goto_targets, &p->cap_goto_targets, 1160 (size_t)*ntargets + 1u, sizeof *p->goto_targets, 1161 "goto targets")) { 1162 return 0; 1163 } 1164 p->goto_targets[*ntargets] = label; 1165 (*ntargets)++; 1166 return 1; 1167 } 1168 1169 static int toy_parse_label_decl_stmt(ToyParser* p) { 1170 KitSym name; 1171 toy_parser_advance(p); /* label */ 1172 if (p->cur.kind != TOK_IDENT) { 1173 toy_error(p, p->cur.loc, "expected label name"); 1174 return 0; 1175 } 1176 name = toy_tok_sym(p, p->cur); 1177 toy_parser_advance(p); 1178 if (!toy_declare_label(p, name)) return 0; 1179 if (!toy_parser_expect(p, TOK_SEMI)) { 1180 toy_error(p, p->cur.loc, "expected ';' after label declaration"); 1181 return 0; 1182 } 1183 return 1; 1184 } 1185 1186 static int toy_parse_goto_stmt(ToyParser* p) { 1187 KitCgTypeId target_ty; 1188 KitCgTypeId void_ptr_ty = 1189 kit_cg_type_ptr(p->c, toy_builtin_type(p, KIT_CG_BUILTIN_VOID), 0); 1190 uint32_t ntargets = 0; 1191 uint32_t i; 1192 toy_parser_advance(p); /* goto */ 1193 if (!toy_parser_expect(p, TOK_STAR)) { 1194 toy_error(p, p->cur.loc, "expected computed goto target"); 1195 return 0; 1196 } 1197 target_ty = toy_parse_expr(p); 1198 if (target_ty == KIT_CG_TYPE_NONE) return 0; 1199 if (target_ty != void_ptr_ty) { 1200 toy_error(p, p->cur.loc, "computed goto target must be *void"); 1201 return 0; 1202 } 1203 if (toy_parser_match(p, TOK_WITHIN)) { 1204 if (!toy_parser_expect(p, TOK_LPAREN)) { 1205 toy_error(p, p->cur.loc, "expected target list"); 1206 return 0; 1207 } 1208 while (p->cur.kind != TOK_RPAREN && p->cur.kind != TOK_EOF) { 1209 KitSym name; 1210 ToyLabel* label; 1211 if (p->cur.kind != TOK_IDENT) { 1212 toy_error(p, p->cur.loc, "expected label in target list"); 1213 return 0; 1214 } 1215 name = toy_tok_sym(p, p->cur); 1216 toy_parser_advance(p); 1217 label = toy_find_label(p, name); 1218 if (!label) { 1219 toy_error(p, p->cur.loc, "unknown label in target list"); 1220 return 0; 1221 } 1222 if (!toy_add_goto_target(p, &ntargets, label->label)) return 0; 1223 if (!toy_parser_match(p, TOK_COMMA)) break; 1224 } 1225 if (!toy_parser_expect(p, TOK_RPAREN)) { 1226 toy_error(p, p->cur.loc, "expected ')' after target list"); 1227 return 0; 1228 } 1229 } 1230 if (ntargets == 0) { 1231 for (i = 0; i < p->nlabels; ++i) { 1232 if (!toy_add_goto_target(p, &ntargets, p->labels[i].label)) return 0; 1233 } 1234 } 1235 kit_cg_computed_goto(p->cg, p->goto_targets, ntargets); 1236 if (!toy_parser_expect(p, TOK_SEMI)) { 1237 toy_error(p, p->cur.loc, "expected ';' after goto"); 1238 return 0; 1239 } 1240 return 1; 1241 } 1242 1243 static int toy_parse_break_stmt(ToyParser* p) { 1244 KitSym target_name = 0; 1245 ToyScope* target_scope; 1246 toy_parser_advance(p); /* break */ 1247 if (p->nscopes == 0) { 1248 toy_error(p, p->cur.loc, "break outside loop"); 1249 return 0; 1250 } 1251 if (p->cur.kind == TOK_IDENT) { 1252 KitSym maybe_target = toy_tok_sym(p, p->cur); 1253 if (toy_find_scope(p, maybe_target)) { 1254 target_name = maybe_target; 1255 toy_parser_advance(p); 1256 } 1257 } 1258 target_scope = toy_find_scope(p, target_name); 1259 if (!target_scope) { 1260 toy_error(p, p->cur.loc, "unknown break target"); 1261 return 0; 1262 } 1263 if (p->cur.kind != TOK_SEMI) { 1264 KitCgTypeId expr_ty = toy_parse_expr(p); 1265 KitCgTypeId result_ty = target_scope->result_type; 1266 if (expr_ty == KIT_CG_TYPE_NONE) return 0; 1267 if (result_ty == KIT_CG_TYPE_NONE) { 1268 toy_error(p, p->cur.loc, "break value type mismatch"); 1269 return 0; 1270 } 1271 if (!toy_check_source_value(p, result_ty, target_scope->result_toy_type, 1272 expr_ty, p->last_type, 1273 "break value type mismatch")) 1274 return 0; 1275 if (expr_ty != result_ty && !toy_emit_checked_cast(p, expr_ty, result_ty)) 1276 return 0; 1277 kit_cg_break(p->cg, target_scope->cg_scope); 1278 if (!toy_parser_expect(p, TOK_SEMI)) { 1279 toy_error(p, p->cur.loc, "expected ';' after break"); 1280 return 0; 1281 } 1282 return 1; 1283 } 1284 kit_cg_break(p->cg, target_scope->cg_scope); 1285 if (!toy_parser_expect(p, TOK_SEMI)) { 1286 toy_error(p, p->cur.loc, "expected ';' after break"); 1287 return 0; 1288 } 1289 return 1; 1290 } 1291 1292 static int toy_parse_continue_stmt(ToyParser* p) { 1293 KitSym target_name = 0; 1294 ToyScope* target_scope; 1295 toy_parser_advance(p); /* continue */ 1296 if (p->nscopes == 0) { 1297 toy_error(p, p->cur.loc, "continue outside loop"); 1298 return 0; 1299 } 1300 if (p->cur.kind == TOK_IDENT) { 1301 target_name = toy_tok_sym(p, p->cur); 1302 toy_parser_advance(p); 1303 target_scope = toy_find_scope(p, target_name); 1304 if (!target_scope) { 1305 toy_error(p, p->cur.loc, "unknown continue target"); 1306 return 0; 1307 } 1308 if (target_scope->kind != TOY_SCOPE_LOOP) { 1309 toy_error(p, p->cur.loc, "continue target is not a loop"); 1310 return 0; 1311 } 1312 } else { 1313 target_scope = toy_find_innermost_loop_scope(p); 1314 if (!target_scope) { 1315 toy_error(p, p->cur.loc, "continue outside loop"); 1316 return 0; 1317 } 1318 } 1319 kit_cg_continue(p->cg, target_scope->cg_scope); 1320 if (!toy_parser_expect(p, TOK_SEMI)) { 1321 toy_error(p, p->cur.loc, "expected ';' after continue"); 1322 return 0; 1323 } 1324 return 1; 1325 } 1326 1327 static int toy_parse_return_stmt(ToyParser* p) { 1328 KitCgTypeId ty; 1329 toy_parser_advance(p); /* return */ 1330 int is_tail = p->cur.kind == TOK_TAIL; 1331 int is_musttail = p->cur.kind == TOK_MUSTTAIL; 1332 if (is_tail || is_musttail) { 1333 int must_tail = is_musttail; 1334 KitSym name; 1335 ToyFn* fn; 1336 ToyToken call_tok; 1337 KitCgTypeId fn_ty; 1338 size_t nargs = 0; 1339 toy_parser_advance(p); /* tail | musttail */ 1340 if (p->cur.kind != TOK_IDENT) { 1341 toy_error(p, p->cur.loc, "expected function name after %s", 1342 must_tail ? "musttail" : "tail"); 1343 return 0; 1344 } 1345 call_tok = p->cur; 1346 name = toy_tok_sym(p, p->cur); 1347 fn = toy_find_fn(p, name); 1348 toy_parser_advance(p); 1349 if (!toy_parser_expect(p, TOK_LPAREN)) return 0; 1350 if (fn) { 1351 fn_ty = fn->type; 1352 } else { 1353 KitCgTypeId callee_ty = toy_push_named_rvalue(p, name); 1354 if (callee_ty == KIT_CG_TYPE_NONE) { 1355 toy_error(p, call_tok.loc, "undefined function in tail call"); 1356 return 0; 1357 } 1358 fn_ty = toy_ptr_pointee_func_type(p, callee_ty); 1359 if (fn_ty == KIT_CG_TYPE_NONE) { 1360 toy_error(p, call_tok.loc, "tail callee is not a function pointer"); 1361 return 0; 1362 } 1363 } 1364 /* Variadic tail calls are not rejected here: realizability is a per-target 1365 * decision owned by CG's precondition and the target's tail_call hook 1366 * (e.g. native fits varargs in the caller's incoming area; wasm cannot, 1367 * since its vararg buffer lives in the frame a sibling call tears down). */ 1368 if (!toy_parse_call_args(p, call_tok, fn_ty, fn ? fn->toy_params : NULL, 1369 fn ? fn->nparams : 0, &nargs)) 1370 return 0; 1371 if (fn && !toy_type_accepts_storage(p, p->cur_fn_ret_toy, fn->toy_ret)) { 1372 toy_error(p, p->cur.loc, "tail call signature mismatch"); 1373 return 0; 1374 } 1375 if (!fn && toy_cg_func_ret(p, fn_ty) != p->cur_fn_ret) { 1376 toy_error(p, p->cur.loc, "tail call signature mismatch"); 1377 return 0; 1378 } 1379 if (fn) { 1380 if (must_tail) 1381 kit_cg_musttail_call_symbol(p->cg, toy_fn_cur_sym(p, fn), 1382 (uint32_t)nargs); 1383 else 1384 kit_cg_tail_call_symbol(p->cg, toy_fn_cur_sym(p, fn), (uint32_t)nargs); 1385 } else { 1386 if (must_tail) 1387 kit_cg_musttail_call(p->cg, (uint32_t)nargs, fn_ty); 1388 else 1389 kit_cg_tail_call(p->cg, (uint32_t)nargs, fn_ty); 1390 } 1391 if (!toy_parser_expect(p, TOK_SEMI)) return 0; 1392 return 1; 1393 } 1394 if (p->cur.kind == TOK_SEMI) { 1395 toy_parser_advance(p); 1396 if (p->cur_fn_ret != toy_builtin_type(p, KIT_CG_BUILTIN_VOID)) { 1397 toy_error(p, p->cur.loc, "return without value in non-void function"); 1398 return 0; 1399 } 1400 kit_cg_ret(p->cg); 1401 return 1; 1402 } 1403 if (p->cur_fn_ret != toy_builtin_type(p, KIT_CG_BUILTIN_VOID)) { 1404 int is_control_expr = p->cur.kind == TOK_IF || p->cur.kind == TOK_SWITCH || 1405 p->cur.kind == TOK_WHILE; 1406 KitSym loop_label = 0; 1407 if (!is_control_expr && p->cur.kind == TOK_IDENT) { 1408 ToyLexer tmp_lex = p->lex; 1409 ToyToken colon_tok = toy_lexer_next(&tmp_lex); 1410 ToyToken while_tok = toy_lexer_next(&tmp_lex); 1411 if (colon_tok.kind == TOK_COLON && while_tok.kind == TOK_WHILE) { 1412 is_control_expr = 1; 1413 loop_label = toy_tok_sym(p, p->cur); 1414 } 1415 } 1416 if (is_control_expr) { 1417 KitCgLocal slot = kit_cg_local(p->cg, p->cur_fn_ret, toy_slot_attrs(0)); 1418 if (p->cur.kind == TOK_IF) { 1419 if (!toy_parse_if_initializer(p, slot, p->cur_fn_ret, 1420 p->cur_fn_ret_toy)) 1421 return 0; 1422 } else if (p->cur.kind == TOK_SWITCH) { 1423 if (!toy_parse_switch_initializer(p, slot, p->cur_fn_ret, 1424 p->cur_fn_ret_toy)) 1425 return 0; 1426 } else if (p->cur.kind == TOK_WHILE) { 1427 if (!toy_parse_while_initializer(p, slot, p->cur_fn_ret, 1428 p->cur_fn_ret_toy)) 1429 return 0; 1430 } else { 1431 toy_parser_advance(p); /* label */ 1432 if (!toy_parser_expect(p, TOK_COLON)) { 1433 toy_error(p, p->cur.loc, "expected ':' after loop label"); 1434 return 0; 1435 } 1436 if (!toy_parse_while_initializer_named(p, slot, p->cur_fn_ret, 1437 p->cur_fn_ret_toy, loop_label)) { 1438 return 0; 1439 } 1440 } 1441 kit_cg_push_local(p->cg, slot); 1442 kit_cg_load(p->cg, toy_mem_access(p, p->cur_fn_ret)); 1443 kit_cg_ret(p->cg); 1444 if (!toy_parser_expect(p, TOK_SEMI)) { 1445 toy_error(p, p->cur.loc, "expected ';' after return"); 1446 return 0; 1447 } 1448 return 1; 1449 } 1450 } 1451 p->allow_tail_call_expr = 1; 1452 p->tail_call_expr = 0; 1453 p->tail_call_ret_toy = TOY_TYPE_NONE; 1454 ty = toy_parse_expr(p); 1455 p->allow_tail_call_expr = 0; 1456 if (ty == KIT_CG_TYPE_NONE) return 0; 1457 if (p->tail_call_expr) { 1458 ToyTypeId tail_toy = p->tail_call_ret_toy; 1459 if (!tail_toy) tail_toy = p->last_type; 1460 if (!toy_check_source_value(p, p->cur_fn_ret, p->cur_fn_ret_toy, ty, 1461 tail_toy, "return type mismatch")) 1462 return 0; 1463 if (!toy_parser_expect(p, TOK_SEMI)) { 1464 toy_error(p, p->cur.loc, "expected ';' after return"); 1465 return 0; 1466 } 1467 p->tail_call_expr = 0; 1468 p->tail_call_ret_toy = TOY_TYPE_NONE; 1469 return 1; 1470 } 1471 if (!toy_check_source_value(p, p->cur_fn_ret, p->cur_fn_ret_toy, ty, 1472 p->last_type, "return type mismatch")) 1473 return 0; 1474 if (ty != p->cur_fn_ret && !toy_emit_checked_cast(p, ty, p->cur_fn_ret)) 1475 return 0; 1476 kit_cg_ret(p->cg); 1477 if (!toy_parser_expect(p, TOK_SEMI)) { 1478 toy_error(p, p->cur.loc, "expected ';' after return"); 1479 return 0; 1480 } 1481 return 1; 1482 } 1483 1484 static int toy_parse_expr_stmt(ToyParser* p) { 1485 KitCgTypeId ty = toy_parse_expr(p); 1486 if (ty == KIT_CG_TYPE_NONE) return 0; 1487 if (p->tail_call_expr) { 1488 toy_error(p, p->cur.loc, "tail @call requires return"); 1489 return 0; 1490 } 1491 if (!toy_parser_expect(p, TOK_SEMI)) { 1492 toy_error(p, p->cur.loc, "expected ';' after expression"); 1493 return 0; 1494 } 1495 if (ty != toy_builtin_type(p, KIT_CG_BUILTIN_VOID)) kit_cg_drop(p->cg); 1496 return 1; 1497 } 1498 1499 static int toy_parse_stmt(ToyParser* p) { 1500 toy_set_loc(p); 1501 if (p->cur.kind == TOK_LET || p->cur.kind == TOK_VAR) 1502 return toy_parse_let_stmt(p); 1503 if (p->cur.kind == TOK_IF) return toy_parse_if_stmt(p); 1504 if (p->cur.kind == TOK_WHILE) return toy_parse_while_stmt(p); 1505 if (p->cur.kind == TOK_SWITCH) return toy_parse_switch_stmt(p); 1506 if (p->cur.kind == TOK_LABEL) return toy_parse_label_decl_stmt(p); 1507 if (p->cur.kind == TOK_GOTO) return toy_parse_goto_stmt(p); 1508 if (p->cur.kind == TOK_BREAK) return toy_parse_break_stmt(p); 1509 if (p->cur.kind == TOK_CONTINUE) return toy_parse_continue_stmt(p); 1510 if (p->cur.kind == TOK_RETURN) return toy_parse_return_stmt(p); 1511 if (p->cur.kind == TOK_LBRACE) return toy_parse_block(p); 1512 1513 /* Assignment or expression statement */ 1514 if (p->cur.kind == TOK_IDENT && toy_lexer_peek(&p->lex).kind == TOK_COLON) { 1515 KitSym name = toy_tok_sym(p, p->cur); 1516 toy_parser_advance(p); /* ident */ 1517 toy_parser_advance(p); /* : */ 1518 if (p->cur.kind == TOK_WHILE) return toy_parse_while_stmt_named(p, name); 1519 if (p->cur.kind == TOK_SWITCH) return toy_parse_switch_stmt_named(p, name); 1520 { 1521 ToyLabel* label = toy_declare_label(p, name); 1522 if (!label) return 0; 1523 kit_cg_label_place(p->cg, label->label); 1524 } 1525 return 1; 1526 } 1527 1528 if (p->cur.kind == TOK_IDENT && 1529 (toy_lexer_peek(&p->lex).kind == TOK_LBRACKET || 1530 toy_lexer_peek(&p->lex).kind == TOK_DOTSTAR || 1531 toy_lexer_peek(&p->lex).kind == TOK_DOT)) { 1532 KitSym name = toy_tok_sym(p, p->cur); 1533 KitCgTypeId lhs_ty; 1534 ToyTypeId lhs_toy_type = TOY_TYPE_NONE; 1535 KitCgTypeId root_ty = KIT_CG_TYPE_NONE; 1536 int root_mutable = 1; 1537 int lhs_slice_metadata = 0; 1538 toy_parser_advance(p); 1539 /* Chain invariant: TOS holds a pointer-rvalue of type `*lhs_ty`. 1540 * Intermediate field / index / dereference steps materialize the 1541 * address via toy_addr_offset / toy_addr_index / explicit loads. 1542 * The final store consumes the pointer with EA {0, 0}. */ 1543 { 1544 ToyVar* v = toy_find_var(p, name); 1545 ToyGlobal* g = toy_find_global(p, name); 1546 if (v) { 1547 root_ty = v->type; 1548 lhs_toy_type = v->toy_type; 1549 root_mutable = v->mutable; 1550 } else if (g) { 1551 root_ty = g->type; 1552 lhs_toy_type = g->toy_type; 1553 root_mutable = g->mutable; 1554 } 1555 if (v) { 1556 toy_push_var_addr(p, v); 1557 lhs_ty = v->type; 1558 } else if (g) { 1559 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 1560 lhs_ty = g->type; 1561 } else { 1562 lhs_ty = KIT_CG_TYPE_NONE; 1563 } 1564 } 1565 if (lhs_ty == KIT_CG_TYPE_NONE) { 1566 toy_error(p, p->cur.loc, "undefined variable in assignment"); 1567 return 0; 1568 } 1569 1570 for (;;) { 1571 if (toy_parser_match(p, TOK_LBRACKET)) { 1572 KitCgTypeId idx_ty = toy_parse_expr(p); 1573 lhs_slice_metadata = 0; 1574 if (idx_ty == KIT_CG_TYPE_NONE) return 0; 1575 if (!toy_type_can_implicitly_cast(p, idx_ty, p->size_type)) { 1576 toy_error(p, p->cur.loc, "index must be isize"); 1577 return 0; 1578 } 1579 if (!toy_emit_implicit_cast(p, idx_ty, p->size_type)) return 0; 1580 idx_ty = p->size_type; 1581 if (!toy_parser_expect(p, TOK_RBRACKET)) { 1582 toy_error(p, p->cur.loc, "expected ']' after index"); 1583 return 0; 1584 } 1585 if (kit_cg_type_kind(p->c, lhs_ty) == KIT_CG_TYPE_PTR) { 1586 /* TOS = **T_chain (where lhs_ty = *T_chain). Load the pointer 1587 * value so the index applies to the pointee. */ 1588 KitCgTypeId pointee = kit_cg_type_ptr_pointee(p->c, lhs_ty); 1589 ToyTypeId source_pointee = toy_type_pointee(p, lhs_toy_type); 1590 /* index is currently on top; stash so we can load the pointer. */ 1591 { 1592 KitCgLocal idx_slot = 1593 kit_cg_local(p->cg, p->size_type, toy_slot_attrs(0)); 1594 kit_cg_push_local(p->cg, idx_slot); 1595 kit_cg_swap(p->cg); 1596 kit_cg_store(p->cg, toy_mem_access(p, p->size_type)); 1597 /* TOS is the chain pointer VALUE (**T); deref to a PLACE and 1598 * load the inner pointer it addresses. */ 1599 kit_cg_deref(p->cg, 0); 1600 kit_cg_load(p->cg, toy_mem_access(p, lhs_ty)); 1601 kit_cg_push_local(p->cg, idx_slot); 1602 kit_cg_load(p->cg, toy_mem_access(p, p->size_type)); 1603 } 1604 if (kit_cg_type_kind(p->c, pointee) == KIT_CG_TYPE_ARRAY) { 1605 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, pointee); 1606 lhs_ty = elem_ty; 1607 lhs_toy_type = toy_type_array_elem(p, source_pointee); 1608 toy_addr_index(p, kit_cg_type_size(p->c, elem_ty), 1609 kit_cg_type_ptr(p->c, elem_ty, 0)); 1610 } else { 1611 lhs_ty = pointee; 1612 lhs_toy_type = source_pointee; 1613 toy_addr_index(p, kit_cg_type_size(p->c, lhs_ty), 1614 kit_cg_type_ptr(p->c, lhs_ty, 0)); 1615 } 1616 } else if (kit_cg_type_kind(p->c, lhs_ty) == KIT_CG_TYPE_ARRAY) { 1617 KitCgTypeId elem_ty = kit_cg_type_array_elem(p->c, lhs_ty); 1618 lhs_ty = elem_ty; 1619 lhs_toy_type = toy_type_array_elem(p, lhs_toy_type); 1620 toy_addr_index(p, kit_cg_type_size(p->c, elem_ty), 1621 kit_cg_type_ptr(p->c, elem_ty, 0)); 1622 } else if (toy_type_is_slice(p, lhs_toy_type)) { 1623 lhs_ty = toy_emit_slice_index_lvalue(p, lhs_ty, lhs_toy_type, 1624 &lhs_toy_type); 1625 if (lhs_ty == KIT_CG_TYPE_NONE) return 0; 1626 } else { 1627 toy_error(p, p->cur.loc, "cannot index non-array/non-pointer"); 1628 return 0; 1629 } 1630 continue; 1631 } 1632 if (toy_parser_match(p, TOK_DOTSTAR)) { 1633 lhs_slice_metadata = 0; 1634 if (kit_cg_type_kind(p->c, lhs_ty) != KIT_CG_TYPE_PTR) { 1635 toy_error(p, p->cur.loc, "cannot dereference non-pointer"); 1636 return 0; 1637 } 1638 /* TOS = `**T` (pointer VALUE); deref to PLACE and load to `*T`. */ 1639 kit_cg_deref(p->cg, 0); 1640 kit_cg_load(p->cg, toy_mem_access(p, lhs_ty)); 1641 lhs_ty = kit_cg_type_ptr_pointee(p->c, lhs_ty); 1642 lhs_toy_type = toy_type_pointee(p, lhs_toy_type); 1643 continue; 1644 } 1645 if (toy_parser_match(p, TOK_DOT)) { 1646 KitCgFieldLayout field; 1647 uint32_t field_index = 0; 1648 ToyNamedType* named; 1649 uint64_t foff = 0; 1650 if (kit_cg_type_kind(p->c, lhs_ty) == KIT_CG_TYPE_PTR && 1651 kit_cg_type_kind(p->c, kit_cg_type_ptr_pointee(p->c, lhs_ty)) == 1652 KIT_CG_TYPE_RECORD) { 1653 /* `p.field`: deref to PLACE and load the pointer value that 1654 * addresses the record. */ 1655 kit_cg_deref(p->cg, 0); 1656 kit_cg_load(p->cg, toy_mem_access(p, lhs_ty)); 1657 lhs_ty = kit_cg_type_ptr_pointee(p->c, lhs_ty); 1658 lhs_toy_type = toy_type_pointee(p, lhs_toy_type); 1659 } 1660 if (kit_cg_type_kind(p->c, lhs_ty) != KIT_CG_TYPE_RECORD) { 1661 toy_error(p, p->cur.loc, "field assignment on non-record"); 1662 return 0; 1663 } 1664 named = toy_find_named_type_by_type(p, lhs_ty); 1665 if (p->cur.kind == TOK_NUMBER && !p->cur.is_float) { 1666 if (p->cur.int_value < 0 || 1667 p->cur.int_value >= 1668 (int64_t)kit_cg_type_record_nfields(p->c, lhs_ty)) { 1669 toy_error(p, p->cur.loc, "invalid tuple field"); 1670 return 0; 1671 } 1672 const KitCgRecordLayout* L; 1673 field_index = (uint32_t)p->cur.int_value; 1674 toy_parser_advance(p); 1675 L = kit_cg_type_record_layout(p->c, lhs_ty); 1676 if (!L || field_index >= L->nfields) return 0; 1677 field = L->fields[field_index]; 1678 foff = field.offset; 1679 } else { 1680 KitSym field_name; 1681 if (p->cur.kind != TOK_IDENT) { 1682 toy_error(p, p->cur.loc, "expected field name"); 1683 return 0; 1684 } 1685 field_name = toy_tok_sym(p, p->cur); 1686 toy_parser_advance(p); 1687 if (!toy_record_field_index(p, lhs_ty, field_name, &field_index, 1688 &field)) { 1689 toy_error(p, p->cur.loc, "unknown record field"); 1690 return 0; 1691 } 1692 foff = field.offset; 1693 } 1694 lhs_slice_metadata = toy_type_is_slice(p, lhs_toy_type) && 1695 (field_index == 0 || field_index == 1); 1696 lhs_ty = field.type; 1697 lhs_toy_type = (named && field_index < named->nfields) 1698 ? named->fields[field_index].toy_type 1699 : TOY_TYPE_NONE; 1700 toy_addr_offset(p, (int64_t)foff, kit_cg_type_ptr(p->c, lhs_ty, 0)); 1701 continue; 1702 } 1703 break; 1704 } 1705 1706 if (!toy_parser_expect(p, TOK_EQ)) { 1707 toy_error(p, p->cur.loc, "expected '=' in assignment"); 1708 return 0; 1709 } 1710 if (!root_mutable && kit_cg_type_kind(p->c, root_ty) != KIT_CG_TYPE_PTR) { 1711 toy_error(p, p->cur.loc, "cannot assign to immutable local"); 1712 return 0; 1713 } 1714 if (lhs_slice_metadata) { 1715 toy_error(p, p->cur.loc, "cannot assign to slice metadata"); 1716 return 0; 1717 } 1718 /* The address chain leaves a pointer VALUE (`*lhs_ty`) on the stack; turn 1719 * it into a PLACE before pushing the rhs so store sees [place, value]. */ 1720 kit_cg_deref(p->cg, 0); 1721 { 1722 KitCgTypeId expr_ty = toy_parse_expr(p); 1723 ToyTypeId expr_toy_type = p->last_type; 1724 if (expr_ty == KIT_CG_TYPE_NONE) return 0; 1725 if (lhs_toy_type != TOY_TYPE_NONE) { 1726 if (!toy_type_accepts_type(p, lhs_toy_type, expr_toy_type)) { 1727 toy_error(p, p->cur.loc, "type mismatch in assignment"); 1728 return 0; 1729 } 1730 if (expr_ty != lhs_ty && !toy_emit_checked_cast(p, expr_ty, lhs_ty)) 1731 return 0; 1732 } else if (!toy_type_can_implicitly_cast(p, expr_ty, lhs_ty)) { 1733 toy_error(p, p->cur.loc, "type mismatch in assignment"); 1734 return 0; 1735 } else if (expr_ty != lhs_ty) { 1736 if (!toy_emit_implicit_cast(p, expr_ty, lhs_ty)) return 0; 1737 } 1738 kit_cg_store(p->cg, toy_mem_access(p, lhs_ty)); 1739 } 1740 if (!toy_parser_expect(p, TOK_SEMI)) { 1741 toy_error(p, p->cur.loc, "expected ';' after assignment"); 1742 return 0; 1743 } 1744 return 1; 1745 } 1746 1747 if (p->cur.kind == TOK_IDENT && toy_lexer_peek(&p->lex).kind == TOK_EQ) { 1748 KitSym name = toy_tok_sym(p, p->cur); 1749 toy_parser_advance(p); /* ident */ 1750 toy_parser_advance(p); /* = */ 1751 KitCgTypeId expr_ty = toy_parse_expr(p); 1752 ToyTypeId expr_toy_type = p->last_type; 1753 if (expr_ty == KIT_CG_TYPE_NONE) return 0; 1754 { 1755 ToyVar* v = toy_find_var(p, name); 1756 if (v) { 1757 if (!v->mutable) { 1758 toy_error(p, p->cur.loc, "cannot assign to immutable local"); 1759 return 0; 1760 } 1761 if (!toy_type_accepts_type(p, v->toy_type, expr_toy_type)) { 1762 toy_error(p, p->cur.loc, "type mismatch in assignment"); 1763 return 0; 1764 } 1765 if (toy_type_is_slice(p, v->toy_type) || 1766 kit_cg_type_kind(p->c, v->type) == KIT_CG_TYPE_RECORD) { 1767 if (!toy_copy_record_lvalue_to_var(p, expr_ty, v, NULL)) return 0; 1768 if (!toy_parser_expect(p, TOK_SEMI)) { 1769 toy_error(p, p->cur.loc, "expected ';' after assignment"); 1770 return 0; 1771 } 1772 return 1; 1773 } 1774 toy_push_var_lvalue(p, v); 1775 kit_cg_deref(p->cg, 0); /* pointer VALUE -> PLACE for store */ 1776 kit_cg_swap(p->cg); 1777 if (expr_ty != v->type && !toy_emit_checked_cast(p, expr_ty, v->type)) 1778 return 0; 1779 kit_cg_store(p->cg, toy_mem_access(p, v->type)); 1780 } else { 1781 ToyGlobal* g = toy_find_global(p, name); 1782 if (!g) { 1783 toy_error(p, p->cur.loc, "undefined variable in assignment"); 1784 return 0; 1785 } 1786 if (!g->mutable) { 1787 toy_error(p, p->cur.loc, "cannot assign to immutable global"); 1788 return 0; 1789 } 1790 if (!toy_type_accepts_type(p, g->toy_type, expr_toy_type)) { 1791 toy_error(p, p->cur.loc, "type mismatch in assignment"); 1792 return 0; 1793 } 1794 if (toy_type_is_slice(p, g->toy_type) || 1795 kit_cg_type_kind(p->c, g->type) == KIT_CG_TYPE_RECORD) { 1796 if (!toy_copy_record_lvalue_to_var(p, expr_ty, NULL, g)) return 0; 1797 if (!toy_parser_expect(p, TOK_SEMI)) { 1798 toy_error(p, p->cur.loc, "expected ';' after assignment"); 1799 return 0; 1800 } 1801 return 1; 1802 } 1803 kit_cg_push_symbol_addr(p->cg, toy_global_cur_sym(p, g), 0); 1804 kit_cg_deref(p->cg, 0); /* pointer VALUE -> PLACE for store */ 1805 kit_cg_swap(p->cg); 1806 if (expr_ty != g->type && !toy_emit_checked_cast(p, expr_ty, g->type)) 1807 return 0; 1808 kit_cg_store(p->cg, toy_mem_access(p, g->type)); 1809 } 1810 } 1811 if (!toy_parser_expect(p, TOK_SEMI)) { 1812 toy_error(p, p->cur.loc, "expected ';' after assignment"); 1813 return 0; 1814 } 1815 return 1; 1816 } 1817 1818 return toy_parse_expr_stmt(p); 1819 } 1820 1821 /* ============================================================ 1822 * Program parsing 1823 * ============================================================ */ 1824 1825 int toy_parse_program(ToyParser* p) { 1826 while (p->cur.kind != TOK_EOF) { 1827 int is_extern = 0; 1828 int is_pub = 0; 1829 if (toy_parser_match(p, TOK_PUB)) { 1830 is_pub = 1; 1831 if (p->cur.kind != TOK_FN && p->cur.kind != TOK_LET && 1832 p->cur.kind != TOK_VAR && p->cur.kind != TOK_ALIAS) { 1833 toy_error(p, p->cur.loc, "expected declaration after pub"); 1834 return 0; 1835 } 1836 } 1837 if (toy_parser_match(p, TOK_EXTERN)) { 1838 is_extern = 1; 1839 if (p->cur.kind != TOK_FN && p->cur.kind != TOK_VAR && 1840 p->cur.kind != TOK_LET) { 1841 toy_error(p, p->cur.loc, "expected extern declaration"); 1842 return 0; 1843 } 1844 } 1845 if (p->cur.kind == TOK_FN) { 1846 int r = toy_parse_fn(p, is_extern, is_pub); 1847 if (r < 0) return 0; 1848 if (r == 0) { 1849 toy_error(p, p->cur.loc, "expected function declaration"); 1850 return 0; 1851 } 1852 } else if (p->cur.kind == TOK_LET || p->cur.kind == TOK_VAR) { 1853 if (!toy_parse_global_var(p, is_extern, is_pub)) return 0; 1854 } else if (p->cur.kind == TOK_TYPE && !is_extern) { 1855 if (!toy_parse_type_alias_decl(p)) return 0; 1856 } else if (p->cur.kind == TOK_RECORD) { 1857 if (!toy_parse_record_decl(p)) return 0; 1858 } else if (p->cur.kind == TOK_TUPLE && !is_extern) { 1859 if (!toy_parse_tuple_decl(p)) return 0; 1860 } else if (p->cur.kind == TOK_ENUM && !is_extern) { 1861 if (!toy_parse_enum_decl(p)) return 0; 1862 } else if (p->cur.kind == TOK_ALIAS && !is_extern) { 1863 if (!toy_parse_alias_decl(p, is_pub)) return 0; 1864 } else { 1865 toy_error(p, p->cur.loc, "expected function or global declaration"); 1866 return 0; 1867 } 1868 } 1869 return 1; 1870 }