authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-15 19:17:50+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-17 14:28:04+03:00
logdb77b6b4e731670188e632657aa0aeadf9c87eb5
treeb638ea5ed949236f002781b931cd230918551802
parent012fac255f35b9cdbe18c14753a195de89d07d28
signature Commit is signed but in an unrecognized format.

stage2: astgen for if and while with optionals


1 files changed, 63 insertions(+), 20 deletions(-)

src-self-hosted/astgen.zig+63-20
......@@ -594,12 +594,55 @@ fn simpleBinOp(
594594 return rlWrap(mod, scope, rl, result);
595595}
596596
597fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) InnerError!*zir.Inst {
598 if (if_node.payload) |payload| {
599 return mod.failNode(scope, payload, "TODO implement astgen.IfExpr for optionals", .{});
597const CondKind = union(enum) {
598 bool,
599 optional: ?*zir.Inst,
600 err_union: ?*zir.Inst,
601
602 fn cond(self: *CondKind, mod: *Module, block_scope: *Scope.GenZIR, src: usize, cond_node: *ast.Node) !*zir.Inst {
603 switch (self.*) {
604 .bool => {
605 const bool_type = try addZIRInstConst(mod, &block_scope.base, src, .{
606 .ty = Type.initTag(.type),
607 .val = Value.initTag(.bool_type),
608 });
609 return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node);
610 },
611 .optional => {
612 const cond_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);
613 self.* = .{ .optional = cond_ptr };
614 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr);
615 return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result);
616 },
617 .err_union => unreachable,
618 }
619 }
620
621 fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, payload_node: ?*ast.Node) !*Scope {
622 if (self == .bool) return &then_scope.base;
623
624 const payload = payload_node.?.castTag(.PointerPayload).?;
625 const is_ptr = payload.ptr_token != null;
626 const ident_node = payload.value_symbol.castTag(.Identifier).?;
627 const ident_name = try identifierTokenString(mod, &then_scope.base, ident_node.token);
628 if (mem.eql(u8, ident_name, "_")) {
629 if (is_ptr)
630 return mod.failTok(&then_scope.base, payload.ptr_token.?, "pointer modifier invalid on discard", .{});
631 return &then_scope.base;
632 }
633
634 return mod.failNode(&then_scope.base, payload.value_symbol, "TODO implement payload symbols", .{});
600635 }
636};
637
638fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) InnerError!*zir.Inst {
639 var cond_kind: CondKind = .bool;
640 if (if_node.payload) |_| cond_kind = .{ .optional = null };
601641 if (if_node.@"else") |else_node| {
602642 if (else_node.payload) |payload| {
643 if (cond_kind != .optional) {
644 return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{});
645 }
603646 return mod.failNode(scope, payload, "TODO implement astgen.IfExpr for error unions", .{});
604647 }
605648 }
......@@ -613,11 +656,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
613656
614657 const tree = scope.tree();
615658 const if_src = tree.token_locs[if_node.if_token].start;
616 const bool_type = try addZIRInstConst(mod, scope, if_src, .{
617 .ty = Type.initTag(.type),
618 .val = Value.initTag(.bool_type),
619 });
620 const cond = try expr(mod, &block_scope.base, .{ .ty = bool_type }, if_node.condition);
659 const cond = try cond_kind.cond(mod, &block_scope, if_src, if_node.condition);
621660
622661 const condbr = try addZIRInstSpecial(mod, &block_scope.base, if_src, zir.Inst.CondBr, .{
623662 .condition = cond,
......@@ -636,6 +675,9 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
636675 };
637676 defer then_scope.instructions.deinit(mod.gpa);
638677
678 // declare payload to the then_scope
679 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, if_node.payload);
680
639681 // Most result location types can be forwarded directly; however
640682 // if we need to write to a pointer which has an inferred type,
641683 // proper type inference requires peer type resolution on the if's
......@@ -645,10 +687,10 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
645687 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
646688 };
647689
648 const then_result = try expr(mod, &then_scope.base, branch_rl, if_node.body);
690 const then_result = try expr(mod, then_sub_scope, branch_rl, if_node.body);
649691 if (!then_result.tag.isNoReturn()) {
650692 const then_src = tree.token_locs[if_node.body.lastToken()].start;
651 _ = try addZIRInst(mod, &then_scope.base, then_src, zir.Inst.Break, .{
693 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
652694 .block = block,
653695 .operand = then_result,
654696 }, .{});
......@@ -690,11 +732,13 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
690732}
691733
692734fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {
693 if (while_node.payload) |payload| {
694 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for optionals", .{});
695 }
735 var cond_kind: CondKind = .bool;
736 if (while_node.payload) |_| cond_kind = .{ .optional = null };
696737 if (while_node.@"else") |else_node| {
697738 if (else_node.payload) |payload| {
739 if (cond_kind != .optional) {
740 return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{});
741 }
698742 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for error unions", .{});
699743 }
700744 }
......@@ -725,15 +769,11 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
725769
726770 const tree = scope.tree();
727771 const while_src = tree.token_locs[while_node.while_token].start;
728 const bool_type = try addZIRInstConst(mod, scope, while_src, .{
729 .ty = Type.initTag(.type),
730 .val = Value.initTag(.bool_type),
731 });
732772 const void_type = try addZIRInstConst(mod, scope, while_src, .{
733773 .ty = Type.initTag(.type),
734774 .val = Value.initTag(.void_type),
735775 });
736 const cond = try expr(mod, &continue_scope.base, .{ .ty = bool_type }, while_node.condition);
776 const cond = try cond_kind.cond(mod, &continue_scope, while_src, while_node.condition);
737777
738778 const condbr = try addZIRInstSpecial(mod, &continue_scope.base, while_src, zir.Inst.CondBr, .{
739779 .condition = cond,
......@@ -764,6 +804,9 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
764804 };
765805 defer then_scope.instructions.deinit(mod.gpa);
766806
807 // declare payload to the then_scope
808 const then_sub_scope = try cond_kind.thenSubScope(mod, &then_scope, while_node.payload);
809
767810 // Most result location types can be forwarded directly; however
768811 // if we need to write to a pointer which has an inferred type,
769812 // proper type inference requires peer type resolution on the while's
......@@ -773,10 +816,10 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
773816 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
774817 };
775818
776 const then_result = try expr(mod, &then_scope.base, branch_rl, while_node.body);
819 const then_result = try expr(mod, then_sub_scope, branch_rl, while_node.body);
777820 if (!then_result.tag.isNoReturn()) {
778821 const then_src = tree.token_locs[while_node.body.lastToken()].start;
779 _ = try addZIRInst(mod, &then_scope.base, then_src, zir.Inst.Break, .{
822 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
780823 .block = cond_block,
781824 .operand = then_result,
782825 }, .{});