diff --git a/modules/registry.go b/modules/registry.go index 5fb9a47..262d7c4 100644 --- a/modules/registry.go +++ b/modules/registry.go @@ -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 }