diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/refl.zig | 91 |
1 files changed, 60 insertions, 31 deletions
diff --git a/src/refl.zig b/src/refl.zig index c26225e..5cfcc52 100644 --- a/src/refl.zig +++ b/src/refl.zig @@ -2,7 +2,7 @@ const std = @import("std"); fn Args(params: []const std.builtin.Type.Fn.Param) type { var argTypes: [params.len]type = undefined; - + for (params, 0..) |p, i| { argTypes[i] = p.type.?; } @@ -13,34 +13,55 @@ fn Args(params: []const std.builtin.Type.Fn.Param) type { fn Val(comptime T: type) type { const ti = @typeInfo(T).@"struct"; - var names: [ti.fields.len + ti.decls.len][]const u8 = undefined; - var types: [ti.fields.len + ti.decls.len]type = undefined; - var attrs: [ti.fields.len + ti.decls.len]std.builtin.Type.StructField.Attributes = undefined; + const fieldCount = ti.fields.len + ti.decls.len + 1; + + var names: [fieldCount][]const u8 = undefined; + var types: [fieldCount]type = undefined; + var attrs: [fieldCount]std.builtin.Type.StructField.Attributes = undefined; inline for (ti.fields, 0..) |field, idx| { - names[idx] = field.name; - types[idx] = struct { - value: field.type, - pub fn get(self: @This()) field.type { - std.debug.print("getting {s}\n", .{field.name}); - return self.value; - } - pub fn set(self: *@This(), value: field.type) void { - std.debug.print("setting {s}\n", .{field.name}); - self.value = value; - } - }; - const default = if (field.default_value_ptr) |def| types[idx]{ .value = @as(*field.type, @ptrCast(@alignCast(@constCast(def)))).* } else null; - attrs[idx] = .{ - .@"comptime" = field.is_comptime, - .@"align" = field.alignment, - .default_value_ptr = &default, - }; + if (field.is_comptime) + @compileError("implement skipping comptime fields"); + + const fi = @typeInfo(field.type); + switch (fi) { + .@"struct" => { + names[idx] = field.name; + const NT = Val(field.type); + types[idx] = NT; + attrs[idx] = .{ + .default_value_ptr = &NT{}, + }; + }, + else => { + names[idx] = field.name; + const NT = struct { + pub fn get(self: *@This()) field.type { + std.debug.print("getting {s}\n", .{field.name}); + const parent = self.valuePtr(); + return @field(parent.value, field.name); + } + pub fn set(self: *@This(), value: field.type) void { + std.debug.print("setting {s}\n", .{field.name}); + const parent = self.valuePtr(); + @field(parent.value, field.name) = value; + } + fn valuePtr(self: *@This()) *align(@alignOf(@This())) Val(T) { + const parent: *align(@alignOf(@This())) Val(T) = @fieldParentPtr(field.name, self); + return parent; + } + }; + types[idx] = NT; + attrs[idx] = .{ + .default_value_ptr = &NT{}, + }; + }, + } } inline for (ti.decls, 0..) |decl, idx| { names[ti.fields.len + idx] = decl.name; const fi = @typeInfo(@TypeOf(@field(T, decl.name))).@"fn"; - + const NT = struct { pub fn call(self: @This(), args: Args(fi.params)) (fi.return_type orelse void) { _ = self; @@ -50,9 +71,15 @@ fn Val(comptime T: type) type { } }; types[ti.fields.len + idx] = NT; - const default = NT {}; - attrs[ti.fields.len + idx] = .{ .default_value_ptr = &default }; + attrs[ti.fields.len + idx] = .{ .default_value_ptr = &NT{} }; } + names[fieldCount - 1] = "value"; + types[fieldCount - 1] = T; + attrs[fieldCount - 1] = .{ + .@"comptime" = false, + .@"align" = @alignOf(T), + .default_value_ptr = &T{}, + }; return @Struct(.auto, null, &names, &types, &attrs); } @@ -61,9 +88,9 @@ pub fn main() !void { var a = Val(struct { i: i32 = 123, j: i32 = 456, - s: Val(struct { + s: struct { i: i32 = 789, - }) = .{}, + } = .{}, pub fn b() void { std.debug.print("B!\n", .{}); } @@ -75,11 +102,13 @@ pub fn main() !void { std.debug.print("D! ({})\n", .{self}); } }){}; - std.debug.print("[{}] {}\n", .{ @TypeOf(a), a }); - a.b.call(.{}); - a.c.call(.{a}); - a.c.call(.{a, 5}); + std.debug.print("[{}] {}\n{}\n", .{ @TypeOf(a), a, a.value }); + // a.b.call(.{}); + // a.c.call(.{a}); + // a.c.call(.{a, 5}); std.debug.print("{}\n", .{a.i.get()}); + std.debug.print("{}\n", .{a.j.get()}); a.j.set(9); std.debug.print("{}\n", .{a.j.get()}); + std.debug.print("{}\n", .{a.s.i.get()}); } |
