envValues.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package env
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. )
  7. // define
  8. // Define defines/sets interface value to symbol in current scope.
  9. func (e *Env) Define(symbol string, value interface{}) error {
  10. if value == nil {
  11. return e.DefineValue(symbol, NilValue)
  12. }
  13. return e.DefineValue(symbol, reflect.ValueOf(value))
  14. }
  15. // DefineValue defines/sets reflect value to symbol in current scope.
  16. func (e *Env) DefineValue(symbol string, value reflect.Value) error {
  17. if strings.Contains(symbol, ".") {
  18. return ErrSymbolContainsDot
  19. }
  20. e.rwMutex.Lock()
  21. e.values[symbol] = value
  22. e.rwMutex.Unlock()
  23. return nil
  24. }
  25. // DefineGlobal defines/sets interface value to symbol in global scope.
  26. func (e *Env) DefineGlobal(symbol string, value interface{}) error {
  27. for e.parent != nil {
  28. e = e.parent
  29. }
  30. return e.Define(symbol, value)
  31. }
  32. // DefineGlobalValue defines/sets reflect value to symbol in global scope.
  33. func (e *Env) DefineGlobalValue(symbol string, value reflect.Value) error {
  34. for e.parent != nil {
  35. e = e.parent
  36. }
  37. return e.DefineValue(symbol, value)
  38. }
  39. // set
  40. // Set interface value to the scope where symbol is frist found.
  41. func (e *Env) Set(symbol string, value interface{}) error {
  42. if value == nil {
  43. return e.SetValue(symbol, NilValue)
  44. }
  45. return e.SetValue(symbol, reflect.ValueOf(value))
  46. }
  47. // SetValue reflect value to the scope where symbol is frist found.
  48. func (e *Env) SetValue(symbol string, value reflect.Value) error {
  49. e.rwMutex.RLock()
  50. _, ok := e.values[symbol]
  51. e.rwMutex.RUnlock()
  52. if ok {
  53. e.rwMutex.Lock()
  54. e.values[symbol] = value
  55. e.rwMutex.Unlock()
  56. return nil
  57. }
  58. if e.parent == nil {
  59. return fmt.Errorf("undefined symbol '%s'", symbol)
  60. }
  61. return e.parent.SetValue(symbol, value)
  62. }
  63. // get
  64. // Get returns interface value from the scope where symbol is frist found.
  65. func (e *Env) Get(symbol string) (interface{}, error) {
  66. rv, err := e.GetValue(symbol)
  67. return rv.Interface(), err
  68. }
  69. // GetValue returns reflect value from the scope where symbol is frist found.
  70. func (e *Env) GetValue(symbol string) (reflect.Value, error) {
  71. e.rwMutex.RLock()
  72. value, ok := e.values[symbol]
  73. e.rwMutex.RUnlock()
  74. if ok {
  75. return value, nil
  76. }
  77. if e.externalLookup != nil {
  78. var err error
  79. value, err = e.externalLookup.Get(symbol)
  80. if err == nil {
  81. return value, nil
  82. }
  83. }
  84. if e.parent == nil {
  85. return NilValue, fmt.Errorf("undefined symbol '%s'", symbol)
  86. }
  87. return e.parent.GetValue(symbol)
  88. }
  89. // delete
  90. // Delete deletes symbol in current scope.
  91. func (e *Env) Delete(symbol string) {
  92. e.rwMutex.Lock()
  93. delete(e.values, symbol)
  94. e.rwMutex.Unlock()
  95. }
  96. // DeleteGlobal deletes the first matching symbol found in current or parent scope.
  97. func (e *Env) DeleteGlobal(symbol string) {
  98. if e.parent == nil {
  99. e.Delete(symbol)
  100. return
  101. }
  102. e.rwMutex.RLock()
  103. _, ok := e.values[symbol]
  104. e.rwMutex.RUnlock()
  105. if ok {
  106. e.Delete(symbol)
  107. return
  108. }
  109. e.parent.DeleteGlobal(symbol)
  110. }
  111. // Addr
  112. // Addr returns reflect.Addr of value for first matching symbol found in current or parent scope.
  113. func (e *Env) Addr(symbol string) (reflect.Value, error) {
  114. e.rwMutex.RLock()
  115. defer e.rwMutex.RUnlock()
  116. if v, ok := e.values[symbol]; ok {
  117. if v.CanAddr() {
  118. return v.Addr(), nil
  119. }
  120. return NilValue, fmt.Errorf("unaddressable")
  121. }
  122. if e.externalLookup != nil {
  123. v, err := e.externalLookup.Get(symbol)
  124. if err == nil {
  125. if v.CanAddr() {
  126. return v.Addr(), nil
  127. }
  128. return NilValue, fmt.Errorf("unaddressable")
  129. }
  130. }
  131. if e.parent == nil {
  132. return NilValue, fmt.Errorf("undefined symbol '%s'", symbol)
  133. }
  134. return e.parent.Addr(symbol)
  135. }