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