| author | |
| committer | |
| log | 8f469c11275e60f5f1a8ae08fc7596ba366eda16 |
| tree | 0d6d8894eeb6f6ce42d7994d92c5df278ba436d9 |
| parent | 0005b346375f1fbe7bc42c22d658e3218bbd599d |
7 files changed, 217 insertions(+), 236 deletions(-)
src/AstGen.zig+54-46| ... | ... | @@ -197,7 +197,7 @@ pub fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerErro |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| 200 | const tree = scope.tree(); | |
| 200 | const tree = gz.tree(); | |
| 201 | 201 | const node_tags = tree.nodes.items(.tag); |
| 202 | 202 | const main_tokens = tree.nodes.items(.main_token); |
| 203 | 203 | switch (node_tags[node]) { |
| ... | ... | @@ -392,7 +392,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins |
| 392 | 392 | /// it must otherwise not be used. |
| 393 | 393 | pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| 394 | 394 | const mod = gz.astgen.mod; |
| 395 | const tree = scope.tree(); | |
| 395 | const tree = gz.tree(); | |
| 396 | 396 | const main_tokens = tree.nodes.items(.main_token); |
| 397 | 397 | const token_tags = tree.tokens.items(.tag); |
| 398 | 398 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -925,7 +925,7 @@ pub fn blockExpr( |
| 925 | 925 | const tracy = trace(@src()); |
| 926 | 926 | defer tracy.end(); |
| 927 | 927 | |
| 928 | const tree = scope.tree(); | |
| 928 | const tree = gz.tree(); | |
| 929 | 929 | const main_tokens = tree.nodes.items(.main_token); |
| 930 | 930 | const token_tags = tree.tokens.items(.tag); |
| 931 | 931 | |
| ... | ... | @@ -996,7 +996,7 @@ fn labeledBlockExpr( |
| 996 | 996 | assert(zir_tag == .block); |
| 997 | 997 | |
| 998 | 998 | const mod = gz.astgen.mod; |
| 999 | const tree = parent_scope.tree(); | |
| 999 | const tree = gz.tree(); | |
| 1000 | 1000 | const main_tokens = tree.nodes.items(.main_token); |
| 1001 | 1001 | const token_tags = tree.tokens.items(.tag); |
| 1002 | 1002 | |
| ... | ... | @@ -1074,7 +1074,7 @@ fn blockExprStmts( |
| 1074 | 1074 | node: ast.Node.Index, |
| 1075 | 1075 | statements: []const ast.Node.Index, |
| 1076 | 1076 | ) !void { |
| 1077 | const tree = parent_scope.tree(); | |
| 1077 | const tree = gz.tree(); | |
| 1078 | 1078 | const main_tokens = tree.nodes.items(.main_token); |
| 1079 | 1079 | const node_tags = tree.nodes.items(.tag); |
| 1080 | 1080 | |
| ... | ... | @@ -1235,7 +1235,6 @@ fn blockExprStmts( |
| 1235 | 1235 | .merge_error_sets, |
| 1236 | 1236 | .error_union_type, |
| 1237 | 1237 | .bit_not, |
| 1238 | .error_set, | |
| 1239 | 1238 | .error_value, |
| 1240 | 1239 | .error_to_int, |
| 1241 | 1240 | .int_to_error, |
| ... | ... | @@ -1305,7 +1304,7 @@ fn varDecl( |
| 1305 | 1304 | return mod.failNode(scope, var_decl.ast.align_node, "TODO implement alignment on locals", .{}); |
| 1306 | 1305 | } |
| 1307 | 1306 | const astgen = gz.astgen; |
| 1308 | const tree = scope.tree(); | |
| 1307 | const tree = gz.tree(); | |
| 1309 | 1308 | const token_tags = tree.tokens.items(.tag); |
| 1310 | 1309 | |
| 1311 | 1310 | const name_token = var_decl.ast.mut_token + 1; |
| ... | ... | @@ -1365,7 +1364,7 @@ fn varDecl( |
| 1365 | 1364 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 1366 | 1365 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 1367 | 1366 | // the variable, no memory location needed. |
| 1368 | if (!nodeMayNeedMemoryLocation(scope, var_decl.ast.init_node)) { | |
| 1367 | if (!nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node)) { | |
| 1369 | 1368 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{ |
| 1370 | 1369 | .ty = try typeExpr(gz, scope, var_decl.ast.type_node), |
| 1371 | 1370 | } else .none; |
| ... | ... | @@ -1502,7 +1501,7 @@ fn varDecl( |
| 1502 | 1501 | } |
| 1503 | 1502 | |
| 1504 | 1503 | fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void { |
| 1505 | const tree = scope.tree(); | |
| 1504 | const tree = gz.tree(); | |
| 1506 | 1505 | const node_datas = tree.nodes.items(.data); |
| 1507 | 1506 | const main_tokens = tree.nodes.items(.main_token); |
| 1508 | 1507 | const node_tags = tree.nodes.items(.tag); |
| ... | ... | @@ -1527,7 +1526,7 @@ fn assignOp( |
| 1527 | 1526 | infix_node: ast.Node.Index, |
| 1528 | 1527 | op_inst_tag: zir.Inst.Tag, |
| 1529 | 1528 | ) InnerError!void { |
| 1530 | const tree = scope.tree(); | |
| 1529 | const tree = gz.tree(); | |
| 1531 | 1530 | const node_datas = tree.nodes.items(.data); |
| 1532 | 1531 | |
| 1533 | 1532 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| ... | ... | @@ -1543,7 +1542,7 @@ fn assignOp( |
| 1543 | 1542 | } |
| 1544 | 1543 | |
| 1545 | 1544 | fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| 1546 | const tree = scope.tree(); | |
| 1545 | const tree = gz.tree(); | |
| 1547 | 1546 | const node_datas = tree.nodes.items(.data); |
| 1548 | 1547 | |
| 1549 | 1548 | const operand = try expr(gz, scope, .{ .ty = .bool_type }, node_datas[node].lhs); |
| ... | ... | @@ -1552,7 +1551,7 @@ fn boolNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inne |
| 1552 | 1551 | } |
| 1553 | 1552 | |
| 1554 | 1553 | fn bitNot(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| 1555 | const tree = scope.tree(); | |
| 1554 | const tree = gz.tree(); | |
| 1556 | 1555 | const node_datas = tree.nodes.items(.data); |
| 1557 | 1556 | |
| 1558 | 1557 | const operand = try expr(gz, scope, .none, node_datas[node].lhs); |
| ... | ... | @@ -1567,7 +1566,7 @@ fn negation( |
| 1567 | 1566 | node: ast.Node.Index, |
| 1568 | 1567 | tag: zir.Inst.Tag, |
| 1569 | 1568 | ) InnerError!zir.Inst.Ref { |
| 1570 | const tree = scope.tree(); | |
| 1569 | const tree = gz.tree(); | |
| 1571 | 1570 | const node_datas = tree.nodes.items(.data); |
| 1572 | 1571 | |
| 1573 | 1572 | const operand = try expr(gz, scope, .none, node_datas[node].lhs); |
| ... | ... | @@ -1582,7 +1581,7 @@ fn ptrType( |
| 1582 | 1581 | node: ast.Node.Index, |
| 1583 | 1582 | ptr_info: ast.full.PtrType, |
| 1584 | 1583 | ) InnerError!zir.Inst.Ref { |
| 1585 | const tree = scope.tree(); | |
| 1584 | const tree = gz.tree(); | |
| 1586 | 1585 | |
| 1587 | 1586 | const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type); |
| 1588 | 1587 | |
| ... | ... | @@ -1664,7 +1663,7 @@ fn ptrType( |
| 1664 | 1663 | } |
| 1665 | 1664 | |
| 1666 | 1665 | fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref { |
| 1667 | const tree = scope.tree(); | |
| 1666 | const tree = gz.tree(); | |
| 1668 | 1667 | const node_datas = tree.nodes.items(.data); |
| 1669 | 1668 | |
| 1670 | 1669 | // TODO check for [_]T |
| ... | ... | @@ -1676,7 +1675,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !z |
| 1676 | 1675 | } |
| 1677 | 1676 | |
| 1678 | 1677 | fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !zir.Inst.Ref { |
| 1679 | const tree = scope.tree(); | |
| 1678 | const tree = gz.tree(); | |
| 1680 | 1679 | const node_datas = tree.nodes.items(.data); |
| 1681 | 1680 | const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel); |
| 1682 | 1681 | |
| ... | ... | @@ -1704,10 +1703,11 @@ fn errorSetDecl( |
| 1704 | 1703 | rl: ResultLoc, |
| 1705 | 1704 | node: ast.Node.Index, |
| 1706 | 1705 | ) InnerError!zir.Inst.Ref { |
| 1707 | if (true) @panic("TODO update for zir-memory-layout branch"); | |
| 1706 | const mod = gz.astgen.mod; | |
| 1708 | 1707 | const tree = gz.tree(); |
| 1709 | 1708 | const main_tokens = tree.nodes.items(.main_token); |
| 1710 | 1709 | const token_tags = tree.tokens.items(.tag); |
| 1710 | const arena = gz.astgen.arena; | |
| 1711 | 1711 | |
| 1712 | 1712 | // Count how many fields there are. |
| 1713 | 1713 | const error_token = main_tokens[node]; |
| ... | ... | @@ -1724,7 +1724,7 @@ fn errorSetDecl( |
| 1724 | 1724 | } else unreachable; // TODO should not need else unreachable here |
| 1725 | 1725 | }; |
| 1726 | 1726 | |
| 1727 | const fields = try scope.arena().alloc([]const u8, count); | |
| 1727 | const fields = try arena.alloc([]const u8, count); | |
| 1728 | 1728 | { |
| 1729 | 1729 | var tok_i = error_token + 2; |
| 1730 | 1730 | var field_i: usize = 0; |
| ... | ... | @@ -1740,8 +1740,21 @@ fn errorSetDecl( |
| 1740 | 1740 | } |
| 1741 | 1741 | } |
| 1742 | 1742 | } |
| 1743 | const result = try addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{}); | |
| 1744 | return rvalue(gz, scope, rl, result); | |
| 1743 | const error_set = try arena.create(Module.ErrorSet); | |
| 1744 | error_set.* = .{ | |
| 1745 | .owner_decl = gz.astgen.decl, | |
| 1746 | .node_offset = gz.astgen.decl.nodeIndexToRelative(node), | |
| 1747 | .names_ptr = fields.ptr, | |
| 1748 | .names_len = @intCast(u32, fields.len), | |
| 1749 | }; | |
| 1750 | const error_set_ty = try Type.Tag.error_set.create(arena, error_set); | |
| 1751 | const typed_value = try arena.create(TypedValue); | |
| 1752 | typed_value.* = .{ | |
| 1753 | .ty = Type.initTag(.type), | |
| 1754 | .val = try Value.Tag.ty.create(arena, error_set_ty), | |
| 1755 | }; | |
| 1756 | const result = try gz.addConst(typed_value); | |
| 1757 | return rvalue(gz, scope, rl, result, node); | |
| 1745 | 1758 | } |
| 1746 | 1759 | |
| 1747 | 1760 | fn orelseCatchExpr( |
| ... | ... | @@ -2518,13 +2531,12 @@ fn getRangeNode( |
| 2518 | 2531 | } |
| 2519 | 2532 | |
| 2520 | 2533 | fn switchExpr( |
| 2521 | gz: *GenZir, | |
| 2534 | parent_gz: *GenZir, | |
| 2522 | 2535 | scope: *Scope, |
| 2523 | 2536 | rl: ResultLoc, |
| 2524 | 2537 | switch_node: ast.Node.Index, |
| 2525 | 2538 | ) InnerError!zir.Inst.Ref { |
| 2526 | 2539 | if (true) @panic("TODO update for zir-memory-layout"); |
| 2527 | const parent_gz = scope.getGenZir(); | |
| 2528 | 2540 | const tree = parent_gz.tree(); |
| 2529 | 2541 | const node_datas = tree.nodes.items(.data); |
| 2530 | 2542 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2541,7 +2553,7 @@ fn switchExpr( |
| 2541 | 2553 | var block_scope: GenZir = .{ |
| 2542 | 2554 | .parent = scope, |
| 2543 | 2555 | .decl = scope.ownerDecl().?, |
| 2544 | .arena = scope.arena(), | |
| 2556 | .arena = parent_gz.astgen.arena, | |
| 2545 | 2557 | .force_comptime = parent_gz.force_comptime, |
| 2546 | 2558 | .instructions = .{}, |
| 2547 | 2559 | }; |
| ... | ... | @@ -2727,7 +2739,7 @@ fn switchExpr( |
| 2727 | 2739 | |
| 2728 | 2740 | cases[case_index] = .{ |
| 2729 | 2741 | .item = item, |
| 2730 | .body = .{ .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items) }, | |
| 2742 | .body = .{ .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items) }, | |
| 2731 | 2743 | }; |
| 2732 | 2744 | case_index += 1; |
| 2733 | 2745 | continue; |
| ... | ... | @@ -2774,14 +2786,14 @@ fn switchExpr( |
| 2774 | 2786 | .else_body = undefined, // populated below |
| 2775 | 2787 | }, .{}); |
| 2776 | 2788 | const cond_block = try addZIRInstBlock(mod, &else_scope.base, case_src, .block, .{ |
| 2777 | .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items), | |
| 2789 | .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items), | |
| 2778 | 2790 | }); |
| 2779 | 2791 | |
| 2780 | 2792 | // reset cond_scope for then_body |
| 2781 | 2793 | case_scope.instructions.items.len = 0; |
| 2782 | 2794 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target); |
| 2783 | 2795 | condbr.positionals.then_body = .{ |
| 2784 | .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items), | |
| 2796 | .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items), | |
| 2785 | 2797 | }; |
| 2786 | 2798 | |
| 2787 | 2799 | // reset cond_scope for else_body |
| ... | ... | @@ -2790,7 +2802,7 @@ fn switchExpr( |
| 2790 | 2802 | .block = cond_block, |
| 2791 | 2803 | }, .{}); |
| 2792 | 2804 | condbr.positionals.else_body = .{ |
| 2793 | .instructions = try scope.arena().dupe(zir.Inst.Ref, case_scope.instructions.items), | |
| 2805 | .instructions = try parent_gz.astgen.arena.dupe(zir.Inst.Ref, case_scope.instructions.items), | |
| 2794 | 2806 | }; |
| 2795 | 2807 | } |
| 2796 | 2808 | |
| ... | ... | @@ -2816,7 +2828,7 @@ fn switchCaseExpr( |
| 2816 | 2828 | case: ast.full.SwitchCase, |
| 2817 | 2829 | target: zir.Inst.Ref, |
| 2818 | 2830 | ) !void { |
| 2819 | const tree = scope.tree(); | |
| 2831 | const tree = gz.tree(); | |
| 2820 | 2832 | const node_datas = tree.nodes.items(.data); |
| 2821 | 2833 | const main_tokens = tree.nodes.items(.main_token); |
| 2822 | 2834 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -2849,13 +2861,13 @@ fn switchCaseExpr( |
| 2849 | 2861 | } |
| 2850 | 2862 | |
| 2851 | 2863 | fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref { |
| 2852 | const tree = scope.tree(); | |
| 2864 | const tree = gz.tree(); | |
| 2853 | 2865 | const node_datas = tree.nodes.items(.data); |
| 2854 | 2866 | const main_tokens = tree.nodes.items(.main_token); |
| 2855 | 2867 | |
| 2856 | 2868 | const operand_node = node_datas[node].lhs; |
| 2857 | 2869 | const operand: zir.Inst.Ref = if (operand_node != 0) operand: { |
| 2858 | const rl: ResultLoc = if (nodeMayNeedMemoryLocation(scope, operand_node)) .{ | |
| 2870 | const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{ | |
| 2859 | 2871 | .ptr = try gz.addNode(.ret_ptr, node), |
| 2860 | 2872 | } else .{ |
| 2861 | 2873 | .ty = try gz.addNode(.ret_type, node), |
| ... | ... | @@ -2876,7 +2888,7 @@ fn identifier( |
| 2876 | 2888 | defer tracy.end(); |
| 2877 | 2889 | |
| 2878 | 2890 | const mod = gz.astgen.mod; |
| 2879 | const tree = scope.tree(); | |
| 2891 | const tree = gz.tree(); | |
| 2880 | 2892 | const main_tokens = tree.nodes.items(.main_token); |
| 2881 | 2893 | |
| 2882 | 2894 | const ident_token = main_tokens[ident]; |
| ... | ... | @@ -2961,7 +2973,7 @@ fn stringLiteral( |
| 2961 | 2973 | rl: ResultLoc, |
| 2962 | 2974 | node: ast.Node.Index, |
| 2963 | 2975 | ) InnerError!zir.Inst.Ref { |
| 2964 | const tree = scope.tree(); | |
| 2976 | const tree = gz.tree(); | |
| 2965 | 2977 | const main_tokens = tree.nodes.items(.main_token); |
| 2966 | 2978 | const string_bytes = &gz.astgen.string_bytes; |
| 2967 | 2979 | const str_index = string_bytes.items.len; |
| ... | ... | @@ -3048,7 +3060,7 @@ fn integerLiteral( |
| 3048 | 3060 | rl: ResultLoc, |
| 3049 | 3061 | node: ast.Node.Index, |
| 3050 | 3062 | ) InnerError!zir.Inst.Ref { |
| 3051 | const tree = scope.tree(); | |
| 3063 | const tree = gz.tree(); | |
| 3052 | 3064 | const main_tokens = tree.nodes.items(.main_token); |
| 3053 | 3065 | const int_token = main_tokens[node]; |
| 3054 | 3066 | const prefixed_bytes = tree.tokenSlice(int_token); |
| ... | ... | @@ -3070,8 +3082,8 @@ fn floatLiteral( |
| 3070 | 3082 | rl: ResultLoc, |
| 3071 | 3083 | node: ast.Node.Index, |
| 3072 | 3084 | ) InnerError!zir.Inst.Ref { |
| 3073 | const arena = scope.arena(); | |
| 3074 | const tree = scope.tree(); | |
| 3085 | const arena = gz.astgen.arena; | |
| 3086 | const tree = gz.tree(); | |
| 3075 | 3087 | const main_tokens = tree.nodes.items(.main_token); |
| 3076 | 3088 | |
| 3077 | 3089 | const main_token = main_tokens[node]; |
| ... | ... | @@ -3088,10 +3100,7 @@ fn floatLiteral( |
| 3088 | 3100 | .ty = Type.initTag(.comptime_float), |
| 3089 | 3101 | .val = try Value.Tag.float_128.create(arena, float_number), |
| 3090 | 3102 | }; |
| 3091 | const result = try gz.add(.{ | |
| 3092 | .tag = .@"const", | |
| 3093 | .data = .{ .@"const" = typed_value }, | |
| 3094 | }); | |
| 3103 | const result = try gz.addConst(typed_value); | |
| 3095 | 3104 | return rvalue(gz, scope, rl, result, node); |
| 3096 | 3105 | } |
| 3097 | 3106 | |
| ... | ... | @@ -3103,8 +3112,8 @@ fn asmExpr( |
| 3103 | 3112 | full: ast.full.Asm, |
| 3104 | 3113 | ) InnerError!zir.Inst.Ref { |
| 3105 | 3114 | const mod = gz.astgen.mod; |
| 3106 | const arena = scope.arena(); | |
| 3107 | const tree = scope.tree(); | |
| 3115 | const arena = gz.astgen.arena; | |
| 3116 | const tree = gz.tree(); | |
| 3108 | 3117 | const main_tokens = tree.nodes.items(.main_token); |
| 3109 | 3118 | const node_datas = tree.nodes.items(.data); |
| 3110 | 3119 | |
| ... | ... | @@ -3289,7 +3298,7 @@ fn typeOf( |
| 3289 | 3298 | const result = try gz.addUnTok(.typeof, try expr(gz, scope, .none, params[0]), node); |
| 3290 | 3299 | return rvalue(gz, scope, rl, result, node); |
| 3291 | 3300 | } |
| 3292 | const arena = scope.arena(); | |
| 3301 | const arena = gz.astgen.arena; | |
| 3293 | 3302 | var items = try arena.alloc(zir.Inst.Ref, params.len); |
| 3294 | 3303 | for (params) |param, param_i| { |
| 3295 | 3304 | items[param_i] = try expr(gz, scope, .none, param); |
| ... | ... | @@ -3311,7 +3320,7 @@ fn builtinCall( |
| 3311 | 3320 | params: []const ast.Node.Index, |
| 3312 | 3321 | ) InnerError!zir.Inst.Ref { |
| 3313 | 3322 | const mod = gz.astgen.mod; |
| 3314 | const tree = scope.tree(); | |
| 3323 | const tree = gz.tree(); | |
| 3315 | 3324 | const main_tokens = tree.nodes.items(.main_token); |
| 3316 | 3325 | |
| 3317 | 3326 | const builtin_token = main_tokens[node]; |
| ... | ... | @@ -3608,8 +3617,7 @@ pub const simple_types = std.ComptimeStringMap(zir.Inst.Ref, .{ |
| 3608 | 3617 | .{ "false", .bool_false }, |
| 3609 | 3618 | }); |
| 3610 | 3619 | |
| 3611 | fn nodeMayNeedMemoryLocation(scope: *Scope, start_node: ast.Node.Index) bool { | |
| 3612 | const tree = scope.tree(); | |
| 3620 | fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool { | |
| 3613 | 3621 | const node_tags = tree.nodes.items(.tag); |
| 3614 | 3622 | const node_datas = tree.nodes.items(.data); |
| 3615 | 3623 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -3842,7 +3850,7 @@ fn rvalue( |
| 3842 | 3850 | }, |
| 3843 | 3851 | .ref => { |
| 3844 | 3852 | // We need a pointer but we have a value. |
| 3845 | const tree = scope.tree(); | |
| 3853 | const tree = gz.tree(); | |
| 3846 | 3854 | const src_token = tree.firstToken(src_node); |
| 3847 | 3855 | return gz.addUnTok(.ref, result, src_token); |
| 3848 | 3856 | }, |
src/Module.zig+29-7| ... | ... | @@ -78,9 +78,11 @@ next_anon_name_index: usize = 0, |
| 78 | 78 | deletion_set: ArrayListUnmanaged(*Decl) = .{}, |
| 79 | 79 | |
| 80 | 80 | /// Error tags and their values, tag names are duped with mod.gpa. |
| 81 | global_error_set: std.StringHashMapUnmanaged(u16) = .{}, | |
| 81 | /// Corresponds with `error_name_list`. | |
| 82 | global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{}, | |
| 82 | 83 | |
| 83 | /// error u16 -> []const u8 for fast lookups for @intToError at comptime | |
| 84 | /// ErrorInt -> []const u8 for fast lookups for @intToError at comptime | |
| 85 | /// Corresponds with `global_error_set`. | |
| 84 | 86 | error_name_list: ArrayListUnmanaged([]const u8) = .{}, |
| 85 | 87 | |
| 86 | 88 | /// Keys are fully qualified paths |
| ... | ... | @@ -108,6 +110,8 @@ emit_h: ?Compilation.EmitLoc, |
| 108 | 110 | |
| 109 | 111 | compile_log_text: ArrayListUnmanaged(u8) = .{}, |
| 110 | 112 | |
| 113 | pub const ErrorInt = u32; | |
| 114 | ||
| 111 | 115 | pub const Export = struct { |
| 112 | 116 | options: std.builtin.ExportOptions, |
| 113 | 117 | src: LazySrcLoc, |
| ... | ... | @@ -341,6 +345,17 @@ pub const EmitH = struct { |
| 341 | 345 | fwd_decl: ArrayListUnmanaged(u8) = .{}, |
| 342 | 346 | }; |
| 343 | 347 | |
| 348 | /// Represents the data that an explicit error set syntax provides. | |
| 349 | pub const ErrorSet = struct { | |
| 350 | owner_decl: *Decl, | |
| 351 | /// Offset from Decl node index, points to the error set AST node. | |
| 352 | node_offset: i32, | |
| 353 | names_len: u32, | |
| 354 | /// The string bytes are stored in the owner Decl arena. | |
| 355 | /// They are in the same order they appear in the AST. | |
| 356 | names_ptr: [*]const []const u8, | |
| 357 | }; | |
| 358 | ||
| 344 | 359 | /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. |
| 345 | 360 | /// Extern functions do not have this data structure; they are represented by |
| 346 | 361 | /// the `Decl` only, with a `Value` tag of `extern_fn`. |
| ... | ... | @@ -1363,6 +1378,13 @@ pub const Scope = struct { |
| 1363 | 1378 | return new_index; |
| 1364 | 1379 | } |
| 1365 | 1380 | |
| 1381 | pub fn addConst(gz: *GenZir, typed_value: *TypedValue) !zir.Inst.Ref { | |
| 1382 | return gz.add(.{ | |
| 1383 | .tag = .@"const", | |
| 1384 | .data = .{ .@"const" = typed_value }, | |
| 1385 | }); | |
| 1386 | } | |
| 1387 | ||
| 1366 | 1388 | pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref { |
| 1367 | 1389 | return gz.astgen.indexToRef(try gz.addAsIndex(inst)); |
| 1368 | 1390 | } |
| ... | ... | @@ -3362,7 +3384,7 @@ fn createNewDecl( |
| 3362 | 3384 | } |
| 3363 | 3385 | |
| 3364 | 3386 | /// Get error value for error tag `name`. |
| 3365 | pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(u16).Entry { | |
| 3387 | pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).Entry { | |
| 3366 | 3388 | const gop = try mod.global_error_set.getOrPut(mod.gpa, name); |
| 3367 | 3389 | if (gop.found_existing) |
| 3368 | 3390 | return gop.entry.*; |
| ... | ... | @@ -3370,7 +3392,7 @@ pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged |
| 3370 | 3392 | errdefer mod.global_error_set.removeAssertDiscard(name); |
| 3371 | 3393 | try mod.error_name_list.ensureCapacity(mod.gpa, mod.error_name_list.items.len + 1); |
| 3372 | 3394 | gop.entry.key = try mod.gpa.dupe(u8, name); |
| 3373 | gop.entry.value = @intCast(u16, mod.error_name_list.items.len); | |
| 3395 | gop.entry.value = @intCast(ErrorInt, mod.error_name_list.items.len); | |
| 3374 | 3396 | mod.error_name_list.appendAssumeCapacity(gop.entry.key); |
| 3375 | 3397 | return gop.entry.*; |
| 3376 | 3398 | } |
| ... | ... | @@ -3580,9 +3602,9 @@ pub fn createAnonymousDecl( |
| 3580 | 3602 | new_decl.analysis = .complete; |
| 3581 | 3603 | new_decl.generation = mod.generation; |
| 3582 | 3604 | |
| 3583 | // TODO: This generates the Decl into the machine code file if it is of a type that is non-zero size. | |
| 3584 | // We should be able to further improve the compiler to not omit Decls which are only referenced at | |
| 3585 | // compile-time and not runtime. | |
| 3605 | // TODO: This generates the Decl into the machine code file if it is of a | |
| 3606 | // type that is non-zero size. We should be able to further improve the | |
| 3607 | // compiler to omit Decls which are only referenced at compile-time and not runtime. | |
| 3586 | 3608 | if (typed_value.ty.hasCodeGenBits()) { |
| 3587 | 3609 | try mod.comp.bin_file.allocateDeclIndexes(new_decl); |
| 3588 | 3610 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = new_decl }); |
src/Sema.zig+77-92| ... | ... | @@ -174,7 +174,6 @@ pub fn analyzeBody( |
| 174 | 174 | .err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true), |
| 175 | 175 | .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false), |
| 176 | 176 | .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false), |
| 177 | .error_set => try sema.zirErrorSet(block, inst), | |
| 178 | 177 | .error_union_type => try sema.zirErrorUnionType(block, inst), |
| 179 | 178 | .error_value => try sema.zirErrorValue(block, inst), |
| 180 | 179 | .error_to_int => try sema.zirErrorToInt(block, inst), |
| ... | ... | @@ -1409,41 +1408,6 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn |
| 1409 | 1408 | return sema.mod.constType(sema.arena, src, err_union_ty); |
| 1410 | 1409 | } |
| 1411 | 1410 | |
| 1412 | fn zirErrorSet(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | |
| 1413 | const tracy = trace(@src()); | |
| 1414 | defer tracy.end(); | |
| 1415 | ||
| 1416 | if (true) @panic("TODO update for zir-memory-layout branch"); | |
| 1417 | ||
| 1418 | // The owner Decl arena will store the hashmap. | |
| 1419 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | |
| 1420 | errdefer new_decl_arena.deinit(); | |
| 1421 | ||
| 1422 | const payload = try new_decl_arena.allocator.create(Value.Payload.ErrorSet); | |
| 1423 | payload.* = .{ | |
| 1424 | .base = .{ .tag = .error_set }, | |
| 1425 | .data = .{ | |
| 1426 | .fields = .{}, | |
| 1427 | .decl = undefined, // populated below | |
| 1428 | }, | |
| 1429 | }; | |
| 1430 | try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, inst.positionals.fields.len)); | |
| 1431 | ||
| 1432 | for (inst.positionals.fields) |field_name| { | |
| 1433 | const entry = try sema.mod.getErrorValue(field_name); | |
| 1434 | if (payload.data.fields.fetchPutAssumeCapacity(entry.key, {})) |_| { | |
| 1435 | return sema.mod.fail(&block.base, inst.base.src, "duplicate error: '{s}'", .{field_name}); | |
| 1436 | } | |
| 1437 | } | |
| 1438 | // TODO create name in format "error:line:column" | |
| 1439 | const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{ | |
| 1440 | .ty = Type.initTag(.type), | |
| 1441 | .val = Value.initPayload(&payload.base), | |
| 1442 | }); | |
| 1443 | payload.data.decl = new_decl; | |
| 1444 | return sema.analyzeDeclVal(block, inst.base.src, new_decl); | |
| 1445 | } | |
| 1446 | ||
| 1447 | 1411 | fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 1448 | 1412 | const tracy = trace(@src()); |
| 1449 | 1413 | defer tracy.end(); |
| ... | ... | @@ -1537,71 +1501,67 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn |
| 1537 | 1501 | if (lhs_ty.zigTypeTag() != .ErrorSet) |
| 1538 | 1502 | return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{lhs_ty}); |
| 1539 | 1503 | |
| 1540 | // anything merged with anyerror is anyerror | |
| 1541 | if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) | |
| 1504 | // Anything merged with anyerror is anyerror. | |
| 1505 | if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) { | |
| 1542 | 1506 | return sema.mod.constInst(sema.arena, src, .{ |
| 1543 | 1507 | .ty = Type.initTag(.type), |
| 1544 | 1508 | .val = Value.initTag(.anyerror_type), |
| 1545 | 1509 | }); |
| 1546 | // The declarations arena will store the hashmap. | |
| 1547 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | |
| 1548 | errdefer new_decl_arena.deinit(); | |
| 1549 | ||
| 1550 | const payload = try new_decl_arena.allocator.create(Value.Payload.ErrorSet); | |
| 1551 | payload.* = .{ | |
| 1552 | .base = .{ .tag = .error_set }, | |
| 1553 | .data = .{ | |
| 1554 | .fields = .{}, | |
| 1555 | .decl = undefined, // populated below | |
| 1556 | }, | |
| 1557 | }; | |
| 1558 | try payload.data.fields.ensureCapacity(&new_decl_arena.allocator, @intCast(u32, switch (rhs_ty.tag()) { | |
| 1559 | .error_set_single => 1, | |
| 1560 | .error_set => rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size, | |
| 1561 | else => unreachable, | |
| 1562 | } + switch (lhs_ty.tag()) { | |
| 1563 | .error_set_single => 1, | |
| 1564 | .error_set => lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields.size, | |
| 1565 | else => unreachable, | |
| 1566 | })); | |
| 1510 | } | |
| 1511 | // When we support inferred error sets, we'll want to use a data structure that can | |
| 1512 | // represent a merged set of errors without forcing them to be resolved here. Until then | |
| 1513 | // we re-use the same data structure that is used for explicit error set declarations. | |
| 1514 | var set: std.StringHashMapUnmanaged(void) = .{}; | |
| 1515 | defer set.deinit(sema.gpa); | |
| 1567 | 1516 | |
| 1568 | 1517 | switch (lhs_ty.tag()) { |
| 1569 | 1518 | .error_set_single => { |
| 1570 | 1519 | const name = lhs_ty.castTag(.error_set_single).?.data; |
| 1571 | payload.data.fields.putAssumeCapacity(name, {}); | |
| 1520 | try set.put(sema.gpa, name, {}); | |
| 1572 | 1521 | }, |
| 1573 | 1522 | .error_set => { |
| 1574 | var multiple = lhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields; | |
| 1575 | var it = multiple.iterator(); | |
| 1576 | while (it.next()) |entry| { | |
| 1577 | payload.data.fields.putAssumeCapacity(entry.key, entry.value); | |
| 1523 | const lhs_set = lhs_ty.castTag(.error_set).?.data; | |
| 1524 | try set.ensureCapacity(sema.gpa, set.count() + lhs_set.names_len); | |
| 1525 | for (lhs_set.names_ptr[0..lhs_set.names_len]) |name| { | |
| 1526 | set.putAssumeCapacityNoClobber(name, {}); | |
| 1578 | 1527 | } |
| 1579 | 1528 | }, |
| 1580 | 1529 | else => unreachable, |
| 1581 | 1530 | } |
| 1582 | ||
| 1583 | 1531 | switch (rhs_ty.tag()) { |
| 1584 | 1532 | .error_set_single => { |
| 1585 | 1533 | const name = rhs_ty.castTag(.error_set_single).?.data; |
| 1586 | payload.data.fields.putAssumeCapacity(name, {}); | |
| 1534 | try set.put(sema.gpa, name, {}); | |
| 1587 | 1535 | }, |
| 1588 | 1536 | .error_set => { |
| 1589 | var multiple = rhs_ty.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields; | |
| 1590 | var it = multiple.iterator(); | |
| 1591 | while (it.next()) |entry| { | |
| 1592 | payload.data.fields.putAssumeCapacity(entry.key, entry.value); | |
| 1537 | const rhs_set = rhs_ty.castTag(.error_set).?.data; | |
| 1538 | try set.ensureCapacity(sema.gpa, set.count() + rhs_set.names_len); | |
| 1539 | for (rhs_set.names_ptr[0..rhs_set.names_len]) |name| { | |
| 1540 | set.putAssumeCapacity(name, {}); | |
| 1593 | 1541 | } |
| 1594 | 1542 | }, |
| 1595 | 1543 | else => unreachable, |
| 1596 | 1544 | } |
| 1597 | // TODO create name in format "error:line:column" | |
| 1598 | const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{ | |
| 1545 | ||
| 1546 | const new_names = try sema.arena.alloc([]const u8, set.count()); | |
| 1547 | var it = set.iterator(); | |
| 1548 | var i: usize = 0; | |
| 1549 | while (it.next()) |entry| : (i += 1) { | |
| 1550 | new_names[i] = entry.key; | |
| 1551 | } | |
| 1552 | ||
| 1553 | const new_error_set = try sema.arena.create(Module.ErrorSet); | |
| 1554 | new_error_set.* = .{ | |
| 1555 | .owner_decl = sema.owner_decl, | |
| 1556 | .node_offset = inst_data.src_node, | |
| 1557 | .names_ptr = new_names.ptr, | |
| 1558 | .names_len = @intCast(u32, new_names.len), | |
| 1559 | }; | |
| 1560 | const error_set_ty = try Type.Tag.error_set.create(sema.arena, new_error_set); | |
| 1561 | return sema.mod.constInst(sema.arena, src, .{ | |
| 1599 | 1562 | .ty = Type.initTag(.type), |
| 1600 | .val = Value.initPayload(&payload.base), | |
| 1563 | .val = try Value.Tag.ty.create(sema.arena, error_set_ty), | |
| 1601 | 1564 | }); |
| 1602 | payload.data.decl = new_decl; | |
| 1603 | ||
| 1604 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 1605 | 1565 | } |
| 1606 | 1566 | |
| 1607 | 1567 | fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| ... | ... | @@ -3441,20 +3401,25 @@ fn namedFieldPtr( |
| 3441 | 3401 | const child_type = try val.toType(sema.arena); |
| 3442 | 3402 | switch (child_type.zigTypeTag()) { |
| 3443 | 3403 | .ErrorSet => { |
| 3444 | var name: []const u8 = undefined; | |
| 3445 | 3404 | // TODO resolve inferred error sets |
| 3446 | if (val.castTag(.error_set)) |payload| | |
| 3447 | name = (payload.data.fields.getEntry(field_name) orelse return sema.mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{ field_name, child_type })).key | |
| 3448 | else | |
| 3449 | name = (try sema.mod.getErrorValue(field_name)).key; | |
| 3450 | ||
| 3451 | const result_type = if (child_type.tag() == .anyerror) | |
| 3452 | try Type.Tag.error_set_single.create(sema.arena, name) | |
| 3453 | else | |
| 3454 | child_type; | |
| 3405 | const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: { | |
| 3406 | const error_set = payload.data; | |
| 3407 | // TODO this is O(N). I'm putting off solving this until we solve inferred | |
| 3408 | // error sets at the same time. | |
| 3409 | const names = error_set.names_ptr[0..error_set.names_len]; | |
| 3410 | for (names) |name| { | |
| 3411 | if (mem.eql(u8, field_name, name)) { | |
| 3412 | break :blk name; | |
| 3413 | } | |
| 3414 | } | |
| 3415 | return sema.mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{ | |
| 3416 | field_name, | |
| 3417 | child_type, | |
| 3418 | }); | |
| 3419 | } else (try sema.mod.getErrorValue(field_name)).key; | |
| 3455 | 3420 | |
| 3456 | 3421 | return sema.mod.constInst(sema.arena, src, .{ |
| 3457 | .ty = try sema.mod.simplePtrType(sema.arena, result_type, false, .One), | |
| 3422 | .ty = try sema.mod.simplePtrType(sema.arena, child_type, false, .One), | |
| 3458 | 3423 | .val = try Value.Tag.ref_val.create( |
| 3459 | 3424 | sema.arena, |
| 3460 | 3425 | try Value.Tag.@"error".create(sema.arena, .{ |
| ... | ... | @@ -4201,15 +4166,35 @@ fn wrapErrorUnion(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: *Inst |
| 4201 | 4166 | } else switch (err_union.data.error_set.tag()) { |
| 4202 | 4167 | .anyerror => val, |
| 4203 | 4168 | .error_set_single => blk: { |
| 4169 | const expected_name = val.castTag(.@"error").?.data.name; | |
| 4204 | 4170 | const n = err_union.data.error_set.castTag(.error_set_single).?.data; |
| 4205 | if (!mem.eql(u8, val.castTag(.@"error").?.data.name, n)) | |
| 4206 | return sema.mod.fail(&block.base, inst.src, "expected type '{}', found type '{}'", .{ err_union.data.error_set, inst.ty }); | |
| 4171 | if (!mem.eql(u8, expected_name, n)) { | |
| 4172 | return sema.mod.fail( | |
| 4173 | &block.base, | |
| 4174 | inst.src, | |
| 4175 | "expected type '{}', found type '{}'", | |
| 4176 | .{ err_union.data.error_set, inst.ty }, | |
| 4177 | ); | |
| 4178 | } | |
| 4207 | 4179 | break :blk val; |
| 4208 | 4180 | }, |
| 4209 | 4181 | .error_set => blk: { |
| 4210 | const f = err_union.data.error_set.castTag(.error_set).?.data.typed_value.most_recent.typed_value.val.castTag(.error_set).?.data.fields; | |
| 4211 | if (f.get(val.castTag(.@"error").?.data.name) == null) | |
| 4212 | return sema.mod.fail(&block.base, inst.src, "expected type '{}', found type '{}'", .{ err_union.data.error_set, inst.ty }); | |
| 4182 | const expected_name = val.castTag(.@"error").?.data.name; | |
| 4183 | const error_set = err_union.data.error_set.castTag(.error_set).?.data; | |
| 4184 | const names = error_set.names_ptr[0..error_set.names_len]; | |
| 4185 | // TODO this is O(N). I'm putting off solving this until we solve inferred | |
| 4186 | // error sets at the same time. | |
| 4187 | const found = for (names) |name| { | |
| 4188 | if (mem.eql(u8, expected_name, name)) break true; | |
| 4189 | } else false; | |
| 4190 | if (!found) { | |
| 4191 | return sema.mod.fail( | |
| 4192 | &block.base, | |
| 4193 | inst.src, | |
| 4194 | "expected type '{}', found type '{}'", | |
| 4195 | .{ err_union.data.error_set, inst.ty }, | |
| 4196 | ); | |
| 4197 | } | |
| 4213 | 4198 | break :blk val; |
| 4214 | 4199 | }, |
| 4215 | 4200 | else => unreachable, |
src/type.zig+11-4| ... | ... | @@ -606,7 +606,7 @@ pub const Type = extern union { |
| 606 | 606 | .payload = try payload.payload.copy(allocator), |
| 607 | 607 | }); |
| 608 | 608 | }, |
| 609 | .error_set => return self.copyPayloadShallow(allocator, Payload.Decl), | |
| 609 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | |
| 610 | 610 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), |
| 611 | 611 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), |
| 612 | 612 | |
| ... | ... | @@ -831,8 +831,8 @@ pub const Type = extern union { |
| 831 | 831 | continue; |
| 832 | 832 | }, |
| 833 | 833 | .error_set => { |
| 834 | const decl = ty.castTag(.error_set).?.data; | |
| 835 | return out_stream.writeAll(std.mem.spanZ(decl.name)); | |
| 834 | const error_set = ty.castTag(.error_set).?.data; | |
| 835 | return out_stream.writeAll(std.mem.spanZ(error_set.owner_decl.name)); | |
| 836 | 836 | }, |
| 837 | 837 | .error_set_single => { |
| 838 | 838 | const name = ty.castTag(.error_set_single).?.data; |
| ... | ... | @@ -3464,7 +3464,7 @@ pub const Type = extern union { |
| 3464 | 3464 | .int_unsigned, |
| 3465 | 3465 | => Payload.Bits, |
| 3466 | 3466 | |
| 3467 | .error_set => Payload.Decl, | |
| 3467 | .error_set => Payload.ErrorSet, | |
| 3468 | 3468 | |
| 3469 | 3469 | .array => Payload.Array, |
| 3470 | 3470 | .array_sentinel => Payload.ArraySentinel, |
| ... | ... | @@ -3548,6 +3548,13 @@ pub const Type = extern union { |
| 3548 | 3548 | }, |
| 3549 | 3549 | }; |
| 3550 | 3550 | |
| 3551 | pub const ErrorSet = struct { | |
| 3552 | pub const base_tag = Tag.error_set; | |
| 3553 | ||
| 3554 | base: Payload = Payload{ .tag = base_tag }, | |
| 3555 | data: *Module.ErrorSet, | |
| 3556 | }; | |
| 3557 | ||
| 3551 | 3558 | pub const Pointer = struct { |
| 3552 | 3559 | pub const base_tag = Tag.pointer; |
| 3553 | 3560 |
src/value.zig+1-46| ... | ... | @@ -102,7 +102,6 @@ pub const Value = extern union { |
| 102 | 102 | float_64, |
| 103 | 103 | float_128, |
| 104 | 104 | enum_literal, |
| 105 | error_set, | |
| 106 | 105 | @"error", |
| 107 | 106 | error_union, |
| 108 | 107 | /// This is a special value that tracks a set of types that have been stored |
| ... | ... | @@ -196,7 +195,6 @@ pub const Value = extern union { |
| 196 | 195 | .float_32 => Payload.Float_32, |
| 197 | 196 | .float_64 => Payload.Float_64, |
| 198 | 197 | .float_128 => Payload.Float_128, |
| 199 | .error_set => Payload.ErrorSet, | |
| 200 | 198 | .@"error" => Payload.Error, |
| 201 | 199 | .inferred_alloc => Payload.InferredAlloc, |
| 202 | 200 | }; |
| ... | ... | @@ -404,7 +402,6 @@ pub const Value = extern union { |
| 404 | 402 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 405 | 403 | }, |
| 406 | 404 | |
| 407 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | |
| 408 | 405 | .inferred_alloc => unreachable, |
| 409 | 406 | } |
| 410 | 407 | } |
| ... | ... | @@ -515,15 +512,6 @@ pub const Value = extern union { |
| 515 | 512 | .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}), |
| 516 | 513 | .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}), |
| 517 | 514 | .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}), |
| 518 | .error_set => { | |
| 519 | const error_set = val.castTag(.error_set).?.data; | |
| 520 | try out_stream.writeAll("error{"); | |
| 521 | var it = error_set.fields.iterator(); | |
| 522 | while (it.next()) |entry| { | |
| 523 | try out_stream.print("{},", .{entry.value}); | |
| 524 | } | |
| 525 | return out_stream.writeAll("}"); | |
| 526 | }, | |
| 527 | 515 | .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}), |
| 528 | 516 | // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that |
| 529 | 517 | .error_union => return out_stream.print("error_union_val({})", .{val.castTag(.error_union).?.data}), |
| ... | ... | @@ -608,10 +596,6 @@ pub const Value = extern union { |
| 608 | 596 | }; |
| 609 | 597 | return Type.initPayload(&new.base); |
| 610 | 598 | }, |
| 611 | .error_set => { | |
| 612 | const payload = self.castTag(.error_set).?.data; | |
| 613 | return Type.Tag.error_set.create(allocator, payload.decl); | |
| 614 | }, | |
| 615 | 599 | |
| 616 | 600 | .undef, |
| 617 | 601 | .zero, |
| ... | ... | @@ -711,7 +695,6 @@ pub const Value = extern union { |
| 711 | 695 | .unreachable_value, |
| 712 | 696 | .empty_array, |
| 713 | 697 | .enum_literal, |
| 714 | .error_set, | |
| 715 | 698 | .error_union, |
| 716 | 699 | .@"error", |
| 717 | 700 | .empty_struct_value, |
| ... | ... | @@ -799,7 +782,6 @@ pub const Value = extern union { |
| 799 | 782 | .unreachable_value, |
| 800 | 783 | .empty_array, |
| 801 | 784 | .enum_literal, |
| 802 | .error_set, | |
| 803 | 785 | .@"error", |
| 804 | 786 | .error_union, |
| 805 | 787 | .empty_struct_value, |
| ... | ... | @@ -887,7 +869,6 @@ pub const Value = extern union { |
| 887 | 869 | .unreachable_value, |
| 888 | 870 | .empty_array, |
| 889 | 871 | .enum_literal, |
| 890 | .error_set, | |
| 891 | 872 | .@"error", |
| 892 | 873 | .error_union, |
| 893 | 874 | .empty_struct_value, |
| ... | ... | @@ -1003,7 +984,6 @@ pub const Value = extern union { |
| 1003 | 984 | .unreachable_value, |
| 1004 | 985 | .empty_array, |
| 1005 | 986 | .enum_literal, |
| 1006 | .error_set, | |
| 1007 | 987 | .@"error", |
| 1008 | 988 | .error_union, |
| 1009 | 989 | .empty_struct_value, |
| ... | ... | @@ -1095,7 +1075,6 @@ pub const Value = extern union { |
| 1095 | 1075 | .unreachable_value, |
| 1096 | 1076 | .empty_array, |
| 1097 | 1077 | .enum_literal, |
| 1098 | .error_set, | |
| 1099 | 1078 | .@"error", |
| 1100 | 1079 | .error_union, |
| 1101 | 1080 | .empty_struct_value, |
| ... | ... | @@ -1256,7 +1235,6 @@ pub const Value = extern union { |
| 1256 | 1235 | .void_value, |
| 1257 | 1236 | .unreachable_value, |
| 1258 | 1237 | .enum_literal, |
| 1259 | .error_set, | |
| 1260 | 1238 | .@"error", |
| 1261 | 1239 | .error_union, |
| 1262 | 1240 | .empty_struct_value, |
| ... | ... | @@ -1335,7 +1313,6 @@ pub const Value = extern union { |
| 1335 | 1313 | .unreachable_value, |
| 1336 | 1314 | .empty_array, |
| 1337 | 1315 | .enum_literal, |
| 1338 | .error_set, | |
| 1339 | 1316 | .@"error", |
| 1340 | 1317 | .error_union, |
| 1341 | 1318 | .empty_struct_value, |
| ... | ... | @@ -1476,15 +1453,10 @@ pub const Value = extern union { |
| 1476 | 1453 | .enum_literal_type, |
| 1477 | 1454 | .ty, |
| 1478 | 1455 | => { |
| 1479 | // Directly return Type.hash, toType can only fail for .int_type and .error_set. | |
| 1456 | // Directly return Type.hash, toType can only fail for .int_type. | |
| 1480 | 1457 | var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{}); |
| 1481 | 1458 | return (self.toType(&allocator.allocator) catch unreachable).hash(); |
| 1482 | 1459 | }, |
| 1483 | .error_set => { | |
| 1484 | // Payload.decl should be same for all instances of the type. | |
| 1485 | const payload = self.castTag(.error_set).?.data; | |
| 1486 | std.hash.autoHash(&hasher, payload.decl); | |
| 1487 | }, | |
| 1488 | 1460 | .int_type => { |
| 1489 | 1461 | const payload = self.castTag(.int_type).?.data; |
| 1490 | 1462 | var int_payload = Type.Payload.Bits{ |
| ... | ... | @@ -1656,7 +1628,6 @@ pub const Value = extern union { |
| 1656 | 1628 | .unreachable_value, |
| 1657 | 1629 | .empty_array, |
| 1658 | 1630 | .enum_literal, |
| 1659 | .error_set, | |
| 1660 | 1631 | .@"error", |
| 1661 | 1632 | .error_union, |
| 1662 | 1633 | .empty_struct_value, |
| ... | ... | @@ -1744,7 +1715,6 @@ pub const Value = extern union { |
| 1744 | 1715 | .void_value, |
| 1745 | 1716 | .unreachable_value, |
| 1746 | 1717 | .enum_literal, |
| 1747 | .error_set, | |
| 1748 | 1718 | .@"error", |
| 1749 | 1719 | .error_union, |
| 1750 | 1720 | .empty_struct_value, |
| ... | ... | @@ -1849,7 +1819,6 @@ pub const Value = extern union { |
| 1849 | 1819 | .float_128, |
| 1850 | 1820 | .void_value, |
| 1851 | 1821 | .enum_literal, |
| 1852 | .error_set, | |
| 1853 | 1822 | .@"error", |
| 1854 | 1823 | .error_union, |
| 1855 | 1824 | .empty_struct_value, |
| ... | ... | @@ -1933,7 +1902,6 @@ pub const Value = extern union { |
| 1933 | 1902 | .float_128, |
| 1934 | 1903 | .void_value, |
| 1935 | 1904 | .enum_literal, |
| 1936 | .error_set, | |
| 1937 | 1905 | .empty_struct_value, |
| 1938 | 1906 | => null, |
| 1939 | 1907 | |
| ... | ... | @@ -2012,7 +1980,6 @@ pub const Value = extern union { |
| 2012 | 1980 | .single_const_pointer_to_comptime_int_type, |
| 2013 | 1981 | .const_slice_u8_type, |
| 2014 | 1982 | .enum_literal_type, |
| 2015 | .error_set, | |
| 2016 | 1983 | => true, |
| 2017 | 1984 | |
| 2018 | 1985 | .zero, |
| ... | ... | @@ -2156,18 +2123,6 @@ pub const Value = extern union { |
| 2156 | 2123 | data: f128, |
| 2157 | 2124 | }; |
| 2158 | 2125 | |
| 2159 | /// TODO move to type.zig | |
| 2160 | pub const ErrorSet = struct { | |
| 2161 | pub const base_tag = Tag.error_set; | |
| 2162 | ||
| 2163 | base: Payload = .{ .tag = base_tag }, | |
| 2164 | data: struct { | |
| 2165 | /// TODO revisit this when we have the concept of the error tag type | |
| 2166 | fields: std.StringHashMapUnmanaged(void), | |
| 2167 | decl: *Module.Decl, | |
| 2168 | }, | |
| 2169 | }; | |
| 2170 | ||
| 2171 | 2126 | pub const Error = struct { |
| 2172 | 2127 | base: Payload = .{ .tag = .@"error" }, |
| 2173 | 2128 | data: struct { |
src/zir.zig+13-9| ... | ... | @@ -314,11 +314,6 @@ pub const Inst = struct { |
| 314 | 314 | /// Create a `E!T` type. |
| 315 | 315 | /// Uses the `pl_node` field with `Bin` payload. |
| 316 | 316 | error_union_type, |
| 317 | /// Create an error set. TODO can't we just do this in astgen? reconsider | |
| 318 | /// memory layout of error sets. if astgen wants to make Sema do the work, | |
| 319 | /// this ZIR instruction could just be an AST node index. If astgen wants to | |
| 320 | /// do the work, it could use a const instruction. | |
| 321 | error_set, | |
| 322 | 317 | /// `error.Foo` syntax. Uses the `str_tok` field of the Data union. |
| 323 | 318 | error_value, |
| 324 | 319 | /// Given a pointer to a struct or object that contains virtual fields, returns a pointer |
| ... | ... | @@ -742,7 +737,6 @@ pub const Inst = struct { |
| 742 | 737 | .merge_error_sets, |
| 743 | 738 | .error_union_type, |
| 744 | 739 | .bit_not, |
| 745 | .error_set, | |
| 746 | 740 | .error_value, |
| 747 | 741 | .slice_start, |
| 748 | 742 | .slice_end, |
| ... | ... | @@ -1459,8 +1453,6 @@ const Writer = struct { |
| 1459 | 1453 | .asm_volatile, |
| 1460 | 1454 | .elem_ptr_node, |
| 1461 | 1455 | .elem_val_node, |
| 1462 | .field_ptr, | |
| 1463 | .field_val, | |
| 1464 | 1456 | .field_ptr_named, |
| 1465 | 1457 | .field_val_named, |
| 1466 | 1458 | .floatcast, |
| ... | ... | @@ -1519,6 +1511,10 @@ const Writer = struct { |
| 1519 | 1511 | .decl_val, |
| 1520 | 1512 | => try self.writePlNodeDecl(stream, inst), |
| 1521 | 1513 | |
| 1514 | .field_ptr, | |
| 1515 | .field_val, | |
| 1516 | => try self.writePlNodeField(stream, inst), | |
| 1517 | ||
| 1522 | 1518 | .as_node => try self.writeAs(stream, inst), |
| 1523 | 1519 | |
| 1524 | 1520 | .breakpoint, |
| ... | ... | @@ -1544,7 +1540,6 @@ const Writer = struct { |
| 1544 | 1540 | .bitcast, |
| 1545 | 1541 | .bitcast_ref, |
| 1546 | 1542 | .bitcast_result_ptr, |
| 1547 | .error_set, | |
| 1548 | 1543 | .store_to_inferred_ptr, |
| 1549 | 1544 | => try stream.writeAll("TODO)"), |
| 1550 | 1545 | } |
| ... | ... | @@ -1733,6 +1728,15 @@ const Writer = struct { |
| 1733 | 1728 | try self.writeSrc(stream, inst_data.src()); |
| 1734 | 1729 | } |
| 1735 | 1730 | |
| 1731 | fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void { | |
| 1732 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | |
| 1733 | const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data; | |
| 1734 | const name = self.code.nullTerminatedString(extra.field_name_start); | |
| 1735 | try self.writeInstRef(stream, extra.lhs); | |
| 1736 | try stream.print(", \"{}\") ", .{std.zig.fmtEscapes(name)}); | |
| 1737 | try self.writeSrc(stream, inst_data.src()); | |
| 1738 | } | |
| 1739 | ||
| 1736 | 1740 | fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 1737 | 1741 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1738 | 1742 | const extra = self.code.extraData(Inst.As, inst_data.payload_index).data; |
test/stage2/test.zig+32-32| ... | ... | @@ -1565,37 +1565,37 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1565 | 1565 | \\} |
| 1566 | 1566 | , ""); |
| 1567 | 1567 | } |
| 1568 | //{ | |
| 1569 | // var case = ctx.exe("merge error sets", linux_x64); | |
| 1568 | { | |
| 1569 | var case = ctx.exe("merge error sets", linux_x64); | |
| 1570 | 1570 | |
| 1571 | // case.addCompareOutput( | |
| 1572 | // \\export fn _start() noreturn { | |
| 1573 | // \\ const E = error{ A, B, D } || error { A, B, C }; | |
| 1574 | // \\ const a = E.A; | |
| 1575 | // \\ const b = E.B; | |
| 1576 | // \\ const c = E.C; | |
| 1577 | // \\ const d = E.D; | |
| 1578 | // \\ const E2 = error { X, Y } || @TypeOf(error.Z); | |
| 1579 | // \\ const x = E2.X; | |
| 1580 | // \\ const y = E2.Y; | |
| 1581 | // \\ const z = E2.Z; | |
| 1582 | // \\ assert(anyerror || error { Z } == anyerror); | |
| 1583 | // \\ exit(); | |
| 1584 | // \\} | |
| 1585 | // \\fn assert(b: bool) void { | |
| 1586 | // \\ if (!b) unreachable; | |
| 1587 | // \\} | |
| 1588 | // \\fn exit() noreturn { | |
| 1589 | // \\ asm volatile ("syscall" | |
| 1590 | // \\ : | |
| 1591 | // \\ : [number] "{rax}" (231), | |
| 1592 | // \\ [arg1] "{rdi}" (0) | |
| 1593 | // \\ : "rcx", "r11", "memory" | |
| 1594 | // \\ ); | |
| 1595 | // \\ unreachable; | |
| 1596 | // \\} | |
| 1597 | // , | |
| 1598 | // "", | |
| 1599 | // ); | |
| 1600 | //} | |
| 1571 | case.addCompareOutput( | |
| 1572 | \\export fn _start() noreturn { | |
| 1573 | \\ const E = error{ A, B, D } || error { A, B, C }; | |
| 1574 | \\ const a = E.A; | |
| 1575 | \\ const b = E.B; | |
| 1576 | \\ const c = E.C; | |
| 1577 | \\ const d = E.D; | |
| 1578 | \\ const E2 = error { X, Y } || @TypeOf(error.Z); | |
| 1579 | \\ const x = E2.X; | |
| 1580 | \\ const y = E2.Y; | |
| 1581 | \\ const z = E2.Z; | |
| 1582 | \\ assert(anyerror || error { Z } == anyerror); | |
| 1583 | \\ exit(); | |
| 1584 | \\} | |
| 1585 | \\fn assert(b: bool) void { | |
| 1586 | \\ if (!b) unreachable; | |
| 1587 | \\} | |
| 1588 | \\fn exit() noreturn { | |
| 1589 | \\ asm volatile ("syscall" | |
| 1590 | \\ : | |
| 1591 | \\ : [number] "{rax}" (231), | |
| 1592 | \\ [arg1] "{rdi}" (0) | |
| 1593 | \\ : "rcx", "r11", "memory" | |
| 1594 | \\ ); | |
| 1595 | \\ unreachable; | |
| 1596 | \\} | |
| 1597 | , | |
| 1598 | "", | |
| 1599 | ); | |
| 1600 | } | |
| 1601 | 1601 | } |