| ... | @@ -327,6 +327,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -327,6 +327,15 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 327 | .while_cont => return whileExpr(mod, scope, tree.whileCont(node)), | 327 | .while_cont => return whileExpr(mod, scope, tree.whileCont(node)), |
| 328 | .@"while" => return whileExpr(mod, scope, rl, tree.whileFull(node)), | 328 | .@"while" => return whileExpr(mod, scope, rl, tree.whileFull(node)), |
| 329 | | 329 | |
| | 330 | .for_simple => return forExpr(mod, scope, rl, tree.forSimple(node)), |
| | 331 | .@"for" => return forExpr(mod, scope, rl, tree.forFull(node)), |
| | 332 | |
| | 333 | // TODO handling these separately would actually be simpler & have fewer branches |
| | 334 | // once we have a ZIR instruction for each of these 3 cases. |
| | 335 | .slice_open => return sliceExpr(mod, scope, rl, tree.sliceOpen(node)), |
| | 336 | .slice => return sliceExpr(mod, scope, rl, tree.slice(node)), |
| | 337 | .slice_sentinel => return sliceExpr(mod, scope, rl, tree.sliceSentinel(node)), |
| | 338 | |
| 330 | .deref => { | 339 | .deref => { |
| 331 | const lhs = try expr(mod, scope, .none, node_datas[node].lhs); | 340 | const lhs = try expr(mod, scope, .none, node_datas[node].lhs); |
| 332 | const src = token_starts[main_tokens[node]]; | 341 | const src = token_starts[main_tokens[node]]; |
| ... | @@ -402,51 +411,122 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -402,51 +411,122 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 402 | const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | 411 | const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; |
| 403 | return blockExpr(mod, scope, rl, node, statements); | 412 | return blockExpr(mod, scope, rl, node, statements); |
| 404 | }, | 413 | }, |
| 405 | | 414 | .enum_literal => { |
| 406 | .@"break" => return rvalue(mod, scope, rl, try breakExpr(mod, scope, node)), | 415 | const ident_token = main_tokens[node]; |
| 407 | .@"continue" => return rvalue(mod, scope, rl, try continueExpr(mod, scope, node)), | 416 | const name = try mod.identifierTokenString(scope, ident_token); |
| 408 | .grouped_expression => return expr(mod, scope, rl, node.expr), | 417 | const src = token_starts[ident_token]; |
| 409 | .array_type => return rvalue(mod, scope, rl, try arrayType(mod, scope, node)), | 418 | const result = try addZIRInst(mod, scope, src, zir.Inst.EnumLiteral, .{ .name = name }, .{}); |
| 410 | .array_type_sentinel => return rvalue(mod, scope, rl, try arrayTypeSentinel(mod, scope, node)), | 419 | return rvalue(mod, scope, rl, result); |
| 411 | .enum_literal => return rvalue(mod, scope, rl, try enumLiteral(mod, scope, node)), | 420 | }, |
| 412 | .char_literal => return rvalue(mod, scope, rl, try charLiteral(mod, scope, node)), | 421 | .error_union => { |
| 413 | .slice_type => return rvalue(mod, scope, rl, try sliceType(mod, scope, node)), | 422 | const error_set = try typeExpr(mod, scope, node_datas[node].lhs); |
| 414 | .error_union => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node, .error_union_type)), | 423 | const payload = try typeExpr(mod, scope, node_datas[node].rhs); |
| 415 | .merge_error_sets => return rvalue(mod, scope, rl, try typeInixOp(mod, scope, node, .merge_error_sets)), | 424 | const src = token_starts[main_tokens[node]]; |
| 416 | .anyframe_type => return rvalue(mod, scope, rl, try anyFrameType(mod, scope, node)), | 425 | const result = try addZIRBinOp(mod, scope, src, .error_union_type, error_set, payload); |
| 417 | .error_set_decl => return rvalue(mod, scope, rl, try errorSetDecl(mod, scope, node)), | 426 | return rvalue(mod, scope, rl, result); |
| 418 | .error_type => return rvalue(mod, scope, rl, try errorType(mod, scope, node)), | 427 | }, |
| 419 | .@"for" => return forExpr(mod, scope, rl, node), | 428 | .merge_error_sets => { |
| | 429 | const lhs = try typeExpr(mod, scope, node_datas[node].lhs); |
| | 430 | const rhs = try typeExpr(mod, scope, node_datas[node].rhs); |
| | 431 | const src = token_starts[main_tokens[node]]; |
| | 432 | const result = try addZIRBinOp(mod, scope, src, .merge_error_sets, lhs, rhs); |
| | 433 | return rvalue(mod, scope, rl, result); |
| | 434 | }, |
| | 435 | .anyframe_literal => { |
| | 436 | const main_token = main_tokens[node]; |
| | 437 | const src = token_starts[main_token]; |
| | 438 | const result = try addZIRInstConst(mod, scope, src, .{ |
| | 439 | .ty = Type.initTag(.type), |
| | 440 | .val = Value.initTag(.anyframe_type), |
| | 441 | }); |
| | 442 | return rvalue(mod, scope, rl, result); |
| | 443 | }, |
| | 444 | .anyframe_type => { |
| | 445 | const src = token_starts[node_datas[node].lhs]; |
| | 446 | const return_type = try typeExpr(mod, scope, node_datas[node].rhs); |
| | 447 | const result = try addZIRUnOp(mod, scope, src, .anyframe_type, return_type); |
| | 448 | return rvalue(mod, scope, rl, result); |
| | 449 | }, |
| | 450 | .@"catch" => { |
| | 451 | const catch_token = main_tokens[node]; |
| | 452 | const payload_token: ?TokenIndex = if (token_tags[catch_token + 1] == .pipe) |
| | 453 | catch_token + 2 |
| | 454 | else |
| | 455 | null; |
| | 456 | switch (rl) { |
| | 457 | .ref => return orelseCatchExpr( |
| | 458 | mod, |
| | 459 | scope, |
| | 460 | rl, |
| | 461 | node_datas[node].lhs, |
| | 462 | main_tokens[node], |
| | 463 | .is_err_ptr, |
| | 464 | .err_union_payload_unsafe_ptr, |
| | 465 | .err_union_code_ptr, |
| | 466 | node_datas[node].rhs, |
| | 467 | payload_token, |
| | 468 | ), |
| | 469 | else => return orelseCatchExpr( |
| | 470 | mod, |
| | 471 | scope, |
| | 472 | rl, |
| | 473 | node_datas[node].lhs, |
| | 474 | main_tokens[node], |
| | 475 | .is_err, |
| | 476 | .err_union_payload_unsafe, |
| | 477 | .err_union_code, |
| | 478 | node_datas[node].rhs, |
| | 479 | payload_token, |
| | 480 | ), |
| | 481 | } |
| | 482 | }, |
| | 483 | .@"orelse" => switch (rl) { |
| | 484 | .ref => return orelseCatchExpr( |
| | 485 | mod, |
| | 486 | scope, |
| | 487 | rl, |
| | 488 | node_datas[node].lhs, |
| | 489 | main_tokens[node], |
| | 490 | .is_null_ptr, |
| | 491 | .optional_payload_unsafe_ptr, |
| | 492 | undefined, |
| | 493 | node_datas[node].rhs, |
| | 494 | null, |
| | 495 | ), |
| | 496 | else => return orelseCatchExpr( |
| | 497 | mod, |
| | 498 | scope, |
| | 499 | rl, |
| | 500 | node_datas[node].lhs, |
| | 501 | main_tokens[node], |
| | 502 | .is_null, |
| | 503 | .optional_payload_unsafe, |
| | 504 | undefined, |
| | 505 | node_datas[node].rhs, |
| | 506 | null, |
| | 507 | ), |
| | 508 | }, |
| | 509 | .@"break" => return breakExpr(mod, scope, rl, node), |
| | 510 | .@"continue" => return continueExpr(mod, scope, rl, node), |
| | 511 | .grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs), |
| | 512 | .array_type => return arrayType(mod, scope, rl, node), |
| | 513 | .array_type_sentinel => return arrayTypeSentinel(mod, scope, rl, node), |
| | 514 | .char_literal => return charLiteral(mod, scope, rl, node), |
| | 515 | .error_set_decl => return errorSetDecl(mod, scope, rl, node), |
| 420 | .array_access => return arrayAccess(mod, scope, rl, node), | 516 | .array_access => return arrayAccess(mod, scope, rl, node), |
| 421 | .slice => return rvalue(mod, scope, rl, try sliceExpr(mod, scope, node)), | 517 | .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs), |
| 422 | .@"catch" => return catchExpr(mod, scope, rl, node), | 518 | .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node), |
| 423 | .@"comptime" => return comptimeKeyword(mod, scope, rl, node), | | |
| 424 | .@"orelse" => return orelseExpr(mod, scope, rl, node), | | |
| 425 | .@"switch" => return switchExpr(mod, scope, rl, node), | | |
| 426 | .ContainerDecl => return containerDecl(mod, scope, rl, node), | | |
| 427 | | 519 | |
| 428 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), | 520 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), |
| 429 | .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}), | 521 | .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}), |
| 430 | .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}), | 522 | .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}), |
| 431 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), | 523 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| 432 | .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}), | | |
| 433 | .ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}), | | |
| 434 | .StructInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializer", .{}), | | |
| 435 | .StructInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializerDot", .{}), | | |
| 436 | .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}), | 524 | .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}), |
| 437 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), | 525 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), |
| 438 | .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}), | | |
| 439 | .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}), | 526 | .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}), |
| 440 | } | 527 | } |
| 441 | } | 528 | } |
| 442 | | 529 | |
| 443 | fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.@"comptime") InnerError!*zir.Inst { | | |
| 444 | const tracy = trace(@src()); | | |
| 445 | defer tracy.end(); | | |
| 446 | | | |
| 447 | return comptimeExpr(mod, scope, rl, node.expr); | | |
| 448 | } | | |
| 449 | | | |
| 450 | pub fn comptimeExpr( | 530 | pub fn comptimeExpr( |
| 451 | mod: *Module, | 531 | mod: *Module, |
| 452 | parent_scope: *Scope, | 532 | parent_scope: *Scope, |
| ... | @@ -493,7 +573,12 @@ pub fn comptimeExpr( | ... | @@ -493,7 +573,12 @@ pub fn comptimeExpr( |
| 493 | return &block.base; | 573 | return &block.base; |
| 494 | } | 574 | } |
| 495 | | 575 | |
| 496 | fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { | 576 | fn breakExpr( |
| | 577 | mod: *Module, |
| | 578 | parent_scope: *Scope, |
| | 579 | rl: ResultLoc, |
| | 580 | node: ast.Node.Index, |
| | 581 | ) InnerError!*zir.Inst { |
| 497 | const tree = parent_scope.tree(); | 582 | const tree = parent_scope.tree(); |
| 498 | const node_datas = tree.nodes.items(.data); | 583 | const node_datas = tree.nodes.items(.data); |
| 499 | const main_tokens = tree.nodes.items(.main_token); | 584 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -524,9 +609,10 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro | ... | @@ -524,9 +609,10 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro |
| 524 | }; | 609 | }; |
| 525 | | 610 | |
| 526 | if (rhs == 0) { | 611 | if (rhs == 0) { |
| 527 | return addZirInstTag(mod, parent_scope, src, .break_void, .{ | 612 | const result = try addZirInstTag(mod, parent_scope, src, .break_void, .{ |
| 528 | .block = block_inst, | 613 | .block = block_inst, |
| 529 | }); | 614 | }); |
| | 615 | return rvalue(mod, parent_scope, rl, result); |
| 530 | } | 616 | } |
| 531 | gen_zir.break_count += 1; | 617 | gen_zir.break_count += 1; |
| 532 | const prev_rvalue_rl_count = gen_zir.rvalue_rl_count; | 618 | const prev_rvalue_rl_count = gen_zir.rvalue_rl_count; |
| ... | @@ -547,7 +633,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro | ... | @@ -547,7 +633,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro |
| 547 | try gen_zir.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst); | 633 | try gen_zir.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst); |
| 548 | } | 634 | } |
| 549 | } | 635 | } |
| 550 | return br; | 636 | return rvalue(mod, parent_scope, rl, br); |
| 551 | }, | 637 | }, |
| 552 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 638 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 553 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 639 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| ... | @@ -561,7 +647,12 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro | ... | @@ -561,7 +647,12 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerErro |
| 561 | } | 647 | } |
| 562 | } | 648 | } |
| 563 | | 649 | |
| 564 | fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { | 650 | fn continueExpr( |
| | 651 | mod: *Module, |
| | 652 | parent_scope: *Scope, |
| | 653 | rl: ResultLoc, |
| | 654 | node: ast.Node.Index, |
| | 655 | ) InnerError!*zir.Inst { |
| 565 | const tree = parent_scope.tree(); | 656 | const tree = parent_scope.tree(); |
| 566 | const node_datas = tree.nodes.items(.data); | 657 | const node_datas = tree.nodes.items(.data); |
| 567 | const main_tokens = tree.nodes.items(.main_token); | 658 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -590,9 +681,10 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerE | ... | @@ -590,9 +681,10 @@ fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerE |
| 590 | continue; | 681 | continue; |
| 591 | } | 682 | } |
| 592 | | 683 | |
| 593 | return addZirInstTag(mod, parent_scope, src, .break_void, .{ | 684 | const result = try addZirInstTag(mod, parent_scope, src, .break_void, .{ |
| 594 | .block = continue_block, | 685 | .block = continue_block, |
| 595 | }); | 686 | }); |
| | 687 | return rvalue(mod, parent_scope, rl, result); |
| 596 | }, | 688 | }, |
| 597 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 689 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 598 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 690 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| ... | @@ -1083,12 +1175,6 @@ fn negation( | ... | @@ -1083,12 +1175,6 @@ fn negation( |
| 1083 | return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs); | 1175 | return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs); |
| 1084 | } | 1176 | } |
| 1085 | | 1177 | |
| 1086 | fn sliceType(mod: *Module, scope: *Scope, node: *ast.Node.slice_type) InnerError!*zir.Inst { | | |
| 1087 | const tree = scope.tree(); | | |
| 1088 | const src = token_starts[node.op_token]; | | |
| 1089 | return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, .Slice); | | |
| 1090 | } | | |
| 1091 | | | |
| 1092 | fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { | 1178 | fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { |
| 1093 | const tree = scope.tree(); | 1179 | const tree = scope.tree(); |
| 1094 | const src = token_starts[node.op_token]; | 1180 | const src = token_starts[node.op_token]; |
| ... | @@ -1146,70 +1232,54 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, | ... | @@ -1146,70 +1232,54 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, |
| 1146 | return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); | 1232 | return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); |
| 1147 | } | 1233 | } |
| 1148 | | 1234 | |
| 1149 | fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.array_type) !*zir.Inst { | 1235 | fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { |
| 1150 | const tree = scope.tree(); | 1236 | const tree = scope.tree(); |
| 1151 | const src = token_starts[node.op_token]; | 1237 | const main_tokens = tree.nodes.items(.main_token); |
| | 1238 | const node_datas = tree.nodes.items(.data); |
| | 1239 | const src = token_starts[main_tokens[node]]; |
| 1152 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1240 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| 1153 | .ty = Type.initTag(.type), | 1241 | .ty = Type.initTag(.type), |
| 1154 | .val = Value.initTag(.usize_type), | 1242 | .val = Value.initTag(.usize_type), |
| 1155 | }); | 1243 | }); |
| | 1244 | const len_node = node_datas[node].lhs; |
| | 1245 | const elem_node = node_datas[node].rhs; |
| | 1246 | if (len_node == 0) { |
| | 1247 | const elem_type = try typeExpr(mod, scope, elem_node); |
| | 1248 | const result = try addZIRUnOp(mod, scope, src, .mut_slice_type, elem_type); |
| | 1249 | return rvalue(mod, scope, rl, result); |
| | 1250 | } else { |
| | 1251 | // TODO check for [_]T |
| | 1252 | const len = try expr(mod, scope, .{ .ty = usize_type }, len_node); |
| | 1253 | const elem_type = try typeExpr(mod, scope, elem_node); |
| 1156 | | 1254 | |
| 1157 | // TODO check for [_]T | 1255 | const result = try addZIRBinOp(mod, scope, src, .array_type, len, elem_type); |
| 1158 | const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr); | 1256 | return rvalue(mod, scope, rl, result); |
| 1159 | const elem_type = try typeExpr(mod, scope, node.rhs); | 1257 | } |
| 1160 | | | |
| 1161 | return addZIRBinOp(mod, scope, src, .array_type, len, elem_type); | | |
| 1162 | } | 1258 | } |
| 1163 | | 1259 | |
| 1164 | fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.array_type_sentinel) !*zir.Inst { | 1260 | fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { |
| 1165 | const tree = scope.tree(); | 1261 | const tree = scope.tree(); |
| 1166 | const src = token_starts[node.op_token]; | 1262 | const main_tokens = tree.nodes.items(.main_token); |
| | 1263 | const len_node = node_datas[node].lhs; |
| | 1264 | const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel); |
| | 1265 | const src = token_starts[main_tokens[node]]; |
| 1167 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1266 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| 1168 | .ty = Type.initTag(.type), | 1267 | .ty = Type.initTag(.type), |
| 1169 | .val = Value.initTag(.usize_type), | 1268 | .val = Value.initTag(.usize_type), |
| 1170 | }); | 1269 | }); |
| 1171 | | 1270 | |
| 1172 | // TODO check for [_]T | 1271 | // TODO check for [_]T |
| 1173 | const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr); | 1272 | const len = try expr(mod, scope, .{ .ty = usize_type }, len_node); |
| 1174 | const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel); | 1273 | const sentinel_uncasted = try expr(mod, scope, .none, extra.sentinel); |
| 1175 | const elem_type = try typeExpr(mod, scope, node.rhs); | 1274 | const elem_type = try typeExpr(mod, scope, extra.elem_type); |
| 1176 | const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted); | 1275 | const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted); |
| 1177 | | 1276 | |
| 1178 | return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{ | 1277 | const result = try addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{ |
| 1179 | .len = len, | 1278 | .len = len, |
| 1180 | .sentinel = sentinel, | 1279 | .sentinel = sentinel, |
| 1181 | .elem_type = elem_type, | 1280 | .elem_type = elem_type, |
| 1182 | }, .{}); | 1281 | }, .{}); |
| 1183 | } | 1282 | return rvalue(mod, scope, rl, result); |
| 1184 | | | |
| 1185 | fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.anyframe_type) InnerError!*zir.Inst { | | |
| 1186 | const tree = scope.tree(); | | |
| 1187 | const src = token_starts[node.anyframe_token]; | | |
| 1188 | if (node.result) |some| { | | |
| 1189 | const return_type = try typeExpr(mod, scope, some.return_type); | | |
| 1190 | return addZIRUnOp(mod, scope, src, .anyframe_type, return_type); | | |
| 1191 | } else { | | |
| 1192 | return addZIRInstConst(mod, scope, src, .{ | | |
| 1193 | .ty = Type.initTag(.type), | | |
| 1194 | .val = Value.initTag(.anyframe_type), | | |
| 1195 | }); | | |
| 1196 | } | | |
| 1197 | } | | |
| 1198 | | | |
| 1199 | fn typeInixOp(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst { | | |
| 1200 | const tree = scope.tree(); | | |
| 1201 | const src = token_starts[node.op_token]; | | |
| 1202 | const error_set = try typeExpr(mod, scope, node.lhs); | | |
| 1203 | const payload = try typeExpr(mod, scope, node.rhs); | | |
| 1204 | return addZIRBinOp(mod, scope, src, op_inst_tag, error_set, payload); | | |
| 1205 | } | | |
| 1206 | | | |
| 1207 | fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.enum_literal) !*zir.Inst { | | |
| 1208 | const tree = scope.tree(); | | |
| 1209 | const src = token_starts[node.name]; | | |
| 1210 | const name = try mod.identifierTokenString(scope, node.name); | | |
| 1211 | | | |
| 1212 | return addZIRInst(mod, scope, src, zir.Inst.EnumLiteral, .{ .name = name }, .{}); | | |
| 1213 | } | 1283 | } |
| 1214 | | 1284 | |
| 1215 | fn containerField( | 1285 | fn containerField( |
| ... | @@ -1394,85 +1464,50 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1394,85 +1464,50 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1394 | } | 1464 | } |
| 1395 | } | 1465 | } |
| 1396 | | 1466 | |
| 1397 | fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.error_set_decl) InnerError!*zir.Inst { | 1467 | fn errorSetDecl( |
| | 1468 | mod: *Module, |
| | 1469 | scope: *Scope, |
| | 1470 | rl: ResultLoc, |
| | 1471 | node: ast.Node.Index, |
| | 1472 | ) InnerError!*zir.Inst { |
| 1398 | const tree = scope.tree(); | 1473 | const tree = scope.tree(); |
| 1399 | const src = token_starts[node.error_token]; | 1474 | const main_tokens = tree.nodes.items(.main_token); |
| 1400 | const decls = node.decls(); | 1475 | const token_tags = tree.tokens.items(.tag); |
| 1401 | const fields = try scope.arena().alloc([]const u8, decls.len); | | |
| 1402 | | | |
| 1403 | for (decls) |decl, i| { | | |
| 1404 | const tag = decl.castTag(.ErrorTag).?; | | |
| 1405 | fields[i] = try mod.identifierTokenString(scope, tag.name_token); | | |
| 1406 | } | | |
| 1407 | | | |
| 1408 | return addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{}); | | |
| 1409 | } | | |
| 1410 | | 1476 | |
| 1411 | fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst { | 1477 | // Count how many fields there are. |
| 1412 | const tree = scope.tree(); | 1478 | const error_token = main_tokens[node]; |
| 1413 | const src = token_starts[node.token]; | 1479 | const count: usize = count: { |
| 1414 | return addZIRInstConst(mod, scope, src, .{ | 1480 | var tok_i = error_token + 2; |
| 1415 | .ty = Type.initTag(.type), | 1481 | var count: usize = 0; |
| 1416 | .val = Value.initTag(.anyerror_type), | 1482 | while (true) : (tok_i += 1) { |
| 1417 | }); | 1483 | switch (token_tags[tok_i]) { |
| 1418 | } | 1484 | .doc_comment, .comma => {}, |
| | 1485 | .identifier => count += 1, |
| | 1486 | .r_paren => break :count count, |
| | 1487 | else => unreachable, |
| | 1488 | } |
| | 1489 | } else unreachable; // TODO should not need else unreachable here |
| | 1490 | }; |
| 1419 | | 1491 | |
| 1420 | fn catchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.@"catch") InnerError!*zir.Inst { | 1492 | const fields = try scope.arena().alloc([]const u8, count); |
| 1421 | switch (rl) { | 1493 | { |
| 1422 | .ref => return orelseCatchExpr( | 1494 | var tok_i = error_token + 2; |
| 1423 | mod, | 1495 | var field_i: usize = 0; |
| 1424 | scope, | 1496 | while (true) : (tok_i += 1) { |
| 1425 | rl, | 1497 | switch (token_tags[tok_i]) { |
| 1426 | node.lhs, | 1498 | .doc_comment, .comma => {}, |
| 1427 | node.op_token, | 1499 | .identifier => { |
| 1428 | .is_err_ptr, | 1500 | fields[field_i] = try mod.identifierTokenString(scope, tok_i); |
| 1429 | .err_union_payload_unsafe_ptr, | 1501 | field_i += 1; |
| 1430 | .err_union_code_ptr, | 1502 | }, |
| 1431 | node.rhs, | 1503 | .r_paren => break, |
| 1432 | node.payload, | 1504 | else => unreachable, |
| 1433 | ), | 1505 | } |
| 1434 | else => return orelseCatchExpr( | 1506 | } |
| 1435 | mod, | | |
| 1436 | scope, | | |
| 1437 | rl, | | |
| 1438 | node.lhs, | | |
| 1439 | node.op_token, | | |
| 1440 | .is_err, | | |
| 1441 | .err_union_payload_unsafe, | | |
| 1442 | .err_union_code, | | |
| 1443 | node.rhs, | | |
| 1444 | node.payload, | | |
| 1445 | ), | | |
| 1446 | } | | |
| 1447 | } | | |
| 1448 | | | |
| 1449 | fn orelseExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { | | |
| 1450 | switch (rl) { | | |
| 1451 | .ref => return orelseCatchExpr( | | |
| 1452 | mod, | | |
| 1453 | scope, | | |
| 1454 | rl, | | |
| 1455 | node.lhs, | | |
| 1456 | node.op_token, | | |
| 1457 | .is_null_ptr, | | |
| 1458 | .optional_payload_unsafe_ptr, | | |
| 1459 | undefined, | | |
| 1460 | node.rhs, | | |
| 1461 | null, | | |
| 1462 | ), | | |
| 1463 | else => return orelseCatchExpr( | | |
| 1464 | mod, | | |
| 1465 | scope, | | |
| 1466 | rl, | | |
| 1467 | node.lhs, | | |
| 1468 | node.op_token, | | |
| 1469 | .is_null, | | |
| 1470 | .optional_payload_unsafe, | | |
| 1471 | undefined, | | |
| 1472 | node.rhs, | | |
| 1473 | null, | | |
| 1474 | ), | | |
| 1475 | } | 1507 | } |
| | 1508 | const src = token_starts[error_token]; |
| | 1509 | const result = try addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{}); |
| | 1510 | return rvalue(mod, scope, rl, result); |
| 1476 | } | 1511 | } |
| 1477 | | 1512 | |
| 1478 | fn orelseCatchExpr( | 1513 | fn orelseCatchExpr( |
| ... | @@ -1681,55 +1716,78 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) I | ... | @@ -1681,55 +1716,78 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) I |
| 1681 | } | 1716 | } |
| 1682 | } | 1717 | } |
| 1683 | | 1718 | |
| 1684 | fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.array_access) InnerError!*zir.Inst { | 1719 | fn arrayAccess( |
| | 1720 | mod: *Module, |
| | 1721 | scope: *Scope, |
| | 1722 | rl: ResultLoc, |
| | 1723 | node: ast.Node.Index, |
| | 1724 | ) InnerError!*zir.Inst { |
| 1685 | const tree = scope.tree(); | 1725 | const tree = scope.tree(); |
| 1686 | const src = token_starts[node.rtoken]; | 1726 | const main_tokens = tree.nodes.items(.main_token); |
| | 1727 | const token_starts = tree.tokens.items(.start); |
| | 1728 | const src = token_starts[main_tokens[node]]; |
| 1687 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1729 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| 1688 | .ty = Type.initTag(.type), | 1730 | .ty = Type.initTag(.type), |
| 1689 | .val = Value.initTag(.usize_type), | 1731 | .val = Value.initTag(.usize_type), |
| 1690 | }); | 1732 | }); |
| 1691 | const index_rl: ResultLoc = .{ .ty = usize_type }; | 1733 | const index_rl: ResultLoc = .{ .ty = usize_type }; |
| 1692 | | 1734 | switch (rl) { |
| 1693 | if (rl == .ref) { | 1735 | .ref => return addZirInstTag(mod, scope, src, .elem_ptr, .{ |
| 1694 | return addZirInstTag(mod, scope, src, .elem_ptr, .{ | 1736 | .array = try expr(mod, scope, .ref, node_datas[node].lhs), |
| 1695 | .array = try expr(mod, scope, .ref, node.lhs), | 1737 | .index = try expr(mod, scope, index_rl, node_datas[node].rhs), |
| 1696 | .index = try expr(mod, scope, index_rl, node.index_expr), | 1738 | }), |
| 1697 | }); | 1739 | else => return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .elem_val, .{ |
| | 1740 | .array = try expr(mod, scope, .none, node_datas[node].lhs), |
| | 1741 | .index = try expr(mod, scope, index_rl, node_datas[node].rhs), |
| | 1742 | })), |
| 1698 | } | 1743 | } |
| 1699 | return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .elem_val, .{ | | |
| 1700 | .array = try expr(mod, scope, .none, node.lhs), | | |
| 1701 | .index = try expr(mod, scope, index_rl, node.index_expr), | | |
| 1702 | })); | | |
| 1703 | } | 1744 | } |
| 1704 | | 1745 | |
| 1705 | fn sliceExpr(mod: *Module, scope: *Scope, node: *ast.Node.slice) InnerError!*zir.Inst { | 1746 | fn sliceExpr( |
| | 1747 | mod: *Module, |
| | 1748 | scope: *Scope, |
| | 1749 | rl: ResultLoc, |
| | 1750 | slice: ast.full.Slice, |
| | 1751 | ) InnerError!*zir.Inst { |
| 1706 | const tree = scope.tree(); | 1752 | const tree = scope.tree(); |
| 1707 | const src = token_starts[node.rtoken]; | 1753 | const token_starts = tree.tokens.items(.start); |
| | 1754 | const src = token_starts[slice.ast.lbracket]; |
| 1708 | | 1755 | |
| 1709 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1756 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| 1710 | .ty = Type.initTag(.type), | 1757 | .ty = Type.initTag(.type), |
| 1711 | .val = Value.initTag(.usize_type), | 1758 | .val = Value.initTag(.usize_type), |
| 1712 | }); | 1759 | }); |
| 1713 | | 1760 | |
| 1714 | const array_ptr = try expr(mod, scope, .ref, node.lhs); | 1761 | const array_ptr = try expr(mod, scope, .ref, slice.ast.sliced); |
| 1715 | const start = try expr(mod, scope, .{ .ty = usize_type }, node.start); | 1762 | const start = try expr(mod, scope, .{ .ty = usize_type }, slice.ast.start); |
| 1716 | | 1763 | |
| 1717 | if (node.end == null and node.sentinel == null) { | 1764 | if (slice.ast.sentinel == 0) { |
| 1718 | return try addZIRBinOp(mod, scope, src, .slice_start, array_ptr, start); | 1765 | if (slice.ast.end == 0) { |
| | 1766 | const result = try addZIRBinOp(mod, scope, src, .slice_start, array_ptr, start); |
| | 1767 | return rvalue(mod, scope, rl, result); |
| | 1768 | } else { |
| | 1769 | const end = try expr(mod, scope, .{ .ty = usize_type }, slice.ast.end); |
| | 1770 | // TODO a ZIR slice_open instruction |
| | 1771 | const result = try addZIRInst(mod, scope, src, zir.Inst.Slice, .{ |
| | 1772 | .array_ptr = array_ptr, |
| | 1773 | .start = start, |
| | 1774 | }, .{ .end = end }); |
| | 1775 | return rvalue(mod, scope, rl, result); |
| | 1776 | } |
| 1719 | } | 1777 | } |
| 1720 | | 1778 | |
| 1721 | const end = if (node.end) |end| try expr(mod, scope, .{ .ty = usize_type }, end) else null; | 1779 | const end = try expr(mod, scope, .{ .ty = usize_type }, slice.ast.end); |
| 1722 | // we could get the child type here, but it is easier to just do it in semantic analysis. | 1780 | // TODO pass the proper result loc to this expression using a ZIR instruction |
| 1723 | const sentinel = if (node.sentinel) |sentinel| try expr(mod, scope, .none, sentinel) else null; | 1781 | // "get the child element type for a slice target". |
| 1724 | | 1782 | const sentinel = try expr(mod, scope, .none, slice.ast.sentinel); |
| 1725 | return try addZIRInst( | 1783 | const result = try addZIRInst(mod, scope, src, zir.Inst.Slice, .{ |
| 1726 | mod, | 1784 | .array_ptr = array_ptr, |
| 1727 | scope, | 1785 | .start = start, |
| 1728 | src, | 1786 | }, .{ |
| 1729 | zir.Inst.Slice, | 1787 | .end = end, |
| 1730 | .{ .array_ptr = array_ptr, .start = start }, | 1788 | .sentinel = sentinel, |
| 1731 | .{ .end = end, .sentinel = sentinel }, | 1789 | }); |
| 1732 | ); | 1790 | return rvalue(mod, scope, rl, result); |
| 1733 | } | 1791 | } |
| 1734 | | 1792 | |
| 1735 | fn simpleBinOp( | 1793 | fn simpleBinOp( |
| ... | @@ -2070,7 +2128,6 @@ fn whileExpr( | ... | @@ -2070,7 +2128,6 @@ fn whileExpr( |
| 2070 | }; | 2128 | }; |
| 2071 | defer then_scope.instructions.deinit(mod.gpa); | 2129 | defer then_scope.instructions.deinit(mod.gpa); |
| 2072 | | 2130 | |
| 2073 | // declare payload to the then_scope | | |
| 2074 | const then_sub_scope = &then_scope.base; | 2131 | const then_sub_scope = &then_scope.base; |
| 2075 | | 2132 | |
| 2076 | loop_scope.break_count += 1; | 2133 | loop_scope.break_count += 1; |
| ... | @@ -2101,7 +2158,7 @@ fn whileExpr( | ... | @@ -2101,7 +2158,7 @@ fn whileExpr( |
| 2101 | | 2158 | |
| 2102 | if (loop_scope.label) |some| { | 2159 | if (loop_scope.label) |some| { |
| 2103 | if (!some.used) { | 2160 | if (!some.used) { |
| 2104 | return mod.fail(scope, token_starts[some.token], "unused while label", .{}); | 2161 | return mod.fail(scope, token_starts[some.token], "unused while loop label", .{}); |
| 2105 | } | 2162 | } |
| 2106 | } | 2163 | } |
| 2107 | return finishThenElseBlock( | 2164 | return finishThenElseBlock( |
| ... | @@ -2126,20 +2183,21 @@ fn forExpr( | ... | @@ -2126,20 +2183,21 @@ fn forExpr( |
| 2126 | mod: *Module, | 2183 | mod: *Module, |
| 2127 | scope: *Scope, | 2184 | scope: *Scope, |
| 2128 | rl: ResultLoc, | 2185 | rl: ResultLoc, |
| 2129 | for_node: *ast.Node.@"for", | 2186 | for_full: ast.full.While, |
| 2130 | ) InnerError!*zir.Inst { | 2187 | ) InnerError!*zir.Inst { |
| 2131 | if (for_node.label) |label| { | 2188 | if (for_full.label_token) |label_token| { |
| 2132 | try checkLabelRedefinition(mod, scope, label); | 2189 | try checkLabelRedefinition(mod, scope, label_token); |
| 2133 | } | 2190 | } |
| 2134 | | 2191 | |
| 2135 | if (for_node.inline_token) |tok| | 2192 | if (for_full.inline_token) |inline_token| { |
| 2136 | return mod.failTok(scope, tok, "TODO inline for", .{}); | 2193 | return mod.failTok(scope, inline_token, "TODO inline for", .{}); |
| | 2194 | } |
| 2137 | | 2195 | |
| 2138 | // setup variables and constants | 2196 | // Set up variables and constants. |
| 2139 | const tree = scope.tree(); | 2197 | const tree = scope.tree(); |
| 2140 | const node_datas = tree.nodes.items(.data); | 2198 | const node_datas = tree.nodes.items(.data); |
| 2141 | const main_tokens = tree.nodes.items(.main_token); | 2199 | const main_tokens = tree.nodes.items(.main_token); |
| 2142 | const for_src = token_starts[for_node.for_token]; | 2200 | const for_src = token_starts[for_full.ast.while_token]; |
| 2143 | const index_ptr = blk: { | 2201 | const index_ptr = blk: { |
| 2144 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ | 2202 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ |
| 2145 | .ty = Type.initTag(.type), | 2203 | .ty = Type.initTag(.type), |
| ... | @@ -2154,8 +2212,8 @@ fn forExpr( | ... | @@ -2154,8 +2212,8 @@ fn forExpr( |
| 2154 | _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero); | 2212 | _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero); |
| 2155 | break :blk index_ptr; | 2213 | break :blk index_ptr; |
| 2156 | }; | 2214 | }; |
| 2157 | const array_ptr = try expr(mod, scope, .ref, for_node.array_expr); | 2215 | const array_ptr = try expr(mod, scope, .ref, for_full.ast.cond_expr); |
| 2158 | const cond_src = token_starts[for_node.array_expr.firstToken()]; | 2216 | const cond_src = token_starts[tree.firstToken(for_full.ast.cond_expr)]; |
| 2159 | const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr); | 2217 | const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr); |
| 2160 | | 2218 | |
| 2161 | var loop_scope: Scope.GenZIR = .{ | 2219 | var loop_scope: Scope.GenZIR = .{ |
| ... | @@ -2217,15 +2275,15 @@ fn forExpr( | ... | @@ -2217,15 +2275,15 @@ fn forExpr( |
| 2217 | }); | 2275 | }); |
| 2218 | loop_scope.break_block = for_block; | 2276 | loop_scope.break_block = for_block; |
| 2219 | loop_scope.continue_block = cond_block; | 2277 | loop_scope.continue_block = cond_block; |
| 2220 | if (for_node.label) |some| { | 2278 | if (for_full.label_token) |label_token| { |
| 2221 | loop_scope.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{ | 2279 | loop_scope.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{ |
| 2222 | .token = some, | 2280 | .token = label_token, |
| 2223 | .block_inst = for_block, | 2281 | .block_inst = for_block, |
| 2224 | }); | 2282 | }); |
| 2225 | } | 2283 | } |
| 2226 | | 2284 | |
| 2227 | // while body | 2285 | // while body |
| 2228 | const then_src = token_starts[for_node.body.lastToken()]; | 2286 | const then_src = token_starts[tree.lastToken(for_full.ast.then_expr)]; |
| 2229 | var then_scope: Scope.GenZIR = .{ | 2287 | var then_scope: Scope.GenZIR = .{ |
| 2230 | .parent = &cond_scope.base, | 2288 | .parent = &cond_scope.base, |
| 2231 | .decl = cond_scope.decl, | 2289 | .decl = cond_scope.decl, |
| ... | @@ -2237,23 +2295,27 @@ fn forExpr( | ... | @@ -2237,23 +2295,27 @@ fn forExpr( |
| 2237 | | 2295 | |
| 2238 | var index_scope: Scope.LocalPtr = undefined; | 2296 | var index_scope: Scope.LocalPtr = undefined; |
| 2239 | const then_sub_scope = blk: { | 2297 | const then_sub_scope = blk: { |
| 2240 | const payload = for_node.payload.castTag(.PointerIndexPayload).?; | 2298 | const payload_token = for_full.payload_token.?; |
| 2241 | const is_ptr = payload.ptr_token != null; | 2299 | const ident = if (token_tags[payload_token] == .asterisk) |
| 2242 | const value_name = tree.tokenSlice(payload.value_symbol.firstToken()); | 2300 | payload_token + 1 |
| | 2301 | else |
| | 2302 | payload_token; |
| | 2303 | const is_ptr = ident != payload_token; |
| | 2304 | const value_name = tree.tokenSlice(ident); |
| 2243 | if (!mem.eql(u8, value_name, "_")) { | 2305 | if (!mem.eql(u8, value_name, "_")) { |
| 2244 | return mod.failNode(&then_scope.base, payload.value_symbol, "TODO implement for value payload", .{}); | 2306 | return mod.failNode(&then_scope.base, ident, "TODO implement for loop value payload", .{}); |
| 2245 | } else if (is_ptr) { | 2307 | } else if (is_ptr) { |
| 2246 | return mod.failTok(&then_scope.base, payload.ptr_token.?, "pointer modifier invalid on discard", .{}); | 2308 | return mod.failTok(&then_scope.base, payload_token, "pointer modifier invalid on discard", .{}); |
| 2247 | } | 2309 | } |
| 2248 | | 2310 | |
| 2249 | const index_symbol_node = payload.index_symbol orelse | 2311 | const index_token = if (token_tags[ident + 1] == .comma) |
| 2250 | break :blk &then_scope.base; | 2312 | ident + 2 |
| 2251 | | 2313 | else |
| 2252 | const index_name = tree.tokenSlice(tree.firstToken(index_symbol_node)); | | |
| 2253 | if (mem.eql(u8, index_name, "_")) { | | |
| 2254 | break :blk &then_scope.base; | 2314 | break :blk &then_scope.base; |
| | 2315 | if (mem.eql(u8, tree.tokenSlice(index_token), "_")) { |
| | 2316 | return mod.failTok(&then_scope.base, index_token, "discard of index capture not allowed; omit it instead", .{}); |
| 2255 | } | 2317 | } |
| 2256 | // TODO make this const without an extra copy? | 2318 | const index_name = try mod.identifierTokenString(&then_scope.base, index_token); |
| 2257 | index_scope = .{ | 2319 | index_scope = .{ |
| 2258 | .parent = &then_scope.base, | 2320 | .parent = &then_scope.base, |
| 2259 | .gen_zir = &then_scope, | 2321 | .gen_zir = &then_scope, |
| ... | @@ -2264,7 +2326,7 @@ fn forExpr( | ... | @@ -2264,7 +2326,7 @@ fn forExpr( |
| 2264 | }; | 2326 | }; |
| 2265 | | 2327 | |
| 2266 | loop_scope.break_count += 1; | 2328 | loop_scope.break_count += 1; |
| 2267 | const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_node.body); | 2329 | const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); |
| 2268 | | 2330 | |
| 2269 | // else branch | 2331 | // else branch |
| 2270 | var else_scope: Scope.GenZIR = .{ | 2332 | var else_scope: Scope.GenZIR = .{ |
| ... | @@ -2276,18 +2338,23 @@ fn forExpr( | ... | @@ -2276,18 +2338,23 @@ fn forExpr( |
| 2276 | }; | 2338 | }; |
| 2277 | defer else_scope.instructions.deinit(mod.gpa); | 2339 | defer else_scope.instructions.deinit(mod.gpa); |
| 2278 | | 2340 | |
| 2279 | var else_src: usize = undefined; | 2341 | const else_node = for_full.ast.else_expr; |
| 2280 | const else_result: ?*zir.Inst = if (for_node.@"else") |else_node| blk: { | 2342 | const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: { |
| 2281 | else_src = token_starts[else_node.body.lastToken()]; | | |
| 2282 | loop_scope.break_count += 1; | 2343 | loop_scope.break_count += 1; |
| 2283 | break :blk try expr(mod, &else_scope.base, loop_scope.break_result_loc, else_node.body); | 2344 | const sub_scope = &else_scope.base; |
| 2284 | } else blk: { | 2345 | break :blk .{ |
| 2285 | else_src = token_starts[for_node.lastToken()]; | 2346 | .src = token_starts[tree.lastToken(else_node)], |
| 2286 | break :blk null; | 2347 | .result = try expr(mod, sub_scope, loop_scope.break_result_loc, else_node), |
| 2287 | }; | 2348 | }; |
| | 2349 | } else |
| | 2350 | .{ |
| | 2351 | .src = token_starts[tree.lastToken(then_node)], |
| | 2352 | .result = null, |
| | 2353 | }; |
| | 2354 | |
| 2288 | if (loop_scope.label) |some| { | 2355 | if (loop_scope.label) |some| { |
| 2289 | if (!some.used) { | 2356 | if (!some.used) { |
| 2290 | return mod.fail(scope, token_starts[some.token], "unused for label", .{}); | 2357 | return mod.fail(scope, token_starts[some.token], "unused for loop label", .{}); |
| 2291 | } | 2358 | } |
| 2292 | } | 2359 | } |
| 2293 | return finishThenElseBlock( | 2360 | return finishThenElseBlock( |
| ... | @@ -2300,41 +2367,46 @@ fn forExpr( | ... | @@ -2300,41 +2367,46 @@ fn forExpr( |
| 2300 | &condbr.positionals.then_body, | 2367 | &condbr.positionals.then_body, |
| 2301 | &condbr.positionals.else_body, | 2368 | &condbr.positionals.else_body, |
| 2302 | then_src, | 2369 | then_src, |
| 2303 | else_src, | 2370 | else_info.src, |
| 2304 | then_result, | 2371 | then_result, |
| 2305 | else_result, | 2372 | else_info.result, |
| 2306 | for_block, | 2373 | for_block, |
| 2307 | cond_block, | 2374 | cond_block, |
| 2308 | ); | 2375 | ); |
| 2309 | } | 2376 | } |
| 2310 | | 2377 | |
| 2311 | fn switchCaseUsesRef(node: *ast.Node.@"switch") bool { | 2378 | fn getRangeNode( |
| 2312 | for (node.cases()) |uncasted_case| { | 2379 | node_tags: []const ast.Node.Tag, |
| 2313 | const case = uncasted_case.castTag(.switch_case).?; | 2380 | node_datas: []const ast.Node.Data, |
| 2314 | const uncasted_payload = case.payload orelse continue; | 2381 | start_node: ast.Node.Index, |
| 2315 | const payload = uncasted_payload.castTag(.PointerPayload).?; | 2382 | ) ?ast.Node.Index { |
| 2316 | if (payload.ptr_token) |_| return true; | 2383 | var node = start_node; |
| 2317 | } | | |
| 2318 | return false; | | |
| 2319 | } | | |
| 2320 | | | |
| 2321 | fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp { | | |
| 2322 | var cur = node; | | |
| 2323 | while (true) { | 2384 | while (true) { |
| 2324 | switch (cur.tag) { | 2385 | switch (node_tags[node]) { |
| 2325 | .range => return @fieldParentPtr(ast.Node.SimpleInfixOp, "base", cur), | 2386 | .switch_range => return node, |
| 2326 | .grouped_expression => cur = @fieldParentPtr(ast.Node.grouped_expression, "base", cur).expr, | 2387 | .grouped_expression => node = node_datas[node].lhs, |
| 2327 | else => return null, | 2388 | else => return null, |
| 2328 | } | 2389 | } |
| 2329 | } | 2390 | } |
| 2330 | } | 2391 | } |
| 2331 | | 2392 | |
| 2332 | fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node.@"switch") InnerError!*zir.Inst { | 2393 | fn switchExpr( |
| | 2394 | mod: *Module, |
| | 2395 | scope: *Scope, |
| | 2396 | rl: ResultLoc, |
| | 2397 | switch_node: ast.Node.Index, |
| | 2398 | ) InnerError!*zir.Inst { |
| 2333 | const tree = scope.tree(); | 2399 | const tree = scope.tree(); |
| 2334 | const node_datas = tree.nodes.items(.data); | 2400 | const node_datas = tree.nodes.items(.data); |
| 2335 | const main_tokens = tree.nodes.items(.main_token); | 2401 | const main_tokens = tree.nodes.items(.main_token); |
| 2336 | const switch_src = token_starts[switch_node.switch_token]; | 2402 | const token_tags = tree.tokens.items(.tag); |
| 2337 | const use_ref = switchCaseUsesRef(switch_node); | 2403 | |
| | 2404 | const switch_token = main_tokens[switch_node]; |
| | 2405 | const target_node = datas[switch_node].lhs; |
| | 2406 | const extra = tree.extraData(datas[switch_node].rhs, ast.switch_node.SubRange); |
| | 2407 | const case_nodes = tree.extra_data[extra.start..extra.end]; |
| | 2408 | |
| | 2409 | const switch_src = token_starts[switch_token]; |
| 2338 | | 2410 | |
| 2339 | var block_scope: Scope.GenZIR = .{ | 2411 | var block_scope: Scope.GenZIR = .{ |
| 2340 | .parent = scope, | 2412 | .parent = scope, |
| ... | @@ -2349,18 +2421,26 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2349,18 +2421,26 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2349 | var items = std.ArrayList(*zir.Inst).init(mod.gpa); | 2421 | var items = std.ArrayList(*zir.Inst).init(mod.gpa); |
| 2350 | defer items.deinit(); | 2422 | defer items.deinit(); |
| 2351 | | 2423 | |
| 2352 | // first we gather all the switch items and check else/'_' prongs | 2424 | // First we gather all the switch items and check else/'_' prongs. |
| 2353 | var else_src: ?usize = null; | 2425 | var else_src: ?usize = null; |
| 2354 | var underscore_src: ?usize = null; | 2426 | var underscore_src: ?usize = null; |
| 2355 | var first_range: ?*zir.Inst = null; | 2427 | var first_range: ?*zir.Inst = null; |
| 2356 | var simple_case_count: usize = 0; | 2428 | var simple_case_count: usize = 0; |
| 2357 | for (switch_node.cases()) |uncasted_case| { | 2429 | var any_payload_is_ref = false; |
| 2358 | const case = uncasted_case.castTag(.switch_case).?; | 2430 | for (case_nodes) |case_node| { |
| 2359 | const case_src = token_starts[case.firstToken()]; | 2431 | const case = switch (node_tags[case_node]) { |
| 2360 | assert(case.items_len != 0); | 2432 | .switch_case_one => tree.switchCaseOne(case_node), |
| 2361 | | 2433 | .switch_case => tree.switchCase(case_node), |
| | 2434 | else => unreachable, |
| | 2435 | }; |
| | 2436 | if (case.payload_token) |payload_token| { |
| | 2437 | if (token_tags[payload_token] == .asterisk) { |
| | 2438 | any_payload_is_ref = true; |
| | 2439 | } |
| | 2440 | } |
| 2362 | // Check for else/_ prong, those are handled last. | 2441 | // Check for else/_ prong, those are handled last. |
| 2363 | if (case.items_len == 1 and case.items()[0].tag == .switch_else) { | 2442 | if (case.ast.values.len == 0) { |
| | 2443 | const case_src = token_starts[case.ast.arrow_token - 1]; |
| 2364 | if (else_src) |src| { | 2444 | if (else_src) |src| { |
| 2365 | const msg = msg: { | 2445 | const msg = msg: { |
| 2366 | const msg = try mod.errMsg( | 2446 | const msg = try mod.errMsg( |
| ... | @@ -2377,9 +2457,11 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2377,9 +2457,11 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2377 | } | 2457 | } |
| 2378 | else_src = case_src; | 2458 | else_src = case_src; |
| 2379 | continue; | 2459 | continue; |
| 2380 | } else if (case.items_len == 1 and case.items()[0].tag == .identifier and | 2460 | } else if (case.ast.values.len == 1 and |
| 2381 | mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_")) | 2461 | node_tags[case.ast.values[0]] == .identifier and |
| | 2462 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")) |
| 2382 | { | 2463 | { |
| | 2464 | const case_src = token_starts[case.ast.arrow_token - 1]; |
| 2383 | if (underscore_src) |src| { | 2465 | if (underscore_src) |src| { |
| 2384 | const msg = msg: { | 2466 | const msg = msg: { |
| 2385 | const msg = try mod.errMsg( | 2467 | const msg = try mod.errMsg( |
| ... | @@ -2416,14 +2498,18 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2416,14 +2498,18 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2416 | } | 2498 | } |
| 2417 | } | 2499 | } |
| 2418 | | 2500 | |
| 2419 | if (case.items_len == 1 and getRangeNode(case.items()[0]) == null) simple_case_count += 1; | 2501 | if (case.ast.values.len == 1 and |
| | 2502 | getRangeNode(node_tags, node_datas, case.ast.values[0]) == null) |
| | 2503 | { |
| | 2504 | simple_case_count += 1; |
| | 2505 | } |
| 2420 | | 2506 | |
| 2421 | // generate all the switch items as comptime expressions | 2507 | // Generate all the switch items as comptime expressions. |
| 2422 | for (case.items()) |item| { | 2508 | for (case.ast.values) |item| { |
| 2423 | if (getRangeNode(item)) |range| { | 2509 | if (getRangeNode(node_tags, node_datas, item)) |range| { |
| 2424 | const start = try comptimeExpr(mod, &block_scope.base, .none, range.lhs); | 2510 | const start = try comptimeExpr(mod, &block_scope.base, .none, node_datas[range].lhs); |
| 2425 | const end = try comptimeExpr(mod, &block_scope.base, .none, range.rhs); | 2511 | const end = try comptimeExpr(mod, &block_scope.base, .none, node_datas[range].rhs); |
| 2426 | const range_src = token_starts[range.op_token]; | 2512 | const range_src = token_starts[main_tokens[range]]; |
| 2427 | const range_inst = try addZIRBinOp(mod, &block_scope.base, range_src, .switch_range, start, end); | 2513 | const range_inst = try addZIRBinOp(mod, &block_scope.base, range_src, .switch_range, start, end); |
| 2428 | try items.append(range_inst); | 2514 | try items.append(range_inst); |
| 2429 | } else { | 2515 | } else { |
| ... | @@ -2438,21 +2524,25 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2438,21 +2524,25 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2438 | if (underscore_src != null) special_prong = .underscore; | 2524 | if (underscore_src != null) special_prong = .underscore; |
| 2439 | var cases = try block_scope.arena.alloc(zir.Inst.SwitchBr.Case, simple_case_count); | 2525 | var cases = try block_scope.arena.alloc(zir.Inst.SwitchBr.Case, simple_case_count); |
| 2440 | | 2526 | |
| 2441 | const target_ptr = if (use_ref) try expr(mod, &block_scope.base, .ref, switch_node.expr) else null; | 2527 | const rl_and_tag: struct { rl: ResultLoc, tag: zir.Inst.Tag } = if (any_payload_is_ref) |
| 2442 | const target = if (target_ptr) |some| | 2528 | .{ |
| 2443 | try addZIRUnOp(mod, &block_scope.base, some.src, .deref, some) | 2529 | .rl = .ref, |
| | 2530 | .tag = .switchbr_ref, |
| | 2531 | } |
| 2444 | else | 2532 | else |
| 2445 | try expr(mod, &block_scope.base, .none, switch_node.expr); | 2533 | .{ |
| 2446 | const switch_inst = try addZIRInst(mod, &block_scope.base, switch_src, zir.Inst.SwitchBr, .{ | 2534 | .rl = .none, |
| | 2535 | .tag = .switchbr, |
| | 2536 | }; |
| | 2537 | const target = try expr(mod, &block_scope.base, rl_and_tag.rl, target_node); |
| | 2538 | const switch_inst = try addZirInstT(mod, &block_scope.base, switch_src, zir.Inst.SwitchBr, rl_and_tag.tag, .{ |
| 2447 | .target = target, | 2539 | .target = target, |
| 2448 | .cases = cases, | 2540 | .cases = cases, |
| 2449 | .items = try block_scope.arena.dupe(*zir.Inst, items.items), | 2541 | .items = try block_scope.arena.dupe(*zir.Inst, items.items), |
| 2450 | .else_body = undefined, // populated below | 2542 | .else_body = undefined, // populated below |
| 2451 | }, .{ | | |
| 2452 | .range = first_range, | 2543 | .range = first_range, |
| 2453 | .special_prong = special_prong, | 2544 | .special_prong = special_prong, |
| 2454 | }); | 2545 | }); |
| 2455 | | | |
| 2456 | const block = try addZIRInstBlock(mod, scope, switch_src, .block, .{ | 2546 | const block = try addZIRInstBlock(mod, scope, switch_src, .block, .{ |
| 2457 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), | 2547 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), |
| 2458 | }); | 2548 | }); |
| ... | @@ -2475,29 +2565,35 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2475,29 +2565,35 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2475 | }; | 2565 | }; |
| 2476 | defer else_scope.instructions.deinit(mod.gpa); | 2566 | defer else_scope.instructions.deinit(mod.gpa); |
| 2477 | | 2567 | |
| 2478 | // Now generate all but the special cases | 2568 | // Now generate all but the special cases. |
| 2479 | var special_case: ?*ast.Node.switch_case = null; | 2569 | var special_case: ?ast.Node.Index = null; |
| 2480 | var items_index: usize = 0; | 2570 | var items_index: usize = 0; |
| 2481 | var case_index: usize = 0; | 2571 | var case_index: usize = 0; |
| 2482 | for (switch_node.cases()) |uncasted_case| { | 2572 | for (case_nodes) |case_node| { |
| 2483 | const case = uncasted_case.castTag(.switch_case).?; | 2573 | const case = switch (node_tags[case_node]) { |
| 2484 | const case_src = token_starts[case.firstToken()]; | 2574 | .switch_case_one => tree.switchCaseOne(case_node), |
| 2485 | // reset without freeing to reduce allocations. | 2575 | .switch_case => tree.switchCase(case_node), |
| 2486 | case_scope.instructions.items.len = 0; | 2576 | else => unreachable, |
| | 2577 | }; |
| | 2578 | const case_src = token_starts[main_tokens[case_node]]; |
| | 2579 | case_scope.instructions.shrinkRetainingCapacity(0); |
| 2487 | | 2580 | |
| 2488 | // Check for else/_ prong, those are handled last. | 2581 | // Check for else/_ prong, those are handled last. |
| 2489 | if (case.items_len == 1 and case.items()[0].tag == .switch_else) { | 2582 | if (case.ast.values.len == 0) { |
| 2490 | special_case = case; | 2583 | special_case = case; |
| 2491 | continue; | 2584 | continue; |
| 2492 | } else if (case.items_len == 1 and case.items()[0].tag == .identifier and | 2585 | } else if (case.ast.values.len == 1 and |
| 2493 | mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_")) | 2586 | node_tags[case.ast.values[0]] == .identifier and |
| | 2587 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")) |
| 2494 | { | 2588 | { |
| 2495 | special_case = case; | 2589 | special_case = case; |
| 2496 | continue; | 2590 | continue; |
| 2497 | } | 2591 | } |
| 2498 | | 2592 | |
| 2499 | // If this is a simple one item prong then it is handled by the switchbr. | 2593 | // If this is a simple one item prong then it is handled by the switchbr. |
| 2500 | if (case.items_len == 1 and getRangeNode(case.items()[0]) == null) { | 2594 | if (case.ast.values.len == 1 and |
| | 2595 | getRangeNode(node_tags, node_datas, case.ast.values[0]) == null) |
| | 2596 | { |
| 2501 | const item = items.items[items_index]; | 2597 | const item = items.items[items_index]; |
| 2502 | items_index += 1; | 2598 | items_index += 1; |
| 2503 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target, target_ptr); | 2599 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target, target_ptr); |
| ... | @@ -2510,16 +2606,14 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2510,16 +2606,14 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2510 | continue; | 2606 | continue; |
| 2511 | } | 2607 | } |
| 2512 | | 2608 | |
| 2513 | // TODO if the case has few items and no ranges it might be better | | |
| 2514 | // to just handle them as switch prongs. | | |
| 2515 | | | |
| 2516 | // Check if the target matches any of the items. | 2609 | // Check if the target matches any of the items. |
| 2517 | // 1, 2, 3..6 will result in | 2610 | // 1, 2, 3..6 will result in |
| 2518 | // target == 1 or target == 2 or (target >= 3 and target <= 6) | 2611 | // target == 1 or target == 2 or (target >= 3 and target <= 6) |
| | 2612 | // TODO handle multiple items as switch prongs rather than along with ranges. |
| 2519 | var any_ok: ?*zir.Inst = null; | 2613 | var any_ok: ?*zir.Inst = null; |
| 2520 | for (case.items()) |item| { | 2614 | for (case.ast.values) |item| { |
| 2521 | if (getRangeNode(item)) |range| { | 2615 | if (getRangeNode(node_tags, node_datas, item)) |range| { |
| 2522 | const range_src = token_starts[range.op_token]; | 2616 | const range_src = token_starts[main_tokens[range]]; |
| 2523 | const range_inst = items.items[items_index].castTag(.switch_range).?; | 2617 | const range_inst = items.items[items_index].castTag(.switch_range).?; |
| 2524 | items_index += 1; | 2618 | items_index += 1; |
| 2525 | | 2619 | |
| ... | @@ -2580,7 +2674,7 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node | ... | @@ -2580,7 +2674,7 @@ fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node |
| 2580 | // Not handling all possible cases is a compile error. | 2674 | // Not handling all possible cases is a compile error. |
| 2581 | _ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreachable_unsafe); | 2675 | _ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreachable_unsafe); |
| 2582 | } | 2676 | } |
| 2583 | switch_inst.castTag(.switchbr).?.positionals.else_body = .{ | 2677 | switch_inst.positionals.else_body = .{ |
| 2584 | .instructions = try block_scope.arena.dupe(*zir.Inst, else_scope.instructions.items), | 2678 | .instructions = try block_scope.arena.dupe(*zir.Inst, else_scope.instructions.items), |
| 2585 | }; | 2679 | }; |
| 2586 | | 2680 | |
| ... | @@ -2592,19 +2686,22 @@ fn switchCaseExpr( | ... | @@ -2592,19 +2686,22 @@ fn switchCaseExpr( |
| 2592 | scope: *Scope, | 2686 | scope: *Scope, |
| 2593 | rl: ResultLoc, | 2687 | rl: ResultLoc, |
| 2594 | block: *zir.Inst.Block, | 2688 | block: *zir.Inst.Block, |
| 2595 | case: *ast.Node.switch_case, | 2689 | case: ast.full.SwitchCase, |
| 2596 | target: *zir.Inst, | 2690 | target: *zir.Inst, |
| 2597 | target_ptr: ?*zir.Inst, | 2691 | target_ptr: ?*zir.Inst, |
| 2598 | ) !void { | 2692 | ) !void { |
| 2599 | const tree = scope.tree(); | 2693 | const tree = scope.tree(); |
| 2600 | const node_datas = tree.nodes.items(.data); | 2694 | const node_datas = tree.nodes.items(.data); |
| 2601 | const main_tokens = tree.nodes.items(.main_token); | 2695 | const main_tokens = tree.nodes.items(.main_token); |
| 2602 | const case_src = token_starts[case.firstToken()]; | 2696 | const case_src = token_starts[case.ast.arrow_token]; |
| 2603 | const sub_scope = blk: { | 2697 | const sub_scope = blk: { |
| 2604 | const uncasted_payload = case.payload orelse break :blk scope; | 2698 | const payload_token = case.payload_token orelse break :blk scope; |
| 2605 | const payload = uncasted_payload.castTag(.PointerPayload).?; | 2699 | const ident = if (token_tags[payload_token] == .asterisk) |
| 2606 | const is_ptr = payload.ptr_token != null; | 2700 | payload_token + 1 |
| 2607 | const value_name = tree.tokenSlice(payload.value_symbol.firstToken()); | 2701 | else |
| | 2702 | payload_token; |
| | 2703 | const is_ptr = ident != payload_token; |
| | 2704 | const value_name = tree.tokenSlice(ident); |
| 2608 | if (mem.eql(u8, value_name, "_")) { | 2705 | if (mem.eql(u8, value_name, "_")) { |
| 2609 | if (is_ptr) { | 2706 | if (is_ptr) { |
| 2610 | return mod.failTok(scope, payload.ptr_token.?, "pointer modifier invalid on discard", .{}); | 2707 | return mod.failTok(scope, payload.ptr_token.?, "pointer modifier invalid on discard", .{}); |
| ... | @@ -2614,7 +2711,7 @@ fn switchCaseExpr( | ... | @@ -2614,7 +2711,7 @@ fn switchCaseExpr( |
| 2614 | return mod.failNode(scope, payload.value_symbol, "TODO implement switch value payload", .{}); | 2711 | return mod.failNode(scope, payload.value_symbol, "TODO implement switch value payload", .{}); |
| 2615 | }; | 2712 | }; |
| 2616 | | 2713 | |
| 2617 | const case_body = try expr(mod, sub_scope, rl, case.expr); | 2714 | const case_body = try expr(mod, sub_scope, rl, case.ast.target_expr); |
| 2618 | if (!case_body.tag.isNoReturn()) { | 2715 | if (!case_body.tag.isNoReturn()) { |
| 2619 | _ = try addZIRInst(mod, sub_scope, case_src, zir.Inst.Break, .{ | 2716 | _ = try addZIRInst(mod, sub_scope, case_src, zir.Inst.Break, .{ |
| 2620 | .block = block, | 2717 | .block = block, |
| ... | @@ -2820,12 +2917,13 @@ fn multilineStringLiteral( | ... | @@ -2820,12 +2917,13 @@ fn multilineStringLiteral( |
| 2820 | return rvalue(mod, scope, rl, str_inst); | 2917 | return rvalue(mod, scope, rl, str_inst); |
| 2821 | } | 2918 | } |
| 2822 | | 2919 | |
| 2823 | fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst { | 2920 | fn charLiteral(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { |
| 2824 | const tree = scope.tree(); | 2921 | const tree = scope.tree(); |
| 2825 | const node_datas = tree.nodes.items(.data); | 2922 | const node_datas = tree.nodes.items(.data); |
| 2826 | const main_tokens = tree.nodes.items(.main_token); | 2923 | const main_tokens = tree.nodes.items(.main_token); |
| 2827 | const src = token_starts[node.token]; | 2924 | const main_token = main_tokens[node]; |
| 2828 | const slice = tree.tokenSlice(node.token); | 2925 | const src = token_starts[main_token]; |
| | 2926 | const slice = tree.tokenSlice(main_token); |
| 2829 | | 2927 | |
| 2830 | var bad_index: usize = undefined; | 2928 | var bad_index: usize = undefined; |
| 2831 | const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) { | 2929 | const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) { |
| ... | @@ -2834,11 +2932,11 @@ fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst | ... | @@ -2834,11 +2932,11 @@ fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst |
| 2834 | return mod.fail(scope, src + bad_index, "invalid character: '{c}'\n", .{bad_byte}); | 2932 | return mod.fail(scope, src + bad_index, "invalid character: '{c}'\n", .{bad_byte}); |
| 2835 | }, | 2933 | }, |
| 2836 | }; | 2934 | }; |
| 2837 | | 2935 | const result = try addZIRInstConst(mod, scope, src, .{ |
| 2838 | return addZIRInstConst(mod, scope, src, .{ | | |
| 2839 | .ty = Type.initTag(.comptime_int), | 2936 | .ty = Type.initTag(.comptime_int), |
| 2840 | .val = try Value.Tag.int_u64.create(scope.arena(), value), | 2937 | .val = try Value.Tag.int_u64.create(scope.arena(), value), |
| 2841 | }); | 2938 | }); |
| | 2939 | return rvalue(mod, scope, rl, result); |
| 2842 | } | 2940 | } |
| 2843 | | 2941 | |
| 2844 | fn integerLiteral( | 2942 | fn integerLiteral( |
| ... | @@ -3675,6 +3773,29 @@ pub fn addZirInstTag( | ... | @@ -3675,6 +3773,29 @@ pub fn addZirInstTag( |
| 3675 | return &inst.base; | 3773 | return &inst.base; |
| 3676 | } | 3774 | } |
| 3677 | | 3775 | |
| | 3776 | pub fn addZirInstT( |
| | 3777 | mod: *Module, |
| | 3778 | scope: *Scope, |
| | 3779 | src: usize, |
| | 3780 | comptime T: type, |
| | 3781 | tag: zir.Inst.Tag, |
| | 3782 | positionals: std.meta.fieldInfo(tag.Type(), .positionals).field_type, |
| | 3783 | ) !*T { |
| | 3784 | const gen_zir = scope.getGenZIR(); |
| | 3785 | try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1); |
| | 3786 | const inst = try gen_zir.arena.create(T); |
| | 3787 | inst.* = .{ |
| | 3788 | .base = .{ |
| | 3789 | .tag = tag, |
| | 3790 | .src = src, |
| | 3791 | }, |
| | 3792 | .positionals = positionals, |
| | 3793 | .kw_args = .{}, |
| | 3794 | }; |
| | 3795 | gen_zir.instructions.appendAssumeCapacity(&inst.base); |
| | 3796 | return inst; |
| | 3797 | } |
| | 3798 | |
| 3678 | pub fn addZIRInstSpecial( | 3799 | pub fn addZIRInstSpecial( |
| 3679 | mod: *Module, | 3800 | mod: *Module, |
| 3680 | scope: *Scope, | 3801 | scope: *Scope, |