diff --git a/compiler.go b/compiler.go index 53cc7d38..f50908d7 100644 --- a/compiler.go +++ b/compiler.go @@ -49,7 +49,7 @@ type Compiler struct { symbolTable *SymbolTable scopes []compilationScope scopeIndex int - modules *ModuleMap + modules ModuleGetter compiledModules map[string]*CompiledFunction allowFileImport bool loops []*loop @@ -63,7 +63,7 @@ func NewCompiler( file *parser.SourceFile, symbolTable *SymbolTable, constants []Object, - modules *ModuleMap, + modules ModuleGetter, trace io.Writer, ) *Compiler { mainScope := compilationScope{ diff --git a/docs/interoperability.md b/docs/interoperability.md index 05911315..df48ce87 100644 --- a/docs/interoperability.md +++ b/docs/interoperability.md @@ -168,6 +168,32 @@ mods.AddSourceModule("double", []byte(`export func(x) { return x * 2 }`)) s.SetImports(mods) ``` +To dynamically load or generate code for imported modules, implement and +provide a `tengo.ModuleGetter`. + +```golang +type DynamicModules struct { + mods tengo.ModuleGetter + fallback func (name string) tengo.Importable +} +func (dm *DynamicModules) Get(name string) tengo.Importable { + if mod := dm.mods.Get(name); mod != nil { + return mod + } + return dm.fallback() +} +// ... +mods := &DynamicModules{ + mods: stdlib.GetModuleMap("math"), + fallback: func(name string) tengo.Importable { + src := ... // load or generate src for `name` + return &tengo.SourceModule{Src: src} + }, +} +s := tengo.NewScript(`foo := import("foo")`) +s.SetImports(mods) +``` + ### Script.SetMaxAllocs(n int64) SetMaxAllocs sets the maximum number of object allocations. Note this is a diff --git a/modules.go b/modules.go index c8fcde7f..dadd5a3b 100644 --- a/modules.go +++ b/modules.go @@ -6,6 +6,11 @@ type Importable interface { Import(moduleName string) (interface{}, error) } +// ModuleGetter enables implementing dynamic module loading. +type ModuleGetter interface { + Get(name string) Importable +} + // ModuleMap represents a set of named modules. Use NewModuleMap to create a // new module map. type ModuleMap struct { diff --git a/script.go b/script.go index 46e48029..73dde316 100644 --- a/script.go +++ b/script.go @@ -12,7 +12,7 @@ import ( // Script can simplify compilation and execution of embedded scripts. type Script struct { variables map[string]*Variable - modules *ModuleMap + modules ModuleGetter input []byte maxAllocs int64 maxConstObjects int @@ -54,7 +54,7 @@ func (s *Script) Remove(name string) bool { } // SetImports sets import modules. -func (s *Script) SetImports(modules *ModuleMap) { +func (s *Script) SetImports(modules ModuleGetter) { s.modules = modules }