Skip to content

Commit

Permalink
Allow defining packages for environments
Browse files Browse the repository at this point in the history
This change enables environments to have a different set of
packages. Accessing a package can now be protected by the environment mutex.

Fixes mattn#358
  • Loading branch information
brutella committed Oct 13, 2023
1 parent afcbc04 commit de3ff89
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
2 changes: 2 additions & 0 deletions env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type (
parent *Env
values map[string]reflect.Value
types map[string]reflect.Type
packages map[string]map[string]reflect.Value
packageTypes map[string]map[string]reflect.Type
externalLookup ExternalLookup
}
)
Expand Down
76 changes: 76 additions & 0 deletions env/envPackage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package env

import "reflect"

// Package returns the methods for the package defined by name.
// If no package is found by this name in the environment,
// the globally defined package with this name is returned.
func (e *Env) Package(name string) map[string]reflect.Value {
e.rwMutex.RLock()
pkg, ok := e.packages[name]
e.rwMutex.RUnlock()

if ok {
return pkg
}

if e.parent == nil {
pkg, ok := Packages[name]
if ok {
return pkg
}
}

return nil
}

// DefinePackage defines methods for the package name.
func (e *Env) DefinePackage(name string, values map[string]reflect.Value) {
e.rwMutex.RLock()
defer e.rwMutex.RUnlock()

if e.packages == nil {
e.packages = map[string]map[string]reflect.Value{}
}
e.packages[name] = make(map[string]reflect.Value, len(values))
for k, v := range values {
e.packages[name][k] = v
}
}

// PackageTypes returns the types for the package defined by name.
// If no package is found by this name in the environment,
// the globally defined package with this name is returned
func (e *Env) PackageTypes(name string) map[string]reflect.Type {
e.rwMutex.RLock()
pkg, ok := e.packageTypes[name]
e.rwMutex.RUnlock()

if ok {
return pkg
}

if e.parent == nil {
pkg, ok := PackageTypes[name]
if ok {
return pkg
}
}

return nil
}

// DefinePackageTypes defines types for the package name.
func (e *Env) DefinePackageTypes(name string, types map[string]reflect.Type) {
e.rwMutex.RLock()
defer e.rwMutex.RUnlock()

if e.packageTypes == nil {
e.packageTypes = map[string]map[string]reflect.Type{}
}

e.packageTypes[name] = make(map[string]reflect.Type, len(types))
for k, v := range types {
e.packageTypes[name][k] = v
}
}
8 changes: 4 additions & 4 deletions vm/vmExpr.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,8 @@ func (runInfo *runInfoStruct) invokeExpr() {
name := runInfo.rv.String()
runInfo.rv = nilValue

methods, ok := env.Packages[name]
if !ok {
methods := runInfo.env.Package(name)
if methods == nil {
runInfo.err = newStringError(expr, "package not found: "+name)
return
}
Expand All @@ -537,8 +537,8 @@ func (runInfo *runInfoStruct) invokeExpr() {
}
}

types, ok := env.PackageTypes[name]
if ok {
types := runInfo.env.PackageTypes(name)
if types != nil {
for typeName, typeValue := range types {
err = pack.DefineReflectType(typeName, typeValue)
if err != nil {
Expand Down

0 comments on commit de3ff89

Please sign in to comment.