func WalkValues(target Value, vr ValueReader, cb SkipValueCallback) {
	visited := hash.HashSet{}
	refs := map[hash.Hash]bool{}
	values := []valueRec{{target, true}}
	for len(values) > 0 || len(refs) > 0 {
		for len(values) > 0 {
			rec := values[len(values)-1]
			values = values[:len(values)-1]
			v := rec.v
			if rec.cb && cb(v) {
				continue
			}
			if _, ok := v.(Blob); ok {
				continue  
			}
			if r, ok := v.(Ref); ok {
				refs[r.TargetHash()] = true
				continue
			}
			if col, ok := v.(Collection); ok && !col.asSequence().isLeaf() {
				col.WalkRefs(func(r Ref) {
					refs[r.TargetHash()] = false
				})
				continue
			}
			v.WalkValues(func(sv Value) {
				values = append(values, valueRec{sv, true})
			})
		}
		if len(refs) == 0 {
			continue
		}
		hs := make(hash.HashSlice, 0, len(refs))
		oldRefs := refs
		refs = map[hash.Hash]bool{}
		for h := range oldRefs {
			if _, ok := visited[h]; ok {
				continue
			}
			if len(hs) >= maxRefCount {
				refs[h] = oldRefs[h]
				continue
			}
			hs = append(hs, h)
			visited.Insert(h)
		}
		if len(hs) > 0 {
			readValues := vr.ReadManyValues(hs)
			for i, sv := range readValues {
				values = append(values, valueRec{sv, oldRefs[hs[i]]})
			}
		}
	}
}
WalkValues recursively walks over all types.Values reachable from r and calls cb on them.
package types
import "github.com/attic-labs/noms/go/hash"
type SkipValueCallback func(v Value) bool
type valueRec struct {
	v  Value
	cb bool
}
const maxRefCount = 1 << 12  