internal/core/runtime: decouple cue API from Runtime

The main goal here is to decouple the caching, and
that to the cue.Runtime. That will ultimately make it
easier to not cache Instances, which can hog memory
allocation.

Change-Id: I0cf9678b867e6afd18d1e5abb6961702e37170c9
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/8222
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/build.go b/cue/build.go
index bdaf00f..2ea58e8 100644
--- a/cue/build.go
+++ b/cue/build.go
@@ -193,25 +193,19 @@
 	})
 }
 
-type importIndex map[*build.Instance]*Instance
-
 // index maps conversions from label names to internal codes.
 //
 // All instances belonging to the same package should share this index.
 type index struct {
 	*runtime.Runtime
-	loaded importIndex
+	loaded map[*build.Instance]*Instance
 }
 
 // NewRuntime creates a *runtime.Runtime with builtins preloaded.
 func NewRuntime() *runtime.Runtime {
-	r := runtime.New()
-	i := &index{
-		Runtime: r,
-		loaded:  importIndex{},
-	}
-	r.Data = i
-	return r
+	i := newIndex()
+	i.Runtime.Data = i
+	return i.Runtime
 }
 
 // newIndex creates a new index.
@@ -219,7 +213,7 @@
 	r := runtime.New()
 	i := &index{
 		Runtime: r,
-		loaded:  importIndex{},
+		loaded:  map[*build.Instance]*Instance{},
 	}
 	r.Data = i
 	return i
@@ -230,6 +224,6 @@
 }
 
 func (idx *index) loadInstance(p *build.Instance) *Instance {
-	idx.Runtime.Build(p)
-	return idx.getImportFromBuild(p)
+	v, _ := idx.Runtime.Build(p)
+	return idx.getImportFromBuild(p, v)
 }
diff --git a/cue/instance.go b/cue/instance.go
index d5b43f3..53bc5d6 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -59,18 +59,13 @@
 	return p
 }
 
-func (x *index) getImportFromBuild(p *build.Instance) *Instance {
+func (x *index) getImportFromBuild(p *build.Instance, v *adt.Vertex) *Instance {
 	inst := x.loaded[p]
 
 	if inst != nil {
 		return inst
 	}
 
-	v := x.GetNodeFromInstance(p)
-	if v == nil {
-		return nil
-	}
-
 	inst = &Instance{
 		ImportPath:  p.ImportPath,
 		Dir:         p.Dir,
@@ -95,7 +90,7 @@
 		return nil
 	}
 
-	return x.getImportFromBuild(p)
+	return x.getImportFromBuild(p, v)
 }
 
 func (x *index) getImportFromPath(id string) *Instance {
diff --git a/cue/types.go b/cue/types.go
index b85cfbf..e78c41f 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -1857,7 +1857,7 @@
 	if v.v == nil {
 		return nil
 	}
-	return v.ctx().getImportFromNode(v.v)
+	return v.idx.getImportFromNode(v.v)
 }
 
 // Reference returns the instance and path referred to by this value such that
diff --git a/internal/core/runtime/build.go b/internal/core/runtime/build.go
index c167e16..0927071 100644
--- a/internal/core/runtime/build.go
+++ b/internal/core/runtime/build.go
@@ -28,7 +28,7 @@
 // Build builds b and all its transitive dependencies, insofar they have not
 // been build yet.
 func (x *Runtime) Build(b *build.Instance) (v *adt.Vertex, errs errors.Error) {
-	if v := x.GetNodeFromInstance(b); v != nil {
+	if v := x.getNodeFromInstance(b); v != nil {
 		return v, b.Err
 	}
 	// TODO: clear cache of old implementation.
diff --git a/internal/core/runtime/imports.go b/internal/core/runtime/imports.go
index 4f25c96..97f718d 100644
--- a/internal/core/runtime/imports.go
+++ b/internal/core/runtime/imports.go
@@ -95,7 +95,7 @@
 	return r.index.imports[key]
 }
 
-func (r *Runtime) GetNodeFromInstance(key *build.Instance) *adt.Vertex {
+func (r *Runtime) getNodeFromInstance(key *build.Instance) *adt.Vertex {
 	return r.index.importsByBuild[key]
 }