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