From e87e08e964135eec936572524caab20f7b6260b9 Mon Sep 17 00:00:00 2001 From: yuzu Date: Fri, 30 May 2025 01:58:02 -0500 Subject: [PATCH] :D --- language.zig | 10 +-------- reflection.zig | 56 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/language.zig b/language.zig index d9d8e5b..83a0aae 100644 --- a/language.zig +++ b/language.zig @@ -103,20 +103,12 @@ pub const Flags = packed struct { allow_comments: bool = false, /// Not to error on trailing comma, default is `false` for obvious reasons allow_trailing_comma: bool = false, - /// Allows parsing `packed struct` as an `int`, size is the backing int - bitfields: bool = false, - /// Allows parsing `enum` as an `int`, size is the backing int - real_enums: bool = false, - /// Allows parsing unions, default behaviour is yet to be concluded - unions: bool = false, - /// To cast numbers always as f64, as the name says - numbersf64: bool = false, }; pub const Options = struct { comptime indent_len: usize = 4, comptime max_depth: usize = 256, - comptime flags: Flags = .{}, + flags: Flags = .{}, }; index: std.MultiArrayList(JsonValue) = .{}, diff --git a/reflection.zig b/reflection.zig index 916c6ee..1677ffe 100644 --- a/reflection.zig +++ b/reflection.zig @@ -33,35 +33,59 @@ pub fn deinit(self: *Self, allocator: mem.Allocator) void { allocator.destroy(self.tokenizer); } -/// always returns 0 (root) -/// needs an index -/// const idx: usize = try self.language.parse(allocator, self.tokenizer); +/// needs an index but useful otherwise +/// root starting from idx pub fn reflectT(self: *Self, comptime T: type, allocator: mem.Allocator, idx: usize) !T { const Schema = @typeInfo(T); + const flags = self.language.options.flags; switch (self.language.index.get(idx)) { .null => { if (Schema == .null) return null; return error.TypeError; }, - .bool => |b| { - if (Schema == .bool) return b; - return error.TypeError; + .bool => |b| switch (Schema) { + .bool => return b, + .@"union" => |unionInfo| inline for (unionInfo.fields) |field| { + var r: T = undefined; + r = @unionInit(T, field.name, b); + return r; + }, + else => return error.TypeError, }, .number => |number| switch (Schema) { .int, .comptime_int => return @intFromFloat(number), .float, .comptime_float => return @floatCast(number), + .@"enum" => |enumInfo| { + const int: enumInfo.tag_type = @intFromFloat(number); + return @enumFromInt(int); + }, .@"struct" => |structInfo| switch (structInfo.layout) { .@"packed" => { - const my_int: structInfo.backing_integer.? = - @intFromFloat(number); - return @bitCast(my_int); + const int: structInfo.backing_integer.? = @intFromFloat(number); + return @bitCast(int); }, else => return error.TypeError, }, + .@"union" => |unionInfo| { + inline for (unionInfo.fields) |field| switch (@typeInfo(field.type)) { + .int, .comptime_int => return @unionInit(T, field.name, @intFromFloat(number)), + .float, .comptime_float => return @unionInit(T, field.name, @floatCast(number)), + else => {}, + }; + return error.TypeError; + }, else => unreachable, }, .string => |string| switch (Schema) { + .@"union" => |unionInfo| inline for (unionInfo.fields) |field| { + if (field.type == []const u8) { + var r: T = undefined; + const strslice = string.slice(&self.language.strings); + r = @unionInit(T, field.name, strslice); + return r; + } + }, .array => |arrayInfo| { assert(arrayInfo.child == u8); const strslice = string.slice(&self.language.strings); @@ -141,7 +165,11 @@ pub fn reflectT(self: *Self, comptime T: type, allocator: mem.Allocator, idx: us if (map.get(field.name)) |next_i| { @field(r, field.name) = try self.reflectT(field.type, allocator, next_i); } else switch (@typeInfo(field.type)) { - .optional => @field(r, field.name) = null, + .optional => { + if (flags.bitfields) + @field(r, field.name) = null; + @panic("Unknown property: " ++ field.name); + }, else => @panic("Unknown property: " ++ field.name), } } @@ -163,7 +191,9 @@ test reflectT { \\ "age": 15, \\ "name": "Yuzu", \\ "admin": true, - \\ "flags": 0 + \\ "flags": 0, + \\ "union": ":D", + \\ "enum": 1 \\} ; var self = try allocator.create(Self); @@ -184,9 +214,11 @@ test reflectT { name: []const u8, admin: bool, flags: UserFlags, + @"union": union { hi: bool, bye: f64, n128: []const u8 }, + @"enum": enum { hello, world }, }; const root = try self.reflectT(UserSchema, allocator, idx); - std.debug.print("is cool? {} is friendly? {}\n", .{ root.flags.is_cool, root.flags.is_friendly }); + std.debug.print("friend? {s}\n", .{root.@"union".n128}); }