cue: more renamings to minimize diffs

Change-Id: I43867f656152bbcfb042fa14c8619c40319ceab0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6513
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/ast.go b/cue/ast.go
index 35a278f..a317f4a 100644
--- a/cue/ast.go
+++ b/cue/ast.go
@@ -152,8 +152,8 @@
 	name := v.ident(n)
 	label := v.Label(name, true)
 	if r := v.resolveRoot; r != nil {
-		for _, a := range r.arcs {
-			if a.feature == label {
+		for _, a := range r.Arcs {
+			if a.Label == label {
 				return &selectorExpr{newExpr(n),
 					&nodeRef{baseValue: newExpr(n), node: r, label: label}, label}
 			}
@@ -345,9 +345,9 @@
 				return v.errf(n, "alias not allowed in list")
 			}
 			v1.sel = strconv.Itoa(i)
-			arcs = append(arcs, arc{feature: label(i), v: elem})
+			arcs = append(arcs, arc{Label: label(i), v: elem})
 		}
-		s := &structLit{baseValue: newExpr(n), arcs: arcs}
+		s := &structLit{baseValue: newExpr(n), Arcs: arcs}
 		list := &list{baseValue: newExpr(n), elem: s}
 		list.initLit()
 		if ellipsis != nil {
diff --git a/cue/binop.go b/cue/binop.go
index e10658f..a310bde 100644
--- a/cue/binop.go
+++ b/cue/binop.go
@@ -615,7 +615,7 @@
 	if x == y {
 		return x
 	}
-	arcs := make(arcs, 0, len(x.arcs)+len(y.arcs))
+	arcs := make(arcs, 0, len(x.Arcs)+len(y.Arcs))
 	var base baseValue
 	if src.computed() != nil {
 		base = baseValue{src.computed()}
@@ -657,38 +657,38 @@
 		}
 	}
 
-	for _, a := range x.arcs {
+	for _, a := range x.Arcs {
 		found := false
-		for _, b := range y.arcs {
-			if a.feature == b.feature {
+		for _, b := range y.Arcs {
+			if a.Label == b.Label {
 				found = true
 				break
 			}
 		}
-		if !unchecked && !found && !y.allows(ctx, a.feature) && !a.definition {
+		if !unchecked && !found && !y.allows(ctx, a.Label) && !a.definition {
 			if a.optional {
 				continue
 			}
 			// TODO: pass position of key, not value. Currently does not have
 			// a position.
 			return ctx.mkErr(a.v, a.v, "field %q not allowed in closed struct",
-				ctx.LabelStr(a.feature))
+				ctx.LabelStr(a.Label))
 		}
 		cp := ctx.copy(a.v)
-		obj.arcs = append(obj.arcs,
-			arc{a.feature, a.optional, a.definition, cp, nil, a.attrs, a.docs})
+		obj.Arcs = append(obj.Arcs,
+			arc{a.Label, a.optional, a.definition, cp, nil, a.attrs, a.docs})
 	}
 outer:
-	for _, a := range y.arcs {
+	for _, a := range y.Arcs {
 		v := ctx.copy(a.v)
 		found := false
-		for i, b := range obj.arcs {
-			if a.feature == b.feature {
+		for i, b := range obj.Arcs {
+			if a.Label == b.Label {
 				found = true
 				if a.definition != b.definition {
 					src := binSrc(x.Pos(), op, a.v, b.v)
 					return ctx.mkErr(src, "field %q declared as definition and regular field",
-						ctx.LabelStr(a.feature))
+						ctx.LabelStr(a.Label))
 				}
 				w := b.v
 				if x.closeStatus.shouldFinalize() {
@@ -698,29 +698,29 @@
 					v = wrapFinalize(ctx, v)
 				}
 				v = mkBin(ctx, src.Pos(), op, w, v)
-				obj.arcs[i].v = v
-				obj.arcs[i].cache = nil
-				obj.arcs[i].optional = a.optional && b.optional
-				obj.arcs[i].docs = mergeDocs(a.docs, b.docs)
+				obj.Arcs[i].v = v
+				obj.Arcs[i].Value = nil
+				obj.Arcs[i].optional = a.optional && b.optional
+				obj.Arcs[i].docs = mergeDocs(a.docs, b.docs)
 				attrs, err := unifyAttrs(ctx, src, a.attrs, b.attrs)
 				if err != nil {
 					return err
 				}
-				obj.arcs[i].attrs = attrs
+				obj.Arcs[i].attrs = attrs
 				continue outer
 			}
 		}
-		if !unchecked && !found && !x.allows(ctx, a.feature) && !a.definition {
+		if !unchecked && !found && !x.allows(ctx, a.Label) && !a.definition {
 			if a.optional {
 				continue
 			}
 			// TODO: pass position of key, not value. Currently does not have a
 			// position.
 			return ctx.mkErr(a.v, x, "field %q not allowed in closed struct",
-				ctx.LabelStr(a.feature))
+				ctx.LabelStr(a.Label))
 		}
 		a.setValue(v)
-		obj.arcs = append(obj.arcs, a)
+		obj.Arcs = append(obj.Arcs, a)
 	}
 	sort.Stable(obj)
 
@@ -1174,15 +1174,15 @@
 			src = mkBin(ctx, src.Pos(), op, x, other)
 			return ctx.mkErr(src, "conflicting list lengths: %v", n)
 		}
-		sx := x.elem.arcs
+		sx := x.elem.Arcs
 		xa := sx
-		sy := y.elem.arcs
+		sy := y.elem.Arcs
 		ya := sy
 		for len(xa) < len(ya) {
-			xa = append(xa, arc{feature: label(len(xa)), v: x.typ})
+			xa = append(xa, arc{Label: label(len(xa)), v: x.typ})
 		}
 		for len(ya) < len(xa) {
-			ya = append(ya, arc{feature: label(len(ya)), v: y.typ})
+			ya = append(ya, arc{Label: label(len(ya)), v: y.typ})
 		}
 
 		typ := x.typ
@@ -1192,11 +1192,11 @@
 		}
 
 		// TODO: use forwarding instead of this mild hack.
-		x.elem.arcs = xa
-		y.elem.arcs = ya
+		x.elem.Arcs = xa
+		y.elem.Arcs = ya
 		s := binOp(ctx, src, op, x.elem, y.elem).(*structLit)
-		x.elem.arcs = sx
-		y.elem.arcs = sy
+		x.elem.Arcs = sx
+		y.elem.Arcs = sy
 
 		base := binSrc(src.Pos(), op, x, other)
 		return &list{baseValue: base, elem: s, typ: typ, len: n}
@@ -1206,10 +1206,10 @@
 		if !ok {
 			break
 		}
-		if len(x.elem.arcs) != len(y.elem.arcs) {
+		if len(x.elem.Arcs) != len(y.elem.Arcs) {
 			return boolTonode(src, false)
 		}
-		for i := range x.elem.arcs {
+		for i := range x.elem.Arcs {
 			if !test(ctx, src, op, x.at(ctx, i), y.at(ctx, i)) {
 				return boolTonode(src, false)
 			}
@@ -1223,11 +1223,11 @@
 		}
 		n := &list{baseValue: binSrc(src.Pos(), op, x, other), typ: y.typ}
 		arcs := []arc{}
-		for _, v := range x.elem.arcs {
-			arcs = append(arcs, arc{feature: label(len(arcs)), v: v.v})
+		for _, v := range x.elem.Arcs {
+			arcs = append(arcs, arc{Label: label(len(arcs)), v: v.v})
 		}
-		for _, v := range y.elem.arcs {
-			arcs = append(arcs, arc{feature: label(len(arcs)), v: v.v})
+		for _, v := range y.elem.Arcs {
+			arcs = append(arcs, arc{Label: label(len(arcs)), v: v.v})
 		}
 		switch v := y.len.(type) {
 		case *numLit:
@@ -1237,7 +1237,7 @@
 			// Open list
 			n.len = y.len // TODO: add length of x?
 		}
-		n.elem = &structLit{baseValue: n.baseValue, arcs: arcs}
+		n.elem = &structLit{baseValue: n.baseValue, Arcs: arcs}
 		return n
 
 	case opMul:
@@ -1247,7 +1247,7 @@
 		}
 		n := &list{baseValue: binSrc(src.Pos(), op, x, other), typ: x.typ}
 		arcs := []arc{}
-		if len(x.elem.arcs) > 0 {
+		if len(x.elem.Arcs) > 0 {
 			if !k.isGround() {
 				// should never reach here.
 				break
@@ -1255,8 +1255,8 @@
 			if ln := other.(*numLit).intValue(ctx); ln > 0 {
 				for i := 0; i < ln; i++ {
 					// TODO: copy values
-					for _, a := range x.elem.arcs {
-						arcs = append(arcs, arc{feature: label(len(arcs)), v: a.v})
+					for _, a := range x.elem.Arcs {
+						arcs = append(arcs, arc{Label: label(len(arcs)), v: a.v})
 					}
 				}
 			} else if ln < 0 {
@@ -1271,7 +1271,7 @@
 			// Open list
 			n.len = x.len // TODO: multiply length?
 		}
-		n.elem = &structLit{baseValue: n.baseValue, arcs: arcs}
+		n.elem = &structLit{baseValue: n.baseValue, Arcs: arcs}
 		return n
 	}
 	return ctx.mkIncompatible(src, op, x, other)
@@ -1301,7 +1301,7 @@
 			if isBottom(v) {
 				return v
 			}
-			arcs[i] = arc{feature: x.arcs[i].feature, v: v}
+			arcs[i] = arc{Label: x.arcs[i].Label, v: v}
 		}
 
 		return lambda
diff --git a/cue/builtin.go b/cue/builtin.go
index 147ed41..4cda187 100644
--- a/cue/builtin.go
+++ b/cue/builtin.go
@@ -81,7 +81,7 @@
 		if b.Const != "" {
 			v = mustParseConstBuiltin(ctx, b.Name, b.Const)
 		}
-		obj.arcs = append(obj.arcs, arc{feature: f, v: v})
+		obj.Arcs = append(obj.Arcs, arc{Label: f, v: v})
 	}
 	sort.Sort(obj)
 
@@ -92,10 +92,10 @@
 			panic(fmt.Errorf("could not parse %v: %v", p.cue, err))
 		}
 		pkg := evalExpr(ctx, obj, expr).(*structLit)
-		for _, a := range pkg.arcs {
+		for _, a := range pkg.Arcs {
 			// Discard option status and attributes at top level.
 			// TODO: filter on capitalized fields?
-			obj.insertValue(ctx, a.feature, false, false, a.v, nil, a.docs)
+			obj.insertValue(ctx, a.Label, false, false, a.v, nil, a.docs)
 		}
 	}
 
@@ -185,9 +185,9 @@
 			c.ret = &top{baseValue{c.src}}
 			return
 		}
-		u := iter.Value().path.v
+		u := iter.Value().v.v
 		for iter.Next() {
-			u = mkBin(c.ctx, c.src.Pos(), opUnify, u, iter.Value().path.v)
+			u = mkBin(c.ctx, c.src.Pos(), opUnify, u, iter.Value().v.v)
 		}
 		c.ret = u
 	},
@@ -201,7 +201,7 @@
 		iter := c.iter(0)
 		d := []dValue{}
 		for iter.Next() {
-			d = append(d, dValue{iter.Value().path.v, false})
+			d = append(d, dValue{iter.Value().v.v, false})
 		}
 		c.ret = &disjunction{baseValue{c.src}, d, nil, false}
 		if len(d) == 0 {
@@ -392,7 +392,7 @@
 		if s == nil {
 			return v
 		}
-		a := s.lookup(ctx, ctx.Label(name, false))
+		a := s.Lookup(ctx, ctx.Label(name, false))
 		if a.v == nil {
 			return v
 		}
diff --git a/cue/builtinutil.go b/cue/builtinutil.go
index e99f132..df22d71 100644
--- a/cue/builtinutil.go
+++ b/cue/builtinutil.go
@@ -47,7 +47,7 @@
 // TODO: consider making this a method on Value.
 func fill(v Value, x interface{}, path ...string) Value {
 	ctx := v.ctx()
-	root := v.path.val()
+	root := v.v.val()
 	for i := len(path) - 1; i >= 0; i-- {
 		x = map[string]interface{}{path[i]: x}
 	}
diff --git a/cue/copy.go b/cue/copy.go
index 4698588..d60f18f 100644
--- a/cue/copy.go
+++ b/cue/copy.go
@@ -29,7 +29,7 @@
 		return &nodeRef{x.baseValue, node, x.label}, false
 
 	case *structLit:
-		arcs := make(arcs, len(x.arcs))
+		arcs := make(arcs, len(x.Arcs))
 
 		obj := &structLit{x.baseValue, nil, nil, x.closeStatus, nil, arcs, nil}
 
@@ -48,7 +48,7 @@
 		}
 		obj.optionals = o
 
-		for i, a := range x.arcs {
+		for i, a := range x.Arcs {
 			a.setValue(ctx.copy(a.v))
 			arcs[i] = a
 		}
@@ -63,7 +63,7 @@
 	case *lambdaExpr:
 		arcs := make([]arc, len(x.arcs))
 		for i, a := range x.arcs {
-			arcs[i] = arc{feature: a.feature, v: ctx.copy(a.v)}
+			arcs[i] = arc{Label: a.Label, v: ctx.copy(a.v)}
 		}
 		lambda := &lambdaExpr{x.baseValue, &params{arcs}, nil}
 		defer ctx.pushForwards(x, lambda).popForwards()
diff --git a/cue/debug.go b/cue/debug.go
index 4472abb..12cd4d9 100644
--- a/cue/debug.go
+++ b/cue/debug.go
@@ -165,7 +165,7 @@
 		return lambdaName(f, x.node)
 	case *lambdaExpr:
 		if f == 0 && len(x.params.arcs) == 1 {
-			return x.params.arcs[0].feature
+			return x.params.arcs[0].Label
 		}
 	}
 	return f
@@ -347,7 +347,7 @@
 			p.str(x.emit)
 			write(", ")
 		}
-		p.str(x.arcs)
+		p.str(x.Arcs)
 		for i, c := range x.comprehensions {
 			if c.checked {
 				p.write("c:")
@@ -358,7 +358,7 @@
 			}
 		}
 		if topDefault && !x.closeStatus.shouldClose() {
-			if len(x.arcs) > 0 {
+			if len(x.Arcs) > 0 {
 				p.write(", ")
 			}
 			p.write("...")
@@ -376,12 +376,12 @@
 
 	case arc:
 		n := x.v
-		str := p.label(x.feature)
+		str := p.label(x.Label)
 		p.writef(str)
 		if x.optional {
 			p.write("?")
 		}
-		if x.definition && !x.feature.IsDef() {
+		if x.definition && !x.Label.IsDef() {
 			p.write(" :: ")
 		} else {
 			p.write(": ")
@@ -413,10 +413,10 @@
 	case *feed:
 		writef(" <%s>for ", p.ctx.ref(x.fn))
 		a := x.fn.params.arcs[0]
-		p.writef(p.label(a.feature))
+		p.writef(p.label(a.Label))
 		writef(", ")
 		a = x.fn.params.arcs[1]
-		p.writef(p.label(a.feature))
+		p.writef(p.label(a.Label))
 		writef(" in ")
 		p.str(x.Src)
 		p.str(x.fn.value)
@@ -477,13 +477,13 @@
 		case *top, *basicType:
 			open = true
 		}
-		if !ok || ln > len(x.elem.arcs) {
+		if !ok || ln > len(x.elem.Arcs) {
 			if !open && !isTop(x.typ) {
 				p.str(x.len)
 				write("*[")
 				p.str(x.typ)
 				write("]")
-				if len(x.elem.arcs) == 0 {
+				if len(x.elem.Arcs) == 0 {
 					break
 				}
 				write("(")
@@ -492,9 +492,9 @@
 			ellipsis = true
 		}
 		write("[")
-		for i, a := range x.elem.arcs {
+		for i, a := range x.elem.Arcs {
 			p.str(a.v)
-			if i < len(x.elem.arcs)-1 {
+			if i < len(x.elem.Arcs)-1 {
 				write(",")
 			}
 		}
diff --git a/cue/errors.go b/cue/errors.go
index 5788607..467254f 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -102,10 +102,10 @@
 }
 
 func (e *valueError) Path() (a []string) {
-	if e.v.path == nil {
+	if e.v.v == nil {
 		return nil
 	}
-	a, _ = e.v.path.appendPath(a, e.v.idx)
+	a, _ = e.v.v.appendPath(a, e.v.idx)
 	return a
 }
 
diff --git a/cue/eval.go b/cue/eval.go
index e348d26..b995a86 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -124,7 +124,7 @@
 		if !ok {
 			return ctx.mkErr(x, "invalid subject to selector (found %v)", v.Kind())
 		}
-		n := sc.lookup(ctx, x.Sel)
+		n := sc.Lookup(ctx, x.Sel)
 		if n.optional {
 			field := ctx.LabelStr(x.Sel)
 			return ctx.mkErr(x, codeIncomplete, "field %q is optional", field)
@@ -138,7 +138,7 @@
 			// TODO: mention x.x in error message?
 			return ctx.mkErr(x, "undefined field %q", field)
 		}
-		return n.cache
+		return n.Value
 	}
 	return e.err(&selectorExpr{x.baseValue, v, x.Sel})
 }
@@ -159,7 +159,7 @@
 		if !ok {
 			return ctx.mkErr(x, "invalid subject to selector (found %v)", v.Kind())
 		}
-		n := sc.lookup(ctx, x.Sel)
+		n := sc.Lookup(ctx, x.Sel)
 		if n.optional {
 			field := ctx.LabelStr(x.Sel)
 			return ctx.mkErr(x, codeIncomplete, "field %q is optional", field)
@@ -198,7 +198,7 @@
 		if e.is(index, stringKind, msgIndexType, k) {
 			s := index.strValue()
 			// TODO: must lookup
-			n := v.lookup(ctx, ctx.StrLabel(s))
+			n := v.Lookup(ctx, ctx.StrLabel(s))
 			if n.definition {
 				return ctx.mkErr(x, index,
 					"field %q is a definition", s)
@@ -212,7 +212,7 @@
 				}
 				return ctx.mkErr(x, index, "undefined field %q", s)
 			}
-			return n.cache
+			return n.Value
 		}
 	case atter:
 		if e.is(index, intKind, msgIndexType, k) {
@@ -247,7 +247,7 @@
 		if e.is(index, stringKind, msgIndexType, k) {
 			s := index.strValue()
 			// TODO: must lookup
-			n := v.lookup(ctx, ctx.StrLabel(s))
+			n := v.Lookup(ctx, ctx.StrLabel(s))
 			if n.definition {
 				return ctx.mkErr(x, index,
 					"field %q is a definition", s)
@@ -424,9 +424,9 @@
 	s := &structLit{baseValue: x.baseValue}
 	list := &list{baseValue: x.baseValue, elem: s}
 	err := x.clauses.yield(ctx, func(v evaluated) *bottom {
-		list.elem.arcs = append(list.elem.arcs, arc{
-			feature: label(len(list.elem.arcs)),
-			v:       v.evalPartial(ctx),
+		list.elem.Arcs = append(list.elem.Arcs, arc{
+			Label: label(len(list.elem.Arcs)),
+			v:     v.evalPartial(ctx),
 		})
 		return nil
 	})
diff --git a/cue/export.go b/cue/export.go
index a16e956..03521b2 100644
--- a/cue/export.go
+++ b/cue/export.go
@@ -41,8 +41,8 @@
 		if err != nil {
 			v = err
 		} else {
-			for _, a := range top.arcs {
-				e.top[a.feature] = true
+			for _, a := range top.Arcs {
+				e.top[a.Label] = true
 			}
 		}
 	}
@@ -167,12 +167,12 @@
 	switch x := v.(type) {
 	case *feed:
 		feed := &ast.ForClause{
-			Value:  p.identifier(x.fn.params.arcs[1].feature),
+			Value:  p.identifier(x.fn.params.arcs[1].Label),
 			Source: p.expr(x.Src),
 		}
 		key := x.fn.params.arcs[0]
-		if p.ctx.LabelStr(key.feature) != "_" {
-			feed.Key = p.identifier(key.feature)
+		if p.ctx.LabelStr(key.Label) != "_" {
+			feed.Key = p.identifier(key.Label)
 		}
 		return feed, x.fn.value.(yielder)
 
@@ -301,7 +301,7 @@
 		if x.isOpen() {
 			return false
 		}
-		for i := range x.elem.arcs {
+		for i := range x.elem.Arcs {
 			if !p.isComplete(x.at(p.ctx, i), all) {
 				return false
 			}
@@ -466,7 +466,7 @@
 			return p.badf("selector without node")
 		}
 		if l, ok := node.node.(*lambdaExpr); ok && len(l.arcs) == 1 {
-			f = l.params.arcs[0].feature
+			f = l.params.arcs[0].Label
 			// TODO: ensure it is shadowed.
 			ident = p.identifier(f)
 			return ident
@@ -593,7 +593,7 @@
 			if x.optionals == nil {
 				break
 			}
-			p.optionals(len(x.arcs) > 0, st, x.optionals)
+			p.optionals(len(x.Arcs) > 0, st, x.optionals)
 		}
 		return expr
 
@@ -684,7 +684,7 @@
 	case *list:
 		list := &ast.ListLit{}
 		var expr ast.Expr = list
-		for i, a := range x.elem.arcs {
+		for i, a := range x.elem.Arcs {
 			if !doEval(p.mode) {
 				list.Elts = append(list.Elts, p.expr(a.v))
 			} else {
@@ -708,7 +708,7 @@
 		case *top, *basicType:
 			open = true
 		}
-		if !ok || ln > len(x.elem.arcs) {
+		if !ok || ln > len(x.elem.Arcs) {
 			list.Elts = append(list.Elts, &ast.Ellipsis{Type: p.expr(x.typ)})
 			if !open && !isTop(x.typ) {
 				expr = ast.NewBinExpr(
@@ -790,7 +790,7 @@
 				v = c.value
 			}
 			f := &ast.Field{
-				Label: p.mkTemplate(t.key, p.identifier(l.params.arcs[0].feature)),
+				Label: p.mkTemplate(t.key, p.identifier(l.params.arcs[0].Label)),
 				Value: p.expr(l.value),
 			}
 			if internal.IsEllipsis(f) {
@@ -836,10 +836,10 @@
 		}
 	}
 
-	for _, a := range x.arcs {
+	for _, a := range x.Arcs {
 		p.stack = append(p.stack, remap{
 			key:  x,
-			from: a.feature,
+			from: a.Label,
 			to:   nil,
 			syn:  obj,
 		})
@@ -852,11 +852,11 @@
 		// Optional field constraints may be omitted if they were already
 		// applied and no more new fields may be added.
 		!(doEval(p.mode) && x.optionals.isEmpty() && p.isClosed(x)) {
-		hasEllipsis = p.optionals(len(x.arcs) > 0, obj, x.optionals)
+		hasEllipsis = p.optionals(len(x.Arcs) > 0, obj, x.optionals)
 	}
-	for i, a := range x.arcs {
+	for i, a := range x.Arcs {
 		f := &ast.Field{
-			Label: p.label(a.feature),
+			Label: p.label(a.Label),
 		}
 		// TODO: allow the removal of hidden fields. However, hidden fields
 		// that still used in incomplete expressions should not be removed
@@ -878,7 +878,7 @@
 				f.Token = token.ISA
 			}
 		}
-		if a.feature.IsHidden() && p.mode.concrete && p.mode.omitHidden {
+		if a.Label.IsHidden() && p.mode.concrete && p.mode.omitHidden {
 			continue
 		}
 		oldInDef := p.inDef
diff --git a/cue/export_test.go b/cue/export_test.go
index 24c90d4..96771bb 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -574,7 +574,7 @@
 			}
 			t.Log(debugStr(ctx, root))
 
-			n := root.(*structLit).arcs[0].v
+			n := root.(*structLit).Arcs[0].v
 			v := newValueRoot(ctx, n)
 
 			opts := options{raw: !tc.eval, omitOptional: tc.noOpt}
diff --git a/cue/go.go b/cue/go.go
index bfbd92b..c0408e0 100644
--- a/cue/go.go
+++ b/cue/go.go
@@ -390,7 +390,7 @@
 					continue
 				}
 				f := ctx.StrLabel(name)
-				obj.arcs = append(obj.arcs, arc{feature: f, v: sub})
+				obj.Arcs = append(obj.Arcs, arc{Label: f, v: sub})
 			}
 			sort.Sort(obj)
 			return obj
@@ -428,7 +428,7 @@
 					sorted = append(sorted, s)
 
 					// Set feature later.
-					obj.arcs = append(obj.arcs, arc{feature: 0, v: sub})
+					obj.Arcs = append(obj.Arcs, arc{Label: 0, v: sub})
 				}
 
 			default:
@@ -443,7 +443,7 @@
 
 			// Now assign the labels to the arcs.
 			for i, k := range keys {
-				obj.arcs[i].feature = ctx.StrLabel(k)
+				obj.Arcs[i].Label = ctx.StrLabel(k)
 			}
 			sort.Sort(obj)
 			return obj
@@ -460,9 +460,9 @@
 				if isBottom(x) {
 					return x
 				}
-				arcs = append(arcs, arc{feature: label(len(arcs)), v: x})
+				arcs = append(arcs, arc{Label: label(len(arcs)), v: x})
 			}
-			list.elem = &structLit{baseValue: list.baseValue, arcs: arcs}
+			list.elem = &structLit{baseValue: list.baseValue, Arcs: arcs}
 			list.initLit()
 			// There is no need to set the type of the list, as the list will
 			// be of fixed size and all elements will already have a defined
@@ -598,8 +598,8 @@
 				continue
 			}
 			l := ctx.StrLabel(name)
-			obj.arcs = append(obj.arcs, arc{
-				feature: l,
+			obj.Arcs = append(obj.Arcs, arc{
+				Label: l,
 				// The GO JSON decoder always allows a value to be undefined.
 				optional: isOptional(&f),
 				v:        elem,
@@ -616,12 +616,12 @@
 			if isBottom(v) {
 				return v
 			}
-			for i, a := range obj.arcs {
-				if a.feature == label {
+			for i, a := range obj.Arcs {
+				if a.Label == label {
 					// Instead of unifying with the existing type, we substitute
 					// with the constraints from the tags. The type constraints
 					// will be implied when unified with a concrete value.
-					obj.arcs[i].v = mkBin(ctx, token.NoPos, opUnify, a.v, v)
+					obj.Arcs[i].v = mkBin(ctx, token.NoPos, opUnify, a.v, v)
 				}
 			}
 		}
diff --git a/cue/instance.go b/cue/instance.go
index 33e9ad9..be61e43 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -80,7 +80,7 @@
 		}
 		return v.ctx().index.addInst(&Instance{
 			rootStruct: st,
-			rootValue:  v.path.v,
+			rootValue:  v.v.v,
 		})
 	}
 }
@@ -131,7 +131,7 @@
 			}
 
 		default:
-			for _, a := range s.arcs {
+			for _, a := range s.Arcs {
 				if !a.definition {
 					v = binOp(ctx, src, opUnify, v, e)
 					break outer
@@ -280,7 +280,7 @@
 	for _, k := range path {
 		obj, err := v.structValData(ctx)
 		if err != nil {
-			return Value{idx, &valueData{arc: arc{cache: err, v: err}}}
+			return Value{idx, &valueData{arc: arc{Value: err, v: err}}}
 		}
 		v = obj.Lookup(k)
 	}
diff --git a/cue/rewrite.go b/cue/rewrite.go
index 82da452..7f7916f 100644
--- a/cue/rewrite.go
+++ b/cue/rewrite.go
@@ -47,10 +47,10 @@
 	if emit != nil {
 		emit = rewrite(ctx, x.emit, fn)
 	}
-	arcs := make(arcs, len(x.arcs))
-	obj := &structLit{baseValue: x.baseValue, emit: emit, arcs: arcs}
+	arcs := make(arcs, len(x.Arcs))
+	obj := &structLit{baseValue: x.baseValue, emit: emit, Arcs: arcs}
 	changed := emit == x.emit
-	for i, a := range x.arcs {
+	for i, a := range x.Arcs {
 		a.setValue(rewrite(ctx, a.v, fn))
 		changed = changed || arcs[i].v != a.v
 		arcs[i] = a
@@ -171,7 +171,7 @@
 	changed := false
 	for i, a := range x.arcs {
 		v := rewrite(ctx, a.v, fn)
-		arcs[i] = arc{feature: a.feature, v: v}
+		arcs[i] = arc{Label: a.Label, v: v}
 		changed = changed || v != a.v
 	}
 	value := rewrite(ctx, x.value, fn)
diff --git a/cue/rewrite_test.go b/cue/rewrite_test.go
index f8e9d1a..4baa561 100644
--- a/cue/rewrite_test.go
+++ b/cue/rewrite_test.go
@@ -60,8 +60,8 @@
 			}
 			return err
 		}
-		arcs := make(arcs, len(x.arcs))
-		for i, a := range x.arcs {
+		arcs := make(arcs, len(x.Arcs))
+		for i, a := range x.Arcs {
 			v := x.at(ctx, i)
 			a.setValue(rewriteRec(ctx, a.v, v, m))
 			arcs[i] = a
diff --git a/cue/strip.go b/cue/strip.go
index c45bb0d..a806a3d 100644
--- a/cue/strip.go
+++ b/cue/strip.go
@@ -56,12 +56,12 @@
 	}
 	var arcs arcs
 	for _, v := range structs {
-		for i := 0; i < len(v.arcs); i++ {
+		for i := 0; i < len(v.Arcs); i++ {
 			w := v.iterAt(ctx, i)
 			arcs = append(arcs, w)
 		}
 	}
-	obj.arcs = arcs
+	obj.Arcs = arcs
 	sort.Stable(obj)
 
 	values := []value{}
@@ -86,7 +86,7 @@
 		// versus having more information tradeoff. It results in the same
 		// value.
 		values := []value{a.v}
-		for i++; i < len(arcs) && a.feature == arcs[i].feature; i++ {
+		for i++; i < len(arcs) && a.Label == arcs[i].Label; i++ {
 			values = append(values, arcs[i].v)
 			a.optional = a.optional && arcs[i].optional
 			var err evaluated
@@ -100,11 +100,11 @@
 			arcs[k] = a
 			continue
 		}
-		a.cache = nil
+		a.Value = nil
 		a.v = &mergedValues{a.v.base(), values}
 		arcs[k] = a
 	}
-	obj.arcs = arcs[:k]
+	obj.Arcs = arcs[:k]
 	return obj
 }
 
diff --git a/cue/subsume.go b/cue/subsume.go
index 5d41200..6eca12d 100644
--- a/cue/subsume.go
+++ b/cue/subsume.go
@@ -176,11 +176,11 @@
 				s.inexact = true
 				return false
 			}
-			for _, b := range o.arcs {
+			for _, b := range o.Arcs {
 				if b.optional || b.definition {
 					continue
 				}
-				name := ctx.LabelStr(b.feature)
+				name := ctx.LabelStr(b.Label)
 				arg := &stringLit{x.baseValue, name, nil}
 				u, _ := x.optionals.constraint(ctx, arg)
 				if u != nil && !s.subsumes(u, b.v) {
@@ -202,11 +202,11 @@
 		oClosed := o.closeStatus.shouldClose() && s.mode&subSchema == 0
 
 		// all arcs in n must exist in v and its values must subsume.
-		for _, a := range x.arcs {
+		for _, a := range x.Arcs {
 			if a.optional && ignoreOptional {
 				continue
 			}
-			b := o.lookup(ctx, a.feature)
+			b := o.Lookup(ctx, a.Label)
 			if !a.optional && b.optional {
 				return false
 			} else if b.val() == nil {
@@ -226,7 +226,7 @@
 				if a.optional && isTop(a.v) {
 					continue
 				}
-				s.missing = a.feature
+				s.missing = a.Label
 				s.gt = a.val()
 				s.lt = o
 				return false
@@ -242,13 +242,13 @@
 				return false
 			}
 			ignoreOptional = ignoreOptional || s.mode&subFinal != 0
-			for _, b := range o.arcs {
+			for _, b := range o.Arcs {
 				if ignoreOptional && b.optional {
 					continue
 				}
-				a := x.lookup(ctx, b.feature)
+				a := x.Lookup(ctx, b.Label)
 				if a.val() == nil {
-					name := ctx.LabelStr(b.feature)
+					name := ctx.LabelStr(b.Label)
 					arg := &stringLit{x.baseValue, name, nil}
 					u, _ := x.optionals.constraint(ctx, arg)
 					if u == nil { // subsumption already checked
@@ -396,7 +396,7 @@
 		}
 		// TODO: assuming continuous indices, use merge sort if we allow
 		// sparse arrays.
-		for _, a := range y.elem.arcs[len(x.elem.arcs):] {
+		for _, a := range y.elem.Arcs[len(x.elem.Arcs):] {
 			if !s.subsumes(x.typ, a.v) {
 				return false
 			}
diff --git a/cue/subsume_test.go b/cue/subsume_test.go
index 38276b8..0f6cd01 100644
--- a/cue/subsume_test.go
+++ b/cue/subsume_test.go
@@ -452,8 +452,8 @@
 
 			// Use low-level lookup to avoid evaluation.
 			var a, b value
-			for _, arc := range root.arcs {
-				switch arc.feature {
+			for _, arc := range root.Arcs {
+				switch arc.Label {
 				case ctx.StrLabel("a"):
 					a = arc.v
 				case ctx.StrLabel("b"):
diff --git a/cue/types.go b/cue/types.go
index 3461339..9ce7cfc 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -82,7 +82,7 @@
 	ctx  *context
 	path *valueData
 	obj  *structLit
-	arcs arcs
+	Arcs arcs
 }
 
 // Len reports the number of fields in this struct.
@@ -90,14 +90,14 @@
 	if o.obj == nil {
 		return 0
 	}
-	return len(o.arcs)
+	return len(o.Arcs)
 }
 
 // At reports the key and value of the ith field, i < o.Len().
 func (o *structValue) At(i int) (key string, v Value) {
-	a := o.arcs[i]
+	a := o.Arcs[i]
 	v = newChildValue(o, i)
-	return o.ctx.LabelStr(a.feature), v
+	return o.ctx.LabelStr(a.Label), v
 }
 
 // Lookup reports the field for the given key. The returned Value is invalid
@@ -107,7 +107,7 @@
 	i := 0
 	len := o.Len()
 	for ; i < len; i++ {
-		if o.arcs[i].feature == f {
+		if o.Arcs[i].Label == f {
 			break
 		}
 	}
@@ -116,7 +116,7 @@
 		ctx := o.ctx
 		x := ctx.mkErr(o.obj, codeNotExist, "value %q not found", key)
 		v := x.evalPartial(ctx)
-		return Value{ctx.index, &valueData{o.path.parent, 0, arc{feature: o.path.feature, cache: v, v: x}}}
+		return Value{ctx.index, &valueData{o.path.parent, 0, arc{Label: o.path.Label, Value: v, v: x}}}
 	}
 	return newChildValue(o, i)
 }
@@ -209,7 +209,7 @@
 	}
 	arc := i.iter.iterAt(i.ctx, i.p)
 	i.cur = i.val.makeChild(i.ctx, uint32(i.p), arc)
-	i.f = arc.feature
+	i.f = arc.Label
 	i.p++
 	return true
 }
@@ -236,12 +236,12 @@
 
 // IsOptional reports if a field is optional.
 func (i *Iterator) IsOptional() bool {
-	return i.cur.path.arc.optional
+	return i.cur.v.arc.optional
 }
 
 // IsDefinition reports if a field is a definition.
 func (i *Iterator) IsDefinition() bool {
-	return i.cur.path.arc.definition
+	return i.cur.v.arc.definition
 }
 
 // marshalJSON iterates over the list and generates JSON output. HasNext
@@ -270,7 +270,7 @@
 	if err := v.checkKind(v.ctx(), k); err != nil {
 		return nil, v.toErr(err)
 	}
-	n, _ := v.path.cache.(*numLit)
+	n, _ := v.v.Value.(*numLit)
 	return n, nil
 }
 
@@ -508,15 +508,15 @@
 	case listKind:
 		a = append(a, strconv.FormatInt(int64(v.index), 10))
 	case structKind:
-		f := idx.LabelStr(v.arc.feature)
-		if l := v.arc.feature; !l.IsDef() && !l.IsHidden() {
+		f := idx.LabelStr(v.arc.Label)
+		if l := v.arc.Label; !l.IsDef() && !l.IsHidden() {
 			if !isIdent(f) && !isNumber(f) {
 				f = quote(f, '"')
 			}
 		}
 		a = append(a, f)
 	}
-	return a, v.arc.cache.Kind()
+	return a, v.arc.Value.Kind()
 }
 
 var validIdent = []*unicode.RangeTable{unicode.L, unicode.N}
@@ -544,42 +544,42 @@
 // Value holds any value, which may be a Boolean, Error, List, Null, Number,
 // Struct, or String.
 type Value struct {
-	idx  *index
-	path *valueData
+	idx *index
+	v   *valueData
 }
 
 func newErrValue(v Value, b *bottom) Value {
 	ctx := v.ctx()
-	p := v.path
+	p := v.v
 	if p == nil {
 		return newValueRoot(ctx, b)
 	}
 	return Value{
 		ctx.index,
 		&valueData{p.parent, p.index, arc{
-			feature: p.arc.feature,
-			cache:   b,
-			v:       b,
+			Label: p.arc.Label,
+			Value: b,
+			v:     b,
 		}},
 	}
 }
 
 func newValueRoot(ctx *context, x value) Value {
 	v := x.evalPartial(ctx)
-	return Value{ctx.index, &valueData{nil, 0, arc{cache: v, v: x}}}
+	return Value{ctx.index, &valueData{nil, 0, arc{Value: v, v: x}}}
 }
 
 func newChildValue(obj *structValue, i int) Value {
-	a := obj.arcs[i]
-	for j, b := range obj.obj.arcs {
-		if b.feature == a.feature {
+	a := obj.Arcs[i]
+	for j, b := range obj.obj.Arcs {
+		if b.Label == a.Label {
 			a = obj.obj.iterAt(obj.ctx, j)
 			// TODO: adding more technical debt here. The evaluator should be
 			// rewritten.
 			x := obj.obj
 			ctx := obj.ctx
 			if x.optionals != nil {
-				name := ctx.LabelStr(x.arcs[i].feature)
+				name := ctx.LabelStr(x.Arcs[i].Label)
 				arg := &stringLit{x.baseValue, name, nil}
 
 				val, _ := x.optionals.constraint(ctx, arg)
@@ -597,19 +597,19 @@
 // Dereference reports the value v refers to if v is a reference or v itself
 // otherwise.
 func Dereference(v Value) Value {
-	if v.path == nil {
+	if v.v == nil {
 		return v
 	}
 
 	ctx := v.ctx()
-	a, n := appendPath(ctx, make([]label, 0, 3), v.path.v)
+	a, n := appendPath(ctx, make([]label, 0, 3), v.v.v)
 
 	if n == nil {
 		return v
 
 	}
 
-	p := locateNode(v.path, n)
+	p := locateNode(v.v, n)
 
 	if p == nil {
 
@@ -622,21 +622,21 @@
 			// See TestPathCorrection.
 			return v
 		}
-		p = &valueData{arc: arc{v: imp.rootValue, cache: imp.rootStruct}}
+		p = &valueData{arc: arc{v: imp.rootValue, Value: imp.rootStruct}}
 	}
 
-	cached := p.cache
+	cached := p.Value
 	if cached == nil {
 		cached = p.v.evalPartial(ctx)
 	}
 	s := cached.(*structLit)
 	for _, f := range a {
-		a := s.lookup(ctx, f)
+		a := s.Lookup(ctx, f)
 		if a.v == nil {
 			return Value{}
 		}
 		p = &valueData{parent: p, arc: a} // index
-		s, _ = a.cache.(*structLit)
+		s, _ = a.Value.(*structLit)
 	}
 
 	v = Value{v.idx, p}
@@ -674,7 +674,7 @@
 }
 
 func remakeValue(base Value, v value) Value {
-	p := base.path
+	p := base.v
 	if n, ok := v.(*nodeRef); ok {
 		if q := locateNode(p, n); q != nil {
 			p = q
@@ -682,13 +682,13 @@
 	}
 	path := *p
 	path.v = v
-	path.cache = v.evalPartial(base.ctx())
+	path.Value = v.evalPartial(base.ctx())
 	return Value{base.idx, &path}
 }
 
 func locateNode(p *valueData, n *nodeRef) *valueData {
 	// the parent must exist.
-	for ; p != nil && p.cache != n.node.(value); p = p.parent {
+	for ; p != nil && p.Value != n.node.(value); p = p.parent {
 	}
 	return p
 }
@@ -698,23 +698,23 @@
 }
 
 func (v Value) makeChild(ctx *context, i uint32, a arc) Value {
-	return Value{v.idx, &valueData{v.path, i, a}}
+	return Value{v.idx, &valueData{v.v, i, a}}
 }
 
 func (v Value) makeElem(x value) Value {
 	v, e := v.evalFull(x)
-	return Value{v.idx, &valueData{v.path, 0, arc{
+	return Value{v.idx, &valueData{v.v, 0, arc{
 		optional: true,
 		v:        x,
-		cache:    e,
+		Value:    e,
 	}}}
 }
 
 func (v Value) eval(ctx *context) evaluated {
-	if v.path == nil || v.path.cache == nil {
+	if v.v == nil || v.v.Value == nil {
 		panic("undefined value")
 	}
-	return ctx.manifest(v.path.cache)
+	return ctx.manifest(v.v.Value)
 }
 
 func (v Value) evalFull(u value) (Value, evaluated) {
@@ -727,9 +727,9 @@
 			x = err
 		}
 		if x != st {
-			p := *v.path
-			p.cache = x
-			v.path = &p
+			p := *v.v
+			p.Value = x
+			v.v = &p
 		}
 	}
 	return v, x
@@ -738,19 +738,19 @@
 // Eval resolves the references of a value and returns the result.
 // This method is not necessary to obtain concrete values.
 func (v Value) Eval() Value {
-	if v.path == nil {
+	if v.v == nil {
 		return v
 	}
-	return remakeValue(v.evalFull(v.path.v))
+	return remakeValue(v.evalFull(v.v.v))
 }
 
 // Default reports the default value and whether it existed. It returns the
 // normal value if there is no default.
 func (v Value) Default() (Value, bool) {
-	if v.path == nil {
+	if v.v == nil {
 		return v, false
 	}
-	v, u := v.evalFull(v.path.v)
+	v, u := v.evalFull(v.v.v)
 	x := v.ctx().manifest(u)
 	if x != u {
 		return remakeValue(v, x), true
@@ -763,22 +763,22 @@
 // TODO: get rid of this somehow. Probably by including a FieldInfo struct
 // or the like.
 func (v Value) Label() (string, bool) {
-	if v.path.feature == 0 {
+	if v.v.Label == 0 {
 		return "", false
 	}
-	return v.idx.LabelStr(v.path.feature), true
+	return v.idx.LabelStr(v.v.Label), true
 }
 
 // Kind returns the kind of value. It returns BottomKind for atomic values that
 // are not concrete. For instance, it will return BottomKind for the bounds
 // >=0.
 func (v Value) Kind() Kind {
-	if v.path == nil {
+	if v.v == nil {
 		return BottomKind
 	}
-	c := v.path.cache
+	c := v.v.Value
 	if c == nil {
-		c = v.path.v.evalPartial(v.ctx())
+		c = v.v.v.evalPartial(v.ctx())
 	}
 	k := c.Kind()
 	if k.isGround() {
@@ -808,11 +808,11 @@
 
 // IncompleteKind returns a mask of all kinds that this value may be.
 func (v Value) IncompleteKind() Kind {
-	if v.path == nil {
+	if v.v == nil {
 		return BottomKind
 	}
 	var k kind
-	x := v.path.v.evalPartial(v.ctx())
+	x := v.v.v.evalPartial(v.ctx())
 	switch x := convertBuiltin(x).(type) {
 	case *builtin:
 		k = x.representedKind()
@@ -858,7 +858,7 @@
 
 func (v Value) marshalJSON() (b []byte, err error) {
 	v, _ = v.Default()
-	if v.path == nil {
+	if v.v == nil {
 		return json.Marshal(nil)
 	}
 	ctx := v.idx.newContext()
@@ -877,7 +877,7 @@
 		return json.Marshal(x.(*bytesLit).B)
 	case listKind:
 		l := x.(*list)
-		i := Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.arcs)}
+		i := Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.Arcs)}
 		return marshalList(&i)
 	case structKind:
 		obj, err := v.structValData(ctx)
@@ -913,7 +913,7 @@
 	// TODO: the default should ideally be simplified representation that
 	// exactly represents the value. The latter can currently only be
 	// ensured with Raw().
-	if v.path == nil || v.path.cache == nil {
+	if v.v == nil || v.v.Value == nil {
 		return nil
 	}
 	ctx := v.ctx()
@@ -923,10 +923,10 @@
 		inst = v.instance()
 	}
 	if o.raw {
-		n, _ := export(ctx, inst, v.path.v, o)
+		n, _ := export(ctx, inst, v.v.v, o)
 		return n
 	}
-	n, _ := export(ctx, inst, v.path.cache, o)
+	n, _ := export(ctx, inst, v.v.Value, o)
 	return n
 }
 
@@ -949,10 +949,10 @@
 // Doc returns all documentation comments associated with the field from which
 // the current value originates.
 func (v Value) Doc() []*ast.CommentGroup {
-	if v.path == nil {
+	if v.v == nil {
 		return nil
 	}
-	return v.path.docs.appendDocs(nil)
+	return v.v.docs.appendDocs(nil)
 }
 
 // Split returns a list of values from which v originated such that
@@ -963,14 +963,14 @@
 //
 // Deprecated: use Expr.
 func (v Value) Split() []Value {
-	if v.path == nil {
+	if v.v == nil {
 		return nil
 	}
 	ctx := v.ctx()
 	a := []Value{}
-	for _, x := range separate(v.path.v) {
-		path := *v.path
-		path.cache = x.evalPartial(ctx)
+	for _, x := range separate(v.v.v) {
+		path := *v.v
+		path.Value = x.evalPartial(ctx)
 		path.v = x
 		a = append(a, Value{v.idx, &path})
 	}
@@ -996,10 +996,10 @@
 // struct literal, a field comprehension, or a file. It returns nil for
 // computed nodes. Use Split to get all source values that apply to a field.
 func (v Value) Source() ast.Node {
-	if v.path == nil {
+	if v.v == nil {
 		return nil
 	}
-	return v.path.v.Source()
+	return v.v.v.Source()
 }
 
 // Err returns the error represented by v or nil v is not an error.
@@ -1012,7 +1012,7 @@
 
 // Pos returns position information.
 func (v Value) Pos() token.Pos {
-	if v.path == nil || v.Source() == nil {
+	if v.v == nil || v.Source() == nil {
 		return token.NoPos
 	}
 	pos := v.Source().Pos()
@@ -1026,13 +1026,13 @@
 func (v Value) IsClosed() bool {
 	switch v.Kind() {
 	case StructKind:
-		if st, ok := v.path.val().(*structLit); ok {
+		if st, ok := v.v.val().(*structLit); ok {
 			return st.closeStatus.shouldClose()
 		}
 	case ListKind:
-		if l, ok := v.path.val().(*list); ok {
+		if l, ok := v.v.val().(*list); ok {
 			if n, ok := l.len.(*numLit); ok {
-				return n.intValue(v.ctx()) == len(l.elem.arcs)
+				return n.intValue(v.ctx()) == len(l.elem.Arcs)
 			}
 		}
 	}
@@ -1044,10 +1044,10 @@
 // It does not verify that values of lists or structs are concrete themselves.
 // To check whether there is a concrete default, use v.Default().IsConcrete().
 func (v Value) IsConcrete() bool {
-	if v.path == nil {
+	if v.v == nil {
 		return false // any is neither concrete, not a list or struct.
 	}
-	x := v.path.v.evalPartial(v.ctx())
+	x := v.v.v.evalPartial(v.ctx())
 
 	// Errors marked as incomplete are treated as not complete.
 	if isIncomplete(x) {
@@ -1072,14 +1072,14 @@
 
 // Exists reports whether this value existed in the configuration.
 func (v Value) Exists() bool {
-	if v.path == nil {
+	if v.v == nil {
 		return false
 	}
 	return exists(v.eval(v.ctx()))
 }
 
 func (v Value) checkKind(ctx *context, want kind) *bottom {
-	if v.path == nil {
+	if v.v == nil {
 		return errNotExists
 	}
 	// TODO: use checkKind
@@ -1102,15 +1102,15 @@
 }
 
 func makeInt(v Value, x int64) Value {
-	return remakeValue(v, newInt(v.path.v.base(), base10).setInt64(x))
+	return remakeValue(v, newInt(v.v.v.base(), base10).setInt64(x))
 }
 
 // Len returns the number of items of the underlying value.
 // For lists it reports the capacity of the list. For structs it indicates the
 // number of fields, for bytes the number of bytes.
 func (v Value) Len() Value {
-	if v.path != nil {
-		switch x := v.path.v.evalPartial(v.ctx()).(type) {
+	if v.v != nil {
+		switch x := v.v.v.evalPartial(v.ctx()).(type) {
 		case *list:
 			return remakeValue(v, x.len.evalPartial(v.ctx()))
 		case *bytesLit:
@@ -1120,13 +1120,13 @@
 		}
 	}
 	const msg = "len not supported for type %v"
-	return remakeValue(v, v.ctx().mkErr(v.path.v, msg, v.Kind()))
+	return remakeValue(v, v.ctx().mkErr(v.v.v, msg, v.Kind()))
 }
 
 // Elem returns the value of undefined element types of lists and structs.
 func (v Value) Elem() (Value, bool) {
 	ctx := v.ctx()
-	switch x := v.path.cache.(type) {
+	switch x := v.v.Value.(type) {
 	case *structLit:
 		t, _ := x.optionals.constraint(ctx, nil)
 		if t == nil {
@@ -1142,7 +1142,7 @@
 // BulkOptionals returns all bulk optional fields as key-value pairs.
 // See also Elem and Template.
 func (v Value) BulkOptionals() [][2]Value {
-	x, ok := v.path.cache.(*structLit)
+	x, ok := v.v.Value.(*structLit)
 	if !ok {
 		return nil
 	}
@@ -1180,7 +1180,7 @@
 		return Iterator{ctx: ctx}, v.toErr(err)
 	}
 	l := v.eval(ctx).(*list)
-	return Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.arcs)}, nil
+	return Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.Arcs)}, nil
 }
 
 // Null reports an error if v is not null.
@@ -1275,8 +1275,8 @@
 	needFilter := false
 	if o.omitHidden || o.omitOptional || o.omitDefinitions {
 		f := label(0)
-		for _, a := range obj.arcs {
-			f |= a.feature
+		for _, a := range obj.Arcs {
+			f |= a.Label
 			if a.optional && o.omitOptional {
 				needFilter = true
 				break
@@ -1290,13 +1290,13 @@
 	}
 
 	if needFilter {
-		arcs := make([]arc, len(obj.arcs))
+		arcs := make([]arc, len(obj.Arcs))
 		k := 0
-		for _, a := range obj.arcs {
+		for _, a := range obj.Arcs {
 			if a.definition && (o.omitDefinitions || o.concrete) {
 				continue
 			}
-			if a.feature.IsHidden() && o.omitHidden {
+			if a.Label.IsHidden() && o.omitHidden {
 				continue
 			}
 			if o.omitOptional && a.optional {
@@ -1308,7 +1308,7 @@
 		arcs = arcs[:k]
 		return structValue{ctx, path, obj, arcs}, nil
 	}
-	return structValue{ctx, path, obj, obj.arcs}, nil
+	return structValue{ctx, path, obj, obj.Arcs}, nil
 }
 
 // Struct returns the underlying struct of a value or an error if the value
@@ -1334,10 +1334,10 @@
 		return nil, nil, err
 	}
 
-	path := v.path
+	path := v.v
 	if obj != orig {
 		p := *path
-		p.arc.cache = obj
+		p.arc.Value = obj
 		path = &p
 	}
 
@@ -1362,20 +1362,20 @@
 }
 
 func (s *Struct) Len() int {
-	return len(s.s.arcs)
+	return len(s.s.Arcs)
 }
 
 // field reports information about the ith field, i < o.Len().
 func (s *Struct) Field(i int) FieldInfo {
 	ctx := s.v.ctx()
-	a := s.s.arcs[i]
-	a.cache = s.s.at(ctx, i)
+	a := s.s.Arcs[i]
+	a.Value = s.s.at(ctx, i)
 
 	// TODO: adding more technical debt here. The evaluator should be
 	// rewritten.
 	x := s.s
 	if x.optionals != nil {
-		name := ctx.LabelStr(x.arcs[i].feature)
+		name := ctx.LabelStr(x.Arcs[i].Label)
 		arg := &stringLit{x.baseValue, name, nil}
 
 		val, _ := x.optionals.constraint(ctx, arg)
@@ -1384,9 +1384,9 @@
 		}
 	}
 
-	v := Value{ctx.index, &valueData{s.v.path, uint32(i), a}}
-	str := ctx.LabelStr(a.feature)
-	return FieldInfo{str, i, v, a.definition, a.optional, a.feature.IsHidden()}
+	v := Value{ctx.index, &valueData{s.v.v, uint32(i), a}}
+	str := ctx.LabelStr(a.Label)
+	return FieldInfo{str, i, v, a.definition, a.optional, a.Label.IsHidden()}
 }
 
 // FieldByName looks up a field for the given name. If isIdent is true, it will
@@ -1394,8 +1394,8 @@
 // it interprets name as an arbitrary string for a regular field.
 func (s *Struct) FieldByName(name string, isIdent bool) (FieldInfo, error) {
 	f := s.v.ctx().Label(name, isIdent)
-	for i, a := range s.s.arcs {
-		if a.feature == f {
+	for i, a := range s.s.Arcs {
+		if a.Label == f {
 			return s.Field(i), nil
 		}
 	}
@@ -1424,10 +1424,10 @@
 		obj.obj.optionals,   // template
 		obj.obj.closeStatus, // closeStatus
 		nil,                 // comprehensions
-		obj.arcs,            // arcs
+		obj.Arcs,            // arcs
 		nil,                 // attributes
 	}
-	return &Iterator{ctx: ctx, val: v, iter: n, len: len(n.arcs)}, nil
+	return &Iterator{ctx: ctx, val: v, iter: n, len: len(n.Arcs)}, nil
 }
 
 // Lookup reports the value at a path starting from v. The empty path returns v
@@ -1461,8 +1461,8 @@
 	}
 
 	f := v.ctx().Label(name, true)
-	for i, a := range o.arcs {
-		if a.feature == f {
+	for i, a := range o.Arcs {
+		if a.Label == f {
 			if f.IsHidden() || !a.definition || a.optional {
 				break
 			}
@@ -1476,7 +1476,7 @@
 			return alt
 		}
 	}
-	return newErrValue(v, ctx.mkErr(v.path.v,
+	return newErrValue(v, ctx.mkErr(v.v.v,
 		"defintion %q not found", name))
 }
 
@@ -1533,20 +1533,20 @@
 // Any reference in v referring to the value at the given path will resolve
 // to x in the newly created value. The resulting value is not validated.
 func (v Value) Fill(x interface{}, path ...string) Value {
-	if v.path == nil {
+	if v.v == nil {
 		return v
 	}
 	ctx := v.ctx()
-	root := v.path.val()
+	root := v.v.val()
 	for i := len(path) - 1; i >= 0; i-- {
 		x = map[string]interface{}{path[i]: x}
 	}
 	value := convertVal(ctx, root, true, x)
-	a := v.path.arc
+	a := v.v.arc
 	a.v = mkBin(ctx, v.Pos(), opUnify, root, value)
-	a.cache = a.v.evalPartial(ctx)
+	a.Value = a.v.evalPartial(ctx)
 	// TODO: validate recursively?
-	return Value{v.idx, &valueData{v.path.parent, v.path.index, a}}
+	return Value{v.idx, &valueData{v.v.parent, v.v.index, a}}
 }
 
 // Template returns a function that represents the template definition for a
@@ -1557,12 +1557,12 @@
 // given its name.
 func (v Value) Template() func(label string) Value {
 	// TODO: rename to optional.
-	if v.path == nil {
+	if v.v == nil {
 		return nil
 	}
 
 	ctx := v.ctx()
-	x, ok := v.path.cache.(*structLit)
+	x, ok := v.v.Value.(*structLit)
 	if !ok || x.optionals.isEmpty() {
 		return nil
 	}
@@ -1622,10 +1622,10 @@
 // TODO: remove this requirement.
 func (v Value) Unify(w Value) Value {
 	ctx := v.ctx()
-	if v.path == nil {
+	if v.v == nil {
 		return w
 	}
-	if w.path == nil {
+	if w.v == nil {
 		return v
 	}
 	if v.Err() != nil {
@@ -1635,8 +1635,8 @@
 	if w.Err() != nil {
 		return w
 	}
-	a := v.path.v
-	b := w.path.v
+	a := v.v.v
+	b := w.v.v
 	src := binSrc(token.NoPos, opUnify, a, b)
 	val := mkBin(ctx, src.Pos(), opUnify, a, b)
 	u := remakeValue(v, val)
@@ -1649,36 +1649,36 @@
 // Equals reports whether two values are equal, ignoring optional fields.
 // The result is undefined for incomplete values.
 func (v Value) Equals(other Value) bool {
-	if v.path == nil || other.path == nil {
+	if v.v == nil || other.v == nil {
 		return false
 	}
-	x := v.path.val()
-	y := other.path.val()
+	x := v.v.val()
+	y := other.v.val()
 	return equals(v.ctx(), x, y)
 }
 
 // Format prints a debug version of a value.
 func (v Value) Format(state fmt.State, verb rune) {
 	ctx := v.ctx()
-	if v.path == nil {
+	if v.v == nil {
 		fmt.Fprint(state, "<nil>")
 		return
 	}
 	switch {
 	case state.Flag('#'):
-		_, _ = io.WriteString(state, ctx.str(v.path.v))
+		_, _ = io.WriteString(state, ctx.str(v.v.v))
 	case state.Flag('+'):
-		_, _ = io.WriteString(state, debugStr(ctx, v.path.v))
+		_, _ = io.WriteString(state, debugStr(ctx, v.v.v))
 	default:
-		_, _ = io.WriteString(state, ctx.str(v.path.cache))
+		_, _ = io.WriteString(state, ctx.str(v.v.Value))
 	}
 }
 
 func (v Value) instance() *Instance {
-	if v.path == nil {
+	if v.v == nil {
 		return nil
 	}
-	return v.ctx().getImportFromNode(v.path.v)
+	return v.ctx().getImportFromNode(v.v.v)
 }
 
 // Reference returns the instance and path referred to by this value such that
@@ -1687,13 +1687,13 @@
 // only return a reference if the index resolves to a concrete value.
 func (v Value) Reference() (inst *Instance, path []string) {
 	// TODO: don't include references to hidden fields.
-	if v.path == nil {
+	if v.v == nil {
 		return nil, nil
 	}
 	ctx := v.ctx()
 	var x value
 	var feature string
-	switch sel := v.path.v.(type) {
+	switch sel := v.v.v.(type) {
 	case *selectorExpr:
 		x = sel.X
 		feature = ctx.LabelStr(sel.Sel)
@@ -1710,7 +1710,7 @@
 	default:
 		return nil, nil
 	}
-	imp, a := mkPath(ctx, v.path, x, feature, 0)
+	imp, a := mkPath(ctx, v.v, x, feature, 0)
 	return imp, a
 }
 
@@ -1763,7 +1763,7 @@
 	}
 	root, a = mkFromRoot(c, up.parent, d+1)
 	if up.parent != nil {
-		a = append(a, c.LabelStr(up.feature))
+		a = append(a, c.LabelStr(up.Label))
 	} else {
 		root = up.v
 	}
@@ -1778,8 +1778,8 @@
 	// TODO: the pathFinder algorithm is quite broken. Using Reference and Expr
 	// will cast a much more accurate net on referenced values.
 	ctx := v.ctx()
-	pf := pathFinder{up: v.path}
-	raw := v.path.v
+	pf := pathFinder{up: v.v}
+	raw := v.v.v
 	if raw == nil {
 		return nil
 	}
@@ -1805,10 +1805,10 @@
 	case *nodeRef:
 		i := len(p.stack)
 		up := p.up
-		for ; up != nil && up.cache != x.node.(value); up = up.parent {
+		for ; up != nil && up.Value != x.node.(value); up = up.parent {
 		}
-		for ; up != nil && up.feature > 0; up = up.parent {
-			p.stack = append(p.stack, up.feature)
+		for ; up != nil && up.Label > 0; up = up.parent {
+			p.stack = append(p.stack, up.Label)
 		}
 		path := make([]string, len(p.stack))
 		for i, v := range p.stack {
@@ -1827,7 +1827,7 @@
 
 		stack := p.stack
 		p.stack = nil
-		for _, a := range x.arcs {
+		for _, a := range x.Arcs {
 			rewrite(ctx, a.v, p.find)
 		}
 		p.stack = stack
@@ -2033,7 +2033,7 @@
 		for i := 0; i < obj.Len(); i++ {
 			_, v := obj.At(i)
 			opts := opts
-			if obj.arcs[i].definition {
+			if obj.Arcs[i].definition {
 				opts.concrete = false
 			}
 			x.walk(v, opts)
@@ -2063,7 +2063,7 @@
 			return x
 		}
 	case *list:
-		for i := 0; i < len(x.elem.arcs); i++ {
+		for i := 0; i < len(x.elem.Arcs); i++ {
 			v := ctx.manifest(x.at(ctx, i))
 			if err := isGroundRecursive(ctx, v); err != nil {
 				return err
@@ -2115,10 +2115,10 @@
 // is no attribute for the requested key.
 func (v Value) Attribute(key string) Attribute {
 	// look up the attributes
-	if v.path == nil || v.path.attrs == nil {
+	if v.v == nil || v.v.attrs == nil {
 		return Attribute{internal.NewNonExisting(key)}
 	}
-	for _, a := range v.path.attrs.attr {
+	for _, a := range v.v.attrs.attr {
 		if a.key() != key {
 			continue
 		}
@@ -2185,13 +2185,13 @@
 // args of the call.
 func (v Value) Expr() (Op, []Value) {
 	// TODO: return v if this is complete? Yes for now
-	if v.path == nil {
+	if v.v == nil {
 		return NoOp, nil
 	}
 	// TODO: replace appends with []Value{}. For not leave.
 	a := []Value{}
 	op := NoOp
-	switch x := v.path.v.(type) {
+	switch x := v.v.v.(type) {
 	case *binaryExpr:
 		a = append(a, remakeValue(v, x.X))
 		a = append(a, remakeValue(v, x.Y))
diff --git a/cue/types_test.go b/cue/types_test.go
index 482ddde..e124aa9 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -1475,7 +1475,7 @@
 					v = v.Lookup(e)
 				}
 			}
-			got, _ := v.path.appendPath(nil, v.idx)
+			got, _ := v.v.appendPath(nil, v.idx)
 			if !reflect.DeepEqual(got, tc) {
 				t.Errorf("got %v; want %v", got, tc)
 			}
@@ -2768,7 +2768,7 @@
 func exprStr(v Value) string {
 	op, operands := v.Expr()
 	if op == NoOp {
-		return debugStr(v.ctx(), v.path.v)
+		return debugStr(v.ctx(), v.v.v)
 	}
 	s := op.String()
 	s += "("
diff --git a/cue/validate.go b/cue/validate.go
index b0b949f..f6890d4 100644
--- a/cue/validate.go
+++ b/cue/validate.go
@@ -31,7 +31,7 @@
 		if ctx.maxDepth++; ctx.maxDepth > internal.MaxDepth {
 			return nil
 		}
-		for i, a := range x.arcs {
+		for i, a := range x.Arcs {
 			if a.optional {
 				continue
 			}
diff --git a/cue/value.go b/cue/value.go
index 8207235..29e81ff 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -52,7 +52,7 @@
 
 type scope interface {
 	value
-	lookup(*context, label) arc
+	Lookup(*context, label) arc
 }
 
 type atter interface {
@@ -213,7 +213,7 @@
 		return arc{}
 	}
 	v := x.at(ctx, i)
-	return arc{v: v, cache: v}
+	return arc{v: v, Value: v}
 }
 
 func (x *bytesLit) at(ctx *context, i int) evaluated {
@@ -267,7 +267,7 @@
 		return arc{}
 	}
 	v := x.at(ctx, i)
-	return arc{v: v, cache: v}
+	return arc{v: v, Value: v}
 }
 
 func (x *stringLit) at(ctx *context, i int) evaluated {
@@ -524,7 +524,7 @@
 
 // initLit initializes a literal list.
 func (x *list) initLit() {
-	x.len = newInt(x, 0).setInt(len(x.elem.arcs))
+	x.len = newInt(x, 0).setInt(len(x.elem.Arcs))
 	x.typ = &top{x.baseValue}
 }
 
@@ -534,7 +534,7 @@
 	}
 	// A list is ground if its length is ground, or if the current length
 	// meets matches the cap.
-	n := newInt(x, 0).setInt(len(x.elem.arcs))
+	n := newInt(x, 0).setInt(len(x.elem.Arcs))
 	if n := binOp(ctx, x, opUnify, n, x.len.evalPartial(ctx)); !isBottom(n) {
 		return &list{
 			baseValue: x.baseValue,
@@ -559,10 +559,10 @@
 // issue evaluating the list itself.
 func (x *list) at(ctx *context, i int) evaluated {
 	arc := x.iterAt(ctx, i)
-	if arc.cache == nil {
+	if arc.Value == nil {
 		return ctx.mkErr(x, "index %d out of bounds", i)
 	}
-	return arc.cache
+	return arc.Value
 }
 
 // iterAt returns the evaluated and original value of position i. List x must
@@ -571,25 +571,25 @@
 func (x *list) iterAt(ctx *context, i int) arc {
 	if i < 0 {
 		v := ctx.mkErr(x, "index %d out of bounds", i)
-		return arc{cache: v}
+		return arc{Value: v}
 	}
-	if i < len(x.elem.arcs) {
+	if i < len(x.elem.Arcs) {
 		a := x.elem.iterAt(ctx, i)
-		a.feature = 0
+		a.Label = 0
 		return a
 	}
 	max := maxNum(x.len.(evaluated))
 	if max.Kind().isGround() {
 		if max.Kind()&intKind == bottomKind {
 			v := ctx.mkErr(max, "length indicator of list not of type int")
-			return arc{cache: v}
+			return arc{Value: v}
 		}
 		n := max.(*numLit).intValue(ctx)
 		if i >= n {
 			return arc{}
 		}
 	}
-	return arc{cache: x.typ.evalPartial(ctx), v: x.typ}
+	return arc{Value: x.typ.evalPartial(ctx), v: x.typ}
 }
 
 func (x *list) isOpen() bool {
@@ -598,7 +598,7 @@
 
 // lo and hi must be nil or a ground integer.
 func (x *list) slice(ctx *context, lo, hi *numLit) evaluated {
-	a := x.elem.arcs
+	a := x.elem.Arcs
 	max := maxNum(x.len).evalPartial(ctx)
 	if hi != nil {
 		n := hi.intValue(ctx)
@@ -634,9 +634,9 @@
 	}
 	arcs := make([]arc, len(a))
 	for i, a := range a {
-		arcs[i] = arc{feature: label(i), v: a.v, docs: a.docs}
+		arcs[i] = arc{Label: label(i), v: a.v, docs: a.docs}
 	}
-	s := &structLit{baseValue: x.baseValue, arcs: arcs}
+	s := &structLit{baseValue: x.baseValue, Arcs: arcs}
 	return &list{baseValue: x.baseValue, elem: s, typ: x.typ, len: max}
 }
 
@@ -669,7 +669,7 @@
 	comprehensions []compValue
 
 	// TODO: consider hoisting the template arc to its own value.
-	arcs     []arc
+	Arcs     []arc
 	expanded evaluated
 }
 
@@ -986,9 +986,9 @@
 
 type arcs []arc
 
-func (x *structLit) Len() int           { return len(x.arcs) }
-func (x *structLit) Less(i, j int) bool { return x.arcs[i].feature < x.arcs[j].feature }
-func (x *structLit) Swap(i, j int)      { x.arcs[i], x.arcs[j] = x.arcs[j], x.arcs[i] }
+func (x *structLit) Len() int           { return len(x.Arcs) }
+func (x *structLit) Less(i, j int) bool { return x.Arcs[i].Label < x.Arcs[j].Label }
+func (x *structLit) Swap(i, j int)      { x.Arcs[i], x.Arcs[j] = x.Arcs[j], x.Arcs[i] }
 
 func (x *structLit) close() *structLit {
 	if x.optionals.isFull() {
@@ -1001,7 +1001,7 @@
 }
 
 // lookup returns the node for the given label f, if present, or nil otherwise.
-func (x *structLit) lookup(ctx *context, f label) arc {
+func (x *structLit) Lookup(ctx *context, f label) arc {
 	x, err := x.expandFields(ctx)
 	if err != nil {
 		return arc{}
@@ -1009,13 +1009,13 @@
 	// Lookup is done by selector or index references. Either this is done on
 	// literal nodes or nodes obtained from references. In the later case,
 	// noderef will have ensured that the ancestors were evaluated.
-	for i, a := range x.arcs {
-		if a.feature == f {
+	for i, a := range x.Arcs {
+		if a.Label == f {
 			a := x.iterAt(ctx, i)
 			// TODO: adding more technical debt here. The evaluator should be
 			// rewritten.
 			if x.optionals != nil {
-				name := ctx.LabelStr(x.arcs[i].feature)
+				name := ctx.LabelStr(x.Arcs[i].Label)
 				arg := &stringLit{x.baseValue, name, nil}
 
 				val, _ := x.optionals.constraint(ctx, arg)
@@ -1031,11 +1031,11 @@
 
 func (x *structLit) iterAt(ctx *context, i int) arc {
 	x, err := x.expandFields(ctx)
-	if err != nil || i >= len(x.arcs) {
+	if err != nil || i >= len(x.Arcs) {
 		return arc{}
 	}
-	a := x.arcs[i]
-	a.cache = x.at(ctx, i) // TODO: return template & v for original?
+	a := x.Arcs[i]
+	a.Value = x.at(ctx, i) // TODO: return template & v for original?
 	return a
 }
 
@@ -1057,7 +1057,7 @@
 	// Lookup is done by selector or index references. Either this is done on
 	// literal nodes or nodes obtained from references. In the later case,
 	// noderef will have ensured that the ancestors were evaluated.
-	if v := x.arcs[i].cache; v == nil {
+	if v := x.Arcs[i].Value; v == nil {
 
 		// cycle detection
 
@@ -1066,12 +1066,12 @@
 			baseValue: x.base(),
 			index:     ctx.index,
 			Code:      codeCycle,
-			value:     x.arcs[i].v,
+			value:     x.Arcs[i].v,
 			format:    "cycle detected",
 		})
-		x.arcs[i].cache = &(ctx.evalStack[len(ctx.evalStack)-1])
+		x.Arcs[i].Value = &(ctx.evalStack[len(ctx.evalStack)-1])
 
-		v := x.arcs[i].v.evalPartial(ctx)
+		v := x.Arcs[i].v.evalPartial(ctx)
 		ctx.evalStack = popped
 
 		var doc *docNode
@@ -1083,7 +1083,7 @@
 			// partial results. Each field involved in the cycle will have to
 			// reevaluated the values from scratch. As the result will be
 			// cached after one cycle, it will evaluate the cycle at most twice.
-			x.arcs[i].cache = nil
+			x.Arcs[i].Value = nil
 			return v
 		}
 
@@ -1098,20 +1098,20 @@
 				v = err
 			}
 		}
-		x.arcs[i].cache = v
+		x.Arcs[i].Value = v
 		if doc != nil {
-			x.arcs[i].docs = &docNode{left: doc, right: x.arcs[i].docs}
+			x.Arcs[i].docs = &docNode{left: doc, right: x.Arcs[i].docs}
 		}
 		if len(ctx.evalStack) == 0 {
 			if err := ctx.processDelayedConstraints(); err != nil {
-				x.arcs[i].cache = err
+				x.Arcs[i].Value = err
 			}
 		}
 	} else if b := cycleError(v); b != nil {
 		copy := *b
 		return &copy
 	}
-	return x.arcs[i].cache
+	return x.Arcs[i].Value
 }
 
 // expandFields merges in embedded and interpolated fields.
@@ -1205,8 +1205,8 @@
 		return v, nil
 	}
 
-	if f := x.arcs[i].feature; !f.IsHidden() && !f.IsDef() {
-		name := ctx.LabelStr(x.arcs[i].feature)
+	if f := x.Arcs[i].Label; !f.IsHidden() && !f.IsDef() {
+		name := ctx.LabelStr(x.Arcs[i].Label)
 		arg := &stringLit{x.baseValue, name, nil}
 
 		var val value
@@ -1231,7 +1231,7 @@
 // however, may have both. In this case, the value must ultimately evaluate
 // to a node, which will then be merged with the existing one.
 type arc struct {
-	feature    label
+	Label      label
 	optional   bool
 	definition bool // field is a definition
 
@@ -1241,7 +1241,7 @@
 	// a linear search in fields.
 
 	v     value
-	cache evaluated // also used as newValue during unification.
+	Value evaluated // also used as newValue during unification.
 	attrs *attributes
 	docs  *docNode
 }
@@ -1286,12 +1286,12 @@
 }
 
 func (a *arc) val() evaluated {
-	return a.cache
+	return a.Value
 }
 
 func (a *arc) setValue(v value) {
 	a.v = v
-	a.cache = nil
+	a.Value = nil
 }
 
 type closeIfStruct struct {
@@ -1343,31 +1343,31 @@
 
 // insertValue is used during initialization but never during evaluation.
 func (x *structLit) insertValue(ctx *context, f label, optional, isDef bool, value value, a *attributes, docs *docNode) {
-	for i, p := range x.arcs {
-		if f != p.feature {
+	for i, p := range x.Arcs {
+		if f != p.Label {
 			continue
 		}
-		x.arcs[i].optional = x.arcs[i].optional && optional
-		x.arcs[i].docs = mergeDocs(x.arcs[i].docs, docs)
-		x.arcs[i].v = mkBin(ctx, token.NoPos, opUnify, p.v, value)
+		x.Arcs[i].optional = x.Arcs[i].optional && optional
+		x.Arcs[i].docs = mergeDocs(x.Arcs[i].docs, docs)
+		x.Arcs[i].v = mkBin(ctx, token.NoPos, opUnify, p.v, value)
 		if isDef != p.definition {
 			src := binSrc(token.NoPos, opUnify, p.v, value)
-			x.arcs[i].v = ctx.mkErr(src,
+			x.Arcs[i].v = ctx.mkErr(src,
 				"field %q declared as definition and regular field",
 				ctx.LabelStr(f))
 			isDef = false
 		}
-		x.arcs[i].definition = isDef
-		attrs, err := unifyAttrs(ctx, x, x.arcs[i].attrs, a)
+		x.Arcs[i].definition = isDef
+		attrs, err := unifyAttrs(ctx, x, x.Arcs[i].attrs, a)
 		if err != nil {
-			x.arcs[i].v = err
+			x.Arcs[i].v = err
 		}
-		x.arcs[i].attrs = attrs
+		x.Arcs[i].attrs = attrs
 		// TODO: should we warn if there is a mixed mode of optional and non
 		// optional fields at this point?
 		return
 	}
-	x.arcs = append(x.arcs, arc{f, optional, isDef, value, nil, a, docs})
+	x.Arcs = append(x.Arcs, arc{f, optional, isDef, value, nil, a, docs})
 	sort.Stable(x)
 }
 
@@ -1463,7 +1463,7 @@
 	if v == nil {
 		panic("nil node")
 	}
-	x.arcs = append(x.arcs, arc{feature: f, v: v})
+	x.arcs = append(x.arcs, arc{Label: f, v: v})
 }
 
 func (x *params) iterAt(ctx *context, i int) (evaluated, value) {
@@ -1478,26 +1478,26 @@
 	// Lookup is done by selector or index references. Either this is done on
 	// literal nodes or nodes obtained from references. In the later case,
 	// noderef will have ensured that the ancestors were evaluated.
-	if x.arcs[i].cache == nil {
-		x.arcs[i].cache = x.arcs[i].v.evalPartial(ctx)
+	if x.arcs[i].Value == nil {
+		x.arcs[i].Value = x.arcs[i].v.evalPartial(ctx)
 	}
-	return x.arcs[i].cache
+	return x.arcs[i].Value
 }
 
 // lookup returns the node for the given label f, if present, or nil otherwise.
-func (x *params) lookup(ctx *context, f label) arc {
+func (x *params) Lookup(ctx *context, f label) arc {
 	if f == 0 && len(x.arcs) == 1 {
 		// A template binding.
 		a := x.arcs[0]
-		a.cache = x.at(ctx, 0)
+		a.Value = x.at(ctx, 0)
 		return a
 	}
 	// Lookup is done by selector or index references. Either this is done on
 	// literal nodes or nodes obtained from references. In the later case,
 	// noderef will have ensured that the ancestors were evaluated.
 	for i, a := range x.arcs {
-		if a.feature == f {
-			a.cache = x.at(ctx, i)
+		if a.Label == f {
+			a.Value = x.at(ctx, i)
 			return a
 		}
 	}
@@ -1532,7 +1532,7 @@
 		if isBottom(v) {
 			return v
 		}
-		arcs[i] = arc{feature: a.feature, v: v, cache: v}
+		arcs[i] = arc{Label: a.Label, v: v, Value: v}
 	}
 	lambda := &lambdaExpr{x.baseValue, &params{arcs}, nil}
 	defer ctx.pushForwards(x, lambda).popForwards()
@@ -1903,13 +1903,13 @@
 		if err != nil {
 			return err
 		}
-		for i, a := range src.arcs {
+		for i, a := range src.Arcs {
 			key := &stringLit{
 				x.baseValue,
-				ctx.LabelStr(a.feature),
+				ctx.LabelStr(a.Label),
 				nil,
 			}
-			if a.definition || a.optional || a.feature.IsHidden() {
+			if a.definition || a.optional || a.Label.IsHidden() {
 				continue
 			}
 			val := src.at(ctx, i)
@@ -1924,7 +1924,7 @@
 		return nil
 
 	case *list:
-		for i := range src.elem.arcs {
+		for i := range src.elem.Arcs {
 			idx := newInt(x, 0).setInt(i)
 			v := fn.call(ctx, x, idx, src.at(ctx, i))
 			if err, ok := v.(*bottom); ok {