cue: refactor index
Prepare to hoist index type.
Moves Loaded to runtime.Runtime.
Change-Id: Id4fb32a487281e0fed35f88fb911d8db8470ad4a
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9363
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 b694906..2101032 100644
--- a/cue/build.go
+++ b/cue/build.go
@@ -79,7 +79,7 @@
if err := p.Complete(); err != nil {
return nil, err
}
- inst := idx.loadInstance(p)
+ inst := loadInstance(idx, p)
inst.ImportPath = p.ImportPath
if inst.Err != nil {
return nil, inst.Err
@@ -165,7 +165,7 @@
_ = p.Complete()
errs = errors.Append(errs, p.Err)
- i := index.loadInstance(p)
+ i := loadInstance(index, p)
errs = errors.Append(errs, i.Err)
loaded = append(loaded, i)
}
@@ -189,7 +189,6 @@
// All instances belonging to the same package should share this index.
type index struct {
*runtime.Runtime
- loaded map[*build.Instance]*Instance
}
// NewRuntime creates a *runtime.Runtime with builtins preloaded.
@@ -204,7 +203,6 @@
r := runtime.New()
i := &index{
Runtime: r,
- loaded: map[*build.Instance]*Instance{},
}
r.Data = i
return i
@@ -214,7 +212,7 @@
return runtime.SharedRuntime.IsBuiltinPackage(s)
}
-func (idx *index) loadInstance(p *build.Instance) *Instance {
+func loadInstance(idx *index, p *build.Instance) *Instance {
v, _ := idx.Runtime.Build(p)
- return idx.getImportFromBuild(p, v)
+ return getImportFromBuild(idx, p, v)
}
diff --git a/cue/build_test.go b/cue/build_test.go
index 55e4268..ccaeca8 100644
--- a/cue/build_test.go
+++ b/cue/build_test.go
@@ -200,7 +200,7 @@
got = err.Error()
} else {
cfg := &debug.Config{Compact: true}
- got = debug.NodeString(insts[0].Runtime, insts[0].Value().v, cfg)
+ got = debug.NodeString(insts[0].index.Runtime, insts[0].Value().v, cfg)
}
if got != tc.emit {
t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
diff --git a/cue/context.go b/cue/context.go
index 33d213d..48a7d09 100644
--- a/cue/context.go
+++ b/cue/context.go
@@ -27,7 +27,7 @@
}
// newContext returns a new evaluation context.
-func (idx *index) newContext() *context {
+func newContext(idx *index) *context {
c := &context{
index: idx,
}
diff --git a/cue/instance.go b/cue/instance.go
index e391129..63b1d68 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -28,7 +28,7 @@
// An Instance defines a single configuration based on a collection of
// underlying CUE files.
type Instance struct {
- *index
+ index *index
root *adt.Vertex
@@ -54,13 +54,20 @@
}
// fmt.Println(p.ImportPath, "XXX")
x.AddInst(p.ImportPath, p.root, p.inst)
- x.loaded[p.inst] = p
+ x.SetBuildData(p.inst, p)
p.index = x
return p
}
-func (x *index) getImportFromBuild(p *build.Instance, v *adt.Vertex) *Instance {
- inst := x.loaded[p]
+func lookupInstance(x *index, p *build.Instance) *Instance {
+ if x, ok := x.BuildData(p); ok {
+ return x.(*Instance)
+ }
+ return nil
+}
+
+func getImportFromBuild(x *index, p *build.Instance, v *adt.Vertex) *Instance {
+ inst := lookupInstance(x, p)
if inst != nil {
return inst
@@ -79,27 +86,27 @@
inst.setListOrError(p.Err)
}
- x.loaded[p] = inst
+ x.SetBuildData(p, inst)
return inst
}
-func (x *index) getImportFromNode(v *adt.Vertex) *Instance {
+func getImportFromNode(x *index, v *adt.Vertex) *Instance {
p := x.GetInstanceFromNode(v)
if p == nil {
return nil
}
- return x.getImportFromBuild(p, v)
+ return getImportFromBuild(x, p, v)
}
-func (x *index) getImportFromPath(id string) *Instance {
+func getImportFromPath(x *index, id string) *Instance {
node, _ := x.LoadImport(id)
if node == nil {
return nil
}
b := x.GetInstanceFromNode(node)
- inst := x.loaded[b]
+ inst := lookupInstance(x, b)
if inst == nil {
inst = &Instance{
ImportPath: b.ImportPath,
@@ -145,7 +152,7 @@
}
x.AddInst(p.ImportPath, v, p)
- x.loaded[p] = inst
+ x.SetBuildData(p, inst)
inst.index = x
return inst
}
@@ -170,7 +177,7 @@
internal.EvalExpr = func(value, expr interface{}) interface{} {
v := value.(Value)
e := expr.(ast.Expr)
- ctx := v.idx.newContext()
+ ctx := newContext(v.idx)
return newValueRoot(ctx, evalExpr(ctx, v.vertex(ctx), e))
}
}
@@ -262,7 +269,7 @@
// defines in emit value, it will be that value. Otherwise it will be all
// top-level values.
func (inst *Instance) Value() Value {
- ctx := inst.newContext()
+ ctx := newContext(inst.index)
inst.root.Finalize(ctx.opCtx)
return newVertexRoot(ctx, inst.root)
}
@@ -271,7 +278,7 @@
//
// Expressions may refer to builtin packages if they can be uniquely identified.
func (inst *Instance) Eval(expr ast.Expr) Value {
- ctx := inst.newContext()
+ ctx := newContext(inst.index)
v := inst.root
v.Finalize(ctx.opCtx)
result := evalExpr(ctx, v, expr)
@@ -285,7 +292,7 @@
v := &adt.Vertex{}
i := inst[0]
- ctx := i.index.newContext().opCtx
+ ctx := newContext(i.index).opCtx
// TODO: interesting test: use actual unification and then on K8s corpus.
@@ -336,7 +343,7 @@
}
func (inst *Instance) value() Value {
- return newVertexRoot(inst.newContext(), inst.root)
+ return newVertexRoot(newContext(inst.index), inst.root)
}
// Lookup reports the value at a path starting from the top level struct. The
diff --git a/cue/marshal.go b/cue/marshal.go
index 8d86525..00e5720 100644
--- a/cue/marshal.go
+++ b/cue/marshal.go
@@ -129,7 +129,7 @@
// The stored instances are functionally the same, but preserving of file
// information is only done on a best-effort basis.
func (r *Runtime) Marshal(instances ...*Instance) (b []byte, err error) {
- ctx := r.index().newContext()
+ ctx := newContext(r.index())
staged := []instanceData{}
done := map[string]int{}
@@ -192,7 +192,7 @@
p := len(staged) - 1
for _, imp := range imports {
- i := ctx.getImportFromPath(imp)
+ i := getImportFromPath(ctx.index, imp)
if i == nil || !strings.Contains(imp, ".") {
continue // a builtin package.
}
diff --git a/cue/types.go b/cue/types.go
index 30efd1e..3df1a5d 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -632,7 +632,7 @@
runtime := ctx.Impl().(*runtime.Runtime)
index := runtime.Data.(*index)
- return newValueRoot(index.newContext(), v)
+ return newValueRoot(newContext(index), v)
}
func makeValue(idx *index, v *adt.Vertex) Value {
@@ -663,7 +663,7 @@
}
func (v Value) ctx() *context {
- return v.idx.newContext()
+ return newContext(v.idx)
}
func (v Value) makeChild(ctx *context, i uint32, a *adt.Vertex) Value {
@@ -876,7 +876,7 @@
if v.v == nil {
return json.Marshal(nil)
}
- ctx := v.idx.newContext()
+ ctx := newContext(v.idx)
x := v.eval(ctx)
if _, ok := x.(adt.Resolver); ok {
@@ -1749,7 +1749,7 @@
addConjuncts(n, v.v)
addConjuncts(n, w.v)
- ctx := v.idx.newContext().opCtx
+ ctx := newContext(v.idx).opCtx
n.Finalize(ctx)
n.Parent = v.v.Parent
@@ -1786,7 +1786,7 @@
n.AddConjunct(adt.MakeRootConjunct(nil, v.v))
n.AddConjunct(adt.MakeRootConjunct(nil, w.v))
- ctx := v.idx.newContext().opCtx
+ ctx := newContext(v.idx).opCtx
n.Finalize(ctx)
n.Parent = v.v.Parent
@@ -1834,7 +1834,7 @@
if v.v == nil {
return nil
}
- return v.idx.getImportFromNode(v.v)
+ return getImportFromNode(v.idx, v.v)
}
// Reference returns the instance and path referred to by this value such that
@@ -1882,7 +1882,7 @@
case *adt.ImportReference:
imp := x.ImportPath.StringValue(ctx)
- inst = c.index.getImportFromPath(imp)
+ inst = getImportFromPath(c.index, imp)
case *adt.SelectorExpr:
inst, path = reference(c, env, x.X)
@@ -1902,7 +1902,7 @@
func mkPath(ctx *context, a []string, v *adt.Vertex) (inst *Instance, path []string) {
if v.Parent == nil {
- return ctx.index.getImportFromNode(v), a
+ return getImportFromNode(ctx.index, v), a
}
inst, path = mkPath(ctx, a, v.Parent)
path = append(path, v.Label.SelectorString(ctx.opCtx))
diff --git a/internal/core/runtime/runtime.go b/internal/core/runtime/runtime.go
index 448dc30..cc67bce 100644
--- a/internal/core/runtime/runtime.go
+++ b/internal/core/runtime/runtime.go
@@ -14,18 +14,41 @@
package runtime
+import (
+ "cuelang.org/go/cue/build"
+)
+
// A Runtime maintains data structures for indexing and resuse for evaluation.
type Runtime struct {
index *index
// Data holds the legacy index strut. It is for transitional purposes only.
Data interface{}
+
+ loaded map[*build.Instance]interface{}
+}
+
+func (r *Runtime) SetBuildData(b *build.Instance, x interface{}) {
+ r.loaded[b] = x
+}
+
+func (r *Runtime) BuildData(b *build.Instance) (x interface{}, ok bool) {
+ x, ok = r.loaded[b]
+ return x, ok
}
// New creates a new Runtime. The builtins registered with RegisterBuiltin
// are available for
func New() *Runtime {
- return &Runtime{
- index: sharedIndex,
+ r := &Runtime{}
+ r.Init()
+ return r
+}
+
+func (r *Runtime) Init() {
+ if r.index != nil {
+ return
}
+ r.index = sharedIndex
+ r.loaded = map[*build.Instance]interface{}{}
}