Skip to content

Commit

Permalink
cue: prepare API implementation for structure sharing
Browse files Browse the repository at this point in the history
The CUE API relies on the Parent field to reflect the
path down which the user descended to obtain the
value. With structure sharing, this means this parent
field may vary by context.

This now adds another field to Value, which keeps
track of a differing parent Value chain. The field
only needs to be set in the case of actual structure
sharing.

Change-Id: Ia03de7d249ce72e72104740ce649827e7b07f2ad
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9572
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
  • Loading branch information
mpvl committed Apr 30, 2021
1 parent d9af603 commit c365513
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 61 deletions.
6 changes: 3 additions & 3 deletions cue/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func Scope(scope Value) BuildOption {
if o.Scope != nil {
panic("more than one scope is given")
}
o.Scope = scope.v
o.Scope = valueScope(scope)
}
}

Expand Down Expand Up @@ -181,8 +181,8 @@ func (c *Context) BuildExpr(x ast.Expr, options ...BuildOption) Value {
func errFn(pos token.Pos, msg string, args ...interface{}) {}

// resolveExpr binds unresolved expressions to values in the expression or v.
func resolveExpr(ctx *adt.OpContext, v *adt.Vertex, x ast.Expr) adt.Value {
cfg := &compile.Config{Scope: v}
func resolveExpr(ctx *adt.OpContext, v Value, x ast.Expr) adt.Value {
cfg := &compile.Config{Scope: valueScope(v)}

astutil.ResolveExpr(x, errFn)

Expand Down
2 changes: 1 addition & 1 deletion cue/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ func (inst *hiddenInstance) Build(p *build.Instance) *Instance {

rErr := r.ResolveFiles(p)

cfg := &compile.Config{Scope: inst.root}
cfg := &compile.Config{Scope: valueScope(Value{idx: r, v: inst.root})}
v, err := compile.Files(cfg, r, p.ID(), p.Files...)

v.AddConjunct(adt.MakeRootConjunct(nil, inst.root))
Expand Down
13 changes: 8 additions & 5 deletions cue/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ import (
// getScopePrefix finds the Vertex that exists in v for the longest prefix of p.
//
// It is used to make the parent scopes visible when resolving expressions.
func getScopePrefix(v Value, p Path) *adt.Vertex {
func getScopePrefix(v Value, p Path) Value {
for _, sel := range p.Selectors() {
w := v.LookupPath(MakePath(sel))
if !w.Exists() {
break
}
v = w
}
return v.v
return v
}

// LookupPath reports the value for path p relative to v.
Expand All @@ -40,25 +40,28 @@ func (v Value) LookupPath(p Path) Value {
return Value{}
}
n := v.v
parent := v.parent_
ctx := v.ctx()

outer:
for _, sel := range p.path {
f := sel.sel.feature(v.idx)
for _, a := range n.Arcs {
if a.Label == f {
parent = linkParent(parent, n, a)
n = a
continue outer
}
}
if sel.sel.optional() {
x := &adt.Vertex{
Parent: v.v,
Parent: n,
Label: sel.sel.feature(ctx),
}
n.MatchAndInsert(ctx, x)
if len(x.Conjuncts) > 0 {
x.Finalize(ctx)
parent = linkParent(parent, n, x)
n = x
continue
}
Expand All @@ -71,8 +74,8 @@ outer:
// TODO: better message.
x = mkErr(v.idx, n, adt.NotExistError, "field %q not found", sel.sel)
}
v := makeValue(v.idx, n)
v := makeValue(v.idx, n, parent)
return newErrValue(v, x)
}
return makeValue(v.idx, n)
return makeValue(v.idx, n, parent)
}

0 comments on commit c365513

Please sign in to comment.