| author | |
| committer | |
| log | 43ac5e5dacab51f381a02366fcc3e65fbd6226d5 |
| tree | 8fa6b2b8cc3dd3fd6e9c16bc1ff35b37c9eded0e |
| parent | eeadd55d15852b6bc67b459b452e83a8a8ba2933 |
| parent | d3e5105eccaa1149a90f8d640d7f5cf90dd46bca |
| signature |
std.meta.TrailerFlags: use @Type to improve API8 files changed, 387 insertions(+), 162 deletions(-)
lib/std/meta/trailer_flags.zig+86-49| ... | ... | @@ -8,6 +8,7 @@ const meta = std.meta; |
| 8 | 8 | const testing = std.testing; |
| 9 | 9 | const mem = std.mem; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | const TypeInfo = std.builtin.TypeInfo; | |
| 11 | 12 | |
| 12 | 13 | /// This is useful for saving memory when allocating an object that has many |
| 13 | 14 | /// optional components. The optional objects are allocated sequentially in |
| ... | ... | @@ -17,91 +18,125 @@ pub fn TrailerFlags(comptime Fields: type) type { |
| 17 | 18 | return struct { |
| 18 | 19 | bits: Int, |
| 19 | 20 | |
| 20 | pub const Int = @Type(.{ .Int = .{ .bits = bit_count, .is_signed = false } }); | |
| 21 | pub const Int = meta.Int(false, bit_count); | |
| 21 | 22 | pub const bit_count = @typeInfo(Fields).Struct.fields.len; |
| 22 | 23 | |
| 24 | pub const FieldEnum = blk: { | |
| 25 | comptime var fields: [bit_count]TypeInfo.EnumField = undefined; | |
| 26 | inline for (@typeInfo(Fields).Struct.fields) |struct_field, i| | |
| 27 | fields[i] = .{ .name = struct_field.name, .value = i }; | |
| 28 | break :blk @Type(.{ | |
| 29 | .Enum = .{ | |
| 30 | .layout = .Auto, | |
| 31 | .tag_type = std.math.IntFittingRange(0, bit_count - 1), | |
| 32 | .fields = &fields, | |
| 33 | .decls = &[_]TypeInfo.Declaration{}, | |
| 34 | .is_exhaustive = true, | |
| 35 | }, | |
| 36 | }); | |
| 37 | }; | |
| 38 | ||
| 39 | pub const InitStruct = blk: { | |
| 40 | comptime var fields: [bit_count]TypeInfo.StructField = undefined; | |
| 41 | inline for (@typeInfo(Fields).Struct.fields) |struct_field, i| { | |
| 42 | fields[i] = TypeInfo.StructField{ | |
| 43 | .name = struct_field.name, | |
| 44 | .field_type = ?struct_field.field_type, | |
| 45 | .default_value = @as( | |
| 46 | ??struct_field.field_type, | |
| 47 | @as(?struct_field.field_type, null), | |
| 48 | ), | |
| 49 | }; | |
| 50 | } | |
| 51 | break :blk @Type(.{ | |
| 52 | .Struct = .{ | |
| 53 | .layout = .Auto, | |
| 54 | .fields = &fields, | |
| 55 | .decls = &[_]TypeInfo.Declaration{}, | |
| 56 | .is_tuple = false, | |
| 57 | }, | |
| 58 | }); | |
| 59 | }; | |
| 60 | ||
| 23 | 61 | pub const Self = @This(); |
| 24 | 62 | |
| 25 | pub fn has(self: Self, comptime name: []const u8) bool { | |
| 26 | const field_index = meta.fieldIndex(Fields, name).?; | |
| 63 | pub fn has(self: Self, comptime field: FieldEnum) bool { | |
| 64 | const field_index = @enumToInt(field); | |
| 27 | 65 | return (self.bits & (1 << field_index)) != 0; |
| 28 | 66 | } |
| 29 | 67 | |
| 30 | pub fn get(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime name: []const u8) ?Field(name) { | |
| 31 | if (!self.has(name)) | |
| 68 | pub fn get(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime field: FieldEnum) ?Field(field) { | |
| 69 | if (!self.has(field)) | |
| 32 | 70 | return null; |
| 33 | return self.ptrConst(p, name).*; | |
| 71 | return self.ptrConst(p, field).*; | |
| 34 | 72 | } |
| 35 | 73 | |
| 36 | pub fn setFlag(self: *Self, comptime name: []const u8) void { | |
| 37 | const field_index = meta.fieldIndex(Fields, name).?; | |
| 74 | pub fn setFlag(self: *Self, comptime field: FieldEnum) void { | |
| 75 | const field_index = @enumToInt(field); | |
| 38 | 76 | self.bits |= 1 << field_index; |
| 39 | 77 | } |
| 40 | 78 | |
| 41 | 79 | /// `fields` is a struct with each field set to an optional value. |
| 42 | /// Missing fields are assumed to be `null`. | |
| 43 | 80 | /// Only the non-null bits are observed and are used to set the flag bits. |
| 44 | pub fn init(fields: anytype) Self { | |
| 81 | pub fn init(fields: InitStruct) Self { | |
| 45 | 82 | var self: Self = .{ .bits = 0 }; |
| 46 | inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { | |
| 47 | const opt: ?Field(field.name) = @field(fields, field.name); | |
| 48 | const field_index = meta.fieldIndex(Fields, field.name).?; | |
| 49 | self.bits |= @as(Int, @boolToInt(opt != null)) << field_index; | |
| 83 | inline for (@typeInfo(Fields).Struct.fields) |field, i| { | |
| 84 | if (@field(fields, field.name)) |_| | |
| 85 | self.bits |= 1 << i; | |
| 50 | 86 | } |
| 51 | 87 | return self; |
| 52 | 88 | } |
| 53 | 89 | |
| 54 | 90 | /// `fields` is a struct with each field set to an optional value (same as `init`). |
| 55 | /// Missing fields are assumed to be `null`. | |
| 56 | pub fn setMany(self: Self, p: [*]align(@alignOf(Fields)) u8, fields: anytype) void { | |
| 57 | inline for (@typeInfo(@TypeOf(fields)).Struct.fields) |field| { | |
| 58 | const opt: ?Field(field.name) = @field(fields, field.name); | |
| 59 | if (opt) |value| { | |
| 60 | self.set(p, field.name, value); | |
| 61 | } | |
| 91 | pub fn setMany(self: Self, p: [*]align(@alignOf(Fields)) u8, fields: InitStruct) void { | |
| 92 | inline for (@typeInfo(Fields).Struct.fields) |field, i| { | |
| 93 | if (@field(fields, field.name)) |value| | |
| 94 | self.set(p, @intToEnum(FieldEnum, i), value); | |
| 62 | 95 | } |
| 63 | 96 | } |
| 64 | 97 | |
| 65 | 98 | pub fn set( |
| 66 | 99 | self: Self, |
| 67 | 100 | p: [*]align(@alignOf(Fields)) u8, |
| 68 | comptime name: []const u8, | |
| 69 | value: Field(name), | |
| 101 | comptime field: FieldEnum, | |
| 102 | value: Field(field), | |
| 70 | 103 | ) void { |
| 71 | self.ptr(p, name).* = value; | |
| 104 | self.ptr(p, field).* = value; | |
| 72 | 105 | } |
| 73 | 106 | |
| 74 | pub fn ptr(self: Self, p: [*]align(@alignOf(Fields)) u8, comptime name: []const u8) *Field(name) { | |
| 75 | if (@sizeOf(Field(name)) == 0) | |
| 107 | pub fn ptr(self: Self, p: [*]align(@alignOf(Fields)) u8, comptime field: FieldEnum) *Field(field) { | |
| 108 | if (@sizeOf(Field(field)) == 0) | |
| 76 | 109 | return undefined; |
| 77 | const off = self.offset(p, name); | |
| 78 | return @ptrCast(*Field(name), @alignCast(@alignOf(Field(name)), p + off)); | |
| 110 | const off = self.offset(p, field); | |
| 111 | return @ptrCast(*Field(field), @alignCast(@alignOf(Field(field)), p + off)); | |
| 79 | 112 | } |
| 80 | 113 | |
| 81 | pub fn ptrConst(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime name: []const u8) *const Field(name) { | |
| 82 | if (@sizeOf(Field(name)) == 0) | |
| 114 | pub fn ptrConst(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime field: FieldEnum) *const Field(field) { | |
| 115 | if (@sizeOf(Field(field)) == 0) | |
| 83 | 116 | return undefined; |
| 84 | const off = self.offset(p, name); | |
| 85 | return @ptrCast(*const Field(name), @alignCast(@alignOf(Field(name)), p + off)); | |
| 117 | const off = self.offset(p, field); | |
| 118 | return @ptrCast(*const Field(field), @alignCast(@alignOf(Field(field)), p + off)); | |
| 86 | 119 | } |
| 87 | 120 | |
| 88 | pub fn offset(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime name: []const u8) usize { | |
| 121 | pub fn offset(self: Self, p: [*]align(@alignOf(Fields)) const u8, comptime field: FieldEnum) usize { | |
| 89 | 122 | var off: usize = 0; |
| 90 | inline for (@typeInfo(Fields).Struct.fields) |field, i| { | |
| 123 | inline for (@typeInfo(Fields).Struct.fields) |field_info, i| { | |
| 91 | 124 | const active = (self.bits & (1 << i)) != 0; |
| 92 | if (comptime mem.eql(u8, field.name, name)) { | |
| 125 | if (i == @enumToInt(field)) { | |
| 93 | 126 | assert(active); |
| 94 | return mem.alignForwardGeneric(usize, off, @alignOf(field.field_type)); | |
| 127 | return mem.alignForwardGeneric(usize, off, @alignOf(field_info.field_type)); | |
| 95 | 128 | } else if (active) { |
| 96 | off = mem.alignForwardGeneric(usize, off, @alignOf(field.field_type)); | |
| 97 | off += @sizeOf(field.field_type); | |
| 129 | off = mem.alignForwardGeneric(usize, off, @alignOf(field_info.field_type)); | |
| 130 | off += @sizeOf(field_info.field_type); | |
| 98 | 131 | } |
| 99 | 132 | } |
| 100 | @compileError("no field named " ++ name ++ " in type " ++ @typeName(Fields)); | |
| 101 | 133 | } |
| 102 | 134 | |
| 103 | pub fn Field(comptime name: []const u8) type { | |
| 104 | return meta.fieldInfo(Fields, name).field_type; | |
| 135 | pub fn Field(comptime field: FieldEnum) type { | |
| 136 | inline for (@typeInfo(Fields).Struct.fields) |field_info, i| { | |
| 137 | if (i == @enumToInt(field)) | |
| 138 | return field_info.field_type; | |
| 139 | } | |
| 105 | 140 | } |
| 106 | 141 | |
| 107 | 142 | pub fn sizeInBytes(self: Self) usize { |
| ... | ... | @@ -125,6 +160,8 @@ test "TrailerFlags" { |
| 125 | 160 | b: bool, |
| 126 | 161 | c: u64, |
| 127 | 162 | }); |
| 163 | testing.expectEqual(u2, @TagType(Flags.FieldEnum)); | |
| 164 | ||
| 128 | 165 | var flags = Flags.init(.{ |
| 129 | 166 | .b = true, |
| 130 | 167 | .c = 1234, |
| ... | ... | @@ -132,19 +169,19 @@ test "TrailerFlags" { |
| 132 | 169 | const slice = try testing.allocator.allocAdvanced(u8, 8, flags.sizeInBytes(), .exact); |
| 133 | 170 | defer testing.allocator.free(slice); |
| 134 | 171 | |
| 135 | flags.set(slice.ptr, "b", false); | |
| 136 | flags.set(slice.ptr, "c", 12345678); | |
| 172 | flags.set(slice.ptr, .b, false); | |
| 173 | flags.set(slice.ptr, .c, 12345678); | |
| 137 | 174 | |
| 138 | testing.expect(flags.get(slice.ptr, "a") == null); | |
| 139 | testing.expect(!flags.get(slice.ptr, "b").?); | |
| 140 | testing.expect(flags.get(slice.ptr, "c").? == 12345678); | |
| 175 | testing.expect(flags.get(slice.ptr, .a) == null); | |
| 176 | testing.expect(!flags.get(slice.ptr, .b).?); | |
| 177 | testing.expect(flags.get(slice.ptr, .c).? == 12345678); | |
| 141 | 178 | |
| 142 | 179 | flags.setMany(slice.ptr, .{ |
| 143 | 180 | .b = true, |
| 144 | 181 | .c = 5678, |
| 145 | 182 | }); |
| 146 | 183 | |
| 147 | testing.expect(flags.get(slice.ptr, "a") == null); | |
| 148 | testing.expect(flags.get(slice.ptr, "b").?); | |
| 149 | testing.expect(flags.get(slice.ptr, "c").? == 5678); | |
| 184 | testing.expect(flags.get(slice.ptr, .a) == null); | |
| 185 | testing.expect(flags.get(slice.ptr, .b).?); | |
| 186 | testing.expect(flags.get(slice.ptr, .c).? == 5678); | |
| 150 | 187 | } |
lib/std/zig/ast.zig+226-38| ... | ... | @@ -915,23 +915,111 @@ pub const Node = struct { |
| 915 | 915 | init_node: *Node, |
| 916 | 916 | }); |
| 917 | 917 | |
| 918 | pub fn getDocComments(self: *const VarDecl) ?*DocComment { | |
| 919 | return self.getTrailer(.doc_comments); | |
| 920 | } | |
| 921 | ||
| 922 | pub fn setDocComments(self: *VarDecl, value: *DocComment) void { | |
| 923 | self.setTrailer(.doc_comments, value); | |
| 924 | } | |
| 925 | ||
| 926 | pub fn getVisibToken(self: *const VarDecl) ?TokenIndex { | |
| 927 | return self.getTrailer(.visib_token); | |
| 928 | } | |
| 929 | ||
| 930 | pub fn setVisibToken(self: *VarDecl, value: TokenIndex) void { | |
| 931 | self.setTrailer(.visib_token, value); | |
| 932 | } | |
| 933 | ||
| 934 | pub fn getThreadLocalToken(self: *const VarDecl) ?TokenIndex { | |
| 935 | return self.getTrailer(.thread_local_token); | |
| 936 | } | |
| 937 | ||
| 938 | pub fn setThreadLocalToken(self: *VarDecl, value: TokenIndex) void { | |
| 939 | self.setTrailer(.thread_local_token, value); | |
| 940 | } | |
| 941 | ||
| 942 | pub fn getEqToken(self: *const VarDecl) ?TokenIndex { | |
| 943 | return self.getTrailer(.eq_token); | |
| 944 | } | |
| 945 | ||
| 946 | pub fn setEqToken(self: *VarDecl, value: TokenIndex) void { | |
| 947 | self.setTrailer(.eq_token, value); | |
| 948 | } | |
| 949 | ||
| 950 | pub fn getComptimeToken(self: *const VarDecl) ?TokenIndex { | |
| 951 | return self.getTrailer(.comptime_token); | |
| 952 | } | |
| 953 | ||
| 954 | pub fn setComptimeToken(self: *VarDecl, value: TokenIndex) void { | |
| 955 | self.setTrailer(.comptime_token, value); | |
| 956 | } | |
| 957 | ||
| 958 | pub fn getExternExportToken(self: *const VarDecl) ?TokenIndex { | |
| 959 | return self.getTrailer(.extern_export_token); | |
| 960 | } | |
| 961 | ||
| 962 | pub fn setExternExportToken(self: *VarDecl, value: TokenIndex) void { | |
| 963 | self.setTrailer(.extern_export_token, value); | |
| 964 | } | |
| 965 | ||
| 966 | pub fn getLibName(self: *const VarDecl) ?*Node { | |
| 967 | return self.getTrailer(.lib_name); | |
| 968 | } | |
| 969 | ||
| 970 | pub fn setLibName(self: *VarDecl, value: *Node) void { | |
| 971 | self.setTrailer(.lib_name, value); | |
| 972 | } | |
| 973 | ||
| 974 | pub fn getTypeNode(self: *const VarDecl) ?*Node { | |
| 975 | return self.getTrailer(.type_node); | |
| 976 | } | |
| 977 | ||
| 978 | pub fn setTypeNode(self: *VarDecl, value: *Node) void { | |
| 979 | self.setTrailer(.type_node, value); | |
| 980 | } | |
| 981 | ||
| 982 | pub fn getAlignNode(self: *const VarDecl) ?*Node { | |
| 983 | return self.getTrailer(.align_node); | |
| 984 | } | |
| 985 | ||
| 986 | pub fn setAlignNode(self: *VarDecl, value: *Node) void { | |
| 987 | self.setTrailer(.align_node, value); | |
| 988 | } | |
| 989 | ||
| 990 | pub fn getSectionNode(self: *const VarDecl) ?*Node { | |
| 991 | return self.getTrailer(.section_node); | |
| 992 | } | |
| 993 | ||
| 994 | pub fn setSectionNode(self: *VarDecl, value: *Node) void { | |
| 995 | self.setTrailer(.section_node, value); | |
| 996 | } | |
| 997 | ||
| 998 | pub fn getInitNode(self: *const VarDecl) ?*Node { | |
| 999 | return self.getTrailer(.init_node); | |
| 1000 | } | |
| 1001 | ||
| 1002 | pub fn setInitNode(self: *VarDecl, value: *Node) void { | |
| 1003 | self.setTrailer(.init_node, value); | |
| 1004 | } | |
| 1005 | ||
| 918 | 1006 | pub const RequiredFields = struct { |
| 919 | 1007 | mut_token: TokenIndex, |
| 920 | 1008 | name_token: TokenIndex, |
| 921 | 1009 | semicolon_token: TokenIndex, |
| 922 | 1010 | }; |
| 923 | 1011 | |
| 924 | pub fn getTrailer(self: *const VarDecl, comptime name: []const u8) ?TrailerFlags.Field(name) { | |
| 1012 | fn getTrailer(self: *const VarDecl, comptime field: TrailerFlags.FieldEnum) ?TrailerFlags.Field(field) { | |
| 925 | 1013 | const trailers_start = @ptrCast([*]const u8, self) + @sizeOf(VarDecl); |
| 926 | return self.trailer_flags.get(trailers_start, name); | |
| 1014 | return self.trailer_flags.get(trailers_start, field); | |
| 927 | 1015 | } |
| 928 | 1016 | |
| 929 | pub fn setTrailer(self: *VarDecl, comptime name: []const u8, value: TrailerFlags.Field(name)) void { | |
| 1017 | fn setTrailer(self: *VarDecl, comptime field: TrailerFlags.FieldEnum, value: TrailerFlags.Field(field)) void { | |
| 930 | 1018 | const trailers_start = @ptrCast([*]u8, self) + @sizeOf(VarDecl); |
| 931 | self.trailer_flags.set(trailers_start, name, value); | |
| 1019 | self.trailer_flags.set(trailers_start, field, value); | |
| 932 | 1020 | } |
| 933 | 1021 | |
| 934 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: anytype) !*VarDecl { | |
| 1022 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: TrailerFlags.InitStruct) !*VarDecl { | |
| 935 | 1023 | const trailer_flags = TrailerFlags.init(trailers); |
| 936 | 1024 | const bytes = try allocator.alignedAlloc(u8, @alignOf(VarDecl), sizeInBytes(trailer_flags)); |
| 937 | 1025 | const var_decl = @ptrCast(*VarDecl, bytes.ptr); |
| ... | ... | @@ -954,22 +1042,22 @@ pub const Node = struct { |
| 954 | 1042 | pub fn iterate(self: *const VarDecl, index: usize) ?*Node { |
| 955 | 1043 | var i = index; |
| 956 | 1044 | |
| 957 | if (self.getTrailer("type_node")) |type_node| { | |
| 1045 | if (self.getTypeNode()) |type_node| { | |
| 958 | 1046 | if (i < 1) return type_node; |
| 959 | 1047 | i -= 1; |
| 960 | 1048 | } |
| 961 | 1049 | |
| 962 | if (self.getTrailer("align_node")) |align_node| { | |
| 1050 | if (self.getAlignNode()) |align_node| { | |
| 963 | 1051 | if (i < 1) return align_node; |
| 964 | 1052 | i -= 1; |
| 965 | 1053 | } |
| 966 | 1054 | |
| 967 | if (self.getTrailer("section_node")) |section_node| { | |
| 1055 | if (self.getSectionNode()) |section_node| { | |
| 968 | 1056 | if (i < 1) return section_node; |
| 969 | 1057 | i -= 1; |
| 970 | 1058 | } |
| 971 | 1059 | |
| 972 | if (self.getTrailer("init_node")) |init_node| { | |
| 1060 | if (self.getInitNode()) |init_node| { | |
| 973 | 1061 | if (i < 1) return init_node; |
| 974 | 1062 | i -= 1; |
| 975 | 1063 | } |
| ... | ... | @@ -978,11 +1066,11 @@ pub const Node = struct { |
| 978 | 1066 | } |
| 979 | 1067 | |
| 980 | 1068 | pub fn firstToken(self: *const VarDecl) TokenIndex { |
| 981 | if (self.getTrailer("visib_token")) |visib_token| return visib_token; | |
| 982 | if (self.getTrailer("thread_local_token")) |thread_local_token| return thread_local_token; | |
| 983 | if (self.getTrailer("comptime_token")) |comptime_token| return comptime_token; | |
| 984 | if (self.getTrailer("extern_export_token")) |extern_export_token| return extern_export_token; | |
| 985 | assert(self.getTrailer("lib_name") == null); | |
| 1069 | if (self.getVisibToken()) |visib_token| return visib_token; | |
| 1070 | if (self.getThreadLocalToken()) |thread_local_token| return thread_local_token; | |
| 1071 | if (self.getComptimeToken()) |comptime_token| return comptime_token; | |
| 1072 | if (self.getExternExportToken()) |extern_export_token| return extern_export_token; | |
| 1073 | assert(self.getLibName() == null); | |
| 986 | 1074 | return self.mut_token; |
| 987 | 1075 | } |
| 988 | 1076 | |
| ... | ... | @@ -1320,34 +1408,126 @@ pub const Node = struct { |
| 1320 | 1408 | std.debug.print("{*} flags: {b} name_token: {} {*} params_len: {}\n", .{ |
| 1321 | 1409 | self, |
| 1322 | 1410 | self.trailer_flags.bits, |
| 1323 | self.getTrailer("name_token"), | |
| 1324 | self.trailer_flags.ptrConst(trailers_start, "name_token"), | |
| 1411 | self.getNameToken(), | |
| 1412 | self.trailer_flags.ptrConst(trailers_start, .name_token), | |
| 1325 | 1413 | self.params_len, |
| 1326 | 1414 | }); |
| 1327 | 1415 | } |
| 1328 | 1416 | |
| 1329 | pub fn body(self: *const FnProto) ?*Node { | |
| 1330 | return self.getTrailer("body_node"); | |
| 1417 | pub fn getDocComments(self: *const FnProto) ?*DocComment { | |
| 1418 | return self.getTrailer(.doc_comments); | |
| 1419 | } | |
| 1420 | ||
| 1421 | pub fn setDocComments(self: *FnProto, value: *DocComment) void { | |
| 1422 | self.setTrailer(.doc_comments, value); | |
| 1423 | } | |
| 1424 | ||
| 1425 | pub fn getBodyNode(self: *const FnProto) ?*Node { | |
| 1426 | return self.getTrailer(.body_node); | |
| 1427 | } | |
| 1428 | ||
| 1429 | pub fn setBodyNode(self: *FnProto, value: *Node) void { | |
| 1430 | self.setTrailer(.body_node, value); | |
| 1431 | } | |
| 1432 | ||
| 1433 | pub fn getLibName(self: *const FnProto) ?*Node { | |
| 1434 | return self.getTrailer(.lib_name); | |
| 1435 | } | |
| 1436 | ||
| 1437 | pub fn setLibName(self: *FnProto, value: *Node) void { | |
| 1438 | self.setTrailer(.lib_name, value); | |
| 1439 | } | |
| 1440 | ||
| 1441 | pub fn getAlignExpr(self: *const FnProto) ?*Node { | |
| 1442 | return self.getTrailer(.align_expr); | |
| 1443 | } | |
| 1444 | ||
| 1445 | pub fn setAlignExpr(self: *FnProto, value: *Node) void { | |
| 1446 | self.setTrailer(.align_expr, value); | |
| 1447 | } | |
| 1448 | ||
| 1449 | pub fn getSectionExpr(self: *const FnProto) ?*Node { | |
| 1450 | return self.getTrailer(.section_expr); | |
| 1451 | } | |
| 1452 | ||
| 1453 | pub fn setSectionExpr(self: *FnProto, value: *Node) void { | |
| 1454 | self.setTrailer(.section_expr, value); | |
| 1455 | } | |
| 1456 | ||
| 1457 | pub fn getCallconvExpr(self: *const FnProto) ?*Node { | |
| 1458 | return self.getTrailer(.callconv_expr); | |
| 1459 | } | |
| 1460 | ||
| 1461 | pub fn setCallconvExpr(self: *FnProto, value: *Node) void { | |
| 1462 | self.setTrailer(.callconv_expr, value); | |
| 1463 | } | |
| 1464 | ||
| 1465 | pub fn getVisibToken(self: *const FnProto) ?TokenIndex { | |
| 1466 | return self.getTrailer(.visib_token); | |
| 1331 | 1467 | } |
| 1332 | 1468 | |
| 1333 | pub fn getTrailer(self: *const FnProto, comptime name: []const u8) ?TrailerFlags.Field(name) { | |
| 1469 | pub fn setVisibToken(self: *FnProto, value: TokenIndex) void { | |
| 1470 | self.setTrailer(.visib_token, value); | |
| 1471 | } | |
| 1472 | ||
| 1473 | pub fn getNameToken(self: *const FnProto) ?TokenIndex { | |
| 1474 | return self.getTrailer(.name_token); | |
| 1475 | } | |
| 1476 | ||
| 1477 | pub fn setNameToken(self: *FnProto, value: TokenIndex) void { | |
| 1478 | self.setTrailer(.name_token, value); | |
| 1479 | } | |
| 1480 | ||
| 1481 | pub fn getVarArgsToken(self: *const FnProto) ?TokenIndex { | |
| 1482 | return self.getTrailer(.var_args_token); | |
| 1483 | } | |
| 1484 | ||
| 1485 | pub fn setVarArgsToken(self: *FnProto, value: TokenIndex) void { | |
| 1486 | self.setTrailer(.var_args_token, value); | |
| 1487 | } | |
| 1488 | ||
| 1489 | pub fn getExternExportInlineToken(self: *const FnProto) ?TokenIndex { | |
| 1490 | return self.getTrailer(.extern_export_inline_token); | |
| 1491 | } | |
| 1492 | ||
| 1493 | pub fn setExternExportInlineToken(self: *FnProto, value: TokenIndex) void { | |
| 1494 | self.setTrailer(.extern_export_inline_token, value); | |
| 1495 | } | |
| 1496 | ||
| 1497 | pub fn getIsExternPrototype(self: *const FnProto) ?void { | |
| 1498 | return self.getTrailer(.is_extern_prototype); | |
| 1499 | } | |
| 1500 | ||
| 1501 | pub fn setIsExternPrototype(self: *FnProto, value: void) void { | |
| 1502 | self.setTrailer(.is_extern_prototype, value); | |
| 1503 | } | |
| 1504 | ||
| 1505 | pub fn getIsAsync(self: *const FnProto) ?void { | |
| 1506 | return self.getTrailer(.is_async); | |
| 1507 | } | |
| 1508 | ||
| 1509 | pub fn setIsAsync(self: *FnProto, value: void) void { | |
| 1510 | self.setTrailer(.is_async, value); | |
| 1511 | } | |
| 1512 | ||
| 1513 | fn getTrailer(self: *const FnProto, comptime field: TrailerFlags.FieldEnum) ?TrailerFlags.Field(field) { | |
| 1334 | 1514 | const trailers_start = @alignCast( |
| 1335 | 1515 | @alignOf(ParamDecl), |
| 1336 | 1516 | @ptrCast([*]const u8, self) + @sizeOf(FnProto) + @sizeOf(ParamDecl) * self.params_len, |
| 1337 | 1517 | ); |
| 1338 | return self.trailer_flags.get(trailers_start, name); | |
| 1518 | return self.trailer_flags.get(trailers_start, field); | |
| 1339 | 1519 | } |
| 1340 | 1520 | |
| 1341 | pub fn setTrailer(self: *FnProto, comptime name: []const u8, value: TrailerFlags.Field(name)) void { | |
| 1521 | fn setTrailer(self: *FnProto, comptime field: TrailerFlags.FieldEnum, value: TrailerFlags.Field(field)) void { | |
| 1342 | 1522 | const trailers_start = @alignCast( |
| 1343 | 1523 | @alignOf(ParamDecl), |
| 1344 | 1524 | @ptrCast([*]u8, self) + @sizeOf(FnProto) + @sizeOf(ParamDecl) * self.params_len, |
| 1345 | 1525 | ); |
| 1346 | self.trailer_flags.set(trailers_start, name, value); | |
| 1526 | self.trailer_flags.set(trailers_start, field, value); | |
| 1347 | 1527 | } |
| 1348 | 1528 | |
| 1349 | 1529 | /// After this the caller must initialize the params list. |
| 1350 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: anytype) !*FnProto { | |
| 1530 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: TrailerFlags.InitStruct) !*FnProto { | |
| 1351 | 1531 | const trailer_flags = TrailerFlags.init(trailers); |
| 1352 | 1532 | const bytes = try allocator.alignedAlloc(u8, @alignOf(FnProto), sizeInBytes( |
| 1353 | 1533 | required.params_len, |
| ... | ... | @@ -1376,7 +1556,7 @@ pub const Node = struct { |
| 1376 | 1556 | pub fn iterate(self: *const FnProto, index: usize) ?*Node { |
| 1377 | 1557 | var i = index; |
| 1378 | 1558 | |
| 1379 | if (self.getTrailer("lib_name")) |lib_name| { | |
| 1559 | if (self.getLibName()) |lib_name| { | |
| 1380 | 1560 | if (i < 1) return lib_name; |
| 1381 | 1561 | i -= 1; |
| 1382 | 1562 | } |
| ... | ... | @@ -1394,12 +1574,12 @@ pub const Node = struct { |
| 1394 | 1574 | } |
| 1395 | 1575 | i -= params_len; |
| 1396 | 1576 | |
| 1397 | if (self.getTrailer("align_expr")) |align_expr| { | |
| 1577 | if (self.getAlignExpr()) |align_expr| { | |
| 1398 | 1578 | if (i < 1) return align_expr; |
| 1399 | 1579 | i -= 1; |
| 1400 | 1580 | } |
| 1401 | 1581 | |
| 1402 | if (self.getTrailer("section_expr")) |section_expr| { | |
| 1582 | if (self.getSectionExpr()) |section_expr| { | |
| 1403 | 1583 | if (i < 1) return section_expr; |
| 1404 | 1584 | i -= 1; |
| 1405 | 1585 | } |
| ... | ... | @@ -1412,7 +1592,7 @@ pub const Node = struct { |
| 1412 | 1592 | .Invalid => {}, |
| 1413 | 1593 | } |
| 1414 | 1594 | |
| 1415 | if (self.body()) |body_node| { | |
| 1595 | if (self.getBodyNode()) |body_node| { | |
| 1416 | 1596 | if (i < 1) return body_node; |
| 1417 | 1597 | i -= 1; |
| 1418 | 1598 | } |
| ... | ... | @@ -1421,14 +1601,14 @@ pub const Node = struct { |
| 1421 | 1601 | } |
| 1422 | 1602 | |
| 1423 | 1603 | pub fn firstToken(self: *const FnProto) TokenIndex { |
| 1424 | if (self.getTrailer("visib_token")) |visib_token| return visib_token; | |
| 1425 | if (self.getTrailer("extern_export_inline_token")) |extern_export_inline_token| return extern_export_inline_token; | |
| 1426 | assert(self.getTrailer("lib_name") == null); | |
| 1604 | if (self.getVisibToken()) |visib_token| return visib_token; | |
| 1605 | if (self.getExternExportInlineToken()) |extern_export_inline_token| return extern_export_inline_token; | |
| 1606 | assert(self.getLibName() == null); | |
| 1427 | 1607 | return self.fn_token; |
| 1428 | 1608 | } |
| 1429 | 1609 | |
| 1430 | 1610 | pub fn lastToken(self: *const FnProto) TokenIndex { |
| 1431 | if (self.body()) |body_node| return body_node.lastToken(); | |
| 1611 | if (self.getBodyNode()) |body_node| return body_node.lastToken(); | |
| 1432 | 1612 | switch (self.return_type) { |
| 1433 | 1613 | .Explicit, .InferErrorSet => |node| return node.lastToken(), |
| 1434 | 1614 | .Invalid => |tok| return tok, |
| ... | ... | @@ -2673,24 +2853,32 @@ pub const Node = struct { |
| 2673 | 2853 | }; |
| 2674 | 2854 | |
| 2675 | 2855 | pub fn getRHS(self: *const ControlFlowExpression) ?*Node { |
| 2676 | return self.getTrailer("rhs"); | |
| 2856 | return self.getTrailer(.rhs); | |
| 2857 | } | |
| 2858 | ||
| 2859 | pub fn setRHS(self: *ControlFlowExpression, value: *Node) void { | |
| 2860 | self.setTrailer(.rhs, value); | |
| 2677 | 2861 | } |
| 2678 | 2862 | |
| 2679 | 2863 | pub fn getLabel(self: *const ControlFlowExpression) ?TokenIndex { |
| 2680 | return self.getTrailer("label"); | |
| 2864 | return self.getTrailer(.label); | |
| 2865 | } | |
| 2866 | ||
| 2867 | pub fn setLabel(self: *ControlFlowExpression, value: TokenIndex) void { | |
| 2868 | self.setTrailer(.label, value); | |
| 2681 | 2869 | } |
| 2682 | 2870 | |
| 2683 | pub fn getTrailer(self: *const ControlFlowExpression, comptime name: []const u8) ?TrailerFlags.Field(name) { | |
| 2871 | fn getTrailer(self: *const ControlFlowExpression, comptime field: TrailerFlags.FieldEnum) ?TrailerFlags.Field(field) { | |
| 2684 | 2872 | const trailers_start = @ptrCast([*]const u8, self) + @sizeOf(ControlFlowExpression); |
| 2685 | return self.trailer_flags.get(trailers_start, name); | |
| 2873 | return self.trailer_flags.get(trailers_start, field); | |
| 2686 | 2874 | } |
| 2687 | 2875 | |
| 2688 | pub fn setTrailer(self: *ControlFlowExpression, comptime name: []const u8, value: TrailerFlags.Field(name)) void { | |
| 2876 | fn setTrailer(self: *ControlFlowExpression, comptime field: TrailerFlags.FieldEnum, value: TrailerFlags.Field(field)) void { | |
| 2689 | 2877 | const trailers_start = @ptrCast([*]u8, self) + @sizeOf(ControlFlowExpression); |
| 2690 | self.trailer_flags.set(trailers_start, name, value); | |
| 2878 | self.trailer_flags.set(trailers_start, field, value); | |
| 2691 | 2879 | } |
| 2692 | 2880 | |
| 2693 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: anytype) !*ControlFlowExpression { | |
| 2881 | pub fn create(allocator: *mem.Allocator, required: RequiredFields, trailers: TrailerFlags.InitStruct) !*ControlFlowExpression { | |
| 2694 | 2882 | const trailer_flags = TrailerFlags.init(trailers); |
| 2695 | 2883 | const bytes = try allocator.alignedAlloc(u8, @alignOf(ControlFlowExpression), sizeInBytes(trailer_flags)); |
| 2696 | 2884 | const ctrl_flow_expr = @ptrCast(*ControlFlowExpression, bytes.ptr); |
lib/std/zig/render.zig+38-38| ... | ... | @@ -232,9 +232,9 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr |
| 232 | 232 | .FnProto => { |
| 233 | 233 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); |
| 234 | 234 | |
| 235 | try renderDocComments(tree, stream, fn_proto, fn_proto.getTrailer("doc_comments"), indent, start_col); | |
| 235 | try renderDocComments(tree, stream, fn_proto, fn_proto.getDocComments(), indent, start_col); | |
| 236 | 236 | |
| 237 | if (fn_proto.getTrailer("body_node")) |body_node| { | |
| 237 | if (fn_proto.getBodyNode()) |body_node| { | |
| 238 | 238 | try renderExpression(allocator, stream, tree, indent, start_col, decl, .Space); |
| 239 | 239 | try renderExpression(allocator, stream, tree, indent, start_col, body_node, space); |
| 240 | 240 | } else { |
| ... | ... | @@ -257,7 +257,7 @@ fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tr |
| 257 | 257 | .VarDecl => { |
| 258 | 258 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); |
| 259 | 259 | |
| 260 | try renderDocComments(tree, stream, var_decl, var_decl.getTrailer("doc_comments"), indent, start_col); | |
| 260 | try renderDocComments(tree, stream, var_decl, var_decl.getDocComments(), indent, start_col); | |
| 261 | 261 | try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); |
| 262 | 262 | }, |
| 263 | 263 | |
| ... | ... | @@ -1520,23 +1520,23 @@ fn renderExpression( |
| 1520 | 1520 | .FnProto => { |
| 1521 | 1521 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); |
| 1522 | 1522 | |
| 1523 | if (fn_proto.getTrailer("visib_token")) |visib_token_index| { | |
| 1523 | if (fn_proto.getVisibToken()) |visib_token_index| { | |
| 1524 | 1524 | const visib_token = tree.token_ids[visib_token_index]; |
| 1525 | 1525 | assert(visib_token == .Keyword_pub or visib_token == .Keyword_export); |
| 1526 | 1526 | |
| 1527 | 1527 | try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub |
| 1528 | 1528 | } |
| 1529 | 1529 | |
| 1530 | if (fn_proto.getTrailer("extern_export_inline_token")) |extern_export_inline_token| { | |
| 1531 | if (fn_proto.getTrailer("is_extern_prototype") == null) | |
| 1530 | if (fn_proto.getExternExportInlineToken()) |extern_export_inline_token| { | |
| 1531 | if (fn_proto.getIsExternPrototype() == null) | |
| 1532 | 1532 | try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export/inline |
| 1533 | 1533 | } |
| 1534 | 1534 | |
| 1535 | if (fn_proto.getTrailer("lib_name")) |lib_name| { | |
| 1535 | if (fn_proto.getLibName()) |lib_name| { | |
| 1536 | 1536 | try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); |
| 1537 | 1537 | } |
| 1538 | 1538 | |
| 1539 | const lparen = if (fn_proto.getTrailer("name_token")) |name_token| blk: { | |
| 1539 | const lparen = if (fn_proto.getNameToken()) |name_token| blk: { | |
| 1540 | 1540 | try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn |
| 1541 | 1541 | try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name |
| 1542 | 1542 | break :blk tree.nextToken(name_token); |
| ... | ... | @@ -1549,11 +1549,11 @@ fn renderExpression( |
| 1549 | 1549 | const rparen = tree.prevToken( |
| 1550 | 1550 | // the first token for the annotation expressions is the left |
| 1551 | 1551 | // parenthesis, hence the need for two prevToken |
| 1552 | if (fn_proto.getTrailer("align_expr")) |align_expr| | |
| 1552 | if (fn_proto.getAlignExpr()) |align_expr| | |
| 1553 | 1553 | tree.prevToken(tree.prevToken(align_expr.firstToken())) |
| 1554 | else if (fn_proto.getTrailer("section_expr")) |section_expr| | |
| 1554 | else if (fn_proto.getSectionExpr()) |section_expr| | |
| 1555 | 1555 | tree.prevToken(tree.prevToken(section_expr.firstToken())) |
| 1556 | else if (fn_proto.getTrailer("callconv_expr")) |callconv_expr| | |
| 1556 | else if (fn_proto.getCallconvExpr()) |callconv_expr| | |
| 1557 | 1557 | tree.prevToken(tree.prevToken(callconv_expr.firstToken())) |
| 1558 | 1558 | else switch (fn_proto.return_type) { |
| 1559 | 1559 | .Explicit => |node| node.firstToken(), |
| ... | ... | @@ -1574,12 +1574,12 @@ fn renderExpression( |
| 1574 | 1574 | for (fn_proto.params()) |param_decl, i| { |
| 1575 | 1575 | try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl, Space.None); |
| 1576 | 1576 | |
| 1577 | if (i + 1 < fn_proto.params_len or fn_proto.getTrailer("var_args_token") != null) { | |
| 1577 | if (i + 1 < fn_proto.params_len or fn_proto.getVarArgsToken() != null) { | |
| 1578 | 1578 | const comma = tree.nextToken(param_decl.lastToken()); |
| 1579 | 1579 | try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , |
| 1580 | 1580 | } |
| 1581 | 1581 | } |
| 1582 | if (fn_proto.getTrailer("var_args_token")) |var_args_token| { | |
| 1582 | if (fn_proto.getVarArgsToken()) |var_args_token| { | |
| 1583 | 1583 | try renderToken(tree, stream, var_args_token, indent, start_col, Space.None); |
| 1584 | 1584 | } |
| 1585 | 1585 | } else { |
| ... | ... | @@ -1591,7 +1591,7 @@ fn renderExpression( |
| 1591 | 1591 | try stream.writeByteNTimes(' ', new_indent); |
| 1592 | 1592 | try renderParamDecl(allocator, stream, tree, new_indent, start_col, param_decl, Space.Comma); |
| 1593 | 1593 | } |
| 1594 | if (fn_proto.getTrailer("var_args_token")) |var_args_token| { | |
| 1594 | if (fn_proto.getVarArgsToken()) |var_args_token| { | |
| 1595 | 1595 | try stream.writeByteNTimes(' ', new_indent); |
| 1596 | 1596 | try renderToken(tree, stream, var_args_token, new_indent, start_col, Space.Comma); |
| 1597 | 1597 | } |
| ... | ... | @@ -1600,7 +1600,7 @@ fn renderExpression( |
| 1600 | 1600 | |
| 1601 | 1601 | try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // ) |
| 1602 | 1602 | |
| 1603 | if (fn_proto.getTrailer("align_expr")) |align_expr| { | |
| 1603 | if (fn_proto.getAlignExpr()) |align_expr| { | |
| 1604 | 1604 | const align_rparen = tree.nextToken(align_expr.lastToken()); |
| 1605 | 1605 | const align_lparen = tree.prevToken(align_expr.firstToken()); |
| 1606 | 1606 | const align_kw = tree.prevToken(align_lparen); |
| ... | ... | @@ -1611,7 +1611,7 @@ fn renderExpression( |
| 1611 | 1611 | try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // ) |
| 1612 | 1612 | } |
| 1613 | 1613 | |
| 1614 | if (fn_proto.getTrailer("section_expr")) |section_expr| { | |
| 1614 | if (fn_proto.getSectionExpr()) |section_expr| { | |
| 1615 | 1615 | const section_rparen = tree.nextToken(section_expr.lastToken()); |
| 1616 | 1616 | const section_lparen = tree.prevToken(section_expr.firstToken()); |
| 1617 | 1617 | const section_kw = tree.prevToken(section_lparen); |
| ... | ... | @@ -1622,7 +1622,7 @@ fn renderExpression( |
| 1622 | 1622 | try renderToken(tree, stream, section_rparen, indent, start_col, Space.Space); // ) |
| 1623 | 1623 | } |
| 1624 | 1624 | |
| 1625 | if (fn_proto.getTrailer("callconv_expr")) |callconv_expr| { | |
| 1625 | if (fn_proto.getCallconvExpr()) |callconv_expr| { | |
| 1626 | 1626 | const callconv_rparen = tree.nextToken(callconv_expr.lastToken()); |
| 1627 | 1627 | const callconv_lparen = tree.prevToken(callconv_expr.firstToken()); |
| 1628 | 1628 | const callconv_kw = tree.prevToken(callconv_lparen); |
| ... | ... | @@ -1631,9 +1631,9 @@ fn renderExpression( |
| 1631 | 1631 | try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // ( |
| 1632 | 1632 | try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None); |
| 1633 | 1633 | try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // ) |
| 1634 | } else if (fn_proto.getTrailer("is_extern_prototype") != null) { | |
| 1634 | } else if (fn_proto.getIsExternPrototype() != null) { | |
| 1635 | 1635 | try stream.writeAll("callconv(.C) "); |
| 1636 | } else if (fn_proto.getTrailer("is_async") != null) { | |
| 1636 | } else if (fn_proto.getIsAsync() != null) { | |
| 1637 | 1637 | try stream.writeAll("callconv(.Async) "); |
| 1638 | 1638 | } |
| 1639 | 1639 | |
| ... | ... | @@ -2221,69 +2221,69 @@ fn renderVarDecl( |
| 2221 | 2221 | start_col: *usize, |
| 2222 | 2222 | var_decl: *ast.Node.VarDecl, |
| 2223 | 2223 | ) (@TypeOf(stream).Error || Error)!void { |
| 2224 | if (var_decl.getTrailer("visib_token")) |visib_token| { | |
| 2224 | if (var_decl.getVisibToken()) |visib_token| { | |
| 2225 | 2225 | try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub |
| 2226 | 2226 | } |
| 2227 | 2227 | |
| 2228 | if (var_decl.getTrailer("extern_export_token")) |extern_export_token| { | |
| 2228 | if (var_decl.getExternExportToken()) |extern_export_token| { | |
| 2229 | 2229 | try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern |
| 2230 | 2230 | |
| 2231 | if (var_decl.getTrailer("lib_name")) |lib_name| { | |
| 2231 | if (var_decl.getLibName()) |lib_name| { | |
| 2232 | 2232 | try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); // "lib" |
| 2233 | 2233 | } |
| 2234 | 2234 | } |
| 2235 | 2235 | |
| 2236 | if (var_decl.getTrailer("comptime_token")) |comptime_token| { | |
| 2236 | if (var_decl.getComptimeToken()) |comptime_token| { | |
| 2237 | 2237 | try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime |
| 2238 | 2238 | } |
| 2239 | 2239 | |
| 2240 | if (var_decl.getTrailer("thread_local_token")) |thread_local_token| { | |
| 2240 | if (var_decl.getThreadLocalToken()) |thread_local_token| { | |
| 2241 | 2241 | try renderToken(tree, stream, thread_local_token, indent, start_col, Space.Space); // threadlocal |
| 2242 | 2242 | } |
| 2243 | 2243 | try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var |
| 2244 | 2244 | |
| 2245 | const name_space = if (var_decl.getTrailer("type_node") == null and | |
| 2246 | (var_decl.getTrailer("align_node") != null or | |
| 2247 | var_decl.getTrailer("section_node") != null or | |
| 2248 | var_decl.getTrailer("init_node") != null)) | |
| 2245 | const name_space = if (var_decl.getTypeNode() == null and | |
| 2246 | (var_decl.getAlignNode() != null or | |
| 2247 | var_decl.getSectionNode() != null or | |
| 2248 | var_decl.getInitNode() != null)) | |
| 2249 | 2249 | Space.Space |
| 2250 | 2250 | else |
| 2251 | 2251 | Space.None; |
| 2252 | 2252 | try renderToken(tree, stream, var_decl.name_token, indent, start_col, name_space); |
| 2253 | 2253 | |
| 2254 | if (var_decl.getTrailer("type_node")) |type_node| { | |
| 2254 | if (var_decl.getTypeNode()) |type_node| { | |
| 2255 | 2255 | try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, start_col, Space.Space); |
| 2256 | const s = if (var_decl.getTrailer("align_node") != null or | |
| 2257 | var_decl.getTrailer("section_node") != null or | |
| 2258 | var_decl.getTrailer("init_node") != null) Space.Space else Space.None; | |
| 2256 | const s = if (var_decl.getAlignNode() != null or | |
| 2257 | var_decl.getSectionNode() != null or | |
| 2258 | var_decl.getInitNode() != null) Space.Space else Space.None; | |
| 2259 | 2259 | try renderExpression(allocator, stream, tree, indent, start_col, type_node, s); |
| 2260 | 2260 | } |
| 2261 | 2261 | |
| 2262 | if (var_decl.getTrailer("align_node")) |align_node| { | |
| 2262 | if (var_decl.getAlignNode()) |align_node| { | |
| 2263 | 2263 | const lparen = tree.prevToken(align_node.firstToken()); |
| 2264 | 2264 | const align_kw = tree.prevToken(lparen); |
| 2265 | 2265 | const rparen = tree.nextToken(align_node.lastToken()); |
| 2266 | 2266 | try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align |
| 2267 | 2267 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( |
| 2268 | 2268 | try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None); |
| 2269 | const s = if (var_decl.getTrailer("section_node") != null or var_decl.getTrailer("init_node") != null) Space.Space else Space.None; | |
| 2269 | const s = if (var_decl.getSectionNode() != null or var_decl.getInitNode() != null) Space.Space else Space.None; | |
| 2270 | 2270 | try renderToken(tree, stream, rparen, indent, start_col, s); // ) |
| 2271 | 2271 | } |
| 2272 | 2272 | |
| 2273 | if (var_decl.getTrailer("section_node")) |section_node| { | |
| 2273 | if (var_decl.getSectionNode()) |section_node| { | |
| 2274 | 2274 | const lparen = tree.prevToken(section_node.firstToken()); |
| 2275 | 2275 | const section_kw = tree.prevToken(lparen); |
| 2276 | 2276 | const rparen = tree.nextToken(section_node.lastToken()); |
| 2277 | 2277 | try renderToken(tree, stream, section_kw, indent, start_col, Space.None); // linksection |
| 2278 | 2278 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( |
| 2279 | 2279 | try renderExpression(allocator, stream, tree, indent, start_col, section_node, Space.None); |
| 2280 | const s = if (var_decl.getTrailer("init_node") != null) Space.Space else Space.None; | |
| 2280 | const s = if (var_decl.getInitNode() != null) Space.Space else Space.None; | |
| 2281 | 2281 | try renderToken(tree, stream, rparen, indent, start_col, s); // ) |
| 2282 | 2282 | } |
| 2283 | 2283 | |
| 2284 | if (var_decl.getTrailer("init_node")) |init_node| { | |
| 2284 | if (var_decl.getInitNode()) |init_node| { | |
| 2285 | 2285 | const s = if (init_node.tag == .MultilineStringLiteral) Space.None else Space.Space; |
| 2286 | try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, indent, start_col, s); // = | |
| 2286 | try renderToken(tree, stream, var_decl.getEqToken().?, indent, start_col, s); // = | |
| 2287 | 2287 | try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None); |
| 2288 | 2288 | } |
| 2289 | 2289 |
src-self-hosted/Module.zig+23-23| ... | ... | @@ -1256,8 +1256,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1256 | 1256 | }; |
| 1257 | 1257 | defer fn_type_scope.instructions.deinit(self.gpa); |
| 1258 | 1258 | |
| 1259 | decl.is_pub = fn_proto.getTrailer("visib_token") != null; | |
| 1260 | const body_node = fn_proto.getTrailer("body_node") orelse | |
| 1259 | decl.is_pub = fn_proto.getVisibToken() != null; | |
| 1260 | const body_node = fn_proto.getBodyNode() orelse | |
| 1261 | 1261 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); |
| 1262 | 1262 | |
| 1263 | 1263 | const param_decls = fn_proto.params(); |
| ... | ... | @@ -1276,19 +1276,19 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1276 | 1276 | }; |
| 1277 | 1277 | param_types[i] = try astgen.expr(self, &fn_type_scope.base, type_type_rl, param_type_node); |
| 1278 | 1278 | } |
| 1279 | if (fn_proto.getTrailer("var_args_token")) |var_args_token| { | |
| 1279 | if (fn_proto.getVarArgsToken()) |var_args_token| { | |
| 1280 | 1280 | return self.failTok(&fn_type_scope.base, var_args_token, "TODO implement var args", .{}); |
| 1281 | 1281 | } |
| 1282 | if (fn_proto.getTrailer("lib_name")) |lib_name| { | |
| 1282 | if (fn_proto.getLibName()) |lib_name| { | |
| 1283 | 1283 | return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{}); |
| 1284 | 1284 | } |
| 1285 | if (fn_proto.getTrailer("align_expr")) |align_expr| { | |
| 1285 | if (fn_proto.getAlignExpr()) |align_expr| { | |
| 1286 | 1286 | return self.failNode(&fn_type_scope.base, align_expr, "TODO implement function align expression", .{}); |
| 1287 | 1287 | } |
| 1288 | if (fn_proto.getTrailer("section_expr")) |sect_expr| { | |
| 1288 | if (fn_proto.getSectionExpr()) |sect_expr| { | |
| 1289 | 1289 | return self.failNode(&fn_type_scope.base, sect_expr, "TODO implement function section expression", .{}); |
| 1290 | 1290 | } |
| 1291 | if (fn_proto.getTrailer("callconv_expr")) |callconv_expr| { | |
| 1291 | if (fn_proto.getCallconvExpr()) |callconv_expr| { | |
| 1292 | 1292 | return self.failNode( |
| 1293 | 1293 | &fn_type_scope.base, |
| 1294 | 1294 | callconv_expr, |
| ... | ... | @@ -1430,10 +1430,10 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1430 | 1430 | self.bin_file.freeDecl(decl); |
| 1431 | 1431 | } |
| 1432 | 1432 | |
| 1433 | if (fn_proto.getTrailer("extern_export_inline_token")) |maybe_export_token| { | |
| 1433 | if (fn_proto.getExternExportInlineToken()) |maybe_export_token| { | |
| 1434 | 1434 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { |
| 1435 | 1435 | const export_src = tree.token_locs[maybe_export_token].start; |
| 1436 | const name_loc = tree.token_locs[fn_proto.getTrailer("name_token").?]; | |
| 1436 | const name_loc = tree.token_locs[fn_proto.getNameToken().?]; | |
| 1437 | 1437 | const name = tree.tokenSliceLoc(name_loc); |
| 1438 | 1438 | // The scope needs to have the decl in it. |
| 1439 | 1439 | try self.analyzeExport(&block_scope.base, export_src, name, decl); |
| ... | ... | @@ -1460,37 +1460,37 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1460 | 1460 | }; |
| 1461 | 1461 | defer block_scope.instructions.deinit(self.gpa); |
| 1462 | 1462 | |
| 1463 | decl.is_pub = var_decl.getTrailer("visib_token") != null; | |
| 1463 | decl.is_pub = var_decl.getVisibToken() != null; | |
| 1464 | 1464 | const is_extern = blk: { |
| 1465 | const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse | |
| 1465 | const maybe_extern_token = var_decl.getExternExportToken() orelse | |
| 1466 | 1466 | break :blk false; |
| 1467 | 1467 | if (tree.token_ids[maybe_extern_token] != .Keyword_extern) break :blk false; |
| 1468 | if (var_decl.getTrailer("init_node")) |some| { | |
| 1468 | if (var_decl.getInitNode()) |some| { | |
| 1469 | 1469 | return self.failNode(&block_scope.base, some, "extern variables have no initializers", .{}); |
| 1470 | 1470 | } |
| 1471 | 1471 | break :blk true; |
| 1472 | 1472 | }; |
| 1473 | if (var_decl.getTrailer("lib_name")) |lib_name| { | |
| 1473 | if (var_decl.getLibName()) |lib_name| { | |
| 1474 | 1474 | assert(is_extern); |
| 1475 | 1475 | return self.failNode(&block_scope.base, lib_name, "TODO implement function library name", .{}); |
| 1476 | 1476 | } |
| 1477 | 1477 | const is_mutable = tree.token_ids[var_decl.mut_token] == .Keyword_var; |
| 1478 | const is_threadlocal = if (var_decl.getTrailer("thread_local_token")) |some| blk: { | |
| 1478 | const is_threadlocal = if (var_decl.getThreadLocalToken()) |some| blk: { | |
| 1479 | 1479 | if (!is_mutable) { |
| 1480 | 1480 | return self.failTok(&block_scope.base, some, "threadlocal variable cannot be constant", .{}); |
| 1481 | 1481 | } |
| 1482 | 1482 | break :blk true; |
| 1483 | 1483 | } else false; |
| 1484 | assert(var_decl.getTrailer("comptime_token") == null); | |
| 1485 | if (var_decl.getTrailer("align_node")) |align_expr| { | |
| 1484 | assert(var_decl.getComptimeToken() == null); | |
| 1485 | if (var_decl.getAlignNode()) |align_expr| { | |
| 1486 | 1486 | return self.failNode(&block_scope.base, align_expr, "TODO implement function align expression", .{}); |
| 1487 | 1487 | } |
| 1488 | if (var_decl.getTrailer("section_node")) |sect_expr| { | |
| 1488 | if (var_decl.getSectionNode()) |sect_expr| { | |
| 1489 | 1489 | return self.failNode(&block_scope.base, sect_expr, "TODO implement function section expression", .{}); |
| 1490 | 1490 | } |
| 1491 | 1491 | |
| 1492 | 1492 | const explicit_type = blk: { |
| 1493 | const type_node = var_decl.getTrailer("type_node") orelse | |
| 1493 | const type_node = var_decl.getTypeNode() orelse | |
| 1494 | 1494 | break :blk null; |
| 1495 | 1495 | |
| 1496 | 1496 | // Temporary arena for the zir instructions. |
| ... | ... | @@ -1517,7 +1517,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1517 | 1517 | }; |
| 1518 | 1518 | |
| 1519 | 1519 | var var_type: Type = undefined; |
| 1520 | const value: ?Value = if (var_decl.getTrailer("init_node")) |init_node| blk: { | |
| 1520 | const value: ?Value = if (var_decl.getInitNode()) |init_node| blk: { | |
| 1521 | 1521 | var gen_scope_arena = std.heap.ArenaAllocator.init(self.gpa); |
| 1522 | 1522 | defer gen_scope_arena.deinit(); |
| 1523 | 1523 | var gen_scope: Scope.GenZIR = .{ |
| ... | ... | @@ -1602,7 +1602,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1602 | 1602 | decl.analysis = .complete; |
| 1603 | 1603 | decl.generation = self.generation; |
| 1604 | 1604 | |
| 1605 | if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| { | |
| 1605 | if (var_decl.getExternExportToken()) |maybe_export_token| { | |
| 1606 | 1606 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { |
| 1607 | 1607 | const export_src = tree.token_locs[maybe_export_token].start; |
| 1608 | 1608 | const name_loc = tree.token_locs[var_decl.name_token]; |
| ... | ... | @@ -1768,7 +1768,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1768 | 1768 | for (decls) |src_decl, decl_i| { |
| 1769 | 1769 | if (src_decl.cast(ast.Node.FnProto)) |fn_proto| { |
| 1770 | 1770 | // We will create a Decl for it regardless of analysis status. |
| 1771 | const name_tok = fn_proto.getTrailer("name_token") orelse { | |
| 1771 | const name_tok = fn_proto.getNameToken() orelse { | |
| 1772 | 1772 | @panic("TODO missing function name"); |
| 1773 | 1773 | }; |
| 1774 | 1774 | |
| ... | ... | @@ -1804,7 +1804,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1804 | 1804 | } else { |
| 1805 | 1805 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); |
| 1806 | 1806 | root_scope.decls.appendAssumeCapacity(new_decl); |
| 1807 | if (fn_proto.getTrailer("extern_export_inline_token")) |maybe_export_token| { | |
| 1807 | if (fn_proto.getExternExportInlineToken()) |maybe_export_token| { | |
| 1808 | 1808 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { |
| 1809 | 1809 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 1810 | 1810 | } |
| ... | ... | @@ -1831,7 +1831,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1831 | 1831 | } else { |
| 1832 | 1832 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); |
| 1833 | 1833 | root_scope.decls.appendAssumeCapacity(new_decl); |
| 1834 | if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| { | |
| 1834 | if (var_decl.getExternExportToken()) |maybe_export_token| { | |
| 1835 | 1835 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { |
| 1836 | 1836 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 1837 | 1837 | } |
src-self-hosted/astgen.zig+6-6| ... | ... | @@ -451,16 +451,16 @@ fn varDecl( |
| 451 | 451 | block_arena: *Allocator, |
| 452 | 452 | ) InnerError!*Scope { |
| 453 | 453 | // TODO implement detection of shadowing |
| 454 | if (node.getTrailer("comptime_token")) |comptime_token| { | |
| 454 | if (node.getComptimeToken()) |comptime_token| { | |
| 455 | 455 | return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{}); |
| 456 | 456 | } |
| 457 | if (node.getTrailer("align_node")) |align_node| { | |
| 457 | if (node.getAlignNode()) |align_node| { | |
| 458 | 458 | return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{}); |
| 459 | 459 | } |
| 460 | 460 | const tree = scope.tree(); |
| 461 | 461 | const name_src = tree.token_locs[node.name_token].start; |
| 462 | 462 | const ident_name = try identifierTokenString(mod, scope, node.name_token); |
| 463 | const init_node = node.getTrailer("init_node") orelse | |
| 463 | const init_node = node.getInitNode() orelse | |
| 464 | 464 | return mod.fail(scope, name_src, "variables must be initialized", .{}); |
| 465 | 465 | |
| 466 | 466 | switch (tree.token_ids[node.mut_token]) { |
| ... | ... | @@ -469,7 +469,7 @@ fn varDecl( |
| 469 | 469 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 470 | 470 | // the variable, no memory location needed. |
| 471 | 471 | const result_loc = if (nodeMayNeedMemoryLocation(init_node)) r: { |
| 472 | if (node.getTrailer("type_node")) |type_node| { | |
| 472 | if (node.getTypeNode()) |type_node| { | |
| 473 | 473 | const type_inst = try typeExpr(mod, scope, type_node); |
| 474 | 474 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst); |
| 475 | 475 | break :r ResultLoc{ .ptr = alloc }; |
| ... | ... | @@ -478,7 +478,7 @@ fn varDecl( |
| 478 | 478 | break :r ResultLoc{ .inferred_ptr = alloc }; |
| 479 | 479 | } |
| 480 | 480 | } else r: { |
| 481 | if (node.getTrailer("type_node")) |type_node| | |
| 481 | if (node.getTypeNode()) |type_node| | |
| 482 | 482 | break :r ResultLoc{ .ty = try typeExpr(mod, scope, type_node) } |
| 483 | 483 | else |
| 484 | 484 | break :r .none; |
| ... | ... | @@ -494,7 +494,7 @@ fn varDecl( |
| 494 | 494 | return &sub_scope.base; |
| 495 | 495 | }, |
| 496 | 496 | .Keyword_var => { |
| 497 | const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTrailer("type_node")) |type_node| a: { | |
| 497 | const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTypeNode()) |type_node| a: { | |
| 498 | 498 | const type_inst = try typeExpr(mod, scope, type_node); |
| 499 | 499 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst); |
| 500 | 500 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; |
src-self-hosted/codegen.zig+1-1| ... | ... | @@ -439,7 +439,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 439 | 439 | if (module_fn.owner_decl.scope.cast(Module.Scope.File)) |scope_file| { |
| 440 | 440 | const tree = scope_file.contents.tree; |
| 441 | 441 | const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?; |
| 442 | const block = fn_proto.body().?.castTag(.Block).?; | |
| 442 | const block = fn_proto.getBodyNode().?.castTag(.Block).?; | |
| 443 | 443 | const lbrace_src = tree.token_locs[block.lbrace].start; |
| 444 | 444 | const rbrace_src = tree.token_locs[block.rbrace].start; |
| 445 | 445 | break :blk .{ .lbrace_src = lbrace_src, .rbrace_src = rbrace_src, .source = tree.source }; |
src-self-hosted/link/Elf.zig+2-2| ... | ... | @@ -1661,7 +1661,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 1661 | 1661 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 1662 | 1662 | // lookup table. Currently this involves scanning over the source code for newlines. |
| 1663 | 1663 | const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; |
| 1664 | const block = fn_proto.body().?.castTag(.Block).?; | |
| 1664 | const block = fn_proto.getBodyNode().?.castTag(.Block).?; | |
| 1665 | 1665 | const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); |
| 1666 | 1666 | break :blk @intCast(u28, line_delta); |
| 1667 | 1667 | } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| { |
| ... | ... | @@ -2160,7 +2160,7 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec |
| 2160 | 2160 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 2161 | 2161 | // lookup table. Currently this involves scanning over the source code for newlines. |
| 2162 | 2162 | const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; |
| 2163 | const block = fn_proto.body().?.castTag(.Block).?; | |
| 2163 | const block = fn_proto.getBodyNode().?.castTag(.Block).?; | |
| 2164 | 2164 | const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); |
| 2165 | 2165 | const casted_line_off = @intCast(u28, line_delta); |
| 2166 | 2166 |
src-self-hosted/translate_c.zig+5-5| ... | ... | @@ -675,7 +675,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 675 | 675 | } |
| 676 | 676 | |
| 677 | 677 | const body_node = try block_scope.complete(rp.c); |
| 678 | proto_node.setTrailer("body_node", body_node); | |
| 678 | proto_node.setBodyNode(body_node); | |
| 679 | 679 | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| 680 | 680 | } |
| 681 | 681 | |
| ... | ... | @@ -4493,7 +4493,7 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a |
| 4493 | 4493 | const block_lbrace = try appendToken(c, .LBrace, "{"); |
| 4494 | 4494 | |
| 4495 | 4495 | const return_kw = try appendToken(c, .Keyword_return, "return"); |
| 4496 | const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.getTrailer("init_node").?); | |
| 4496 | const unwrap_expr = try transCreateNodeUnwrapNull(c, ref.cast(ast.Node.VarDecl).?.getInitNode().?); | |
| 4497 | 4497 | |
| 4498 | 4498 | const call_expr = try c.createCall(unwrap_expr, fn_params.items.len); |
| 4499 | 4499 | const call_params = call_expr.params(); |
| ... | ... | @@ -6361,7 +6361,7 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node { |
| 6361 | 6361 | const ident = node.castTag(.Identifier).?; |
| 6362 | 6362 | if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| { |
| 6363 | 6363 | if (value.cast(ast.Node.VarDecl)) |var_decl| |
| 6364 | return getContainer(c, var_decl.getTrailer("init_node").?); | |
| 6364 | return getContainer(c, var_decl.getInitNode().?); | |
| 6365 | 6365 | } |
| 6366 | 6366 | }, |
| 6367 | 6367 | |
| ... | ... | @@ -6390,7 +6390,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 6390 | 6390 | if (ref.castTag(.Identifier)) |ident| { |
| 6391 | 6391 | if (c.global_scope.sym_table.get(tokenSlice(c, ident.token))) |value| { |
| 6392 | 6392 | if (value.cast(ast.Node.VarDecl)) |var_decl| { |
| 6393 | if (var_decl.getTrailer("type_node")) |ty| | |
| 6393 | if (var_decl.getTypeNode()) |ty| | |
| 6394 | 6394 | return getContainer(c, ty); |
| 6395 | 6395 | } |
| 6396 | 6396 | } |
| ... | ... | @@ -6412,7 +6412,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 6412 | 6412 | } |
| 6413 | 6413 | |
| 6414 | 6414 | fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto { |
| 6415 | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getTrailer("init_node").? else return null; | |
| 6415 | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getInitNode().? else return null; | |
| 6416 | 6416 | if (getContainerTypeOf(c, init)) |ty_node| { |
| 6417 | 6417 | if (ty_node.castTag(.OptionalType)) |prefix| { |
| 6418 | 6418 | if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| { |