[MODS/VM]: Get calls to deinit working and call deinit on sideros_cleanup
This commit is contained in:
parent
120da3e3cd
commit
3b8ea60141
5 changed files with 80 additions and 44 deletions
Binary file not shown.
|
|
@ -330,6 +330,9 @@ pub fn parseModule(self: *Parser) !void {
|
|||
if (self.exports.init != null and self.exports.init.? != 0){
|
||||
self.exports.init.? -= self.importCount;
|
||||
}
|
||||
if (self.exports.deinit != null and self.exports.deinit.? != 0){
|
||||
self.exports.deinit.? -= self.importCount;
|
||||
}
|
||||
}
|
||||
|
||||
fn parseCustomsec(self: *Parser) !void {
|
||||
|
|
@ -559,6 +562,8 @@ fn parseExportsec(self: *Parser) !void {
|
|||
.func => {
|
||||
if (std.mem.eql(u8, e.name, "init")) {
|
||||
self.exports.init = e.exportdesc.func + self.importCount;
|
||||
} else if (std.mem.eql(u8, e.name, "deinit")) {
|
||||
self.exports.deinit = e.exportdesc.func + self.importCount;
|
||||
} else {
|
||||
std.log.warn("exported function {s} not supported\n", .{e.name});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ pub const Function = struct { func_type: Functype, typ: union(enum) {
|
|||
|
||||
pub const ExportFunction = enum {
|
||||
init,
|
||||
deinit,
|
||||
logErr,
|
||||
logWarn,
|
||||
logInfo,
|
||||
|
|
@ -41,6 +42,7 @@ pub const ExportFunction = enum {
|
|||
};
|
||||
pub const Exports = struct {
|
||||
init: ?u32 = null,
|
||||
deinit: ?u32 = null,
|
||||
logErr: ?u32 = null,
|
||||
logWarn: ?u32 = null,
|
||||
logInfo: ?u32 = null,
|
||||
|
|
@ -647,6 +649,13 @@ pub const Runtime = struct {
|
|||
std.debug.panic("Function init unavailable\n", .{});
|
||||
}
|
||||
},
|
||||
.deinit => {
|
||||
if (self.module.exports.deinit) |func| {
|
||||
try self.call(allocator, func, parameters);
|
||||
} else {
|
||||
std.debug.panic("Function deinit unavailable\n", .{});
|
||||
}
|
||||
},
|
||||
else => {
|
||||
std.debug.panic("Function {any} not handled\n", .{name});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,28 +12,21 @@ pub const Type = enum(u8) {
|
|||
};
|
||||
|
||||
pub const GlobalRuntime = struct {
|
||||
functions: std.StringHashMap(*const fn (stack: *std.ArrayList(vm.Value)) void),
|
||||
globals: std.AutoHashMap(u32, Parser.Globaltype),
|
||||
globalExprs: std.AutoHashMap(u32, vm.Value),
|
||||
|
||||
pub fn init(allocator: Allocator) GlobalRuntime {
|
||||
return GlobalRuntime{
|
||||
.functions = std.StringHashMap(*const fn (stack: *std.ArrayList(vm.Value)) void).init(allocator),
|
||||
.globals = std.AutoHashMap(u32, Parser.Globaltype).init(allocator),
|
||||
.globalExprs = std.AutoHashMap(u32, vm.Value).init(allocator)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *GlobalRuntime) void {
|
||||
self.functions.deinit();
|
||||
self.globals.deinit();
|
||||
self.globalExprs.deinit();
|
||||
}
|
||||
|
||||
pub fn addFunction(self: *GlobalRuntime, name: []const u8, function: *const fn (stack: *std.ArrayList(vm.Value)) void) !void {
|
||||
try self.functions.put(name, function);
|
||||
}
|
||||
|
||||
pub fn addGlobal(self: *GlobalRuntime, index: u32, @"type": Parser.Globaltype, initValue: vm.Value) !void {
|
||||
try self.globals.put(index, @"type");
|
||||
try self.globalExprs.put(index, initValue);
|
||||
|
|
|
|||
103
src/sideros.zig
103
src/sideros.zig
|
|
@ -23,7 +23,7 @@ var input: ecs.Input = .{ .key_pressed = .{false} ** @intFromEnum(ecs.Input.KeyC
|
|||
var resources: ecs.Resources = undefined;
|
||||
const ModInfo = struct {
|
||||
name: []const u8,
|
||||
runtime: mods.Runtime,
|
||||
runtime: *mods.Runtime,
|
||||
modIdx: u32,
|
||||
};
|
||||
var loadedMods: std.ArrayListUnmanaged(ModInfo) = .{};
|
||||
|
|
@ -42,20 +42,72 @@ fn openOrCreateDir(fs: std.fs.Dir, path: []const u8) !std.fs.Dir {
|
|||
return dir;
|
||||
}
|
||||
|
||||
fn untarToDirAndGetFile(fs: std.fs.Dir, name: []const u8) !std.fs.File {
|
||||
var modDir = try openOrCreateDir(fs,name);
|
||||
defer modDir.close();
|
||||
fn untarToDirAndGetFile(fs: std.fs.Dir, name: []const u8, unpack: []const u8) !std.fs.File {
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var modDir = try openOrCreateDir(fs,unpack);
|
||||
defer modDir.close();
|
||||
var tarFile = try fs.openFile(try std.fmt.bufPrint(&buffer, "{s}.tar", .{name}), .{});
|
||||
defer tarFile.close();
|
||||
const tarData = try tarFile.readToEndAlloc(allocator, 1_000_000);
|
||||
defer allocator.free(tarData);
|
||||
var tarReader = std.io.Reader.fixed(tarData);
|
||||
try std.tar.pipeToFileSystem(modDir, &tarReader, .{});
|
||||
return try fs.openFile(try std.fmt.bufPrint(&buffer, "{s}/main.wasm", .{name}), .{});
|
||||
return try fs.openFile(try std.fmt.bufPrint(&buffer, "{s}/main.wasm", .{unpack}), .{});
|
||||
}
|
||||
|
||||
fn loadMod(entry: std.fs.Dir.Entry) !void {
|
||||
const modName = entry.name.ptr[0..entry.name.len - 4];
|
||||
const fullDir = std.fmt.allocPrint(allocator, "assets/mods/{s}", .{modName}) catch @panic("Failed to allocate for fullDir");
|
||||
defer allocator.free(fullDir);
|
||||
const modDir = try std.fmt.allocPrint(allocator, "{s}_siderosmod__", .{fullDir});
|
||||
const global_runtime = allocator.create(mods.GlobalRuntime) catch @panic("Failed to create global runtime");
|
||||
global_runtime.* = mods.GlobalRuntime.init(allocator);
|
||||
|
||||
std.fs.cwd().deleteTree(modDir) catch |err| {
|
||||
std.debug.panic("Failed to delete {s} (reason: {any})", .{modDir, err});
|
||||
};
|
||||
var file = untarToDirAndGetFile(std.fs.cwd(), fullDir, modDir) catch |err| {
|
||||
return err;
|
||||
};
|
||||
defer std.fs.cwd().deleteTree(modDir) catch |err| {
|
||||
std.debug.panic("Failed to delete {s} (reason: {any})", .{modDir, err});
|
||||
};
|
||||
defer file.close();
|
||||
const all = file.readToEndAlloc(allocator, 1_000_000) catch @panic("Unable to read main file");
|
||||
defer allocator.free(all);
|
||||
var parser = mods.Parser.init(allocator, all) catch @panic("Failed to init parser");
|
||||
defer parser.deinit();
|
||||
parser.parseModule() catch |err| {
|
||||
std.debug.print("[ERROR]: error {any} at byte {x}(0x{x})\n", .{ err, parser.byte_idx, parser.bytes[parser.byte_idx] });
|
||||
return err;
|
||||
};
|
||||
const module = parser.module();
|
||||
|
||||
for (0..parser.globalTypes.len) |i| {
|
||||
global_runtime.addGlobal(@intCast(i), parser.globalTypes[i], parser.globalValues[i]) catch @panic("Failed to add runtime global");
|
||||
}
|
||||
|
||||
var runtime = allocator.create(mods.Runtime) catch |err| {
|
||||
std.debug.print("Failed to create runtime", .{});
|
||||
return err;
|
||||
};
|
||||
runtime.* = mods.Runtime.init(allocator, module, global_runtime) catch |err| {
|
||||
std.debug.print("Failed to init runtime", .{});
|
||||
return err;
|
||||
};
|
||||
|
||||
const modIdx: u32 = @intCast(loadedMods.items.len);
|
||||
var parameters = [_]mods.VM.Value{.{ .i32 = @intCast(modIdx) }};
|
||||
runtime.externalCall(allocator, .init, ¶meters) catch @panic("Failed to call to init");
|
||||
const result = runtime.stack.pop().?.i64;
|
||||
if (result != 0){
|
||||
std.debug.print("[ERROR]: Mod {s} init returned {d}\n", .{modName, result});
|
||||
return error.Failure;
|
||||
}
|
||||
loadedMods.append(allocator, .{.name = try allocator.dupe(u8, modName), .runtime = runtime, .modIdx = modIdx}) catch @panic("Failed to append to loadedMods");
|
||||
}
|
||||
|
||||
fn init_mods() void {
|
||||
|
||||
var modsDir = std.fs.cwd().openDir("./assets/mods", .{.iterate = true}) catch @panic("Failed to open assets/mods");
|
||||
defer modsDir.close();
|
||||
|
||||
|
|
@ -69,33 +121,7 @@ fn init_mods() void {
|
|||
std.debug.print("[WARNING]: Found non tar extension in mods directory\n", .{});
|
||||
continue;
|
||||
}
|
||||
const fullDir = std.fmt.allocPrint(allocator, "assets/mods/{s}", .{entry.name.ptr[0..entry.name.len - 4]}) catch @panic("Failed to allocate for fullDir");
|
||||
var global_runtime = mods.GlobalRuntime.init(allocator);
|
||||
|
||||
var file = untarToDirAndGetFile(std.fs.cwd(), fullDir) catch @panic("Failed to load mod");
|
||||
defer file.close();
|
||||
const all = file.readToEndAlloc(allocator, 1_000_000) catch @panic("Unable to read main file");
|
||||
defer allocator.free(all);
|
||||
var parser = mods.Parser.init(allocator, all) catch @panic("Failed to init parser");
|
||||
defer parser.deinit();
|
||||
parser.parseModule() catch |err| {
|
||||
std.debug.panic("[ERROR]: error {any} at byte {x}(0x{x})\n", .{ err, parser.byte_idx, parser.bytes[parser.byte_idx] });
|
||||
};
|
||||
const module = parser.module();
|
||||
|
||||
for (0..parser.globalTypes.len) |i| {
|
||||
global_runtime.addGlobal(@intCast(i), parser.globalTypes[i], parser.globalValues[i]) catch @panic("Failed to add runtime global");
|
||||
}
|
||||
|
||||
var runtime = mods.Runtime.init(allocator, module, &global_runtime) catch @panic("Failed to init runtime");
|
||||
|
||||
const modIdx: u32 = @intCast(loadedMods.items.len);
|
||||
var parameters = [_]mods.VM.Value{.{ .i32 = @intCast(modIdx) }};
|
||||
runtime.externalCall(allocator, .init, ¶meters) catch @panic("Failed to call to init");
|
||||
const result = runtime.stack.pop().?;
|
||||
std.debug.print("Result of {s} init: {any}\n", .{fullDir, result});
|
||||
loadedMods.append(allocator, .{.name = fullDir, .runtime = runtime, .modIdx = modIdx}) catch @panic("Failed to append to loadedMods");
|
||||
std.fs.cwd().deleteTree(fullDir) catch std.debug.panic("Failed to delete {s}", .{fullDir});
|
||||
loadMod(entry) catch @panic("Failed to load mod");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,10 +149,13 @@ export fn sideros_update(gameUpdate: api.GameUpdate) callconv(.c) void {
|
|||
export fn sideros_cleanup() callconv(.c) void {
|
||||
for (loadedMods.items) |info| {
|
||||
var runtime = info.runtime;
|
||||
// runtime.externalCall(allocator, .deinit, &.{});
|
||||
// const result = runtime.stack.pop().?;
|
||||
// std.debug.print("Result of {s} init: {any}\n", .{info.name, result});
|
||||
runtime.deinit(allocator);
|
||||
runtime.externalCall(allocator, .deinit, &.{}) catch @panic("Failed to call deinit");
|
||||
const result = runtime.stack.pop().?.i64;
|
||||
if (result != 0){
|
||||
std.debug.panic("[ERROR]: Mod {s} deinit returned {d}\n", .{info.name, result});
|
||||
}
|
||||
defer runtime.deinit(allocator);
|
||||
defer allocator.free(info.name);
|
||||
}
|
||||
loadedMods.deinit(allocator);
|
||||
renderer.deinit();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue