cue: return arc type, instead of individual parameters
Change-Id: I97c7a8d761e5a51fdfe0a5e22db34b41b5969da1
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/1681
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/instance.go b/cue/instance.go
index 87481bf..b2c17f2 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -217,7 +217,7 @@
obj, err := v.structVal(ctx)
if err != nil {
v := err.(*bottom)
- return Value{idx, &valueData{v: v, raw: v}}
+ return Value{idx, &valueData{arc: arc{cache: v, v: v}}}
}
v = obj.Lookup(k)
}
diff --git a/cue/types.go b/cue/types.go
index 1f0a368..949df68 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -148,9 +148,9 @@
i.cur = Value{}
return false
}
- eval, orig, f, attrs := i.iter.iterAt(i.ctx, i.p)
- i.cur = i.val.makeChild(i.ctx, uint32(i.p), f, eval, orig, attrs)
- i.f = f
+ arc := i.iter.iterAt(i.ctx, i.p)
+ i.cur = i.val.makeChild(i.ctx, uint32(i.p), arc)
+ i.f = arc.feature
i.p++
return true
}
@@ -201,7 +201,7 @@
if err := v.checkKind(v.ctx(), k); err != nil {
return nil, err
}
- n, _ := v.path.v.(*numLit)
+ n, _ := v.path.cache.(*numLit)
return n, nil
}
@@ -288,7 +288,7 @@
if !v.IsInt() {
return false
}
- n, _ := v.path.v.(*numLit)
+ n, _ := v.path.cache.(*numLit)
return n.v.Sign() >= 0
}
@@ -439,12 +439,9 @@
}
type valueData struct {
- parent *valueData
- feature label
- index uint32
- v evaluated
- raw value
- attrs *attributes
+ parent *valueData
+ index uint32
+ arc
}
// Value holds any value, which may be a Boolean, Error, List, Null, Number,
@@ -456,29 +453,30 @@
func newValueRoot(ctx *context, x value) Value {
v := x.evalPartial(ctx)
- return Value{ctx.index, &valueData{nil, 0, 0, v, x, nil}}
+ return Value{ctx.index, &valueData{nil, 0, arc{cache: v, v: x}}}
}
func newChildValue(obj *structValue, i int) Value {
- eval := obj.ctx.manifest(obj.n.at(obj.ctx, i))
a := obj.n.arcs[i]
- return Value{obj.ctx.index, &valueData{obj.path, a.feature, uint32(i), eval, a.v, a.attrs}}
+ a.cache = obj.ctx.manifest(obj.n.at(obj.ctx, i))
+
+ return Value{obj.ctx.index, &valueData{obj.path, uint32(i), a}}
}
func (v Value) ctx() *context {
return v.idx.newContext()
}
-func (v Value) makeChild(ctx *context, i uint32, f label, eval evaluated, raw value, attrs *attributes) Value {
- eval = ctx.manifest(eval)
- return Value{v.idx, &valueData{v.path, f, i, eval, raw, attrs}}
+func (v Value) makeChild(ctx *context, i uint32, a arc) Value {
+ a.cache = ctx.manifest(a.cache)
+ return Value{v.idx, &valueData{v.path, i, a}}
}
func (v Value) eval(ctx *context) value {
- if v.path == nil || v.path.v == nil {
+ if v.path == nil || v.path.cache == nil {
panic("undefined value")
}
- return ctx.manifest(v.path.v)
+ return ctx.manifest(v.path.cache)
}
// Label reports he label used to obtain this value from the enclosing struct.
@@ -586,7 +584,7 @@
// Syntax converts the possibly partially evaluated value into syntax. This
// can use used to print the value with package format.
func (v Value) Syntax() ast.Expr {
- if v.path == nil || v.path.v == nil {
+ if v.path == nil || v.path.cache == nil {
return nil
}
ctx := v.ctx()
@@ -618,10 +616,10 @@
}
ctx := v.ctx()
a := []Value{}
- for _, x := range separate(v.path.raw) {
+ for _, x := range separate(v.path.v) {
path := *v.path
- path.v = x.evalPartial(ctx)
- path.raw = x
+ path.cache = x.evalPartial(ctx)
+ path.v = x
a = append(a, Value{v.idx, &path})
}
return a
@@ -649,7 +647,7 @@
if v.path == nil {
return nil
}
- return v.path.raw.syntax()
+ return v.path.v.syntax()
}
// Err returns the error represented by v or nil v is not an error.
@@ -682,7 +680,7 @@
// IsValid reports whether this value is defined and evaluates to something
// other than an error.
func (v Value) IsValid() bool {
- if v.path == nil || v.path.v == nil {
+ if v.path == nil || v.path.cache == nil {
return false
}
k := v.eval(v.ctx()).kind()
@@ -882,7 +880,7 @@
// given its name.
func (v Value) Template() func(label string) Value {
ctx := v.ctx()
- x, ok := v.path.v.(*structLit)
+ x, ok := v.path.cache.(*structLit)
if !ok || x.template == nil {
return nil
}
@@ -934,7 +932,7 @@
fmt.Fprint(state, "<nil>")
return
}
- io.WriteString(state, debugStr(ctx, v.path.v))
+ io.WriteString(state, debugStr(ctx, v.path.cache))
}
// References reports all references used to evaluate this value. It does not
@@ -942,7 +940,7 @@
func (v Value) References() [][]string {
ctx := v.ctx()
pf := pathFinder{up: v.path}
- raw := v.path.raw
+ raw := v.path.v
if raw == nil {
return nil
}
@@ -967,7 +965,7 @@
case *nodeRef:
i := len(p.stack)
up := p.up
- for ; up != nil && up.v != x.node.(value); up = up.parent {
+ for ; up != nil && up.cache != x.node.(value); up = up.parent {
}
for ; up != nil && up.feature > 0; up = up.parent {
p.stack = append(p.stack, ctx.labelStr(up.feature))
diff --git a/cue/value.go b/cue/value.go
index f615bc3..5c432b1 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -60,11 +60,9 @@
}
type iterAtter interface {
- // TODO: make iterAt return a struct type instead, possibly an arc!
-
// at returns the evaluated and its original value at the given position.
// If the original could not be found, it returns an error and nil.
- iterAt(*context, int) (evaluated, value, label, *attributes)
+ iterAt(*context, int) arc
}
// caller must be implemented by any concrete lambdaKind
@@ -206,12 +204,12 @@
func (x *bytesLit) kind() kind { return bytesKind }
func (x *bytesLit) strValue() string { return string(x.b) }
-func (x *bytesLit) iterAt(ctx *context, i int) (evaluated, value, label, *attributes) {
+func (x *bytesLit) iterAt(ctx *context, i int) arc {
if i >= len(x.b) {
- return nil, nil, 0, nil
+ return arc{}
}
v := x.at(ctx, i)
- return v, v, 0, nil
+ return arc{v: v, cache: v}
}
func (x *bytesLit) at(ctx *context, i int) evaluated {
@@ -260,13 +258,13 @@
func (x *stringLit) kind() kind { return stringKind }
func (x *stringLit) strValue() string { return x.str }
-func (x *stringLit) iterAt(ctx *context, i int) (evaluated, value, label, *attributes) {
+func (x *stringLit) iterAt(ctx *context, i int) arc {
runes := []rune(x.str)
if i >= len(runes) {
- return nil, nil, 0, nil
+ return arc{}
}
v := x.at(ctx, i)
- return v, v, 0, nil
+ return arc{v: v, cache: v}
}
func (x *stringLit) at(ctx *context, i int) evaluated {
@@ -489,34 +487,36 @@
// already have been evaluated. It returns an error and nil if there was an
// issue evaluating the list itself.
func (x *list) at(ctx *context, i int) evaluated {
- e, _, _, _ := x.iterAt(ctx, i)
- if e == nil {
+ arc := x.iterAt(ctx, i)
+ if arc.cache == nil {
return ctx.mkErr(x, "index %d out of bounds", i)
}
- return e
+ return arc.cache
}
// iterAt returns the evaluated and original value of position i. List x must
// already have been evaluated. It returns an error and nil if there was an
// issue evaluating the list itself.
-func (x *list) iterAt(ctx *context, i int) (evaluated, value, label, *attributes) {
+func (x *list) iterAt(ctx *context, i int) arc {
if i < 0 {
- return ctx.mkErr(x, "index %d out of bounds", i), nil, 0, nil
+ v := ctx.mkErr(x, "index %d out of bounds", i)
+ return arc{cache: v}
}
if i < len(x.a) {
- return x.a[i].evalPartial(ctx), x.a[i], 0, nil
+ return arc{cache: x.a[i].evalPartial(ctx), v: x.a[i]}
}
max := maxNum(x.len.(evaluated))
if max.kind().isGround() {
if max.kind()&intKind == bottomKind {
- return ctx.mkErr(max, "length indicator of list not of type int"), nil, 0, nil
+ v := ctx.mkErr(max, "length indicator of list not of type int")
+ return arc{cache: v}
}
n := max.(*numLit).intValue(ctx)
if i >= n {
- return nil, nil, 0, nil
+ return arc{}
}
}
- return x.typ.(evaluated), x.typ, 0, nil
+ return arc{cache: x.typ.(evaluated), v: x.typ}
}
func (x *list) isOpen() bool {
@@ -605,13 +605,14 @@
return nil, nil
}
-func (x *structLit) iterAt(ctx *context, i int) (evaluated, value, label, *attributes) {
+func (x *structLit) iterAt(ctx *context, i int) arc {
x = x.expandFields(ctx)
if i >= len(x.arcs) {
- return nil, nil, 0, nil
+ return arc{}
}
- v := x.at(ctx, i)
- return v, x.arcs[i].v, x.arcs[i].feature, x.arcs[i].attrs // TODO: return template & v for original?
+ a := x.arcs[i]
+ a.cache = x.at(ctx, i) // TODO: return template & v for original?
+ return a
}
func (x *structLit) at(ctx *context, i int) evaluated {