From f173d078c780c9946742c4ce686ccd0dccdb7e98 Mon Sep 17 00:00:00 2001 From: Vexu Date: Sun, 15 Nov 2020 13:03:48 +0200 Subject: stage2: outline container types --- src/type.zig | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) (limited to 'src/type.zig') diff --git a/src/type.zig b/src/type.zig index 31f84cdec4..02a5245e40 100644 --- a/src/type.zig +++ b/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"); }; }; -- cgit v1.2.3 From c1e19f4c0a62047c26d5baabe25887e533cc739f Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 16 Nov 2020 20:45:53 +0200 Subject: stage2: initial container astgen --- src/Module.zig | 32 +++++++--- src/astgen.zig | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/type.zig | 8 +-- src/type/Enum.zig | 12 ++-- src/type/Struct.zig | 11 ++-- src/type/Union.zig | 9 ++- src/zir.zig | 25 ++++---- src/zir_sema.zig | 8 +++ 8 files changed, 228 insertions(+), 41 deletions(-) (limited to 'src/type.zig') diff --git a/src/Module.zig b/src/Module.zig index 3e6be31be1..831aedf054 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -469,12 +469,12 @@ pub const Scope = struct { } } - pub fn getOwnerPkg(base: *Scope) *Package { + pub fn getFileScope(base: *Scope) *Scope.File { var cur = base; while (true) { cur = switch (cur.tag) { - .container => return @fieldParentPtr(Container, "base", cur).file_scope.pkg, - .file => return @fieldParentPtr(File, "base", cur).pkg, + .container => return @fieldParentPtr(Container, "base", cur).file_scope, + .file => return @fieldParentPtr(File, "base", cur), .zir_module => unreachable, // TODO are zir modules allowed to import packages? .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent, .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, @@ -550,7 +550,7 @@ pub const Scope = struct { file_scope: *Scope.File, /// Direct children of the file. - decls: std.AutoArrayHashMapUnmanaged(*Decl, void), + decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, ty: Type, pub fn deinit(self: *Container, gpa: *Allocator) void { @@ -2273,8 +2273,15 @@ 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); +pub fn createContainerDecl( + self: *Module, + scope: *Scope, + base_token: std.zig.ast.TokenIndex, + decl_arena: *std.heap.ArenaAllocator, + typed_value: TypedValue, +) !*Decl { + const scope_decl = scope.decl().?; + const name = try self.getAnonTypeName(scope, base_token); defer self.gpa.free(name); const name_hash = scope.namespace().fullyQualifiedNameHash(name); const src_hash: std.zig.SrcHash = undefined; @@ -2282,18 +2289,25 @@ fn createContainerDecl(self: *Module, scope: *Scope, container_node: *std.zig.as const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); decl_arena_state.* = decl_arena.state; + new_decl.typed_value = .{ + .most_recent = .{ + .typed_value = typed_value, + .arena = decl_arena_state, + }, + }; + new_decl.analysis = .complete; 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 tree = scope.tree(); const base_name = switch (tree.token_ids[base_token]) { .Keyword_struct => "struct", .Keyword_enum => "enum", .Keyword_union => "union", + .Keyword_opaque => "opaque", else => unreachable, }; const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]); @@ -2487,7 +2501,7 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, } pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) !*Scope.File { - const cur_pkg = scope.getOwnerPkg(); + const cur_pkg = scope.getFileScope().pkg; const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse "."; const found_pkg = cur_pkg.table.get(target_string); diff --git a/src/astgen.zig b/src/astgen.zig index 37b1eab9a6..37436373f0 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -281,6 +281,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?), .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?), .Switch => return switchExpr(mod, scope, rl, node.castTag(.Switch).?), + .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?), .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}), @@ -294,7 +295,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .Continue => return mod.failNode(scope, node, "TODO implement astgen.expr for .Continue", .{}), .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}), .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}), - .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}), .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}), } } @@ -765,6 +765,168 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si return rlWrapPtr(mod, scope, rl, try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand)); } +fn containerField(mod: *Module, scope: *Scope, node: *ast.Node.ContainerField) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.firstToken()].start; + const name = try identifierTokenString(mod, scope, node.name_token); + + if (node.comptime_token == null and node.value_expr == null and node.align_expr == null) { + if (node.type_expr) |some| { + const ty = try typeExpr(mod, scope, some); + return addZIRInst(mod, scope, src, zir.Inst.ContainerFieldTyped, .{ + .bytes = name, + .ty = ty, + }, .{}); + } else { + return addZIRInst(mod, scope, src, zir.Inst.ContainerFieldNamed, .{ + .bytes = name, + }, .{}); + } + } + + const ty = if (node.type_expr) |some| try typeExpr(mod, scope, some) else null; + const alignment = if (node.align_expr) |some| try expr(mod, scope, .none, some) else null; + const init = if (node.value_expr) |some| try expr(mod, scope, .none, some) else null; + + return addZIRInst(mod, scope, src, zir.Inst.ContainerField, .{ + .bytes = name, + }, .{ + .ty = ty, + .init = init, + .alignment = alignment, + .is_comptime = node.comptime_token != null, + }); +} + +fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ContainerDecl) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.kind_token].start; + + var gen_scope: Scope.GenZIR = .{ + .parent = scope, + .decl = scope.decl().?, + .arena = scope.arena(), + .instructions = .{}, + }; + defer gen_scope.instructions.deinit(mod.gpa); + + var fields = std.ArrayList(*zir.Inst).init(mod.gpa); + defer fields.deinit(); + + for (node.fieldsAndDecls()) |fd| { + if (fd.castTag(.ContainerField)) |f| { + try fields.append(try containerField(mod, &gen_scope.base, f)); + } + } + + var decl_arena = std.heap.ArenaAllocator.init(mod.gpa); + errdefer decl_arena.deinit(); + const arena = &decl_arena.allocator; + + var layout: std.builtin.TypeInfo.ContainerLayout = .Auto; + if (node.layout_token) |some| switch (tree.token_ids[some]) { + .Keyword_extern => layout = .Extern, + .Keyword_packed => layout = .Packed, + else => unreachable, + }; + + const container_type = switch (tree.token_ids[node.kind_token]) { + .Keyword_enum => blk: { + const tag_type: ?*zir.Inst = switch (node.init_arg_expr) { + .Type => |t| try typeExpr(mod, &gen_scope.base, t), + .None => null, + .Enum => unreachable, + }; + const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.EnumType, .{ + .fields = try arena.dupe(*zir.Inst, fields.items), + }, .{ + .layout = layout, + .tag_type = tag_type, + }); + const enum_type = try arena.create(Type.Payload.Enum); + enum_type.* = .{ + .analysis = .{ + .queued = .{ + .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) }, + .inst = inst, + }, + }, + .scope = .{ + .file_scope = scope.getFileScope(), + .ty = Type.initPayload(&enum_type.base), + }, + }; + break :blk Type.initPayload(&enum_type.base); + }, + .Keyword_struct => blk: { + assert(node.init_arg_expr == .None); + const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{ + .fields = try arena.dupe(*zir.Inst, fields.items), + }, .{ + .layout = layout, + }); + const struct_type = try arena.create(Type.Payload.Struct); + struct_type.* = .{ + .analysis = .{ + .queued = .{ + .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) }, + .inst = inst, + }, + }, + .scope = .{ + .file_scope = scope.getFileScope(), + .ty = Type.initPayload(&struct_type.base), + }, + }; + break :blk Type.initPayload(&struct_type.base); + }, + .Keyword_union => blk: { + const init_inst = switch (node.init_arg_expr) { + .Enum => |e| if (e) |t| try typeExpr(mod, &gen_scope.base, t) else null, + .None => null, + .Type => |t| try typeExpr(mod, &gen_scope.base, t), + }; + const init_kind: zir.Inst.UnionType.InitKind = switch (node.init_arg_expr) { + .Enum => .enum_type, + .None => .none, + .Type => .tag_type, + }; + const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.UnionType, .{ + .fields = try arena.dupe(*zir.Inst, fields.items), + }, .{ + .layout = layout, + .init_kind = init_kind, + .init_inst = init_inst, + }); + const union_type = try arena.create(Type.Payload.Union); + union_type.* = .{ + .analysis = .{ + .queued = .{ + .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) }, + .inst = inst, + }, + }, + .scope = .{ + .file_scope = scope.getFileScope(), + .ty = Type.initPayload(&union_type.base), + }, + }; + break :blk Type.initPayload(&union_type.base); + }, + .Keyword_opaque => return mod.fail(scope, src, "TODO opaque containers", .{}), + else => unreachable, + }; + const type_payload = try arena.create(Value.Payload.Ty); + type_payload.* = .{ + .ty = container_type, + }; + const decl = try mod.createContainerDecl(scope, node.kind_token, &decl_arena, .{ + .ty = Type.initTag(.type), + .val = Value.initPayload(&type_payload.base), + }); + return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{})); +} + fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst { const tree = scope.tree(); const src = tree.token_locs[node.error_token].start; diff --git a/src/type.zig b/src/type.zig index 02a5245e40..0cde8644fd 100644 --- a/src/type.zig +++ b/src/type.zig @@ -923,7 +923,7 @@ pub const Type = extern union { @panic("TODO abiAlignment error union"); }, - .@"enum" => self.cast(Payload.Enum).?.abiAlignment(), + .@"enum" => self.cast(Payload.Enum).?.abiAlignment(target), .@"struct" => @panic("TODO"), .@"union" => @panic("TODO"), @@ -3221,9 +3221,9 @@ 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"); + pub const Enum = @import("type/Enum.zig"); + pub const Struct = @import("type/Struct.zig"); + pub const Union = @import("type/Union.zig"); }; }; diff --git a/src/type/Enum.zig b/src/type/Enum.zig index 0042ddc8bf..1d937df7ce 100644 --- a/src/type/Enum.zig +++ b/src/type/Enum.zig @@ -1,8 +1,10 @@ const std = @import("std"); +const zir = @import("../zir.zig"); const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; const Module = @import("../Module.zig"); const Scope = Module.Scope; +const Enum = @This(); base: Type.Payload = .{ .tag = .@"enum" }, @@ -12,6 +14,7 @@ analysis: union(enum) { resolved: Size, failed, }, +scope: Scope.Container, pub const Field = struct { value: Value, @@ -20,13 +23,10 @@ pub const Field = struct { 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, + tag_type: Type, fields: std.AutoArrayHashMap([]const u8, Field), }; @@ -45,11 +45,11 @@ pub fn resolve(self: *Enum, mod: *Module, scope: *Scope) !void { } // TODO should this resolve the type or assert that it has already been resolved? -pub fn abiAlignment(self: *Enum) u32 { +pub fn abiAlignment(self: *Enum, target: std.Target) 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(), + .resolved => |r| return r.tag_type.abiAlignment(target), } } diff --git a/src/type/Struct.zig b/src/type/Struct.zig index bb1fe56995..2d4a160d0c 100644 --- a/src/type/Struct.zig +++ b/src/type/Struct.zig @@ -1,8 +1,10 @@ const std = @import("std"); +const zir = @import("../zir.zig"); const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; const Module = @import("../Module.zig"); const Scope = Module.Scope; +const Struct = @This(); base: Type.Payload = .{ .tag = .@"struct" }, @@ -11,7 +13,7 @@ analysis: union(enum) { zero_bits_in_progress, zero_bits: Zero, in_progress, - alignment: Align, + // alignment: Align, resolved: Size, failed, }, @@ -24,7 +26,6 @@ pub const Field = struct { pub const Zir = struct { body: zir.Module.Body, inst: *zir.Inst, - arena: std.heap.ArenaAllocator.State, }; pub const Zero = struct { @@ -39,11 +40,11 @@ pub const Size = struct { fields: std.AutoArrayHashMap([]const u8, Field), }; -pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void { +pub fn resolveZeroBits(self: *Struct, 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", .{}); + return mod.fail(scope, src, "struct '{}' depends on itself", .{}); }, .queued => |zir| zir, else => return, @@ -53,5 +54,3 @@ pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void { // TODO } - -pub fn resolveSize(self: *Enum,) \ No newline at end of file diff --git a/src/type/Union.zig b/src/type/Union.zig index bb1fe56995..f62c7e56fa 100644 --- a/src/type/Union.zig +++ b/src/type/Union.zig @@ -1,8 +1,10 @@ const std = @import("std"); +const zir = @import("../zir.zig"); const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; const Module = @import("../Module.zig"); const Scope = Module.Scope; +const Union = @This(); base: Type.Payload = .{ .tag = .@"struct" }, @@ -11,7 +13,7 @@ analysis: union(enum) { zero_bits_in_progress, zero_bits: Zero, in_progress, - alignment: Align, + // alignment: Align, resolved: Size, failed, }, @@ -24,7 +26,6 @@ pub const Field = struct { pub const Zir = struct { body: zir.Module.Body, inst: *zir.Inst, - arena: std.heap.ArenaAllocator.State, }; pub const Zero = struct { @@ -39,7 +40,7 @@ pub const Size = struct { fields: std.AutoArrayHashMap([]const u8, Field), }; -pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void { +pub fn resolveZeroBits(self: *Union, mod: *Module, scope: *Scope) !void { const zir = switch (self.analysis) { .failed => return error.AnalysisFail, .zero_bits_in_progress => { @@ -53,5 +54,3 @@ pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void { // TODO } - -pub fn resolveSize(self: *Enum,) \ No newline at end of file diff --git a/src/zir.zig b/src/zir.zig index 03b3a630a4..2017ad0f15 100644 --- a/src/zir.zig +++ b/src/zir.zig @@ -1084,12 +1084,13 @@ pub const Inst = struct { positionals: struct { bytes: []const u8, - ty: ?*Inst, - init: ?*Inst, - alignment: ?*Inst, - is_comptime: bool, }, - kw_args: struct {}, + kw_args: struct { + ty: ?*Inst = null, + init: ?*Inst = null, + alignment: ?*Inst = null, + is_comptime: bool = false, + }, }; pub const EnumType = struct { @@ -1125,13 +1126,17 @@ pub const Inst = struct { fields: []*Inst, }, kw_args: struct { - init_expr: union(enum) { - enum_type: ?*Inst, - tag_type: *Inst, - none, - }, + init_inst: ?*Inst = null, + init_kind: InitKind = .none, layout: std.builtin.TypeInfo.ContainerLayout = .Auto, }, + + // TODO error: values of type '(enum literal)' must be comptime known + pub const InitKind = enum { + enum_type, + tag_type, + none, + }; }; }; diff --git a/src/zir_sema.zig b/src/zir_sema.zig index 602da97f81..5729644061 100644 --- a/src/zir_sema.zig +++ b/src/zir_sema.zig @@ -139,6 +139,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .switch_range => return analyzeInstSwitchRange(mod, scope, old_inst.castTag(.switch_range).?), .booland => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.booland).?), .boolor => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.boolor).?), + + .container_field_named, + .container_field_typed, + .container_field, + .enum_type, + .union_type, + .struct_type, + => return mod.fail(scope, old_inst.src, "TODO analyze container instructions", .{}), } } -- cgit v1.2.3 From bace1181b2f6d63e51b6e511aa8318481e2eafee Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 17 Nov 2020 21:33:26 +0200 Subject: stage2: handle opaque containers --- src/Module.zig | 2 +- src/astgen.zig | 14 +++++++++++++- src/type.zig | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 4 deletions(-) (limited to 'src/type.zig') diff --git a/src/Module.zig b/src/Module.zig index 831aedf054..4b41d4c737 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1515,7 +1515,6 @@ 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); @@ -2302,6 +2301,7 @@ pub fn createContainerDecl( } fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 { + // TODO add namespaces, generic function signatrues const tree = scope.tree(); const base_name = switch (tree.token_ids[base_token]) { .Keyword_struct => "struct", diff --git a/src/astgen.zig b/src/astgen.zig index 37436373f0..a95fbbe06b 100644 --- a/src/astgen.zig +++ b/src/astgen.zig @@ -913,7 +913,19 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con }; break :blk Type.initPayload(&union_type.base); }, - .Keyword_opaque => return mod.fail(scope, src, "TODO opaque containers", .{}), + .Keyword_opaque => blk: { + if (fields.items.len > 0) { + return mod.fail(scope, fields.items[0].src, "opaque types cannot have fields", .{}); + } + const opaque_type = try arena.create(Type.Payload.Opaque); + opaque_type.* = .{ + .scope = .{ + .file_scope = scope.getFileScope(), + .ty = Type.initPayload(&opaque_type.base), + }, + }; + break :blk Type.initPayload(&opaque_type.base); + }, else => unreachable, }; const type_payload = try arena.create(Value.Payload.Ty); diff --git a/src/type.zig b/src/type.zig index 0cde8644fd..39987a1d92 100644 --- a/src/type.zig +++ b/src/type.zig @@ -49,7 +49,7 @@ pub const Type = extern union { .f128, => return .Float, - .c_void => return .Opaque, + .c_void, .@"opaque" => return .Opaque, .bool => return .Bool, .void => return .Void, .type => return .Type, @@ -449,6 +449,7 @@ pub const Type = extern union { .@"enum" => return self, .@"struct" => return self, .@"union" => return self, + .@"opaque" => return self, } } @@ -680,10 +681,11 @@ pub const Type = extern union { const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise); return out_stream.print("error{{{}}}", .{payload.name}); }, - // TODO improve + // TODO use declaration name .@"enum" => return out_stream.writeAll("enum {}"), .@"struct" => return out_stream.writeAll("struct {}"), .@"union" => return out_stream.writeAll("union {}"), + .@"opaque" => return out_stream.writeAll("opaque {}"), } unreachable; } @@ -809,6 +811,7 @@ pub const Type = extern union { .@"undefined", .enum_literal, .empty_struct, + .@"opaque", => false, }; } @@ -937,6 +940,7 @@ pub const Type = extern union { .@"undefined", .enum_literal, .empty_struct, + .@"opaque", => unreachable, }; } @@ -960,6 +964,7 @@ pub const Type = extern union { .enum_literal => unreachable, .single_const_pointer_to_comptime_int => unreachable, .empty_struct => unreachable, + .@"opaque" => unreachable, .u8, .i8, @@ -1143,6 +1148,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .single_const_pointer, @@ -1221,6 +1227,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .const_slice, @@ -1296,6 +1303,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .single_const_pointer, @@ -1380,6 +1388,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .pointer => { @@ -1459,6 +1468,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .pointer => { @@ -1580,6 +1590,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, .array => self.cast(Payload.Array).?.elem_type, @@ -1711,6 +1722,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, .array => self.cast(Payload.Array).?.len, @@ -1780,6 +1792,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, .single_const_pointer, @@ -1866,6 +1879,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .int_signed, @@ -1944,6 +1958,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .int_unsigned, @@ -2012,6 +2027,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits }, @@ -2098,6 +2114,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, .usize, @@ -2213,6 +2230,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, }; } @@ -2294,6 +2312,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, } } @@ -2374,6 +2393,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, } } @@ -2454,6 +2474,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, }; } @@ -2531,6 +2552,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, }; } @@ -2608,6 +2630,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => unreachable, }; } @@ -2685,6 +2708,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => false, }; } @@ -2742,6 +2766,7 @@ pub const Type = extern union { .error_union, .error_set, .error_set_single, + .@"opaque", => return null, .@"enum" => @panic("TODO onePossibleValue enum"), @@ -2860,6 +2885,7 @@ pub const Type = extern union { .@"enum", .@"struct", .@"union", + .@"opaque", => return false, .c_const_pointer, @@ -2951,6 +2977,7 @@ pub const Type = extern union { .@"enum" => &self.cast(Type.Payload.Enum).?.scope, .@"struct" => &self.cast(Type.Payload.Struct).?.scope, .@"union" => &self.cast(Type.Payload.Union).?.scope, + .@"opaque" => &self.cast(Type.Payload.Union).?.scope, }; } @@ -3105,6 +3132,7 @@ pub const Type = extern union { @"enum", @"struct", @"union", + @"opaque", pub const last_no_payload_tag = Tag.const_slice_u8; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; @@ -3221,6 +3249,12 @@ pub const Type = extern union { scope: *Module.Scope.Container, }; + pub const Opaque = struct { + base: Payload = .{ .tag = .@"opaque" }, + + scope: Module.Scope.Container, + }; + pub const Enum = @import("type/Enum.zig"); pub const Struct = @import("type/Struct.zig"); pub const Union = @import("type/Union.zig"); -- cgit v1.2.3