internal/core/adt: add logging utilities for debugging

Change-Id: I5983a0b0758785a08674aa5a42ec636ef16bd347
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8044
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index 8da752a..3f8f792 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"log"
 	"os"
 	"reflect"
 	"regexp"
@@ -34,6 +35,11 @@
 // false otherwise.
 var Debug bool = os.Getenv("CUE_DEBUG") != "0"
 
+// Verbosity sets the log level. There are currently only two levels:
+//   0: no logging
+//   1: logging
+var Verbosity int
+
 // Assert panics if the condition is false. Assert can be used to check for
 // conditions that are considers to break an internal variant or unexpected
 // condition, but that nonetheless probably will be handled correctly down the
@@ -59,6 +65,43 @@
 	}
 }
 
+func init() {
+	log.SetFlags(log.Lshortfile)
+}
+
+func Logf(format string, args ...interface{}) {
+	if Verbosity == 0 {
+		return
+	}
+	s := fmt.Sprintf(format, args...)
+	_ = log.Output(2, s)
+}
+
+var pMap = map[*Vertex]int{}
+
+func (c *OpContext) Logf(v *Vertex, format string, args ...interface{}) {
+	if Verbosity == 0 {
+		return
+	}
+	p := pMap[v]
+	if p == 0 {
+		p = len(pMap) + 1
+		pMap[v] = p
+	}
+	a := append([]interface{}{
+		p,
+		v.Label.SelectorString(c),
+		v.Path(),
+	}, args...)
+	for i := 2; i < len(a); i++ {
+		if n, ok := a[i].(Node); ok {
+			a[i] = c.Str(n)
+		}
+	}
+	s := fmt.Sprintf(" [%d] %s/%v"+format, a...)
+	_ = log.Output(2, s)
+}
+
 // A Unifier implements a strategy for CUE's unification operation. It must
 // handle the following aspects of CUE evaluation:
 //
diff --git a/internal/core/eval/eval_test.go b/internal/core/eval/eval_test.go
index a167a2c..8d1d225 100644
--- a/internal/core/eval/eval_test.go
+++ b/internal/core/eval/eval_test.go
@@ -23,6 +23,7 @@
 	"github.com/rogpeppe/go-internal/txtar"
 
 	"cuelang.org/go/cue"
+	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/debug"
 	"cuelang.org/go/internal/core/eval"
 	"cuelang.org/go/internal/core/validate"
@@ -120,9 +121,11 @@
 	// t.Error(debug.NodeString(r, v, nil))
 	// eval.Debug = true
 
+	adt.Verbosity = 1
 	e := eval.New(r)
 	ctx := e.NewContext(v)
 	v.Finalize(ctx)
+	adt.Verbosity = 0
 
 	t.Error(debug.NodeString(r, v, nil))