authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-19 15:02:50-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-19 15:11:18-07:00
log746435a9549b1dee6d39e73991592a26cdd582ac
tree09553253738e7b0b46c2e73eda2bb3ea2c1036af
parentb0cdd3d0e691b20043bb7fb763f983b25bfcb2d2

Sema: implement `@typeInfo` for list literals


3 files changed, 93 insertions(+), 47 deletions(-)

src/Sema.zig+83-41
...@@ -4192,12 +4192,12 @@ fn analyzeCall(...@@ -4192,12 +4192,12 @@ fn analyzeCall(
4192 .auto,4192 .auto,
4193 .always_inline,4193 .always_inline,
4194 .compile_time,4194 .compile_time,
4195 .no_async,
4195 => {},4196 => {},
41964197
4197 .async_kw,4198 .async_kw,
4198 .never_tail,4199 .never_tail,
4199 .never_inline,4200 .never_inline,
4200 .no_async,
4201 .always_tail,4201 .always_tail,
4202 => return sema.fail(block, call_src, "TODO implement call with modifier {}", .{4202 => return sema.fail(block, call_src, "TODO implement call with modifier {}", .{
4203 modifier,4203 modifier,
...@@ -10035,51 +10035,93 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10035,51 +10035,93 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10035 var buffer: Value.ToTypeBuffer = undefined;10035 var buffer: Value.ToTypeBuffer = undefined;
10036 break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());10036 break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
10037 };10037 };
10038
10039 const struct_ty = try sema.resolveTypeFields(block, src, ty);10038 const struct_ty = try sema.resolveTypeFields(block, src, ty);
10040 const struct_fields = struct_ty.structFields();
10041 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
10042 const layout = struct_ty.containerLayout();10039 const layout = struct_ty.containerLayout();
1004310040
10044 for (struct_field_vals) |*field_val, i| {10041 const struct_field_vals = fv: {
10045 const field = struct_fields.values()[i];10042 if (struct_ty.castTag(.tuple)) |payload| {
10046 const name = struct_fields.keys()[i];10043 const field_types = payload.data.types;
10047 const name_val = v: {10044 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
10048 var anon_decl = try block.startAnonDecl(src);10045 for (struct_field_vals) |*struct_field_val, i| {
10049 defer anon_decl.deinit();10046 const field_ty = field_types[i];
10050 const bytes = try anon_decl.arena().dupeZ(u8, name);10047 const name_val = v: {
10051 const new_decl = try anon_decl.finish(10048 var anon_decl = try block.startAnonDecl(src);
10052 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),10049 defer anon_decl.deinit();
10053 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),10050 const bytes = try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
10054 );10051 const new_decl = try anon_decl.finish(
10055 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);10052 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10056 };10053 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10054 );
10055 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
10056 };
1005710057
10058 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);10058 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
10059 const opt_default_val = if (field.default_val.tag() == .unreachable_value)10059 const field_val = payload.data.values[i];
10060 null10060 const is_comptime = field_val.tag() != .unreachable_value;
10061 else10061 const opt_default_val = if (is_comptime) field_val else null;
10062 field.default_val;10062 const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);
10063 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);10063 const alignment = field_ty.abiAlignment(target);
10064 const alignment = switch (layout) {10064
10065 .Auto, .Extern => field.normalAlignment(target),10065 struct_field_fields.* = .{
10066 .Packed => field.packedAlignment(),10066 // name: []const u8,
10067 };10067 name_val,
10068 // field_type: type,
10069 try Value.Tag.ty.create(fields_anon_decl.arena(), field_ty),
10070 // default_value: ?*const anyopaque,
10071 try default_val_ptr.copy(fields_anon_decl.arena()),
10072 // is_comptime: bool,
10073 Value.makeBool(is_comptime),
10074 // alignment: comptime_int,
10075 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),
10076 };
10077 struct_field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), struct_field_fields);
10078 }
10079 break :fv struct_field_vals;
10080 }
10081 const struct_fields = struct_ty.structFields();
10082 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
10083
10084 for (struct_field_vals) |*field_val, i| {
10085 const field = struct_fields.values()[i];
10086 const name = struct_fields.keys()[i];
10087 const name_val = v: {
10088 var anon_decl = try block.startAnonDecl(src);
10089 defer anon_decl.deinit();
10090 const bytes = try anon_decl.arena().dupeZ(u8, name);
10091 const new_decl = try anon_decl.finish(
10092 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10093 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10094 );
10095 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
10096 };
1006810097
10069 struct_field_fields.* = .{10098 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
10070 // name: []const u8,10099 const opt_default_val = if (field.default_val.tag() == .unreachable_value)
10071 name_val,10100 null
10072 // field_type: type,10101 else
10073 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),10102 field.default_val;
10074 // default_value: ?*const anyopaque,10103 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
10075 try default_val_ptr.copy(fields_anon_decl.arena()),10104 const alignment = switch (layout) {
10076 // is_comptime: bool,10105 .Auto, .Extern => field.normalAlignment(target),
10077 Value.makeBool(field.is_comptime),10106 .Packed => field.packedAlignment(),
10078 // alignment: comptime_int,10107 };
10079 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),10108
10080 };10109 struct_field_fields.* = .{
10081 field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), struct_field_fields);10110 // name: []const u8,
10082 }10111 name_val,
10112 // field_type: type,
10113 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),
10114 // default_value: ?*const anyopaque,
10115 try default_val_ptr.copy(fields_anon_decl.arena()),
10116 // is_comptime: bool,
10117 Value.makeBool(field.is_comptime),
10118 // alignment: comptime_int,
10119 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),
10120 };
10121 field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), struct_field_fields);
10122 }
10123 break :fv struct_field_vals;
10124 };
1008310125
10084 const fields_val = v: {10126 const fields_val = v: {
10085 const new_decl = try fields_anon_decl.finish(10127 const new_decl = try fields_anon_decl.finish(
src/type.zig+5-4
...@@ -2031,21 +2031,21 @@ pub const Type = extern union {...@@ -2031,21 +2031,21 @@ pub const Type = extern union {
2031 .empty_struct,2031 .empty_struct,
2032 .void,2032 .void,
2033 .anyopaque,2033 .anyopaque,
2034 => return 0,
2035
2036 .empty_struct_literal,2034 .empty_struct_literal,
2037 .type,2035 .type,
2038 .comptime_int,2036 .comptime_int,
2039 .comptime_float,2037 .comptime_float,
2040 .noreturn,
2041 .@"null",2038 .@"null",
2042 .@"undefined",2039 .@"undefined",
2043 .enum_literal,2040 .enum_literal,
2041 .type_info,
2042 => return 0,
2043
2044 .noreturn,
2044 .inferred_alloc_const,2045 .inferred_alloc_const,
2045 .inferred_alloc_mut,2046 .inferred_alloc_mut,
2046 .@"opaque",2047 .@"opaque",
2047 .var_args_param,2048 .var_args_param,
2048 .type_info,
2049 .bound_fn,2049 .bound_fn,
2050 => unreachable,2050 => unreachable,
20512051
...@@ -4782,6 +4782,7 @@ pub const Type = extern union {...@@ -4782,6 +4782,7 @@ pub const Type = extern union {
4782 base: Payload = .{ .tag = .tuple },4782 base: Payload = .{ .tag = .tuple },
4783 data: struct {4783 data: struct {
4784 types: []Type,4784 types: []Type,
4785 /// unreachable_value elements are used to indicate runtime-known.
4785 values: []Value,4786 values: []Value,
4786 },4787 },
4787 };4788 };
test/behavior/type_info.zig+5-2
...@@ -454,10 +454,13 @@ test "Declarations are returned in declaration order" {...@@ -454,10 +454,13 @@ test "Declarations are returned in declaration order" {
454 try expect(std.mem.eql(u8, d[4].name, "e"));454 try expect(std.mem.eql(u8, d[4].name, "e"));
455}455}
456456
457test "Struct.is_tuple" {457test "Struct.is_tuple for anon list literal" {
458 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
459}
460
461test "Struct.is_tuple for anon struct literal" {
458 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO462 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
459463
460 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
461 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);464 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
462}465}
463466