simplify module registry

This commit is contained in:
Sky Johnson 2025-07-17 13:40:41 -05:00
parent abf3aaba35
commit 09bfd24c8d

View File

@ -4,9 +4,6 @@ import (
"embed"
"fmt"
"maps"
"path/filepath"
"strings"
"sync"
"Moonshark/modules/crypto"
"Moonshark/modules/fs"
@ -27,100 +24,60 @@ var embeddedModules embed.FS
type Registry struct {
modules map[string]string
goFuncs map[string]luajit.GoFunction
mutex sync.RWMutex
}
// New creates a new registry with all Go functions loaded
// New creates a new registry with all modules loaded
func New() *Registry {
r := &Registry{
modules: make(map[string]string),
goFuncs: make(map[string]luajit.GoFunction),
}
// Load all Go functions from each module
// Load all Go functions
maps.Copy(r.goFuncs, json.GetFunctionList())
maps.Copy(r.goFuncs, lua_string.GetFunctionList())
maps.Copy(r.goFuncs, math.GetFunctionList())
maps.Copy(r.goFuncs, fs.GetFunctionList())
maps.Copy(r.goFuncs, crypto.GetFunctionList())
r.loadEmbeddedModules()
return r
}
// LoadEmbeddedModules loads all .lua files from embedded filesystem
func (r *Registry) LoadEmbeddedModules() error {
r.mutex.Lock()
defer r.mutex.Unlock()
// loadEmbeddedModules discovers and loads all .lua files
func (r *Registry) loadEmbeddedModules() {
// Discover all directories from embed
dirs, _ := embeddedModules.ReadDir(".")
// Load modules from subdirectories
subdirs := []string{"crypto", "fs", "json", "math", "string"}
for _, subdir := range subdirs {
if err := r.loadModulesFromDir(subdir); err != nil {
return err
}
}
return nil
}
// loadModulesFromDir loads all .lua files from a specific directory
func (r *Registry) loadModulesFromDir(dir string) error {
entries, err := embeddedModules.ReadDir(dir)
if err != nil {
return nil // Skip missing directories
}
for _, entry := range entries {
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".lua") {
for _, dir := range dirs {
if !dir.IsDir() {
continue
}
fileName := strings.TrimSuffix(entry.Name(), ".lua")
// If filename matches directory name (e.g., math/math.lua),
// register as just the directory name for require("math")
var moduleName string
if fileName == dir {
moduleName = dir
} else {
moduleName = dir + "/" + fileName
// Assume one module file per directory: dirname/dirname.lua
modulePath := fmt.Sprintf("%s/%s.lua", dir.Name(), dir.Name())
if source, err := embeddedModules.ReadFile(modulePath); err == nil {
r.modules[dir.Name()] = string(source)
}
source, err := embeddedModules.ReadFile(filepath.Join(dir, entry.Name()))
if err != nil {
return fmt.Errorf("failed to read module %s: %w", moduleName, err)
}
r.modules[moduleName] = string(source)
}
return nil
}
// InstallInState sets up the complete module system in a Lua state
func (r *Registry) InstallInState(state *luajit.State) error {
r.mutex.RLock()
defer r.mutex.RUnlock()
// Create moonshark global table
// Create moonshark global table with Go functions
state.NewTable()
state.SetGlobal("moonshark")
// Install Go functions
state.GetGlobal("moonshark")
for name, fn := range r.goFuncs {
if err := state.PushGoFunction(fn); err != nil {
return fmt.Errorf("failed to register Go function '%s': %w", name, err)
}
state.SetField(-2, name)
}
state.Pop(1) // Remove moonshark table
state.SetGlobal("moonshark")
// Backup original require
// Backup original require and install custom one
state.GetGlobal("require")
state.SetGlobal("_require_original")
// Install custom require function
return state.RegisterGoFunction("require", func(s *luajit.State) int {
if err := s.CheckMinArgs(1); err != nil {
return s.PushError("require: %v", err)
@ -132,11 +89,7 @@ func (r *Registry) InstallInState(state *luajit.State) error {
}
// Check built-in modules first
r.mutex.RLock()
source, exists := r.modules[moduleName]
r.mutex.RUnlock()
if exists {
if source, exists := r.modules[moduleName]; exists {
if err := s.LoadString(source); err != nil {
return s.PushError("require: failed to load module '%s': %v", moduleName, err)
}
@ -160,8 +113,8 @@ func (r *Registry) InstallInState(state *luajit.State) error {
})
}
// Initialize sets up the global registry with all modules loaded
// Initialize sets up the global registry
func Initialize() error {
Global = New()
return Global.LoadEmbeddedModules()
return nil
}