2018-02-16 17:36:02 +03:00
|
|
|
package match
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"sync/atomic"
|
|
|
|
)
|
|
|
|
|
|
|
|
var i = new(int32)
|
|
|
|
|
|
|
|
func logf(f string, args ...interface{}) {
|
|
|
|
n := int(atomic.LoadInt32(i))
|
|
|
|
fmt.Fprint(os.Stderr,
|
|
|
|
strings.Repeat(" ", n),
|
|
|
|
fmt.Sprintf("(%d) ", n),
|
|
|
|
fmt.Sprintf(f, args...),
|
|
|
|
"\n",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func enter() {
|
|
|
|
atomic.AddInt32(i, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func leave() {
|
|
|
|
atomic.AddInt32(i, -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Graphviz(pattern string, m Matcher) string {
|
|
|
|
return fmt.Sprintf(`digraph G {graph[label="%s"];%s}`, pattern, graphviz(m, fmt.Sprintf("%x", rand.Int63())))
|
|
|
|
}
|
|
|
|
|
|
|
|
func graphviz(m Matcher, id string) string {
|
|
|
|
buf := &bytes.Buffer{}
|
|
|
|
|
|
|
|
switch v := m.(type) {
|
|
|
|
case Tree:
|
|
|
|
fmt.Fprintf(buf, `"%s"[label="%s"];`, id, v.value)
|
|
|
|
for _, m := range []Matcher{v.left, v.right} {
|
|
|
|
switch n := m.(type) {
|
|
|
|
case nil:
|
|
|
|
rnd := rand.Int63()
|
|
|
|
fmt.Fprintf(buf, `"%x"[label="<nil>"];`, rnd)
|
|
|
|
fmt.Fprintf(buf, `"%s"->"%x";`, id, rnd)
|
|
|
|
|
|
|
|
default:
|
|
|
|
sub := fmt.Sprintf("%x", rand.Int63())
|
|
|
|
fmt.Fprintf(buf, `"%s"->"%s";`, id, sub)
|
|
|
|
fmt.Fprintf(buf, graphviz(n, sub))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case Container:
|
2019-02-06 23:43:38 +03:00
|
|
|
fmt.Fprintf(buf, `"%s"[label="Container(%T)"];`, id, m)
|
|
|
|
v.Content(func(m Matcher) {
|
2018-02-16 17:36:02 +03:00
|
|
|
rnd := rand.Int63()
|
|
|
|
fmt.Fprintf(buf, graphviz(m, fmt.Sprintf("%x", rnd)))
|
|
|
|
fmt.Fprintf(buf, `"%s"->"%x";`, id, rnd)
|
2019-02-06 23:43:38 +03:00
|
|
|
})
|
2018-02-16 17:36:02 +03:00
|
|
|
|
|
|
|
default:
|
|
|
|
fmt.Fprintf(buf, `"%s"[label="%s"];`, id, m)
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.String()
|
|
|
|
}
|