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(
41924192 .auto,
41934193 .always_inline,
41944194 .compile_time,
4195 .no_async,
41954196 => {},
41964197
41974198 .async_kw,
41984199 .never_tail,
41994200 .never_inline,
4200 .no_async,
42014201 .always_tail,
42024202 => return sema.fail(block, call_src, "TODO implement call with modifier {}", .{
42034203 modifier,
......@@ -10035,51 +10035,93 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1003510035 var buffer: Value.ToTypeBuffer = undefined;
1003610036 break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
1003710037 };
10038
1003910038 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());
1004210039 const layout = struct_ty.containerLayout();
1004310040
10044 for (struct_field_vals) |*field_val, i| {
10045 const field = struct_fields.values()[i];
10046 const name = struct_fields.keys()[i];
10047 const name_val = v: {
10048 var anon_decl = try block.startAnonDecl(src);
10049 defer anon_decl.deinit();
10050 const bytes = try anon_decl.arena().dupeZ(u8, name);
10051 const new_decl = try anon_decl.finish(
10052 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
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 };
10041 const struct_field_vals = fv: {
10042 if (struct_ty.castTag(.tuple)) |payload| {
10043 const field_types = payload.data.types;
10044 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
10045 for (struct_field_vals) |*struct_field_val, i| {
10046 const field_ty = field_types[i];
10047 const name_val = v: {
10048 var anon_decl = try block.startAnonDecl(src);
10049 defer anon_decl.deinit();
10050 const bytes = try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
10051 const new_decl = try anon_decl.finish(
10052 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
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);
10059 const opt_default_val = if (field.default_val.tag() == .unreachable_value)
10060 null
10061 else
10062 field.default_val;
10063 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
10064 const alignment = switch (layout) {
10065 .Auto, .Extern => field.normalAlignment(target),
10066 .Packed => field.packedAlignment(),
10067 };
10058 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
10059 const field_val = payload.data.values[i];
10060 const is_comptime = field_val.tag() != .unreachable_value;
10061 const opt_default_val = if (is_comptime) field_val else null;
10062 const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);
10063 const alignment = field_ty.abiAlignment(target);
10064
10065 struct_field_fields.* = .{
10066 // name: []const u8,
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.* = .{
10070 // name: []const u8,
10071 name_val,
10072 // field_type: type,
10073 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),
10074 // default_value: ?*const anyopaque,
10075 try default_val_ptr.copy(fields_anon_decl.arena()),
10076 // is_comptime: bool,
10077 Value.makeBool(field.is_comptime),
10078 // alignment: comptime_int,
10079 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),
10080 };
10081 field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), struct_field_fields);
10082 }
10098 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
10099 const opt_default_val = if (field.default_val.tag() == .unreachable_value)
10100 null
10101 else
10102 field.default_val;
10103 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
10104 const alignment = switch (layout) {
10105 .Auto, .Extern => field.normalAlignment(target),
10106 .Packed => field.packedAlignment(),
10107 };
10108
10109 struct_field_fields.* = .{
10110 // name: []const u8,
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
1008410126 const fields_val = v: {
1008510127 const new_decl = try fields_anon_decl.finish(
src/type.zig+5-4
......@@ -2031,21 +2031,21 @@ pub const Type = extern union {
20312031 .empty_struct,
20322032 .void,
20332033 .anyopaque,
2034 => return 0,
2035
20362034 .empty_struct_literal,
20372035 .type,
20382036 .comptime_int,
20392037 .comptime_float,
2040 .noreturn,
20412038 .@"null",
20422039 .@"undefined",
20432040 .enum_literal,
2041 .type_info,
2042 => return 0,
2043
2044 .noreturn,
20442045 .inferred_alloc_const,
20452046 .inferred_alloc_mut,
20462047 .@"opaque",
20472048 .var_args_param,
2048 .type_info,
20492049 .bound_fn,
20502050 => unreachable,
20512051
......@@ -4782,6 +4782,7 @@ pub const Type = extern union {
47824782 base: Payload = .{ .tag = .tuple },
47834783 data: struct {
47844784 types: []Type,
4785 /// unreachable_value elements are used to indicate runtime-known.
47854786 values: []Value,
47864787 },
47874788 };
test/behavior/type_info.zig+5-2
......@@ -454,10 +454,13 @@ test "Declarations are returned in declaration order" {
454454 try expect(std.mem.eql(u8, d[4].name, "e"));
455455}
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" {
458462 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
459463
460 try expect(@typeInfo(@TypeOf(.{0})).Struct.is_tuple);
461464 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
462465}
463466