github.com/elves/Elvish@v0.12.0/eval/ns.go (about)

     1  package eval
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/elves/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  }