| ... | ... | @@ -100,6 +100,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 100 | 100 | .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat), |
| 101 | 101 | .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul), |
| 102 | 102 | |
| 103 | .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?), |
| 104 | .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?), |
| 105 | |
| 103 | 106 | .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?), |
| 104 | 107 | .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)), |
| 105 | 108 | .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)), |
| ... | ... | @@ -124,11 +127,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 124 | 127 | .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?), |
| 125 | 128 | .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)), |
| 126 | 129 | .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)), |
| 130 | .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr), |
| 127 | 131 | |
| 128 | 132 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), |
| 129 | 133 | .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}), |
| 130 | | .BoolAnd => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolAnd", .{}), |
| 131 | | .BoolOr => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolOr", .{}), |
| 132 | 134 | .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}), |
| 133 | 135 | .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}), |
| 134 | 136 | .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}), |
| ... | ... | @@ -159,7 +161,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 159 | 161 | .EnumLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .EnumLiteral", .{}), |
| 160 | 162 | .MultilineStringLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .MultilineStringLiteral", .{}), |
| 161 | 163 | .CharLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .CharLiteral", .{}), |
| 162 | | .GroupedExpression => return mod.failNode(scope, node, "TODO implement astgen.expr for .GroupedExpression", .{}), |
| 163 | 164 | .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}), |
| 164 | 165 | .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}), |
| 165 | 166 | .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}), |
| ... | ... | @@ -568,6 +569,88 @@ fn simpleBinOp( |
| 568 | 569 | return rlWrap(mod, scope, rl, result); |
| 569 | 570 | } |
| 570 | 571 | |
| 572 | fn boolBinOp( |
| 573 | mod: *Module, |
| 574 | scope: *Scope, |
| 575 | rl: ResultLoc, |
| 576 | infix_node: *ast.Node.SimpleInfixOp, |
| 577 | ) InnerError!*zir.Inst { |
| 578 | const tree = scope.tree(); |
| 579 | const src = tree.token_locs[infix_node.op_token].start; |
| 580 | const bool_type = try addZIRInstConst(mod, scope, src, .{ |
| 581 | .ty = Type.initTag(.type), |
| 582 | .val = Value.initTag(.bool_type), |
| 583 | }); |
| 584 | |
| 585 | var block_scope: Scope.GenZIR = .{ |
| 586 | .parent = scope, |
| 587 | .decl = scope.decl().?, |
| 588 | .arena = scope.arena(), |
| 589 | .instructions = .{}, |
| 590 | }; |
| 591 | defer block_scope.instructions.deinit(mod.gpa); |
| 592 | |
| 593 | const lhs = try expr(mod, scope, .{ .ty = bool_type }, infix_node.lhs); |
| 594 | const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{ |
| 595 | .condition = lhs, |
| 596 | .then_body = undefined, // populated below |
| 597 | .else_body = undefined, // populated below |
| 598 | }, .{}); |
| 599 | |
| 600 | const block = try addZIRInstBlock(mod, scope, src, .{ |
| 601 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), |
| 602 | }); |
| 603 | |
| 604 | var rhs_scope: Scope.GenZIR = .{ |
| 605 | .parent = scope, |
| 606 | .decl = block_scope.decl, |
| 607 | .arena = block_scope.arena, |
| 608 | .instructions = .{}, |
| 609 | }; |
| 610 | defer rhs_scope.instructions.deinit(mod.gpa); |
| 611 | |
| 612 | const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, infix_node.rhs); |
| 613 | _ = try addZIRInst(mod, &rhs_scope.base, src, zir.Inst.Break, .{ |
| 614 | .block = block, |
| 615 | .operand = rhs, |
| 616 | }, .{}); |
| 617 | |
| 618 | var const_scope: Scope.GenZIR = .{ |
| 619 | .parent = scope, |
| 620 | .decl = block_scope.decl, |
| 621 | .arena = block_scope.arena, |
| 622 | .instructions = .{}, |
| 623 | }; |
| 624 | defer const_scope.instructions.deinit(mod.gpa); |
| 625 | |
| 626 | const is_bool_and = infix_node.base.tag == .BoolAnd; |
| 627 | _ = try addZIRInst(mod, &const_scope.base, src, zir.Inst.Break, .{ |
| 628 | .block = block, |
| 629 | .operand = try addZIRInstConst(mod, &const_scope.base, src, .{ |
| 630 | .ty = Type.initTag(.bool), |
| 631 | .val = if (is_bool_and) Value.initTag(.bool_false) else Value.initTag(.bool_true), |
| 632 | }), |
| 633 | }, .{}); |
| 634 | |
| 635 | if (is_bool_and) { |
| 636 | // if lhs // AND |
| 637 | // break rhs |
| 638 | // else |
| 639 | // break false |
| 640 | condbr.positionals.then_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) }; |
| 641 | condbr.positionals.else_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) }; |
| 642 | } else { |
| 643 | // if lhs // OR |
| 644 | // break true |
| 645 | // else |
| 646 | // break rhs |
| 647 | condbr.positionals.then_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) }; |
| 648 | condbr.positionals.else_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) }; |
| 649 | } |
| 650 | |
| 651 | return rlWrap(mod, scope, rl, &block.base); |
| 652 | } |
| 653 | |
| 571 | 654 | const CondKind = union(enum) { |
| 572 | 655 | bool, |
| 573 | 656 | optional: ?*zir.Inst, |