module: do not expose list of modules
Doing so would encourage accidentally creating dependency loops. Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
b4a479fb3f
commit
5dbf9ece3b
2 changed files with 20 additions and 20 deletions
|
|
@ -24,7 +24,7 @@ pub const Engine = @import("engine.zig").Engine;
|
||||||
pub const ModSet = @import("module.zig").ModSet;
|
pub const ModSet = @import("module.zig").ModSet;
|
||||||
|
|
||||||
// TODO: perhaps this could be a comptime var rather than @import("root")?
|
// TODO: perhaps this could be a comptime var rather than @import("root")?
|
||||||
const modules = blk: {
|
pub const modules = blk: {
|
||||||
if (!@hasDecl(@import("root"), "modules")) {
|
if (!@hasDecl(@import("root"), "modules")) {
|
||||||
@compileError("expected `pub const modules = .{};` in root file");
|
@compileError("expected `pub const modules = .{};` in root file");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,11 @@ fn Serializable(comptime T: type) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Manages comptime .{A, B, C} modules and runtime modules.
|
/// Manages comptime .{A, B, C} modules and runtime modules.
|
||||||
pub fn Modules(comptime modules2: anytype) type {
|
pub fn Modules(comptime modules: anytype) type {
|
||||||
// Verify that each module is valid.
|
// Verify that each module is valid.
|
||||||
inline for (modules2) |M| _ = ModuleInterface(M);
|
inline for (modules) |M| _ = ModuleInterface(M);
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
// TODO: avoid exposing this?
|
|
||||||
/// Comptime modules
|
|
||||||
pub const modules = modules2;
|
|
||||||
|
|
||||||
// TODO: add runtime module support
|
// TODO: add runtime module support
|
||||||
pub const ModuleID = u32;
|
pub const ModuleID = u32;
|
||||||
pub const EventID = u32;
|
pub const EventID = u32;
|
||||||
|
|
@ -276,7 +272,7 @@ pub fn Modules(comptime modules2: anytype) type {
|
||||||
switch (module_name) {
|
switch (module_name) {
|
||||||
inline else => |mod_name| {
|
inline else => |mod_name| {
|
||||||
// TODO: DRY with callGlobal
|
// TODO: DRY with callGlobal
|
||||||
const M = @field(NamespacedModules(@This().modules){}, @tagName(mod_name));
|
const M = @field(NamespacedModules(modules){}, @tagName(mod_name));
|
||||||
_ = ModuleInterface(M); // Validate the module
|
_ = ModuleInterface(M); // Validate the module
|
||||||
if (@hasDecl(M, "local_events")) inline for (@typeInfo(@TypeOf(M.local_events)).Struct.fields) |field| {
|
if (@hasDecl(M, "local_events")) inline for (@typeInfo(@TypeOf(M.local_events)).Struct.fields) |field| {
|
||||||
comptime if (!std.mem.eql(u8, @tagName(ev_name), field.name)) continue;
|
comptime if (!std.mem.eql(u8, @tagName(ev_name), field.name)) continue;
|
||||||
|
|
@ -407,7 +403,7 @@ pub fn ModSet(comptime modules: anytype) type {
|
||||||
|
|
||||||
pub inline fn send(m: *@This(), comptime event_name: LocalEventEnumM(M), args: LocalArgsM(M, event_name)) void {
|
pub inline fn send(m: *@This(), comptime event_name: LocalEventEnumM(M), args: LocalArgsM(M, event_name)) void {
|
||||||
const ModulesT = Modules(modules);
|
const ModulesT = Modules(modules);
|
||||||
const MByName = ModsByName(ModulesT.modules);
|
const MByName = ModsByName(modules);
|
||||||
const mod_ptr: *MByName = @alignCast(@fieldParentPtr(MByName, @tagName(module_tag), m));
|
const mod_ptr: *MByName = @alignCast(@fieldParentPtr(MByName, @tagName(module_tag), m));
|
||||||
const mods = @fieldParentPtr(ModulesT, "mod", mod_ptr);
|
const mods = @fieldParentPtr(ModulesT, "mod", mod_ptr);
|
||||||
mods.sendToModule(module_tag, event_name, args);
|
mods.sendToModule(module_tag, event_name, args);
|
||||||
|
|
@ -415,7 +411,7 @@ pub fn ModSet(comptime modules: anytype) type {
|
||||||
|
|
||||||
pub inline fn sendGlobal(m: *@This(), comptime event_name: GlobalEventEnumM(M), args: GlobalArgsM(M, event_name)) void {
|
pub inline fn sendGlobal(m: *@This(), comptime event_name: GlobalEventEnumM(M), args: GlobalArgsM(M, event_name)) void {
|
||||||
const ModulesT = Modules(modules);
|
const ModulesT = Modules(modules);
|
||||||
const MByName = ModsByName(ModulesT.modules);
|
const MByName = ModsByName(modules);
|
||||||
const mod_ptr: *MByName = @alignCast(@fieldParentPtr(MByName, @tagName(module_tag), m));
|
const mod_ptr: *MByName = @alignCast(@fieldParentPtr(MByName, @tagName(module_tag), m));
|
||||||
const mods = @fieldParentPtr(ModulesT, "mod", mod_ptr);
|
const mods = @fieldParentPtr(ModulesT, "mod", mod_ptr);
|
||||||
mods.sendGlobal(module_tag, event_name, args);
|
mods.sendGlobal(module_tag, event_name, args);
|
||||||
|
|
@ -424,7 +420,7 @@ pub fn ModSet(comptime modules: anytype) type {
|
||||||
// TODO: eliminate this
|
// TODO: eliminate this
|
||||||
pub fn dispatchNoError(m: *@This()) void {
|
pub fn dispatchNoError(m: *@This()) void {
|
||||||
const ModulesT = Modules(modules);
|
const ModulesT = Modules(modules);
|
||||||
const MByName = ModsByName(ModulesT.modules);
|
const MByName = ModsByName(modules);
|
||||||
const mod_ptr: *MByName = @alignCast(@fieldParentPtr(MByName, @tagName(module_tag), m));
|
const mod_ptr: *MByName = @alignCast(@fieldParentPtr(MByName, @tagName(module_tag), m));
|
||||||
const mods = @fieldParentPtr(ModulesT, "mod", mod_ptr);
|
const mods = @fieldParentPtr(ModulesT, "mod", mod_ptr);
|
||||||
mods.dispatch() catch |err| @panic(@errorName(err));
|
mods.dispatch() catch |err| @panic(@errorName(err));
|
||||||
|
|
@ -1018,12 +1014,13 @@ test ModuleName {
|
||||||
const Sprite2D = ModuleInterface(struct {
|
const Sprite2D = ModuleInterface(struct {
|
||||||
pub const name = .engine_sprite2d;
|
pub const name = .engine_sprite2d;
|
||||||
});
|
});
|
||||||
const Ms = Modules(.{
|
const modules = .{
|
||||||
Physics,
|
Physics,
|
||||||
Renderer,
|
Renderer,
|
||||||
Sprite2D,
|
Sprite2D,
|
||||||
});
|
};
|
||||||
const info = @typeInfo(ModuleName(Ms.modules)).Enum;
|
_ = Modules(modules);
|
||||||
|
const info = @typeInfo(ModuleName(modules)).Enum;
|
||||||
|
|
||||||
try testing.expect(type, u2).eql(info.tag_type);
|
try testing.expect(type, u2).eql(info.tag_type);
|
||||||
try testing.expect(usize, 3).eql(info.fields.len);
|
try testing.expect(usize, 3).eql(info.fields.len);
|
||||||
|
|
@ -1192,10 +1189,11 @@ test "event name calling" {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var modules: Modules(.{
|
const modules2 = .{
|
||||||
Physics,
|
Physics,
|
||||||
Renderer,
|
Renderer,
|
||||||
}) = undefined;
|
};
|
||||||
|
var modules: Modules(modules2) = undefined;
|
||||||
try modules.init(testing.allocator);
|
try modules.init(testing.allocator);
|
||||||
defer modules.deinit(testing.allocator);
|
defer modules.deinit(testing.allocator);
|
||||||
|
|
||||||
|
|
@ -1216,7 +1214,8 @@ test "event name calling" {
|
||||||
// Check we can use .callLocal() with a runtime-known event and module name.
|
// Check we can use .callLocal() with a runtime-known event and module name.
|
||||||
const m_alloc = try testing.allocator.create(u3);
|
const m_alloc = try testing.allocator.create(u3);
|
||||||
defer testing.allocator.destroy(m_alloc);
|
defer testing.allocator.destroy(m_alloc);
|
||||||
const M = ModuleName(@TypeOf(modules).modules);
|
const M = ModuleName(modules2);
|
||||||
|
|
||||||
m_alloc.* = @intFromEnum(@as(M, .engine_renderer));
|
m_alloc.* = @intFromEnum(@as(M, .engine_renderer));
|
||||||
alloc.* = @intFromEnum(@as(LE, .update));
|
alloc.* = @intFromEnum(@as(LE, .update));
|
||||||
var module_name = @as(M, @enumFromInt(m_alloc.*));
|
var module_name = @as(M, @enumFromInt(m_alloc.*));
|
||||||
|
|
@ -1314,17 +1313,18 @@ test "dispatch" {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var modules: Modules(.{
|
const modules2 = .{
|
||||||
Minimal,
|
Minimal,
|
||||||
Physics,
|
Physics,
|
||||||
Renderer,
|
Renderer,
|
||||||
}) = undefined;
|
};
|
||||||
|
var modules: Modules(modules2) = undefined;
|
||||||
try modules.init(testing.allocator);
|
try modules.init(testing.allocator);
|
||||||
defer modules.deinit(testing.allocator);
|
defer modules.deinit(testing.allocator);
|
||||||
|
|
||||||
const GE = @TypeOf(modules).GlobalEvent;
|
const GE = @TypeOf(modules).GlobalEvent;
|
||||||
const LE = @TypeOf(modules).LocalEvent;
|
const LE = @TypeOf(modules).LocalEvent;
|
||||||
const M = ModuleName(@TypeOf(modules).modules);
|
const M = ModuleName(modules2);
|
||||||
|
|
||||||
// Global events
|
// Global events
|
||||||
//
|
//
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue