/
printstate.go
100 lines (84 loc) · 1.96 KB
/
printstate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package zygo
import (
"fmt"
)
// begin supporting SexpString structs
// PrintState threads the state of display through SexpString() and Show() calls,
// to give pretty-printing indentation and to avoid infinite looping on
// cyclic data structures.
type PrintState struct {
Indent int
Seen Seen
}
func (ps *PrintState) SetSeen(x interface{}, name string) {
if ps == nil {
panic("can't SetSeen on a nil PrintState")
}
ps.Seen[x] = struct{}{}
}
func (ps *PrintState) GetSeen(x interface{}) bool {
if ps == nil {
return false
}
_, ok := ps.Seen[x]
return ok
}
func (ps *PrintState) GetIndent() int {
if ps == nil {
return 0
}
return ps.Indent
}
func (ps *PrintState) AddIndent(addme int) *PrintState {
if ps == nil {
return &PrintState{
Indent: addme,
Seen: NewSeen(),
}
}
return &PrintState{
Indent: ps.Indent + addme,
Seen: ps.Seen,
}
}
func NewPrintState() *PrintState {
return &PrintState{
Seen: NewSeen(),
}
}
func NewPrintStateWithIndent(indent int) *PrintState {
return &PrintState{
Indent: indent,
Seen: NewSeen(),
}
}
func (ps *PrintState) Clear() {
ps.Indent = 0
ps.Seen = NewSeen()
}
func (ps *PrintState) Dump() {
fmt.Printf("ps Dump: ")
if ps == nil {
fmt.Printf("nil\n")
return
}
for k, v := range ps.Seen {
fmt.Printf("ps Dump: %p -- %v\n", k, v)
}
fmt.Printf("\n")
}
// Seen tracks if a value has already been displayed, to
// detect and avoid cycles.
//
/* Q: How to do garbage-collection safe graph traversal in a graph of Go objects?
A: "Instead of converting the pointer to a uintptr, just store the pointer
itself in a map[interface{}]bool. If you encounter the same pointer
again, you will get the same map entry. The GC must guarantee that
using pointers as map keys will work even if the pointers move."
- Ian Lance Taylor on golang-nuts (2016 June 20).
*/
type Seen map[interface{}]struct{}
func NewSeen() Seen {
return Seen(make(map[interface{}]struct{}))
}
// end supporting SexpString structs