stage2: outline container types

This commit is contained in:
Vexu 2020-11-15 13:03:48 +02:00
parent 643f526cd1
commit f173d078c7
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
6 changed files with 298 additions and 3 deletions

View File

@ -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);
}

View File

@ -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");
};
};

55
src/type/Enum.zig Normal file
View File

@ -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(),
}
}

57
src/type/Struct.zig Normal file
View File

@ -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,)

57
src/type/Union.zig Normal file
View File

@ -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,)

View File

@ -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 },