package interp import ( "fmt" "reflect" "strings" ) // Set trace to true for debugging the cfg and other processes. var trace = false func traceIndent(n *node) string { return strings.Repeat(" ", n.depth()) } // tracePrintln works like fmt.Println, with indenting by depth // and key info on given node. func tracePrintln(n *node, v ...any) { if !trace { return } fmt.Println(append([]any{traceIndent(n), n}, v...)...) } // tracePrintTree is particularly useful in post-order for seeing the full // structure of a given code segment of interest. // //nolint:unused // debugging facility func tracePrintTree(n *node, v ...any) { if !trace { return } tracePrintln(n, v...) n.Walk(func(n *node) bool { tracePrintln(n) return true }, nil) } // nodeAddr returns the pointer address of node, short version. func ptrAddr(v any) string { p := fmt.Sprintf("%p", v) return p[:2] + p[9:] // unique bits } // valString returns string rep of given value, showing underlying pointers etc. // //nolint:unused // debugging facility func valString(v reflect.Value) string { s := v.String() if v.Kind() == reflect.Func || v.Kind() == reflect.Map || v.Kind() == reflect.Pointer || v.Kind() == reflect.Slice || v.Kind() == reflect.UnsafePointer { p := fmt.Sprintf("%#x", v.Pointer()) ln := len(p) s += " " + p[:2] + p[max(2, ln-4):] } return s } func (n *node) String() string { s := n.kind.String() if n.ident != "" { s += " " + n.ident } s += " " + ptrAddr(n) if n.sym != nil { s += " sym:" + n.sym.String() } else if n.typ != nil { s += " typ:" + n.typ.String() } if n.findex >= 0 { s += fmt.Sprintf(" fidx: %d lev: %d", n.findex, n.level) } if n.start != nil && n.start != n { s += fmt.Sprintf(" ->start: %s %s", n.start.kind.String(), ptrAddr(n.start)) } if n.tnext != nil { s += fmt.Sprintf(" ->tnext: %s %s", n.tnext.kind.String(), ptrAddr(n.tnext)) } if n.fnext != nil { s += fmt.Sprintf(" ->fnext: %s %s", n.fnext.kind.String(), ptrAddr(n.fnext)) } return s } func (n *node) depth() int { if n.anc != nil { return n.anc.depth() + 1 } return 0 } func (sy *symbol) String() string { s := sy.kind.String() if sy.typ != nil { s += " (" + sy.typ.String() + ")" } if sy.rval.IsValid() { s += " = " + sy.rval.String() } if sy.index >= 0 { s += fmt.Sprintf(" idx: %d", sy.index) } if sy.node != nil { s += " " + sy.node.String() } return s } func (t *itype) String() string { if t.str != "" { return t.str } s := t.cat.String() if t.name != "" { s += " (" + t.name + ")" } return s }