Skip to content

Instantly share code, notes, and snippets.

@iv-menshenin
Created February 1, 2020 18:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iv-menshenin/78a6f1cfc1126e4ab853e5dc8342be08 to your computer and use it in GitHub Desktop.
Save iv-menshenin/78a6f1cfc1126e4ab853e5dc8342be08 to your computer and use it in GitHub Desktop.
Visualize the principle of tree walking
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"os"
"strings"
)
var goCode = `
package test
func test() {
var i string
if (true) {
var i *int
for {
*i++
}
}
i += "done"
return i
}
`
type(
Walker struct {
pass bool
names []*ast.Ident
}
)
func (w *Walker) Visit(n ast.Node) ast.Visitor {
var pass = w.pass
if decl, ok := n.(*ast.DeclStmt); ok {
if spec, ok := decl.Decl.(*ast.GenDecl); ok {
if spec.Tok == token.VAR {
pass = true
for _, s := range spec.Specs {
if v, ok := s.(*ast.ValueSpec); ok {
if _, ok := v.Type.(*ast.StarExpr); ok {
w.names = append(w.names, v.Names...)
}
}
}
}
}
} else
if n != nil {
if x, ok := n.(*ast.Ident); ok && !w.pass {
for _, i := range w.names {
if x.Name == i.Name {
println("PANIC! USAGE OF REF: " + i.Name)
}
}
}
a := make([]string, 0, len(w.names))
for _, i := range w.names {
a = append(a, i.Name)
}
if len(a) > 0 {
println("ref variables: " + strings.Join(a, ", "))
}
println(fmt.Sprintf("<%T>: %+v", n, n))
println(fmt.Sprintf("%+v", w))
println("----------------")
}
return &Walker{
pass: pass,
names: append([]*ast.Ident{}, w.names...),
}
}
func main(){
var(
err error
walker Walker
)
fset1 := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset1, "", strings.NewReader(goCode), 0)
if err != nil {
panic(err)
}
filePrinter := printer.Config{
Mode: printer.UseSpaces | printer.TabIndent,
Tabwidth: 8,
}
if err := filePrinter.Fprint(os.Stdout, fset1, f); err != nil {
panic(err)
}
if err := ast.Print(fset1, f); err != nil {
panic(err)
}
ast.Walk(&walker, f)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment