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(...@@ -594,12 +594,55 @@ fn simpleBinOp(
594 return rlWrap(mod, scope, rl, result);594 return rlWrap(mod, scope, rl, result);
595}595}
596596
597fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) InnerError!*zir.Inst {597const CondKind = union(enum) {
598 if (if_node.payload) |payload| {598 bool,
599 return mod.failNode(scope, payload, "TODO implement astgen.IfExpr for optionals", .{});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", .{});
600 }635 }
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 };
601 if (if_node.@"else") |else_node| {641 if (if_node.@"else") |else_node| {
602 if (else_node.payload) |payload| {642 if (else_node.payload) |payload| {
643 if (cond_kind != .optional) {
644 return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{});
645 }
603 return mod.failNode(scope, payload, "TODO implement astgen.IfExpr for error unions", .{});646 return mod.failNode(scope, payload, "TODO implement astgen.IfExpr for error unions", .{});
604 }647 }
605 }648 }
...@@ -613,11 +656,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -613,11 +656,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
613656
614 const tree = scope.tree();657 const tree = scope.tree();
615 const if_src = tree.token_locs[if_node.if_token].start;658 const if_src = tree.token_locs[if_node.if_token].start;
616 const bool_type = try addZIRInstConst(mod, scope, if_src, .{659 const cond = try cond_kind.cond(mod, &block_scope, if_src, if_node.condition);
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);
621660
622 const condbr = try addZIRInstSpecial(mod, &block_scope.base, if_src, zir.Inst.CondBr, .{661 const condbr = try addZIRInstSpecial(mod, &block_scope.base, if_src, zir.Inst.CondBr, .{
623 .condition = cond,662 .condition = cond,
...@@ -636,6 +675,9 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -636,6 +675,9 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
636 };675 };
637 defer then_scope.instructions.deinit(mod.gpa);676 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
639 // Most result location types can be forwarded directly; however681 // Most result location types can be forwarded directly; however
640 // if we need to write to a pointer which has an inferred type,682 // if we need to write to a pointer which has an inferred type,
641 // proper type inference requires peer type resolution on the if's683 // 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...@@ -645,10 +687,10 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
645 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },687 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
646 };688 };
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);
649 if (!then_result.tag.isNoReturn()) {691 if (!then_result.tag.isNoReturn()) {
650 const then_src = tree.token_locs[if_node.body.lastToken()].start;692 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, .{
652 .block = block,694 .block = block,
653 .operand = then_result,695 .operand = then_result,
654 }, .{});696 }, .{});
...@@ -690,11 +732,13 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn...@@ -690,11 +732,13 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
690}732}
691733
692fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {734fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.While) InnerError!*zir.Inst {
693 if (while_node.payload) |payload| {735 var cond_kind: CondKind = .bool;
694 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for optionals", .{});736 if (while_node.payload) |_| cond_kind = .{ .optional = null };
695 }
696 if (while_node.@"else") |else_node| {737 if (while_node.@"else") |else_node| {
697 if (else_node.payload) |payload| {738 if (else_node.payload) |payload| {
739 if (cond_kind != .optional) {
740 return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{});
741 }
698 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for error unions", .{});742 return mod.failNode(scope, payload, "TODO implement astgen.whileExpr for error unions", .{});
699 }743 }
700 }744 }
...@@ -725,15 +769,11 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -725,15 +769,11 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
725769
726 const tree = scope.tree();770 const tree = scope.tree();
727 const while_src = tree.token_locs[while_node.while_token].start;771 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 });
732 const void_type = try addZIRInstConst(mod, scope, while_src, .{772 const void_type = try addZIRInstConst(mod, scope, while_src, .{
733 .ty = Type.initTag(.type),773 .ty = Type.initTag(.type),
734 .val = Value.initTag(.void_type),774 .val = Value.initTag(.void_type),
735 });775 });
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
738 const condbr = try addZIRInstSpecial(mod, &continue_scope.base, while_src, zir.Inst.CondBr, .{778 const condbr = try addZIRInstSpecial(mod, &continue_scope.base, while_src, zir.Inst.CondBr, .{
739 .condition = cond,779 .condition = cond,
...@@ -764,6 +804,9 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W...@@ -764,6 +804,9 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
764 };804 };
765 defer then_scope.instructions.deinit(mod.gpa);805 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
767 // Most result location types can be forwarded directly; however810 // Most result location types can be forwarded directly; however
768 // if we need to write to a pointer which has an inferred type,811 // if we need to write to a pointer which has an inferred type,
769 // proper type inference requires peer type resolution on the while's812 // 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...@@ -773,10 +816,10 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
773 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },816 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
774 };817 };
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);
777 if (!then_result.tag.isNoReturn()) {820 if (!then_result.tag.isNoReturn()) {
778 const then_src = tree.token_locs[while_node.body.lastToken()].start;821 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, .{
780 .block = cond_block,823 .block = cond_block,
781 .operand = then_result,824 .operand = then_result,
782 }, .{});825 }, .{});