feat: return detailed lua errors from some API functions rather than logging

This commit is contained in:
LordMZTE 2024-06-22 13:21:04 +02:00
parent d2d1b47b51
commit 190dfa2695
Signed by untrusted user: LordMZTE
GPG key ID: B64802DC33A64FF6
3 changed files with 68 additions and 26 deletions

View file

@ -1,3 +1,6 @@
// FIXME: This whole thing badly needs to be reworked! It barely works, has some nonsensical design
// in places, misses some errors like incorrect delimiters and tends to crash.
const std = @import("std");
const c = @import("ffi.zig").c;
@ -49,6 +52,7 @@ pub fn next(self: *Parser) !?Token {
self.pos = i + 1;
current_type = .lua_literal;
} else if (std.mem.eql(u8, charpair, "%>")) {
// FIXME: underflow on mismatched delimiters
depth -= 1;
if (depth > 0)
continue;
@ -121,6 +125,8 @@ pub fn next(self: *Parser) !?Token {
self.pos = i;
// FIXME: Unclosed delimeters not properly detected! Example: "<%"
return tok;
}

View file

@ -11,14 +11,17 @@ pub fn luaFunc(comptime func: anytype) c.lua_CFunction {
return &struct {
fn f(l: ?*c.lua_State) callconv(.C) c_int {
return func(l.?) catch |e| {
var buf: [128]u8 = undefined;
const err_s = std.fmt.bufPrint(
&buf,
"Zig Error: {s}",
.{@errorName(e)},
) catch unreachable;
c.lua_pushlstring(l, err_s.ptr, err_s.len);
_ = c.lua_error(l);
// If error.LuaError is returned, an error value must be on the stack.
if (e != error.LuaError) {
var buf: [128]u8 = undefined;
const err_s = std.fmt.bufPrint(
&buf,
"Zig Error: {s}",
.{@errorName(e)},
) catch unreachable;
luaPushString(l.?, err_s);
}
_ = c.lua_error(l.?);
unreachable;
};
}
@ -60,3 +63,30 @@ pub fn luaConvertString(l: *c.lua_State, idx: c_int) []const u8 {
c.lua_pop(l, 1);
return s;
}
pub inline fn luaPushString(l: *c.lua_State, s: []const u8) void {
c.lua_pushlstring(l, s.ptr, s.len);
}
const StackWriter = struct {
l: *c.lua_State,
written: u31 = 0,
const Writer = std.io.Writer(*StackWriter, error{}, write);
fn write(self: *StackWriter, bytes: []const u8) error{}!usize {
luaPushString(self.l, bytes);
self.written += 1;
return bytes.len;
}
fn writer(self: *StackWriter) Writer {
return .{ .context = self };
}
};
pub fn luaFmtString(l: *c.lua_State, comptime fmt: []const u8, args: anytype) !void {
var ctx = StackWriter{ .l = l };
try std.fmt.format(ctx.writer(), fmt, args);
c.lua_concat(l, ctx.written);
}

View file

@ -8,6 +8,8 @@ const TemplateCode = luagen.TemplateCode;
pub const state_key = "cg_state";
pub const on_done_callbacks_key = "on_done_callbacks";
const iters_alive_errmsg = "Cannot add file as file iterators are still alive!";
pub const CgState = struct {
rootpath: []const u8,
files: std.StringHashMap(CgFile),
@ -240,7 +242,10 @@ fn lAddString(l: *c.lua_State) !c_int {
const state = getState(l);
if (state.nfile_iters != 0) return error.IteratorsAlive; // TODO: Nicer error
if (state.nfile_iters != 0) {
ffi.luaPushString(l, iters_alive_errmsg);
return error.LuaError;
}
const outpath_d = try state.files.allocator.dupe(u8, outpath);
errdefer state.files.allocator.free(outpath_d);
@ -264,7 +269,10 @@ fn lAddPath(l: *c.lua_State) !c_int {
const state = getState(l);
if (state.nfile_iters != 0) return error.IteratorsAlive; // TODO: Nicer error
if (state.nfile_iters != 0) {
ffi.luaPushString(l, iters_alive_errmsg);
return error.LuaError;
}
var dir = try std.fs.cwd().openDir(path, .{ .iterate = true });
defer dir.close();
@ -302,7 +310,10 @@ fn lAddPath(l: *c.lua_State) !c_int {
fn lAddFile(l: *c.lua_State) !c_int {
const state = getState(l);
if (state.nfile_iters != 0) return error.IteratorsAlive; // TODO: Nicer error
if (state.nfile_iters != 0) {
ffi.luaPushString(l, iters_alive_errmsg);
return error.LuaError;
}
const argc = c.lua_gettop(l);
@ -377,9 +388,8 @@ fn lDoTemplate(l: *c.lua_State) !c_int {
tmpl_code.content.len,
tmpl_code.name.ptr,
) != 0) {
// TODO: turn this into a lua error
std.log.err("loading template: {?s}", .{ffi.luaToString(l, -1)});
return error.LoadTemplate;
try ffi.luaFmtString(l, "loading template:\n{?s}", .{ffi.luaToString(l, -1)});
return error.LuaError;
}
// create env table
@ -402,9 +412,8 @@ fn lDoTemplate(l: *c.lua_State) !c_int {
_ = c.lua_setfenv(l, -2);
if (c.lua_pcall(l, 0, 0, 0) != 0) {
// TODO: turn this into a lua error
std.log.err("failed to run template: {?s}", .{ffi.luaToString(l, -1)});
return error.RunTemplate;
try ffi.luaFmtString(l, "failed to run template:\n{?s}", .{ffi.luaToString(l, -1)});
return error.LuaError;
}
const output = try tmpl.getOutput(l);
@ -447,9 +456,8 @@ fn lDoTemplateFile(l: *c.lua_State) !c_int {
tmpl_code.content.len,
tmpl_code.name.ptr,
) != 0) {
// TODO: turn this into a lua error
std.log.err("loading template: {?s}", .{ffi.luaConvertString(l, -1)});
return error.LoadTemplate;
try ffi.luaFmtString(l, "loading template:\n{?s}", .{ffi.luaToString(l, -1)});
return error.LuaError;
}
// create env
@ -471,9 +479,8 @@ fn lDoTemplateFile(l: *c.lua_State) !c_int {
_ = c.lua_setfenv(l, -2);
if (c.lua_pcall(l, 0, 0, 0) != 0) {
// TODO: turn this into a lua error
std.log.err("failed to run template: {?s}", .{ffi.luaToString(l, -1)});
return error.RunTemplate;
try ffi.luaFmtString(l, "failed to run template:\n{?s}", .{ffi.luaToString(l, -1)});
return error.LuaError;
}
const output = try tmpl.getOutput(l);
@ -659,9 +666,8 @@ pub const LTemplate = struct {
// call post processor
if (c.lua_pcall(l, 1, 1, 0) != 0) {
// TODO: return this instead of logging
std.log.err("running post processor: {?s}", .{ffi.luaToString(l, -1)});
return error.PostProcessor;
try ffi.luaFmtString(l, "running post processor: {?s}", .{ffi.luaToString(l, -1)});
return error.LuaError;
}
const out = ffi.luaConvertString(l, -1);