github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/cmds/elvish/eval/ns.go (about) 1 package eval 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/u-root/u-root/cmds/elvish/eval/vars" 8 ) 9 10 // Ns is a map from names to variables. 11 type Ns map[string]vars.Var 12 13 var _ interface{} = Ns(nil) 14 15 // NewNs creates an empty namespace. 16 func NewNs() Ns { 17 return make(Ns) 18 } 19 20 func (Ns) Kind() string { 21 return "ns" 22 } 23 24 func (ns Ns) Hash() uint32 { 25 return uint32(addrOf(ns)) 26 } 27 28 func (ns Ns) Equal(rhs interface{}) bool { 29 if ns2, ok := rhs.(Ns); ok { 30 return addrOf(ns) == addrOf(ns2) 31 } 32 return false 33 } 34 35 func (ns Ns) Repr(int) string { 36 return fmt.Sprintf("<ns 0x%x>", addrOf(ns)) 37 } 38 39 func (ns Ns) Index(k interface{}) (interface{}, bool) { 40 if kstring, ok := k.(string); ok { 41 if v, ok := ns[kstring]; ok { 42 return v.Get(), true 43 } 44 } 45 return nil, false 46 } 47 48 func (ns Ns) IterateKeys(f func(interface{}) bool) { 49 for k := range ns { 50 if !f(k) { 51 break 52 } 53 } 54 } 55 56 // HasName reports the namespace contains the given name. 57 func (ns Ns) HasName(name string) bool { 58 _, ok := ns[name] 59 return ok 60 } 61 62 // PopName removes a name from the namespace and returns the variable it used to 63 // contain. 64 func (ns Ns) PopName(name string) vars.Var { 65 v := ns[name] 66 delete(ns, name) 67 return v 68 } 69 70 // Clone returns a shallow copy of the namespace. 71 func (ns Ns) Clone() Ns { 72 ns2 := make(Ns) 73 for name, variable := range ns { 74 ns2[name] = variable 75 } 76 return ns2 77 } 78 79 // Add adds a variable to the namespace and returns the namespace itself. 80 func (ns Ns) Add(name string, v vars.Var) Ns { 81 ns[name] = v 82 return ns 83 } 84 85 // AddFn adds a function to a namespace. It returns the namespace itself. 86 func (ns Ns) AddFn(name string, v Callable) Ns { 87 return ns.Add(name+FnSuffix, vars.FromPtr(&v)) 88 } 89 90 // AddNs adds a sub-namespace to a namespace. It returns the namespace itself. 91 func (ns Ns) AddNs(name string, v Ns) Ns { 92 return ns.Add(name+NsSuffix, vars.FromPtr(&v)) 93 } 94 95 // AddBuiltinFn adds a builtin function to a namespace. It returns the namespace 96 // itself. 97 func (ns Ns) AddBuiltinFn(nsName, name string, impl interface{}) Ns { 98 return ns.AddFn(name, NewBuiltinFn(nsName+name, impl)) 99 } 100 101 // AddBuiltinFns adds builtin functions to a namespace. It returns the namespace 102 // itself. 103 func (ns Ns) AddBuiltinFns(nsName string, fns map[string]interface{}) Ns { 104 for name, impl := range fns { 105 ns.AddBuiltinFn(nsName, name, impl) 106 } 107 return ns 108 } 109 110 func addrOf(a interface{}) uintptr { 111 return reflect.ValueOf(a).Pointer() 112 } 113 114 func (ns Ns) static() staticNs { 115 static := make(staticNs) 116 for name := range ns { 117 static.set(name) 118 } 119 return static 120 } 121 122 // staticNs represents static information of an Ns. 123 type staticNs map[string]struct{} 124 125 func (ns staticNs) set(name string) { 126 ns[name] = struct{}{} 127 } 128 129 func (ns staticNs) del(name string) { 130 delete(ns, name) 131 } 132 133 func (ns staticNs) has(name string) bool { 134 _, ok := ns[name] 135 return ok 136 }