Commit f173d078c7
Changed files (6)
src/type/Enum.zig
@@ -0,0 +1,55 @@
+const std = @import("std");
+const Value = @import("../value.zig").Value;
+const Type = @import("../type.zig").Type;
+const Module = @import("../Module.zig");
+const Scope = Module.Scope;
+
+base: Type.Payload = .{ .tag = .@"enum" },
+
+analysis: union(enum) {
+ queued: Zir,
+ in_progress,
+ resolved: Size,
+ failed,
+},
+
+pub const Field = struct {
+ value: Value,
+};
+
+pub const Zir = struct {
+ body: zir.Module.Body,
+ inst: *zir.Inst,
+ arena: std.heap.ArenaAllocator.State,
+};
+
+pub const Size = struct {
+ is_zero_bits: bool,
+ alignment: u32,
+ size: u32,
+ fields: std.AutoArrayHashMap([]const u8, Field),
+};
+
+pub fn resolve(self: *Enum, mod: *Module, scope: *Scope) !void {
+ const zir = switch (self.analysis) {
+ .failed => return error.AnalysisFail,
+ .resolved => return,
+ .in_progress => {
+ return mod.fail(scope, src, "enum '{}' depends on itself", .{enum_name});
+ },
+ .queued => |zir| zir,
+ };
+ self.analysis = .in_progress;
+
+ // TODO
+}
+
+// TODO should this resolve the type or assert that it has already been resolved?
+pub fn abiAlignment(self: *Enum) u32 {
+ switch (self.analysis) {
+ .queued => unreachable, // alignment has not been resolved
+ .in_progress => unreachable, // alignment has not been resolved
+ .failed => unreachable, // type resolution failed
+ .resolved => |r| return r.tag_type.abiAlignment(),
+ }
+}
src/type/Struct.zig
@@ -0,0 +1,57 @@
+const std = @import("std");
+const Value = @import("../value.zig").Value;
+const Type = @import("../type.zig").Type;
+const Module = @import("../Module.zig");
+const Scope = Module.Scope;
+
+base: Type.Payload = .{ .tag = .@"struct" },
+
+analysis: union(enum) {
+ queued: Zir,
+ zero_bits_in_progress,
+ zero_bits: Zero,
+ in_progress,
+ alignment: Align,
+ resolved: Size,
+ failed,
+},
+scope: Scope.Container,
+
+pub const Field = struct {
+ value: Value,
+};
+
+pub const Zir = struct {
+ body: zir.Module.Body,
+ inst: *zir.Inst,
+ arena: std.heap.ArenaAllocator.State,
+};
+
+pub const Zero = struct {
+ is_zero_bits: bool,
+ fields: std.AutoArrayHashMap([]const u8, Field),
+};
+
+pub const Size = struct {
+ is_zero_bits: bool,
+ alignment: u32,
+ size: u32,
+ fields: std.AutoArrayHashMap([]const u8, Field),
+};
+
+pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void {
+ const zir = switch (self.analysis) {
+ .failed => return error.AnalysisFail,
+ .zero_bits_in_progress => {
+ return mod.fail(scope, src, "union '{}' depends on itself", .{});
+ },
+ .queued => |zir| zir,
+ else => return,
+ };
+
+ self.analysis = .zero_bits_in_progress;
+
+ // TODO
+}
+
+pub fn resolveSize(self: *Enum,)
\ No newline at end of file
src/type/Union.zig
@@ -0,0 +1,57 @@
+const std = @import("std");
+const Value = @import("../value.zig").Value;
+const Type = @import("../type.zig").Type;
+const Module = @import("../Module.zig");
+const Scope = Module.Scope;
+
+base: Type.Payload = .{ .tag = .@"struct" },
+
+analysis: union(enum) {
+ queued: Zir,
+ zero_bits_in_progress,
+ zero_bits: Zero,
+ in_progress,
+ alignment: Align,
+ resolved: Size,
+ failed,
+},
+scope: Scope.Container,
+
+pub const Field = struct {
+ value: Value,
+};
+
+pub const Zir = struct {
+ body: zir.Module.Body,
+ inst: *zir.Inst,
+ arena: std.heap.ArenaAllocator.State,
+};
+
+pub const Zero = struct {
+ is_zero_bits: bool,
+ fields: std.AutoArrayHashMap([]const u8, Field),
+};
+
+pub const Size = struct {
+ is_zero_bits: bool,
+ alignment: u32,
+ size: u32,
+ fields: std.AutoArrayHashMap([]const u8, Field),
+};
+
+pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void {
+ const zir = switch (self.analysis) {
+ .failed => return error.AnalysisFail,
+ .zero_bits_in_progress => {
+ return mod.fail(scope, src, "union '{}' depends on itself", .{});
+ },
+ .queued => |zir| zir,
+ else => return,
+ };
+
+ self.analysis = .zero_bits_in_progress;
+
+ // TODO
+}
+
+pub fn resolveSize(self: *Enum,)
\ No newline at end of file
src/Module.zig
@@ -428,7 +428,7 @@ pub const Scope = struct {
};
}
- /// Asserts the scope has a parent which is a ZIRModule, Contaienr or File and
+ /// Asserts the scope has a parent which is a ZIRModule, Container or File and
/// returns the sub_file_path field.
pub fn subFilePath(base: *Scope) []const u8 {
switch (base.tag) {
@@ -1515,6 +1515,7 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void
// an incremental update. This code handles both cases.
const tree = try self.getAstTree(container_scope);
const decls = tree.root_node.decls();
+ // const decls = container_scope.root_node.decls();
try self.comp.work_queue.ensureUnusedCapacity(decls.len);
try container_scope.decls.ensureCapacity(self.gpa, decls.len);
@@ -2272,6 +2273,33 @@ pub fn createAnonymousDecl(
return new_decl;
}
+fn createContainerDecl(self: *Module, scope: *Scope, container_node: *std.zig.ast.Node.ContainerDecl) !*Decl {
+ const name = try self.getAnonTypeName(scope, container_node.kind_token);
+ defer self.gpa.free(name);
+ const name_hash = scope.namespace().fullyQualifiedNameHash(name);
+ const src_hash: std.zig.SrcHash = undefined;
+ const new_decl = try self.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash);
+ const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
+
+ decl_arena_state.* = decl_arena.state;
+ new_decl.generation = self.generation;
+
+ return new_decl;
+}
+
+fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 {
+ const container = scope.getContainer();
+ const tree = self.getAstTree(container);
+ const base_name = switch (tree.token_ids[base_token]) {
+ .Keyword_struct => "struct",
+ .Keyword_enum => "enum",
+ .Keyword_union => "union",
+ else => unreachable,
+ };
+ const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]);
+ return std.fmt.allocPrint(self.gpa, "{}:{}:{}", .{ base_name, loc.line, loc.column });
+}
+
fn getNextAnonNameIndex(self: *Module) usize {
return @atomicRmw(usize, &self.next_anon_name_index, .Add, 1, .Monotonic);
}
src/type.zig
@@ -90,7 +90,9 @@ pub const Type = extern union {
.anyframe_T, .@"anyframe" => return .AnyFrame,
- .empty_struct => return .Struct,
+ .@"struct", .empty_struct => return .Struct,
+ .@"enum" => return .Enum,
+ .@"union" => return .Union,
}
}
@@ -442,6 +444,11 @@ pub const Type = extern union {
.error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
.error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle),
.empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct),
+
+ // memory managed by the decl
+ .@"enum" => return self,
+ .@"struct" => return self,
+ .@"union" => return self,
}
}
@@ -673,6 +680,10 @@ pub const Type = extern union {
const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise);
return out_stream.print("error{{{}}}", .{payload.name});
},
+ // TODO improve
+ .@"enum" => return out_stream.writeAll("enum {}"),
+ .@"struct" => return out_stream.writeAll("struct {}"),
+ .@"union" => return out_stream.writeAll("union {}"),
}
unreachable;
}
@@ -784,6 +795,10 @@ pub const Type = extern union {
return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits();
},
+ .@"enum" => @panic("TODO"),
+ .@"struct" => @panic("TODO"),
+ .@"union" => @panic("TODO"),
+
.c_void,
.void,
.type,
@@ -908,6 +923,10 @@ pub const Type = extern union {
@panic("TODO abiAlignment error union");
},
+ .@"enum" => self.cast(Payload.Enum).?.abiAlignment(),
+ .@"struct" => @panic("TODO"),
+ .@"union" => @panic("TODO"),
+
.c_void,
.void,
.type,
@@ -1050,6 +1069,10 @@ pub const Type = extern union {
}
@panic("TODO abiSize error union");
},
+
+ .@"enum" => @panic("TODO"),
+ .@"struct" => @panic("TODO"),
+ .@"union" => @panic("TODO"),
};
}
@@ -1117,6 +1140,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.single_const_pointer,
@@ -1192,6 +1218,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.const_slice,
@@ -1264,6 +1293,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.single_const_pointer,
@@ -1345,6 +1377,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.pointer => {
@@ -1421,6 +1456,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.pointer => {
@@ -1539,6 +1577,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
.array => self.cast(Payload.Array).?.elem_type,
@@ -1667,6 +1708,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
.array => self.cast(Payload.Array).?.len,
@@ -1733,6 +1777,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
.single_const_pointer,
@@ -1816,6 +1863,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.int_signed,
@@ -1891,6 +1941,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.int_unsigned,
@@ -1956,6 +2009,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
.int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
@@ -2039,6 +2095,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
.usize,
@@ -2151,6 +2210,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
};
}
@@ -2229,6 +2291,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
}
}
@@ -2306,6 +2371,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
}
}
@@ -2383,6 +2451,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
};
}
@@ -2457,6 +2528,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
};
}
@@ -2531,6 +2605,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> unreachable,
};
}
@@ -2605,6 +2682,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> false,
};
}
@@ -2664,6 +2744,10 @@ pub const Type = extern union {
.error_set_single,
=> return null,
+ .@"enum" => @panic("TODO onePossibleValue enum"),
+ .@"struct" => @panic("TODO onePossibleValue struct"),
+ .@"union" => @panic("TODO onePossibleValue union"),
+
.empty_struct => return Value.initTag(.empty_struct_value),
.void => return Value.initTag(.void_value),
.noreturn => return Value.initTag(.unreachable_value),
@@ -2773,6 +2857,9 @@ pub const Type = extern union {
.error_set,
.error_set_single,
.empty_struct,
+ .@"enum",
+ .@"struct",
+ .@"union",
=> return false,
.c_const_pointer,
@@ -2861,6 +2948,9 @@ pub const Type = extern union {
=> unreachable,
.empty_struct => self.cast(Type.Payload.EmptyStruct).?.scope,
+ .@"enum" => &self.cast(Type.Payload.Enum).?.scope,
+ .@"struct" => &self.cast(Type.Payload.Struct).?.scope,
+ .@"union" => &self.cast(Type.Payload.Union).?.scope,
};
}
@@ -3012,6 +3102,9 @@ pub const Type = extern union {
error_set,
error_set_single,
empty_struct,
+ @"enum",
+ @"struct",
+ @"union",
pub const last_no_payload_tag = Tag.const_slice_u8;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -3127,6 +3220,10 @@ pub const Type = extern union {
scope: *Module.Scope.Container,
};
+
+ pub const Enum = @import("value/Enum.zig");
+ pub const Struct = @import("value/Struct.zig");
+ pub const Union = @import("value/Union.zig");
};
};
src/value.zig
@@ -252,7 +252,7 @@ pub const Value = extern union {
.@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
// memory is managed by the declaration
- .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
+ .error_set => return self,
}
}
@@ -1865,6 +1865,7 @@ pub const Value = extern union {
val: f128,
};
+ // TODO move to type.zig
pub const ErrorSet = struct {
base: Payload = .{ .tag = .error_set },