mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-18 13:01:11 +01:00
101 lines
2.0 KiB
Go
101 lines
2.0 KiB
Go
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
|