env.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package env
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "reflect"
  7. "sync"
  8. )
  9. type (
  10. // ExternalLookup for Env external lookup of values and types.
  11. ExternalLookup interface {
  12. Get(string) (reflect.Value, error)
  13. Type(string) (reflect.Type, error)
  14. }
  15. // Env is the environment needed for a VM to run in.
  16. Env struct {
  17. rwMutex *sync.RWMutex
  18. parent *Env
  19. values map[string]reflect.Value
  20. types map[string]reflect.Type
  21. externalLookup ExternalLookup
  22. }
  23. )
  24. var (
  25. // Packages is a where packages can be stored so VM import command can be used to import them.
  26. // reflect.Value must be valid or VM may crash.
  27. // For nil must use NilValue.
  28. Packages = make(map[string]map[string]reflect.Value)
  29. // PackageTypes is a where package types can be stored so VM import command can be used to import them
  30. // reflect.Type must be valid or VM may crash.
  31. // For nil type must use NilType.
  32. PackageTypes = make(map[string]map[string]reflect.Type)
  33. // NilType is the reflect.type of nil
  34. NilType = reflect.TypeOf(nil)
  35. // NilValue is the reflect.value of nil
  36. NilValue = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()).Elem()
  37. basicTypes = map[string]reflect.Type{
  38. "interface": reflect.ValueOf([]interface{}{int64(1)}).Index(0).Type(),
  39. "bool": reflect.TypeOf(true),
  40. "string": reflect.TypeOf("a"),
  41. "int": reflect.TypeOf(int(1)),
  42. "int32": reflect.TypeOf(int32(1)),
  43. "int64": reflect.TypeOf(int64(1)),
  44. "uint": reflect.TypeOf(uint(1)),
  45. "uint32": reflect.TypeOf(uint32(1)),
  46. "uint64": reflect.TypeOf(uint64(1)),
  47. "byte": reflect.TypeOf(byte(1)),
  48. "rune": reflect.TypeOf('a'),
  49. "float32": reflect.TypeOf(float32(1)),
  50. "float64": reflect.TypeOf(float64(1)),
  51. }
  52. // ErrSymbolContainsDot symbol contains .
  53. ErrSymbolContainsDot = errors.New("symbol contains '.'")
  54. )
  55. // NewEnv creates new global scope.
  56. func NewEnv() *Env {
  57. return &Env{
  58. rwMutex: &sync.RWMutex{},
  59. values: make(map[string]reflect.Value),
  60. }
  61. }
  62. // NewEnv creates new child scope.
  63. func (e *Env) NewEnv() *Env {
  64. return &Env{
  65. rwMutex: &sync.RWMutex{},
  66. parent: e,
  67. values: make(map[string]reflect.Value),
  68. }
  69. }
  70. // NewModule creates new child scope and define it as a symbol.
  71. // This is a shortcut for calling e.NewEnv then Define that new Env.
  72. func (e *Env) NewModule(symbol string) (*Env, error) {
  73. module := &Env{
  74. rwMutex: &sync.RWMutex{},
  75. parent: e,
  76. values: make(map[string]reflect.Value),
  77. }
  78. return module, e.Define(symbol, module)
  79. }
  80. // SetExternalLookup sets an external lookup
  81. func (e *Env) SetExternalLookup(externalLookup ExternalLookup) {
  82. e.externalLookup = externalLookup
  83. }
  84. // String returns string of values and types in current scope.
  85. func (e *Env) String() string {
  86. var buffer bytes.Buffer
  87. e.rwMutex.RLock()
  88. if e.parent == nil {
  89. buffer.WriteString("No parent\n")
  90. } else {
  91. buffer.WriteString("Has parent\n")
  92. }
  93. for symbol, value := range e.values {
  94. buffer.WriteString(fmt.Sprintf("%v = %#v\n", symbol, value))
  95. }
  96. for symbol, aType := range e.types {
  97. buffer.WriteString(fmt.Sprintf("%v = %v\n", symbol, aType))
  98. }
  99. e.rwMutex.RUnlock()
  100. return buffer.String()
  101. }
  102. // GetEnvFromPath returns Env from path
  103. func (e *Env) GetEnvFromPath(path []string) (*Env, error) {
  104. if len(path) < 1 {
  105. return e, nil
  106. }
  107. var value reflect.Value
  108. var ok bool
  109. for {
  110. // find starting env
  111. value, ok = e.values[path[0]]
  112. if ok {
  113. e, ok = value.Interface().(*Env)
  114. if ok {
  115. break
  116. }
  117. }
  118. if e.parent == nil {
  119. return nil, fmt.Errorf("no namespace called: %v", path[0])
  120. }
  121. e = e.parent
  122. }
  123. for i := 1; i < len(path); i++ {
  124. // find child env
  125. value, ok = e.values[path[i]]
  126. if ok {
  127. e, ok = value.Interface().(*Env)
  128. if ok {
  129. continue
  130. }
  131. }
  132. return nil, fmt.Errorf("no namespace called: %v", path[i])
  133. }
  134. return e, nil
  135. }
  136. // Copy the Env for current scope
  137. func (e *Env) Copy() *Env {
  138. e.rwMutex.RLock()
  139. copy := Env{
  140. rwMutex: &sync.RWMutex{},
  141. parent: e.parent,
  142. values: make(map[string]reflect.Value, len(e.values)),
  143. externalLookup: e.externalLookup,
  144. }
  145. for name, value := range e.values {
  146. copy.values[name] = value
  147. }
  148. if e.types != nil {
  149. copy.types = make(map[string]reflect.Type, len(e.types))
  150. for name, t := range e.types {
  151. copy.types[name] = t
  152. }
  153. }
  154. e.rwMutex.RUnlock()
  155. return &copy
  156. }
  157. // DeepCopy the Env for current scope and parent scopes.
  158. // Note that each scope is a consistent snapshot but not the whole.
  159. func (e *Env) DeepCopy() *Env {
  160. e = e.Copy()
  161. if e.parent != nil {
  162. e.parent = e.parent.DeepCopy()
  163. }
  164. return e
  165. }