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