internal: replace internal.CoreValue with more type-safe variant

CoreValue is now typed throught the internal/{value|types} packages.

Change-Id: I4b2df582a21fff2aaa83df61735141de11b6acbf
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9366
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/custom.go b/cmd/cue/cmd/custom.go
index ac5d554..ead236c 100644
--- a/cmd/cue/cmd/custom.go
+++ b/cmd/cue/cmd/custom.go
@@ -30,8 +30,8 @@
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/core/adt"
 	itask "cuelang.org/go/internal/task"
+	"cuelang.org/go/internal/value"
 	_ "cuelang.org/go/pkg/tool/cli" // Register tasks
 	_ "cuelang.org/go/pkg/tool/exec"
 	_ "cuelang.org/go/pkg/tool/file"
@@ -76,8 +76,7 @@
 	// TODO: remove this block to allow commands to be defined in any file.
 outer:
 	for _, v := range []cue.Value{tools.Lookup(typ), o} {
-		_, vv := internal.CoreValue(v)
-		w := vv.(*adt.Vertex)
+		_, w := value.ToInternal(v)
 		for _, c := range w.Conjuncts {
 			src := c.Source()
 			if src == nil {
diff --git a/cue/build.go b/cue/build.go
index 61f9f81..5900e89 100644
--- a/cue/build.go
+++ b/cue/build.go
@@ -56,13 +56,6 @@
 		}
 		return &Runtime{idx: newIndex()}
 	}
-
-	internal.CoreValue = func(value interface{}) (runtime, vertex interface{}) {
-		if v, ok := value.(Value); ok && v.v != nil {
-			return v.idx, v.v
-		}
-		return nil, nil
-	}
 }
 
 func dummyLoad(token.Pos, string) *build.Instance { return nil }
diff --git a/cue/types.go b/cue/types.go
index 1d1d844..a0e3d95 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -40,6 +40,7 @@
 	"cuelang.org/go/internal/core/runtime"
 	"cuelang.org/go/internal/core/subsume"
 	"cuelang.org/go/internal/core/validate"
+	"cuelang.org/go/internal/types"
 )
 
 // Kind determines the underlying type of a Value.
@@ -564,6 +565,14 @@
 	v   *adt.Vertex
 }
 
+type hiddenValue = Value
+
+// Core is for internal use only.
+func (v hiddenValue) Core(x *types.Value) {
+	x.V = v.v
+	x.R = v.idx
+}
+
 func newErrValue(v Value, b *adt.Bottom) Value {
 	node := &adt.Vertex{BaseValue: b}
 	if v.v != nil {
diff --git a/internal/core/convert/go.go b/internal/core/convert/go.go
index 5191467..5c4d646 100644
--- a/internal/core/convert/go.go
+++ b/internal/core/convert/go.go
@@ -33,10 +33,9 @@
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/compile"
-	"cuelang.org/go/internal/core/runtime"
+	"cuelang.org/go/internal/types"
 )
 
 // This file contains functionality for converting Go to CUE.
@@ -225,14 +224,9 @@
 }
 
 func convertRec(ctx *adt.OpContext, nilIsTop bool, x interface{}) adt.Value {
-	if internal.CoreValue != nil {
-		if ii, iv := internal.CoreValue(x); ii != nil {
-			i := ii.(*runtime.Runtime)
-			v := iv.(*adt.Vertex)
-			// TODO: panic if nto the same runtime.
-			_ = i
-			return v
-		}
+	if t := (&types.Value{}); types.CastValue(t, x) {
+		// TODO: panic if nto the same runtime.
+		return t.V
 	}
 	src := ctx.Source()
 	switch v := x.(type) {
diff --git a/internal/core/convert/go_test.go b/internal/core/convert/go_test.go
index 1a034c7..9d3a35f 100644
--- a/internal/core/convert/go_test.go
+++ b/internal/core/convert/go_test.go
@@ -23,7 +23,6 @@
 	"github.com/cockroachdb/apd/v2"
 	"github.com/google/go-cmp/cmp"
 
-	_ "cuelang.org/go/cue" // set internal.CoreValue
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/convert"
diff --git a/internal/core/dep/dep_test.go b/internal/core/dep/dep_test.go
index 6fb476b..449279b 100644
--- a/internal/core/dep/dep_test.go
+++ b/internal/core/dep/dep_test.go
@@ -20,14 +20,13 @@
 	"testing"
 
 	"cuelang.org/go/cue"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/debug"
 	"cuelang.org/go/internal/core/dep"
 	"cuelang.org/go/internal/core/eval"
-	"cuelang.org/go/internal/core/runtime"
 	"cuelang.org/go/internal/cuetest"
 	"cuelang.org/go/internal/cuetxtar"
+	"cuelang.org/go/internal/value"
 )
 
 func TestVisit(t *testing.T) {
@@ -45,8 +44,7 @@
 			t.Fatal(inst.Err())
 		}
 
-		rx, nx := internal.CoreValue(inst)
-		ctxt := eval.NewContext(rx.(*runtime.Runtime), nx.(*adt.Vertex))
+		ctxt := eval.NewContext(value.ToInternal(inst))
 
 		testCases := []struct {
 			name string
@@ -69,8 +67,7 @@
 		for _, tc := range testCases {
 			v := inst.LookupPath(cue.ParsePath(tc.root))
 
-			_, nx = internal.CoreValue(v)
-			n := nx.(*adt.Vertex)
+			_, n := value.ToInternal(v)
 			w := t.Writer(tc.name)
 
 			t.Run(tc.name, func(sub *testing.T) {
@@ -105,9 +102,7 @@
 
 	v := inst.Lookup("a")
 
-	rx, nx := internal.CoreValue(v)
-	r := rx.(*runtime.Runtime)
-	n := nx.(*adt.Vertex)
+	r, n := value.ToInternal(v)
 
 	ctxt := eval.NewContext(r, n)
 
diff --git a/internal/internal.go b/internal/internal.go
index 7544d95..31112fe 100644
--- a/internal/internal.go
+++ b/internal/internal.go
@@ -70,10 +70,6 @@
 // GetRuntime reports the runtime for an Instance or Value.
 var GetRuntime func(instance interface{}) interface{}
 
-// CoreValue returns an *runtime.Index and *adt.Vertex for a cue.Value.
-// It returns nil if value is not a cue.Value.
-var CoreValue func(value interface{}) (runtime, vertex interface{})
-
 // MakeInstance makes a new instance from a value.
 var MakeInstance func(value interface{}) (instance interface{})
 
diff --git a/internal/task/task.go b/internal/task/task.go
index b0af1d1..1b43bb4 100644
--- a/internal/task/task.go
+++ b/internal/task/task.go
@@ -23,8 +23,7 @@
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/value"
 )
 
 // A Context provides context for running a task.
@@ -117,9 +116,9 @@
 }
 
 func (t *taskError) InputPositions() (a []token.Pos) {
-	_, nx := internal.CoreValue(t.v)
+	_, nx := value.ToInternal(t.v)
 
-	for _, x := range nx.(*adt.Vertex).Conjuncts {
+	for _, x := range nx.Conjuncts {
 		if src := x.Source(); src != nil {
 			a = append(a, src.Pos())
 		}
diff --git a/internal/types/value.go b/internal/types/value.go
new file mode 100644
index 0000000..7b0301f
--- /dev/null
+++ b/internal/types/value.go
@@ -0,0 +1,37 @@
+// Copyright 2021 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/runtime"
+)
+
+type Value struct {
+	R *runtime.Runtime
+	V *adt.Vertex
+}
+
+type Interface interface {
+	Core(v *Value)
+}
+
+func CastValue(t *Value, x interface{}) bool {
+	c, ok := x.(Interface)
+	if ok {
+		c.Core(t)
+	}
+	return ok
+}
diff --git a/internal/value/value.go b/internal/value/value.go
new file mode 100644
index 0000000..62a127d
--- /dev/null
+++ b/internal/value/value.go
@@ -0,0 +1,40 @@
+// Copyright 2021 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package value contains functions for converting values to internal types
+// and various other Value-related utilities.
+package value
+
+import (
+	"cuelang.org/go/cue"
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/runtime"
+	"cuelang.org/go/internal/types"
+)
+
+func ToInternal(v cue.Value) (*runtime.Runtime, *adt.Vertex) {
+	var t types.Value
+	v.Core(&t)
+	return t.R, t.V
+}
+
+// TODO:
+//
+// func Make(r *runtime.Runtime, v *adt.Vertex) cue.Value {
+// 	return cue.Value{}
+// }
+
+// func MakeError(r *runtime.Runtime, err error) cue.Value {
+// 	return cue.Value{}
+// }
diff --git a/tools/flow/flow.go b/tools/flow/flow.go
index b8861b6..3669efa 100644
--- a/tools/flow/flow.go
+++ b/tools/flow/flow.go
@@ -71,11 +71,10 @@
 
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/convert"
 	"cuelang.org/go/internal/core/eval"
-	"cuelang.org/go/internal/core/runtime"
+	"cuelang.org/go/internal/value"
 )
 
 var (
@@ -197,8 +196,7 @@
 // New creates a Controller for a given Instance and TaskFunc.
 func New(cfg *Config, inst *cue.Instance, f TaskFunc) *Controller {
 	v := inst.Value()
-	rx, nx := internal.CoreValue(v)
-	ctx := eval.NewContext(rx.(*runtime.Runtime), nx.(*adt.Vertex))
+	ctx := eval.NewContext(value.ToInternal(v))
 
 	c := &Controller{
 		isTask: f,
@@ -335,8 +333,8 @@
 }
 
 func (t *Task) vertex() *adt.Vertex {
-	_, x := internal.CoreValue(t.v)
-	return x.(*adt.Vertex)
+	_, x := value.ToInternal(t.v)
+	return x
 }
 
 func (t *Task) addDep(path string, dep *Task) {
diff --git a/tools/flow/run.go b/tools/flow/run.go
index de0f55f..91336b1 100644
--- a/tools/flow/run.go
+++ b/tools/flow/run.go
@@ -28,15 +28,13 @@
 import (
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/eval"
-	"cuelang.org/go/internal/core/runtime"
+	"cuelang.org/go/internal/value"
 )
 
 func (c *Controller) runLoop() {
-	_, x := internal.CoreValue(c.inst)
-	root := x.(*adt.Vertex)
+	_, root := value.ToInternal(c.inst)
 
 	// Copy the initial conjuncts.
 	n := len(root.Conjuncts)
@@ -64,8 +62,7 @@
 				t.state = Running
 				c.updateTaskValue(t)
 
-				rx, nx := internal.CoreValue(t.v)
-				t.ctxt = eval.NewContext(rx.(*runtime.Runtime), nx.(*adt.Vertex))
+				t.ctxt = eval.NewContext(value.ToInternal(t.v))
 
 				go func(t *Task) {
 					if err := t.r.Run(t, nil); err != nil {
diff --git a/tools/flow/tasks.go b/tools/flow/tasks.go
index a20c0be..a09e680 100644
--- a/tools/flow/tasks.go
+++ b/tools/flow/tasks.go
@@ -20,9 +20,9 @@
 import (
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/dep"
+	"cuelang.org/go/internal/value"
 )
 
 // initTasks takes the current configuration and adds tasks to the list of
@@ -82,8 +82,7 @@
 // getTask finds and marks tasks that are descendents of v.
 func (c *Controller) getTask(scope *Task, v cue.Value) *Task {
 	// Look up cached node.
-	_, n := internal.CoreValue(v)
-	w := n.(*adt.Vertex)
+	_, w := value.ToInternal(v)
 	if t, ok := c.nodes[w]; ok {
 		return t
 	}
diff --git a/tools/trim/trim.go b/tools/trim/trim.go
index 0199689..d2dea39 100644
--- a/tools/trim/trim.go
+++ b/tools/trim/trim.go
@@ -56,11 +56,10 @@
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/ast/astutil"
-	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/debug"
-	"cuelang.org/go/internal/core/runtime"
 	"cuelang.org/go/internal/core/subsume"
+	"cuelang.org/go/internal/value"
 )
 
 // Config configures trim options.
@@ -73,9 +72,7 @@
 // Trimming is done on a best-effort basis and only when the removed field
 // is clearly implied by another field, rather than equal sibling fields.
 func Files(files []*ast.File, inst *cue.Instance, cfg *Config) error {
-	rx, vx := internal.CoreValue(inst.Value())
-	r := rx.(*runtime.Runtime)
-	v := vx.(*adt.Vertex)
+	r, v := value.ToInternal(inst.Value())
 
 	t := &trimmer{
 		Config:  *cfg,