github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/callgraph/vta/internal/trie/trie.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // trie implements persistent Patricia trie maps. 6 // 7 // Each Map is effectively a map from uint64 to interface{}. Patricia tries are 8 // a form of radix tree that are particularly appropriate when many maps will be 9 // created, merged together and large amounts of sharing are expected (e.g. 10 // environment abstract domains in program analysis). 11 // 12 // This implementation closely follows the paper: 13 // C. Okasaki and A. Gill, “Fast mergeable integer maps,” in ACM SIGPLAN 14 // Workshop on ML, September 1998, pp. 77–86. 15 // Each Map is immutable and can be read from concurrently. The map does not 16 // guarantee that the value pointed to by the interface{} value is not updated 17 // concurrently. 18 // 19 // These Maps are optimized for situations where there will be many maps created at 20 // with a high degree of sharing and combining of maps together. If you do not expect, 21 // significant amount of sharing, the builtin map[T]U is much better choice! 22 // 23 // Each Map is created by a Builder. Each Builder has a unique Scope and each node is 24 // created within this scope. Maps x and y are == if they contains the same 25 // (key,value) mappings and have equal scopes. 26 // 27 // Internally these are big endian Patricia trie nodes, and the keys are sorted. 28 package trie 29 30 import ( 31 "fmt" 32 "strings" 33 ) 34 35 // Map is effectively a finite mapping from uint64 keys to interface{} values. 36 // Maps are immutable and can be read from concurrently. 37 // 38 // Notes on concurrency: 39 // - A Map value itself is an interface and assignments to a Map value can race. 40 // - Map does not guarantee that the value pointed to by the interface{} value 41 // is not updated concurrently. 42 type Map struct { 43 s Scope 44 n node 45 } 46 47 func (m Map) Scope() Scope { 48 return m.s 49 } 50 func (m Map) Size() int { 51 if m.n == nil { 52 return 0 53 } 54 return m.n.size() 55 } 56 func (m Map) Lookup(k uint64) (interface{}, bool) { 57 if m.n != nil { 58 if leaf := m.n.find(key(k)); leaf != nil { 59 return leaf.v, true 60 } 61 } 62 return nil, false 63 } 64 65 // Converts the map into a {<key>: <value>[, ...]} string. This uses the default 66 // %s string conversion for <value>. 67 func (m Map) String() string { 68 var kvs []string 69 m.Range(func(u uint64, i interface{}) bool { 70 kvs = append(kvs, fmt.Sprintf("%d: %s", u, i)) 71 return true 72 }) 73 return fmt.Sprintf("{%s}", strings.Join(kvs, ", ")) 74 } 75 76 // Range over the leaf (key, value) pairs in the map in order and 77 // applies cb(key, value) to each. Stops early if cb returns false. 78 // Returns true if all elements were visited without stopping early. 79 func (m Map) Range(cb func(uint64, interface{}) bool) bool { 80 if m.n != nil { 81 return m.n.visit(cb) 82 } 83 return true 84 } 85 86 // DeepEqual returns true if m and other contain the same (k, v) mappings 87 // [regardless of Scope]. 88 // 89 // Equivalently m.DeepEqual(other) <=> reflect.DeepEqual(Elems(m), Elems(other)) 90 func (m Map) DeepEqual(other Map) bool { 91 if m.Scope() == other.Scope() { 92 return m.n == other.n 93 } 94 if (m.n == nil) || (other.n == nil) { 95 return m.Size() == 0 && other.Size() == 0 96 } 97 return m.n.deepEqual(other.n) 98 } 99 100 // Elems are the (k,v) elements in the Map as a map[uint64]interface{} 101 func Elems(m Map) map[uint64]interface{} { 102 dest := make(map[uint64]interface{}, m.Size()) 103 m.Range(func(k uint64, v interface{}) bool { 104 dest[k] = v 105 return true 106 }) 107 return dest 108 } 109 110 // node is an internal node within a trie map. 111 // A node is either empty, a leaf or a branch. 112 type node interface { 113 size() int 114 115 // visit the leaves (key, value) pairs in the map in order and 116 // applies cb(key, value) to each. Stops early if cb returns false. 117 // Returns true if all elements were visited without stopping early. 118 visit(cb func(uint64, interface{}) bool) bool 119 120 // Two nodes contain the same elements regardless of scope. 121 deepEqual(node) bool 122 123 // find the leaf for the given key value or nil if it is not present. 124 find(k key) *leaf 125 126 // implementations must implement this. 127 nodeImpl() 128 } 129 130 // empty represents the empty map within a scope. 131 // 132 // The current builder ensure 133 type empty struct { 134 s Scope 135 } 136 137 // leaf represents a single <key, value> pair. 138 type leaf struct { 139 k key 140 v interface{} 141 } 142 143 // branch represents a tree node within the Patricia trie. 144 // 145 // All keys within the branch match a `prefix` of the key 146 // up to a `branching` bit, and the left and right nodes 147 // contain keys that disagree on the bit at the `branching` bit. 148 type branch struct { 149 sz int // size. cached for O(1) lookup 150 prefix prefix // == mask(p0, branching) for some p0 151 branching bitpos 152 153 // Invariants: 154 // - neither is nil. 155 // - neither is *empty. 156 // - all keys in left are <= p. 157 // - all keys in right are > p. 158 left, right node 159 } 160 161 // all of these types are Maps. 162 var _ node = &empty{} 163 var _ node = &leaf{} 164 var _ node = &branch{} 165 166 func (*empty) nodeImpl() {} 167 func (*leaf) nodeImpl() {} 168 func (*branch) nodeImpl() {} 169 170 func (*empty) find(k key) *leaf { return nil } 171 func (l *leaf) find(k key) *leaf { 172 if k == l.k { 173 return l 174 } 175 return nil 176 } 177 func (br *branch) find(k key) *leaf { 178 kp := prefix(k) 179 if !matchPrefix(kp, br.prefix, br.branching) { 180 return nil 181 } 182 if zeroBit(kp, br.branching) { 183 return br.left.find(k) 184 } 185 return br.right.find(k) 186 } 187 188 func (*empty) size() int { return 0 } 189 func (*leaf) size() int { return 1 } 190 func (br *branch) size() int { return br.sz } 191 192 func (*empty) deepEqual(m node) bool { 193 _, ok := m.(*empty) 194 return ok 195 } 196 func (l *leaf) deepEqual(m node) bool { 197 if m, ok := m.(*leaf); ok { 198 return m == l || (l.k == m.k && l.v == m.v) 199 } 200 return false 201 } 202 203 func (br *branch) deepEqual(m node) bool { 204 if m, ok := m.(*branch); ok { 205 if br == m { 206 return true 207 } 208 return br.sz == m.sz && br.branching == m.branching && br.prefix == m.prefix && 209 br.left.deepEqual(m.left) && br.right.deepEqual(m.right) 210 } 211 // if m is not a branch, m contains 0 or 1 elem. 212 // br contains at least 2 keys that disagree on a prefix. 213 return false 214 } 215 216 func (*empty) visit(cb func(uint64, interface{}) bool) bool { 217 return true 218 } 219 func (l *leaf) visit(cb func(uint64, interface{}) bool) bool { 220 return cb(uint64(l.k), l.v) 221 } 222 func (br *branch) visit(cb func(uint64, interface{}) bool) bool { 223 if !br.left.visit(cb) { 224 return false 225 } 226 return br.right.visit(cb) 227 }