cue: add internal error types

Issue #52

Change-Id: I15a132abf391fd891672ae41f2213cd380d7d8f3
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2203
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/errors.go b/cue/errors.go
index c74708f..bc1e2ae 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -15,13 +15,66 @@
 package cue
 
 import (
+	"fmt"
 	"sort"
 
+	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
-	"golang.org/x/exp/errors"
-	"golang.org/x/exp/errors/fmt"
+	"golang.org/x/xerrors"
 )
 
+// A nodeError is an error associated with processing an AST node.
+type nodeError struct {
+	path []string // optional
+	n    ast.Node
+
+	errors.Message
+}
+
+func nodeErrorf(n ast.Node, format string, args ...interface{}) *nodeError {
+	return &nodeError{
+		n:       n,
+		Message: errors.Message{Format: format, Args: args},
+	}
+}
+
+func (e *nodeError) Position() token.Position {
+	return e.n.Pos().Position()
+}
+
+func (e *nodeError) Path() []string {
+	return e.path
+}
+
+func (v Value) toErr(b *bottom) errors.Error {
+	return &valueError{
+		Message: errors.Message{
+			Format: b.msg,
+			Args:   nil,
+		},
+		v:   v,
+		err: b,
+	}
+}
+
+// A valueError is returned as a result of evaluating a value.
+type valueError struct {
+	errors.Message
+
+	v   Value
+	err *bottom
+}
+
+func (e *valueError) Position() token.Position {
+	return e.err.pos.Pos().Position()
+}
+
+func (e *valueError) Path() (a []string) {
+	a, _ = e.v.path.appendPath(a, e.v.idx)
+	return a
+}
+
 type errCode int
 
 const (
@@ -109,7 +162,11 @@
 
 func (x *bottom) Error() string { return fmt.Sprint(x) }
 
-func (x *bottom) FormatError(p errors.Printer) error {
+func (x *bottom) Format(s fmt.State, verb rune) {
+	xerrors.FormatError(x, s, verb)
+}
+
+func (x *bottom) FormatError(p xerrors.Printer) error {
 	p.Print(x.msg)
 	if p.Detail() && x.index != nil {
 		locs := appendLocations(nil, x.pos)
diff --git a/cue/value.go b/cue/value.go
index 66ae5e4..4ffbbb1 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -1245,6 +1245,7 @@
 		// Take the first error as an example.
 		err := x.values[0].val
 		if !isBottom(err) {
+			// TODO: use format instead of debugStr.
 			err = ctx.mkErr(src, debugStr(ctx, err))
 		}
 		return mVal{ctx.mkErr(src, "empty disjunction: %v", err), false}