package evalimport ()// Ns is the runtime representation of a namespace. The zero value of Ns is an// empty namespace. To create a non-empty Ns, use either NsBuilder or CombineNs.//// An Ns is immutable after creation.typeNsstruct {// All variables in the namespace. Static variable accesses are compiled // into indexed accesses into this slice.slots []vars.Var// Names for the variables, used for introspection. Typical real programs // only contain a small number of names in each namespace, in which case a // linear search in a slice is usually faster than map access.names []string// Whether the variable has been deleted. Deleted variables can still be // kept in the Ns since there might be a reference to them in a closure. // Shadowed variables are also considered deleted.deleted []bool}// CombineNs returns an *Ns that contains all the bindings from both ns1 and// ns2. Names in ns2 takes precedence over those in ns1.func ( *Ns, *Ns) *Ns { := &Ns{append([]vars.Var(nil), .slots...),append([]string(nil), .names...),append([]bool(nil), .deleted...)} := map[string]bool{}for , := range .names {if !.deleted[] { [] = true } }for , := range .names {if !.deleted[] && ![] { .slots = append(.slots, .slots[]) .names = append(.names, ) .deleted = append(.deleted, false) } }return}// Kind returns "ns".func ( *Ns) () string {return"ns"}// Hash returns a hash of the address of ns.func ( *Ns) () uint32 {returnhash.Pointer(unsafe.Pointer())}// Equal returns whether rhs has the same identity as ns.func ( *Ns) ( interface{}) bool {if , := .(*Ns); {return == }returnfalse}// Repr returns an opaque representation of the Ns showing its address.func ( *Ns) (int) string {returnfmt.Sprintf("<ns %p>", )}// Index looks up a variable with the given name, and returns its value if it// exists. This is only used for introspection from Elvish code; for// introspection from Go code, use IndexName.func ( *Ns) ( interface{}) (interface{}, bool) {if , := .(string); { := .IndexName()if == nil {returnnil, false }return .Get(), true }returnnil, false}// IndexName looks up a variable with the given name, and returns its value if it exists, or nil if// it does not. This is the type-safe version of Index and is useful for introspection from Go code.func ( *Ns) ( string) vars.Var { := .lookup()if != -1 {return .slots[] }returnnil}func ( *Ns) ( string) int {for , := range .names {if == && !.deleted[] {return } }return -1}// IterateKeys produces the names of all the variables in this Ns.func ( *Ns) ( func(interface{}) bool) {for , := range .names {if .slots[] == nil || .deleted[] {continue }if !() {break } }}// IterateNames produces the names of all variables in the Ns. It is the// type-safe version of IterateKeys and is useful for introspection from Go// code. It doesn't support breaking early.func ( *Ns) ( func(string)) {for , := range .names {if .slots[] != nil && !.deleted[] { () } }}// HasName reports whether the Ns has a variable with the given name.func ( *Ns) ( string) bool {for , := range .names {if == && !.deleted[] {return .slots[] != nil } }returnfalse}func ( *Ns) () *staticNs {return &staticNs{.names, .deleted}}// NsBuilder is a helper type used for building an Ns.typeNsBuildermap[string]vars.Var// Add adds a variable.func ( NsBuilder) ( string, vars.Var) NsBuilder { [] = return}// AddFn adds a function. The resulting variable will be read-only.func ( NsBuilder) ( string, Callable) NsBuilder {return .Add(+FnSuffix, vars.NewReadOnly())}// AddNs adds a sub-namespace. The resulting variable will be read-only.func ( NsBuilder) ( string, *Ns) NsBuilder {return .Add(+NsSuffix, vars.NewReadOnly())}// AddGoFn adds a Go function. The resulting variable will be read-only.func ( NsBuilder) (, string, interface{}) NsBuilder {return .AddFn(, NewGoFn(+, ))}// AddGoFns adds Go functions. The resulting variables will be read-only.func ( NsBuilder) ( string, map[string]interface{}) NsBuilder {for , := range { .AddGoFn(, , ) }return}// Ns builds a namespace.func ( NsBuilder) () *Ns { := len() := &Ns{make([]vars.Var, ), make([]string, ), make([]bool, )} := 0for , := range { .slots[] = .names[] = ++ }return}// The compile-time representation of a namespace. Called "static" namespace// since it contains information that are known without executing the code.// The data structure itself, however, is not static, and gets mutated as the// compiler gains more information about the namespace. The zero value of// staticNs is an empty namespace.typestaticNsstruct {names []stringdeleted []bool}func ( *staticNs) () *staticNs {return &staticNs{append([]string{}, .names...), append([]bool{}, .deleted...)}}func ( *staticNs) ( string) {if := .lookup(); != -1 { .deleted[] = true }}// Adds a name, shadowing any existing one.func ( *staticNs) ( string) int { .del()return .addInner()}// Adds a name, assuming that it either doesn't exist yet or has been deleted.func ( *staticNs) ( string) int { .names = append(.names, ) .deleted = append(.deleted, false)returnlen(.names) - 1}func ( *staticNs) ( string) int {for , := range .names {if == && !.deleted[] {return } }return -1}typestaticUpNsstruct {names []string// For each name, whether the upvalue comes from the immediate outer scope, // i.e. the local scope a lambda is evaluated in.local []bool// Index of the upvalue variable, either into the local scope (if // the corresponding value in local is true) or the up scope (if the // corresponding value in local is false).index []int}func ( *staticUpNs) ( string, bool, int) int {for , := range .names {if == {return } } .names = append(.names, ) .local = append(.local, ) .index = append(.index, )returnlen(.names) - 1}
The pages are generated with Goldsv0.2.8-preview. (GOOS=darwin GOARCH=arm64)