Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
cue: fix lookup for cue API
Browse files Browse the repository at this point in the history
Fixes analogue of commit c937e7a.

Fixes #157
Issue #202

Change-Id: Ieb3e37206b5cbe1ddddebfb2712f07b9e9efccf6
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4220
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
mpvl committed Dec 2, 2019
1 parent 3a2e63b commit 8bd2426
Showing 3 changed files with 121 additions and 25 deletions.
2 changes: 1 addition & 1 deletion cue/instance.go
Original file line number Diff line number Diff line change
@@ -257,7 +257,7 @@ func (inst *Instance) Build(p *build.Instance) *Instance {
i.setError(val.toErr(err))
return i
}
i.scope = v.n
i.scope = v.obj

if err := resolveFiles(idx, p); err != nil {
i.setError(err)
78 changes: 55 additions & 23 deletions cue/types.go
Original file line number Diff line number Diff line change
@@ -135,20 +135,21 @@ var kindStrs = map[Kind]string{
type structValue struct {
ctx *context
path *valueData
n *structLit
obj *structLit
arcs arcs
}

// Len reports the number of fields in this struct.
func (o *structValue) Len() int {
if o.n == nil {
if o.obj == nil {
return 0
}
return len(o.n.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.n.arcs[i]
a := o.arcs[i]
v = newChildValue(o, i)
return o.ctx.labelStr(a.feature), v
}
@@ -160,19 +161,17 @@ func (o *structValue) Lookup(key string) Value {
i := 0
len := o.Len()
for ; i < len; i++ {
if o.n.arcs[i].feature == f {
if o.arcs[i].feature == f {
break
}
}
if i == len {
// TODO: better message.
ctx := o.ctx
x := ctx.mkErr(o.n, codeNotExist, "value %q not found", key)
x := ctx.mkErr(o.obj, codeNotExist, "value %q not found", key)
v := x.evalPartial(ctx)
return Value{ctx.index, &valueData{o.path, 0, arc{cache: v, v: x}}}
}
// v, _ := o.n.lookup(o.ctx, f)
// v = o.ctx.manifest(v)
return newChildValue(o, i)
}

@@ -606,8 +605,26 @@ func newValueRoot(ctx *context, x value) Value {
}

func newChildValue(obj *structValue, i int) Value {
a := obj.n.arcs[i]
a.cache = obj.n.at(obj.ctx, i)
a := obj.arcs[i]
for j, b := range obj.obj.arcs {
if b.feature == a.feature {
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)
arg := &stringLit{x.baseValue, name, nil}

val, _ := x.optionals.constraint(ctx, arg)
if val != nil {
a.v = mkBin(ctx, x.Pos(), opUnify, a.v, val)
}
}
break
}
}

return Value{obj.ctx.index, &valueData{obj.path, uint32(i), a}}
}
@@ -640,7 +657,8 @@ func (v Value) Eval() Value {
if v.path == nil {
return v
}
return remakeValue(v, v.path.v.evalPartial(v.ctx()))
fmt.Println(v)
return remakeValue(v, v.path.v)
}

// Default reports the default value and whether it existed. It returns the
@@ -1148,17 +1166,9 @@ func (v Value) structValOpts(ctx *context, o options) (structValue, *bottom) {
k++
}
arcs = arcs[:k]
obj = &structLit{
obj.baseValue, // baseValue
obj.emit, // emit
obj.optionals, // template
obj.closeStatus, // closeStatus
nil, // comprehensions
arcs, // arcs
nil, // attributes
}
return structValue{ctx, v.path, obj, arcs}, nil
}
return structValue{ctx, v.path, obj}, nil
return structValue{ctx, v.path, obj, obj.arcs}, nil
}

// Struct returns the underlying struct of a value or an error if the value
@@ -1206,6 +1216,19 @@ func (s *Struct) Field(i int) FieldInfo {
a := s.s.arcs[i]
a.cache = 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)
arg := &stringLit{x.baseValue, name, nil}

val, _ := x.optionals.constraint(ctx, arg)
if val != nil {
a.v = mkBin(ctx, x.Pos(), opUnify, a.v, val)
}
}

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&hidden != 0}
@@ -1237,7 +1260,16 @@ func (v Value) Fields(opts ...Option) (Iterator, error) {
if err != nil {
return Iterator{ctx: ctx}, v.toErr(err)
}
return Iterator{ctx: ctx, val: v, iter: obj.n, len: len(obj.n.arcs)}, nil
n := &structLit{
obj.obj.baseValue, // baseValue

This comment has been minimized.

Copy link
@rogpeppe

rogpeppe Dec 3, 2019

Contributor

why not just put some field names in here?

This comment has been minimized.

Copy link
@mpvl

mpvl Dec 3, 2019

Author Contributor

I want to enforce compilation breaks if I add a field to structLit.

obj.obj.emit, // emit
obj.obj.optionals, // template
obj.obj.closeStatus, // closeStatus
nil, // comprehensions
obj.arcs, // arcs
nil, // attributes
}
return Iterator{ctx: ctx, val: v, iter: n, len: len(n.arcs)}, nil
}

// Lookup reports the value at a path starting from v.
@@ -1665,7 +1697,7 @@ func (x *validator) walk(v Value, opts options) {
for i := 0; i < obj.Len(); i++ {
_, v := obj.At(i)
opts := opts
if obj.n.arcs[i].definition {
if obj.arcs[i].definition {
opts.concrete = false
}
x.walk(v, opts)
66 changes: 65 additions & 1 deletion cue/types_test.go
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ package cue
import (
"bytes"
"fmt"
"go/parser"
"io/ioutil"
"math"
"math/big"
@@ -687,6 +688,69 @@ func TestAllFields(t *testing.T) {
}
}

func TestLookup(t *testing.T) {
_ = parser.ParseFile
var runtime = new(Runtime)
inst, err := runtime.Compile("x.cue", `
V :: {
x: int
}
X :: {
<_>: int64
} & V
v: X
`)
if err != nil {
t.Fatalf("compile: %v", err)
}
// expr, err := parser.ParseExpr("lookup.cue", `v`, parser.DeclarationErrors, parser.AllErrors)
// if err != nil {
// log.Fatalf("parseExpr: %v", err)
// }
// v := inst.Eval(expr)
testCases := []struct {
ref []string
raw string
eval string
}{{
ref: []string{"v", "x"},
raw: "(int & <=9223372036854775807 & int & >=-9223372036854775808)",
eval: "int64",
}}
for _, tc := range testCases {
v := inst.Lookup(tc.ref...)

if got := fmt.Sprint(v); got != tc.raw {
t.Errorf("got %v; want %v", got, tc.raw)
}

if got := fmt.Sprint(v.Eval().Syntax()); got != tc.eval {
t.Errorf("got %v; want %v", got, tc.eval)
}

v = inst.Lookup()
for _, ref := range tc.ref {
s, err := v.Struct()
if err != nil {
t.Fatal(err)
}
fi, err := s.FieldByName(ref)
if err != nil {
t.Fatal(err)
}
v = fi.Value
}

if got := fmt.Sprint(v); got != tc.raw {
t.Errorf("got %v; want %v", got, tc.raw)
}

if got := fmt.Sprint(v.Eval().Syntax()); got != tc.eval {
t.Errorf("got %v; want %v", got, tc.eval)
}
}
}

func TestDefaults(t *testing.T) {
testCases := []struct {
value string
@@ -1745,7 +1809,7 @@ func docStr(docs []*ast.CommentGroup) string {
return doc
}

func TestMashalJSON(t *testing.T) {
func TestMarshalJSON(t *testing.T) {
testCases := []struct {
value string
json string

0 comments on commit 8bd2426

Please sign in to comment.