diff --git a/ly-core/src/root.zig b/ly-core/src/root.zig index 917cb8b..3ca6c49 100644 --- a/ly-core/src/root.zig +++ b/ly-core/src/root.zig @@ -122,13 +122,39 @@ pub fn LuaParser(comptime Struct: type) type { errors: std.ArrayList(Error), maybe_load_error: ?anyerror, allocator: std.mem.Allocator, + arena: std.heap.ArenaAllocator, pub fn init( allocator: std.mem.Allocator, path: []const u8, ) !Self { + var arena = std.heap.ArenaAllocator.init(allocator); + const arena_alloc = arena.allocator(); + var maybe_load_error: ?anyerror = null; errdefer |err| maybe_load_error = err; + + const data = parseLua(arena_alloc, path) catch load_error: { + break :load_error Struct{}; + }; + + if (global_errors.items.len != 0) { + maybe_load_error = error.InvalidConfig; + } + + return .{ + .structure = data, + .errors = global_errors, + .maybe_load_error = maybe_load_error, + .allocator = allocator, + .arena = arena, + }; + } + + fn parseLua( + allocator: std.mem.Allocator, + path: []const u8, + ) !Struct { var lua: *Lua = try .init(allocator); defer lua.deinit(); @@ -152,19 +178,10 @@ pub fn LuaParser(comptime Struct: type) type { }, else => @compileError("Expected a struct."), } - if (global_errors.items.len != 0) { - maybe_load_error = error.InvalidConfig; - } // Parse custom binds and labels try parseCustom(lua); - - return .{ - .structure = data, - .errors = global_errors, - .maybe_load_error = maybe_load_error, - .allocator = allocator, - }; + return data; } pub fn setField(allocator: std.mem.Allocator, lua: *Lua, comptime field: std.builtin.Type.StructField, data: *Struct) !void { @@ -187,7 +204,7 @@ pub fn LuaParser(comptime Struct: type) type { // handle missing required fields if (lua.isNil(-1)) { - return error.MissingRequiredField; + return; } const actual_type_info = @typeInfo(actual_type); @@ -342,19 +359,7 @@ pub fn LuaParser(comptime Struct: type) type { } pub fn deinit(self: *Self) void { - inline for (@typeInfo(Struct).@"struct".fields) |field| { - const type_info = @typeInfo(field.type); - const actual_type = if (type_info == .optional) type_info.optional.child else field.type; - - const value = @field(self.structure, field.name); - if (actual_type == []const u8 or actual_type == [:0]const u8) { - if (type_info == .optional) { - if (value) |inner| self.allocator.free(inner); - } else { - self.allocator.free(value); - } - } - } + self.arena.deinit(); for (0..global_errors.items.len) |i| { const err = global_errors.items[i]; temporary_allocator.free(err.type_name);