···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "strconv"
2020+2121+ "cuelang.org/go/cue/ast"
2222+ "cuelang.org/go/cue/build"
2323+ "cuelang.org/go/cue/token"
2424+)
2525+2626+// insertFile inserts the given file at the root of the instance.
2727+//
2828+// The contents will be merged (unified) with any pre-existing value. In this
2929+// case an error may be reported, but only if the merge failed at the top-level.
3030+// Other errors will be recorded at the respective values in the tree.
3131+//
3232+// There should be no unresolved identifiers in file, meaning the Node field
3333+// of all identifiers should be set to a non-nil value.
3434+func (inst *Instance) insertFile(f *ast.File) error {
3535+ // TODO: insert by converting to value first so that the trim command can
3636+ // also remove top-level fields.
3737+ // First process single file.
3838+ v := newVisitor(inst.index, inst.inst, inst.rootStruct, inst.scope)
3939+ v.astState.astMap[f] = inst.rootStruct
4040+ result := v.walk(f)
4141+ if isBottom(result) {
4242+ return result.(*bottom)
4343+ }
4444+4545+ for _, c := range v.comprehensions {
4646+ inst.rootValue = mkBin(v.ctx(), token.NoPos, opUnify, inst.rootValue, c)
4747+ }
4848+4949+ return nil
5050+}
5151+5252+type astVisitor struct {
5353+ *astState
5454+ object *structLit
5555+ comprehensions []*structComprehension
5656+5757+ inSelector int
5858+}
5959+6060+func (v *astVisitor) ctx() *context {
6161+ return v.astState.ctx
6262+}
6363+6464+type astState struct {
6565+ ctx *context
6666+ *index
6767+ inst *build.Instance
6868+6969+ litParser *litParser
7070+ resolveRoot *structLit
7171+7272+ // make unique per level to avoid reuse of structs being an issue.
7373+ astMap map[ast.Node]scope
7474+}
7575+7676+func (s *astState) mapScope(n ast.Node) (m scope) {
7777+ if m = s.astMap[n]; m == nil {
7878+ m = newStruct(newNode(n))
7979+ s.astMap[n] = m
8080+ }
8181+ return m
8282+}
8383+8484+func (s *astState) setScope(n ast.Node, v scope) {
8585+ if m, ok := s.astMap[n]; ok && m != v {
8686+ panic("already defined")
8787+ }
8888+ s.astMap[n] = v
8989+}
9090+9191+func newVisitor(idx *index, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
9292+ ctx := idx.newContext()
9393+ v := &astVisitor{
9494+ object: obj,
9595+ }
9696+ v.astState = &astState{
9797+ ctx: ctx,
9898+ index: ctx.index,
9999+ inst: inst,
100100+ litParser: &litParser{ctx: ctx},
101101+ resolveRoot: resolveRoot,
102102+ astMap: map[ast.Node]scope{},
103103+ }
104104+ return v
105105+}
106106+107107+func (v *astVisitor) error(n ast.Node, args ...interface{}) value {
108108+ return v.mkErr(newNode(n), args...)
109109+}
110110+111111+func (v *astVisitor) resolve(n *ast.Ident) value {
112112+ ctx := v.ctx()
113113+ label := v.label(n.Name, true)
114114+ if r := v.resolveRoot; r != nil {
115115+ if value, _ := r.lookup(v.ctx(), label); value != nil {
116116+ return &selectorExpr{newExpr(n),
117117+ &nodeRef{baseValue: newExpr(n), node: r}, label}
118118+ }
119119+ if v.inSelector > 0 {
120120+ if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
121121+ return &nodeRef{baseValue: newExpr(n), node: p}
122122+ }
123123+ }
124124+ }
125125+ return nil
126126+}
127127+128128+func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
129129+ ctx := v.ctx()
130130+ val := lookupBuiltinPkg(ctx, imp)
131131+ if !isBottom(val) {
132132+ return val
133133+ }
134134+ path, err := strconv.Unquote(imp.Path.Value)
135135+ if err != nil {
136136+ return ctx.mkErr(newNode(imp), "illformed import spec")
137137+ }
138138+ bimp := v.inst.LookupImport(path)
139139+ if bimp == nil {
140140+ return ctx.mkErr(newNode(imp), "package %q not found", path)
141141+ }
142142+ impInst := v.index.loadInstance(bimp)
143143+ return impInst.rootValue.evalPartial(ctx)
144144+}
145145+146146+// We probably don't need to call Walk.s
147147+func (v *astVisitor) walk(astNode ast.Node) (value value) {
148148+ switch n := astNode.(type) {
149149+ case *ast.File:
150150+ obj := v.object
151151+ v1 := &astVisitor{
152152+ astState: v.astState,
153153+ object: obj,
154154+ }
155155+ for _, e := range n.Decls {
156156+ switch x := e.(type) {
157157+ case *ast.EmitDecl:
158158+ if v1.object.emit == nil {
159159+ v1.object.emit = v1.walk(x.Expr)
160160+ } else {
161161+ v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
162162+ }
163163+ default:
164164+ v1.walk(e)
165165+ }
166166+ }
167167+ for _, c := range v1.comprehensions {
168168+ v.comprehensions = append(v.comprehensions, c)
169169+ }
170170+ value = obj
171171+172172+ case *ast.ImportDecl:
173173+ for _, s := range n.Specs {
174174+ v.walk(s)
175175+ }
176176+177177+ case *ast.ImportSpec:
178178+ val := v.loadImport(n)
179179+ if !isBottom(val) {
180180+ v.setScope(n, val.(*structLit))
181181+ }
182182+183183+ case *ast.StructLit:
184184+ obj := v.mapScope(n).(*structLit)
185185+ v1 := &astVisitor{
186186+ astState: v.astState,
187187+ object: obj,
188188+ }
189189+ for _, e := range n.Elts {
190190+ switch x := e.(type) {
191191+ case *ast.EmitDecl:
192192+ // Only allowed at top-level.
193193+ v1.error(x, "emitting values is only allowed at top level")
194194+ case *ast.Field, *ast.Alias:
195195+ v1.walk(e)
196196+ case *ast.ComprehensionDecl:
197197+ v1.walk(x)
198198+ }
199199+ }
200200+ value = obj
201201+ for i, c := range v1.comprehensions {
202202+ if i == 0 && obj.template == nil && len(obj.arcs) == 0 {
203203+ value = c
204204+ continue
205205+ }
206206+ value = mkBin(v.ctx(), token.NoPos, opUnify, value, c)
207207+ }
208208+209209+ case *ast.ComprehensionDecl:
210210+ yielder := &yield{baseValue: newExpr(n.Field.Value)}
211211+ sc := &structComprehension{
212212+ baseValue: newDecl(n),
213213+ clauses: wrapClauses(v, yielder, n.Clauses),
214214+ }
215215+ field := n.Field
216216+ switch x := field.Label.(type) {
217217+ case *ast.Interpolation:
218218+ yielder.key = v.walk(x)
219219+ yielder.value = v.walk(field.Value)
220220+221221+ case *ast.ExprLabel:
222222+ yielder.key = v.walk(x.Label)
223223+ yielder.value = v.walk(field.Value)
224224+225225+ case *ast.TemplateLabel:
226226+ f := v.label(x.Ident.Name, true)
227227+228228+ sig := ¶ms{}
229229+ sig.add(f, &basicType{newNode(field.Label), stringKind})
230230+ template := &lambdaExpr{newExpr(field.Value), sig, nil}
231231+232232+ v.setScope(field, template)
233233+ template.value = v.walk(field.Value)
234234+ yielder.value = template
235235+ sc.isTemplate = true
236236+237237+ case *ast.BasicLit, *ast.Ident:
238238+ name, ok := ast.LabelName(x)
239239+ if !ok {
240240+ return v.error(x, "invalid field name: %v", x)
241241+ }
242242+ if name != "" {
243243+ yielder.key = &stringLit{newNode(x), name}
244244+ yielder.value = v.walk(field.Value)
245245+ }
246246+247247+ default:
248248+ panic("cue: unknown label type")
249249+ }
250250+ // yielder.key = v.walk(n.Field.Label)
251251+ // yielder.value = v.walk(n.Field.Value)
252252+ v.comprehensions = append(v.comprehensions, sc)
253253+254254+ case *ast.Field:
255255+ switch x := n.Label.(type) {
256256+ case *ast.Interpolation:
257257+ yielder := &yield{baseValue: newNode(x)}
258258+ sc := &structComprehension{
259259+ baseValue: newDecl(n),
260260+ clauses: yielder,
261261+ }
262262+ yielder.key = v.walk(x)
263263+ yielder.value = v.walk(n.Value)
264264+ v.comprehensions = append(v.comprehensions, sc)
265265+266266+ case *ast.ExprLabel:
267267+ yielder := &yield{baseValue: newNode(x.Label)}
268268+ sc := &structComprehension{
269269+ baseValue: newDecl(n),
270270+ clauses: yielder,
271271+ }
272272+ yielder.key = v.walk(x.Label)
273273+ yielder.value = v.walk(n.Value)
274274+ v.comprehensions = append(v.comprehensions, sc)
275275+276276+ case *ast.TemplateLabel:
277277+ f := v.label(x.Ident.Name, true)
278278+279279+ sig := ¶ms{}
280280+ sig.add(f, &basicType{newNode(n.Label), stringKind})
281281+ template := &lambdaExpr{newExpr(n.Value), sig, nil}
282282+283283+ v.setScope(n, template)
284284+ template.value = v.walk(n.Value)
285285+286286+ if v.object.template == nil {
287287+ v.object.template = template
288288+ } else {
289289+ v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
290290+ }
291291+292292+ case *ast.BasicLit, *ast.Ident:
293293+ f, ok := v.nodeLabel(x)
294294+ if !ok {
295295+ return v.error(n.Label, "invalid field name: %v", n.Label)
296296+ }
297297+ if f != 0 {
298298+ v.object.insertValue(v.ctx(), f, v.walk(n.Value))
299299+ }
300300+301301+ default:
302302+ panic("cue: unknown label type")
303303+ }
304304+305305+ case *ast.Alias:
306306+ // parsed verbatim at reference.
307307+308308+ case *ast.LambdaExpr:
309309+ sig := ¶ms{}
310310+ lambda := &lambdaExpr{newExpr(n), sig, nil}
311311+ v.setScope(n, lambda)
312312+313313+ for _, p := range n.Params {
314314+ f, _ := v.nodeLabel(p.Label)
315315+ if p.Value != nil {
316316+ sig.add(f, v.walk(p.Value))
317317+ } else {
318318+ src := &ast.Ident{NamePos: p.Pos(), Name: "_"}
319319+ sig.add(f, &top{baseValue: newExpr(src)})
320320+ }
321321+ }
322322+ lambda.value = v.walk(n.Expr)
323323+ return lambda
324324+325325+ case *ast.ListComprehension:
326326+ yielder := &yield{baseValue: newExpr(n.Expr)}
327327+ lc := &listComprehension{
328328+ newExpr(n),
329329+ wrapClauses(v, yielder, n.Clauses),
330330+ }
331331+ // we don't support key for lists (yet?)
332332+ yielder.value = v.walk(n.Expr)
333333+ return lc
334334+335335+ case *ast.ExprLabel:
336336+337337+ // Expressions
338338+ case *ast.Ident:
339339+ if n.Node == nil {
340340+ if value = v.resolve(n); value != nil {
341341+ break
342342+ }
343343+344344+ switch n.Name {
345345+ case "_":
346346+ return &top{newExpr(n)}
347347+ case "string":
348348+ return &basicType{newExpr(n), stringKind}
349349+ case "bytes":
350350+ return &basicType{newExpr(n), bytesKind}
351351+ case "bool":
352352+ return &basicType{newExpr(n), boolKind}
353353+ case "int":
354354+ return &basicType{newExpr(n), intKind}
355355+ case "float":
356356+ return &basicType{newExpr(n), floatKind}
357357+ case "number":
358358+ return &basicType{newExpr(n), numKind}
359359+ case "duration":
360360+ return &basicType{newExpr(n), durationKind}
361361+362362+ case "len":
363363+ return lenBuiltin
364364+ }
365365+ if r, ok := predefinedRanges[n.Name]; ok {
366366+ return r
367367+ }
368368+369369+ value = v.error(n, "reference %q not found", n.Name)
370370+ break
371371+ }
372372+373373+ if a, ok := n.Node.(*ast.Alias); ok {
374374+ value = v.walk(a.Expr)
375375+ break
376376+ }
377377+378378+ label := v.label(n.Name, true)
379379+ if n.Scope != nil {
380380+ n2 := v.mapScope(n.Scope)
381381+ value = &nodeRef{baseValue: newExpr(n), node: n2}
382382+ value = &selectorExpr{newExpr(n), value, label}
383383+ } else {
384384+ n2 := v.mapScope(n.Node)
385385+ value = &nodeRef{baseValue: newExpr(n), node: n2}
386386+ }
387387+388388+ case *ast.BottomLit:
389389+ value = v.error(n, "from source")
390390+391391+ case *ast.BadDecl:
392392+ // nothing to do
393393+394394+ case *ast.BadExpr:
395395+ value = v.error(n, "invalid expression")
396396+397397+ case *ast.BasicLit:
398398+ value = v.litParser.parse(n)
399399+400400+ case *ast.Interpolation:
401401+ if len(n.Elts) == 0 {
402402+ return v.error(n, "invalid interpolation")
403403+ }
404404+ first, ok1 := n.Elts[0].(*ast.BasicLit)
405405+ last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
406406+ if !ok1 || !ok2 {
407407+ return v.error(n, "invalid interpolation")
408408+ }
409409+ if len(n.Elts) == 1 {
410410+ value = v.walk(n.Elts[0])
411411+ break
412412+ }
413413+ lit := &interpolation{baseValue: newExpr(n), k: stringKind}
414414+ value = lit
415415+ quote, err := stringType(first.Value)
416416+ if err != nil {
417417+ return v.error(n, "invalid interpolation: %v", err)
418418+ }
419419+ if quote[0] == '\'' {
420420+ return v.error(n, "interpolation not implemented for bytes: %v", err)
421421+ }
422422+ ws, err := wsPrefix(last.Value, quote)
423423+ if err != nil {
424424+ return v.error(n, "invalid interpolation: %v", err)
425425+ }
426426+ prefix := quote
427427+ multi := len(quote) == 3
428428+ p := v.litParser
429429+ for i := 0; i < len(n.Elts); i += 2 {
430430+ l, ok := n.Elts[i].(*ast.BasicLit)
431431+ if !ok {
432432+ return v.error(n, "invalid interpolation")
433433+ }
434434+ if err := p.init(l); err != nil {
435435+ return v.error(n, "invalid interpolation: %v", err)
436436+ }
437437+ if i+1 < len(n.Elts) {
438438+ x := p.parseString(prefix, `\(`, ws, multi, quote[0])
439439+ lit.parts = append(lit.parts, x, v.walk(n.Elts[i+1]))
440440+ } else {
441441+ x := p.parseString(prefix, quote, ws, multi, quote[0])
442442+ lit.parts = append(lit.parts, x)
443443+ }
444444+ prefix = ")"
445445+ }
446446+447447+ case *ast.ListLit:
448448+ list := &list{baseValue: newExpr(n)}
449449+ for _, e := range n.Elts {
450450+ list.a = append(list.a, v.walk(e))
451451+ }
452452+ list.initLit()
453453+ if n.Ellipsis != token.NoPos || n.Type != nil {
454454+ list.len = &rangeLit{list.baseValue, list.len, &top{list.baseValue}}
455455+ if n.Type != nil {
456456+ list.typ = v.walk(n.Type)
457457+ }
458458+ }
459459+ value = list
460460+461461+ case *ast.ParenExpr:
462462+ value = v.walk(n.X)
463463+464464+ case *ast.SelectorExpr:
465465+ v.inSelector++
466466+ value = &selectorExpr{
467467+ newExpr(n),
468468+ v.walk(n.X),
469469+ v.label(n.Sel.Name, true),
470470+ }
471471+ v.inSelector--
472472+473473+ case *ast.IndexExpr:
474474+ value = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
475475+476476+ case *ast.SliceExpr:
477477+ slice := &sliceExpr{baseValue: newExpr(n), x: v.walk(n.X)}
478478+ if n.Low != nil {
479479+ slice.lo = v.walk(n.Low)
480480+ }
481481+ if n.High != nil {
482482+ slice.hi = v.walk(n.High)
483483+ }
484484+ value = slice
485485+486486+ case *ast.CallExpr:
487487+ call := &callExpr{baseValue: newExpr(n), x: v.walk(n.Fun)}
488488+ for _, a := range n.Args {
489489+ call.args = append(call.args, v.walk(a))
490490+ }
491491+ value = call
492492+493493+ case *ast.UnaryExpr:
494494+ value = &unaryExpr{
495495+ newExpr(n),
496496+ tokenMap[n.Op],
497497+ v.walk(n.X),
498498+ }
499499+500500+ case *ast.BinaryExpr:
501501+ switch n.Op {
502502+ case token.DISJUNCTION:
503503+ value = makeDisjunction(v.ctx(), n, v.walk(n.X), v.walk(n.Y))
504504+ case token.RANGE:
505505+ value = &rangeLit{
506506+ newExpr(n),
507507+ v.walk(n.X), // from
508508+ v.walk(n.Y), // to
509509+ }
510510+ default:
511511+ value = &binaryExpr{
512512+ newExpr(n),
513513+ tokenMap[n.Op], // op
514514+ v.walk(n.X), // left
515515+ v.walk(n.Y), // right
516516+ }
517517+ }
518518+519519+ // nothing to do
520520+ // case *syntax.EmitDecl:
521521+ default:
522522+ // TODO: unhandled node.
523523+ // value = ctx.mkErr(n, "unknown node type %T", n)
524524+ panic(fmt.Sprintf("unimplemented %T", n))
525525+526526+ }
527527+ return value
528528+}
529529+530530+func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
531531+ for _, c := range clauses {
532532+ if n, ok := c.(*ast.ForClause); ok {
533533+ params := ¶ms{}
534534+ fn := &lambdaExpr{newExpr(n.Source), params, nil}
535535+ v.setScope(n, fn)
536536+ }
537537+ }
538538+ for i := len(clauses) - 1; i >= 0; i-- {
539539+ switch n := clauses[i].(type) {
540540+ case *ast.ForClause:
541541+ fn := v.mapScope(n).(*lambdaExpr)
542542+ fn.value = y
543543+544544+ key := "_"
545545+ if n.Key != nil {
546546+ key = n.Key.Name
547547+ }
548548+ f := v.label(key, true)
549549+ fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
550550+551551+ f = v.label(n.Value.Name, true)
552552+ fn.add(f, &top{})
553553+554554+ y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
555555+556556+ case *ast.IfClause:
557557+ y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
558558+ }
559559+ }
560560+ return y
561561+}
+289
cue/ast_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+ "testing"
2020+2121+ "cuelang.org/go/cue/errors"
2222+)
2323+2424+func TestCompile(t *testing.T) {
2525+ testCases := []struct {
2626+ in string
2727+ out string
2828+ }{{
2929+ in: `{
3030+ foo: 1,
3131+ }`,
3232+ out: "<0>{}", // emitted value, but no top-level fields
3333+ }, {
3434+ in: `
3535+ foo: 1
3636+ `,
3737+ out: "<0>{foo: 1}",
3838+ }, {
3939+ in: `
4040+ a: true
4141+ b: 2K
4242+ c: 4_5
4343+ d: "abc"
4444+ e: 3e2 // 3h1m2ss
4545+ `,
4646+ out: "<0>{a: true, b: 2000, c: 45, d: \"abc\", e: 3e+2}",
4747+ }, {
4848+ in: `
4949+ a: null
5050+ b: true
5151+ c: false
5252+ `,
5353+ out: "<0>{a: null, b: true, c: false}",
5454+ }, {
5555+ in: "" +
5656+ `a: "\(4)",
5757+ b: "one \(a) two \( a + c )",
5858+ c: "one"`,
5959+ out: `<0>{a: ""+4+"", b: "one "+<0>.a+" two "+(<0>.a + <0>.c)+"", c: "one"}`,
6060+ }, {
6161+ in: "" +
6262+ `a: """
6363+ multi
6464+ """,
6565+ b: '''
6666+ hello world
6767+ goodbye globe
6868+ welcome back planet
6969+ '''`,
7070+ out: `<0>{a: "multi", b: 'hello world\ngoodbye globe\nwelcome back planet'}`,
7171+ }, {
7272+ in: "" +
7373+ `a: """
7474+ multi \(4)
7575+ """,
7676+ b: """
7777+ hello \("world")
7878+ goodbye \("globe")
7979+ welcome back \("planet")
8080+ """`,
8181+ out: `<0>{a: "multi "+4+"", b: "hello "+"world"+"\ngoodbye "+"globe"+"\nwelcome back "+"planet"+""}`,
8282+ }, {
8383+ in: `
8484+ a: _
8585+ b: int
8686+ c: float
8787+ d: bool
8888+ e: duration
8989+ f: string
9090+ `,
9191+ out: "<0>{a: _, b: int, c: float, d: bool, e: duration, f: string}",
9292+ }, {
9393+ in: `
9494+ a: null
9595+ b: true
9696+ c: false
9797+ `,
9898+ out: "<0>{a: null, b: true, c: false}",
9999+ }, {
100100+ in: `
101101+ null: null
102102+ true: true
103103+ false: false
104104+ `,
105105+ out: "<0>{null: null, true: true, false: false}",
106106+ }, {
107107+ in: `
108108+ a: 1 + 2
109109+ b: -2 - 3
110110+ c: !d
111111+ d: true
112112+ `,
113113+ out: "<0>{a: (1 + 2), b: (-2 - 3), c: !<0>.d, d: true}",
114114+ }, {
115115+ in: `
116116+ l0: 3*[int]
117117+ l0: [1, 2, 3]
118118+ l1: (0..5)*[string]
119119+ l1: ["a", "b"]
120120+ l2: (0..5)*[{ a: int }]
121121+ l2: [{a: 1}, {a: 2, b: 3}]
122122+ l3: (0..10)*[int]
123123+ l3: [1, 2, 3, ...]
124124+ l4: [1, 2, ...]
125125+ l4: [...int]
126126+ l5: [1, ...int]
127127+128128+ s1: ((0..6)*[int])[2:3]
129129+ s2: [0,2,3][1:2]
130130+131131+ e0: (2..5)*[{}]
132132+ e0: [{}]
133133+ `,
134134+ out: `<0>{l0: ((3 * [int]) & [1,2,3]), l1: (((0..5) * [string]) & ["a","b"]), l2: (((0..5) * [<1>{a: int}]) & [<2>{a: 1},<3>{a: 2, b: 3}]), l3: (((0..10) * [int]) & [1,2,3, ...]), l4: ([1,2, ...] & [, ...int]), l5: [1, ...int], s1: ((0..6) * [int])[2:3], s2: [0,2,3][1:2], e0: (((2..5) * [<4>{}]) & [<5>{}])}`,
135135+ }, {
136136+ in: `
137137+ a: 5 | "a" | true
138138+ b c: {
139139+ cc: { ccc: 3 }
140140+ }
141141+ d: true
142142+ `,
143143+ out: "<0>{a: (5 | \"a\" | true), b: <1>{c: <2>{cc: <3>{ccc: 3}}}, d: true}",
144144+ }, {
145145+ in: `
146146+ a a: { b: a } // referencing ancestor nodes is legal.
147147+ a b: a.a // do lookup before merging of nodes
148148+ b: a.a // different node as a.a.b, as first node counts
149149+ c: a // same node as b, as first node counts
150150+ d: a["a"]
151151+ `,
152152+ out: `<0>{a: (<1>{a: <2>{b: <2>}} & <3>{b: <3>.a}), b: <0>.a.a, c: <0>.a, d: <0>.a["a"]}`,
153153+ }, {
154154+ // bunch of aliases
155155+ in: `
156156+ a1 = a2
157157+ a2 = 5
158158+ b: a1
159159+ a3 = d
160160+ c: {
161161+ d: {
162162+ r: a3
163163+ }
164164+ r: a3
165165+ }
166166+ d: { e: 4 }
167167+ `,
168168+ out: `<0>{b: 5, c: <1>{d: <2>{r: <0>.d}, r: <0>.d}, d: <3>{e: 4}}`,
169169+ }, {
170170+ // aliases with errors
171171+ in: `
172172+ e1 = 1
173173+ e1 = 2
174174+ e1v: e1
175175+ e2: "a"
176176+ e2 = "a"
177177+ `,
178178+ out: "cannot have two aliases with the same name in the same scope:\n" +
179179+ " test:3:3\n" +
180180+ "cannot have alias and non-alias with the same name:\n" +
181181+ " test:6:3\n" +
182182+ "<0>{}",
183183+ }, {
184184+ in: `
185185+ a = b
186186+ b: {
187187+ c: a // reference to own root.
188188+ }
189189+ `,
190190+ out: `<0>{b: <1>{c: <0>.b}}`,
191191+ }, {
192192+ in: `
193193+ a: {
194194+ <name>: { n: name }
195195+ k: 1
196196+ }
197197+ b: {
198198+ <x>: { x: 0, y: 1 }
199199+ v: {}
200200+ }
201201+ `,
202202+ out: `<0>{a: <1>{<>: <2>(name: string)-><3>{n: <2>.name}, k: 1}, b: <4>{<>: <5>(x: string)-><6>{x: 0, y: 1}, v: <7>{}}}`,
203203+ }, {
204204+ in: `
205205+ a: { [k]: v for k, v in b if b.a < k }
206206+ b: {
207207+ a: 1
208208+ b: 2
209209+ c: 3
210210+ }
211211+ `,
212212+ out: `<0>{a: { <1>for k, v in <0>.b if (<0>.b.a < <1>.k) yield (<1>.k): <1>.v }, b: <2>{a: 1, b: 2, c: 3}}`,
213213+ }, {
214214+ in: `
215215+ a: { [v]: v for k, v in b }
216216+ b: { a: "aa", b: "bb", c: "cc" }
217217+ `,
218218+ out: `<0>{a: { <1>for k, v in <0>.b yield (<1>.v): <1>.v }, b: <2>{a: "aa", b: "bb", c: "cc"}}`,
219219+ }, {
220220+ in: `
221221+ a: [ v for _, v in b ]
222222+ b: { a: 1, b: 2, c: 3 }
223223+ `,
224224+ out: `<0>{a: [ <1>for _, v in <0>.b yield (*nil*): <1>.v ], b: <2>{a: 1, b: 2, c: 3}}`,
225225+ }, {
226226+ in: `
227227+ a: 1..2
228228+ b: 1..2..3
229229+ c: "a".."b"
230230+ d: (2+3)..(4+5)
231231+ `,
232232+ out: `<0>{a: (1..2), b: ((1..2)..3), c: ("a".."b"), d: ((2 + 3)..(4 + 5))}`,
233233+ }}
234234+ for _, tc := range testCases {
235235+ t.Run("", func(t *testing.T) {
236236+ ctx, root, errs := compileFileWithErrors(t, tc.in)
237237+ buf := &bytes.Buffer{}
238238+ if len(errs) > 0 {
239239+ errors.Print(buf, errs)
240240+ }
241241+ buf.WriteString(debugStr(ctx, root))
242242+ got := buf.String()
243243+ if got != tc.out {
244244+ t.Errorf("output differs:\ngot %q\nwant %q", got, tc.out)
245245+ }
246246+ })
247247+ }
248248+}
249249+250250+func TestEmit(t *testing.T) {
251251+ testCases := []struct {
252252+ in string
253253+ out string
254254+ rw rewriteMode
255255+ }{{
256256+ in: `"\(hello), \(world)!"` + `
257257+ hello: "Hello"
258258+ world: "World"
259259+ `,
260260+ out: `""+<0>.hello+", "+<0>.world+"!"`,
261261+ rw: evalRaw,
262262+ }, {
263263+ in: `"\(hello), \(world)!"` + `
264264+ hello: "Hello"
265265+ world: "World"
266266+ `,
267267+ out: `"Hello, World!"`,
268268+ rw: evalPartial,
269269+ }, {
270270+ // Ambiguous disjunction must cary over to emit value.
271271+ in: `baz
272272+273273+ baz: {
274274+ a: 8000 | 7080
275275+ a: 7080 | int
276276+ }`,
277277+ out: `<0>{a: _|_((8000! | 7080! | 7080):ambiguous disjunction)}`,
278278+ rw: evalFull,
279279+ }}
280280+ for _, tc := range testCases {
281281+ t.Run("", func(t *testing.T) {
282282+ ctx, root := compileFile(t, tc.in)
283283+ v := testResolve(ctx, root.emit, tc.rw)
284284+ if got := debugStr(ctx, v); got != tc.out {
285285+ t.Errorf("output differs:\ngot %q\nwant %q", got, tc.out)
286286+ }
287287+ })
288288+ }
289289+}
+975
cue/binop.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+ "math/big"
2020+ "sort"
2121+ "strings"
2222+ "time"
2323+2424+ "cuelang.org/go/cue/token"
2525+ "github.com/cockroachdb/apd"
2626+)
2727+2828+// binSrc returns a baseValue representing a binary expression of the given
2929+// values.
3030+func binSrc(pos token.Pos, op op, a, b value) baseValue {
3131+ return baseValue{&computedSource{pos, op, a, b}}
3232+}
3333+3434+type binFunc func(ctx *context, src source, op op, left, right evaluated) evaluated
3535+3636+func binSwap(ctx *context, src source, op op, x, y evaluated) evaluated {
3737+ return binOp(ctx, src, op, y, x)
3838+}
3939+4040+func unify(ctx *context, src source, left, right evaluated) evaluated {
4141+ return binOp(ctx, src, opUnify, left, right)
4242+}
4343+4444+func binOp(ctx *context, src source, op op, left, right evaluated) (result evaluated) {
4545+ if err := firstBottom(left, right); err != nil {
4646+ return err
4747+ }
4848+4949+ leftKind := left.kind()
5050+ rightKind := right.kind()
5151+ kind, invert := matchBinOpKind(op, leftKind, rightKind)
5252+ if kind == bottomKind {
5353+ return ctx.mkIncompatible(src, op, left, right)
5454+ }
5555+ if kind.hasReferences() {
5656+ panic("unexpected references in expression")
5757+ }
5858+ if invert {
5959+ left, right = right, left
6060+ }
6161+ if op != opUnify {
6262+ v := left.binOp(ctx, src, op, right) // may return incomplete
6363+ return v
6464+ }
6565+6666+ // op == opUnify
6767+6868+ // Evaluated and recompose disjunctions.
6969+7070+ if dl, ok := left.(*disjunction); ok {
7171+ if dr, ok := right.(*disjunction); ok {
7272+ return dl.cross(ctx, src, op, dr)
7373+ }
7474+ return dl.expand(ctx, src, op, right, binOp)
7575+ } else if dr, ok := right.(*disjunction); ok {
7676+ return dr.expand(ctx, src, op, left, binSwap)
7777+ }
7878+7979+ // TODO: unify type masks.
8080+ if left == right {
8181+ return left
8282+ }
8383+ if isTop(left) {
8484+ return right
8585+ }
8686+ if isTop(right) {
8787+ return left
8888+ }
8989+9090+ // TODO: value may be incomplete if there is a cycle. Instead of an error
9191+ // schedule an assert and return the atomic value, if applicable.
9292+ v := left.binOp(ctx, src, op, right)
9393+ if isBottom(v) {
9494+ v := right.binOp(ctx, src, op, left)
9595+ // Return the original failure if both fail, as this will result in
9696+ // better error messages.
9797+ if !isBottom(v) {
9898+ return v
9999+ }
100100+ }
101101+ return v
102102+}
103103+104104+func (x *disjunction) expand(ctx *context, src source, op op, y evaluated, fn binFunc) evaluated {
105105+ // disjunction & single value
106106+ dn := disjunction{src.base(), make([]dValue, 0, len(x.values))}
107107+ changed := false
108108+ for _, v := range x.values {
109109+ e := fn(ctx, src, op, v.val.(evaluated), y)
110110+ changed = changed || e != v.val
111111+ dn.add(ctx, e, v.ambiguous)
112112+ }
113113+ if !changed {
114114+ return x
115115+ }
116116+ return dn.simplify(ctx, binSrc(src.Pos(), op, x, y)).(evaluated)
117117+}
118118+119119+func (x *disjunction) cross(ctx *context, src source, op op, y *disjunction) evaluated {
120120+ vr := []dValue{}
121121+ idx := make([]int, 0, len(y.values))
122122+ for _, va := range x.values {
123123+ for j, vb := range y.values {
124124+ e := binOp(ctx, src, op, va.val.(evaluated), vb.val.(evaluated))
125125+ if isBottom(e) {
126126+ continue
127127+ }
128128+129129+ // TODO: filter using subsumption.
130130+131131+ // Mark crossing values as ambiguous.
132132+ ambiguous := va.ambiguous || vb.ambiguous
133133+ for xi, x := range idx {
134134+ if x > j {
135135+ vr[xi].ambiguous = true
136136+ ambiguous = true
137137+ }
138138+ }
139139+ vr = append(vr, dValue{e, ambiguous})
140140+ idx = append(idx, j)
141141+ }
142142+ }
143143+144144+ d := &disjunction{baseValue: src.base(), values: vr}
145145+ return d.simplify(ctx, binSrc(src.Pos(), op, x, y)).(evaluated)
146146+}
147147+148148+func (x *disjunction) binOp(ctx *context, src source, op op, other evaluated) evaluated {
149149+ panic("unreachable: special-cased")
150150+}
151151+152152+func (x *bottom) binOp(ctx *context, src source, op op, other evaluated) evaluated {
153153+ panic("unreachable: special-cased")
154154+}
155155+156156+func (x *top) binOp(ctx *context, src source, op op, other evaluated) evaluated {
157157+ switch op {
158158+ case opUnify:
159159+ return other
160160+ }
161161+ src = mkBin(ctx, src.Pos(), op, x, other)
162162+ return ctx.mkErr(src, "binary operation on non-ground top value")
163163+}
164164+165165+func (x *basicType) binOp(ctx *context, src source, op op, other evaluated) evaluated {
166166+ k := unifyType(x.kind(), other.kind())
167167+ switch y := other.(type) {
168168+ case *basicType:
169169+ switch op {
170170+ // TODO: other types.
171171+ case opUnify:
172172+ if k&typeKinds != bottomKind {
173173+ return &basicType{binSrc(src.Pos(), op, x, other), k & typeKinds}
174174+ }
175175+ }
176176+ case *rangeLit:
177177+ src = mkBin(ctx, src.Pos(), op, x, other)
178178+ return ctx.mkErr(src, codeIncomplete, "%s with incomplete values", op)
179179+ case *numLit:
180180+ if op == opUnify {
181181+ if k == y.k {
182182+ return y
183183+ }
184184+ i := *y
185185+ i.k = k
186186+ return &i
187187+ }
188188+ src = mkBin(ctx, src.Pos(), op, x, other)
189189+ return ctx.mkErr(src, codeIncomplete, "%s with incomplete values", op)
190190+ default:
191191+ if k&typeKinds != bottomKind {
192192+ return other
193193+ }
194194+ }
195195+ return ctx.mkIncompatible(src, op, x, other)
196196+}
197197+198198+// unifyFrom determines the maximum value of a and b.
199199+func unifyFrom(ctx *context, src source, a, b evaluated) evaluated {
200200+ if a.kind().isGround() && b.kind().isGround() {
201201+ if leq(ctx, src, a, b) {
202202+ return b
203203+ }
204204+ return a
205205+ }
206206+ if isTop(a) {
207207+ return b
208208+ }
209209+ if isTop(b) {
210210+ return a
211211+ }
212212+ if x, ok := a.(*rangeLit); ok {
213213+ return unifyFrom(ctx, src, x.from.(evaluated), b)
214214+ }
215215+ if x, ok := b.(*rangeLit); ok {
216216+ return unifyFrom(ctx, src, a, x.from.(evaluated))
217217+ }
218218+ src = mkBin(ctx, src.Pos(), opUnify, a, b)
219219+ return ctx.mkErr(src, "incompatible types %v and %v", a.kind(), b.kind())
220220+}
221221+222222+// unifyTo determines the minimum value of a and b.
223223+func unifyTo(ctx *context, src source, a, b evaluated) evaluated {
224224+ if a.kind().isGround() && b.kind().isGround() {
225225+ if leq(ctx, src, a, b) {
226226+ return a
227227+ }
228228+ return b
229229+ }
230230+ if isTop(a) {
231231+ return b
232232+ }
233233+ if isTop(b) {
234234+ return a
235235+ }
236236+ if x, ok := a.(*rangeLit); ok {
237237+ return unifyTo(ctx, src, x.to.(evaluated), b)
238238+ }
239239+ if x, ok := b.(*rangeLit); ok {
240240+ return unifyTo(ctx, src, a, x.to.(evaluated))
241241+ }
242242+ src = mkBin(ctx, src.Pos(), opUnify, a, b)
243243+ return ctx.mkErr(src, "incompatible types %v and %v", a.kind(), b.kind())
244244+}
245245+246246+func errInRange(ctx *context, pos token.Pos, r *rangeLit, v evaluated) *bottom {
247247+ if pos == token.NoPos {
248248+ pos = r.Pos()
249249+ }
250250+ const msgInRange = "value %v not in range %v"
251251+ e := mkBin(ctx, pos, opUnify, r, v)
252252+ return ctx.mkErr(e, msgInRange, v.strValue(), debugStr(ctx, r))
253253+}
254254+255255+func (x *rangeLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
256256+ combine := func(x, y evaluated) evaluated {
257257+ if _, ok := x.(*numLit); !ok {
258258+ return x
259259+ }
260260+ if _, ok := y.(*numLit); !ok {
261261+ return y
262262+ }
263263+ return binOp(ctx, src, op, x, y)
264264+ }
265265+ from := x.from.(evaluated)
266266+ to := x.to.(evaluated)
267267+ newSrc := mkBin(ctx, src.Pos(), op, x, other)
268268+ switch op {
269269+ case opUnify:
270270+ k := unifyType(x.kind(), other.kind())
271271+ if k&comparableKind != bottomKind {
272272+ switch y := other.(type) {
273273+ case *basicType:
274274+ from := unify(ctx, src, x.from.(evaluated), y)
275275+ to := unify(ctx, src, x.to.(evaluated), y)
276276+ if from == x.from && to == x.to {
277277+ return x
278278+ }
279279+ return &rangeLit{newSrc.base(), from, to}
280280+ case *rangeLit:
281281+ from := unifyFrom(ctx, src, x.from.(evaluated), y.from.(evaluated))
282282+ to := unifyTo(ctx, src, x.to.(evaluated), y.to.(evaluated))
283283+ if from.kind().isGround() && to.kind().isGround() && !leq(ctx, src, from, to) {
284284+ r1 := debugStr(ctx, x)
285285+ r2 := debugStr(ctx, y)
286286+ return ctx.mkErr(newSrc, "non-overlapping ranges %s and %s", r1, r2)
287287+ }
288288+ return ctx.manifest(&rangeLit{newSrc.base(), from, to})
289289+290290+ case *numLit:
291291+ if !leq(ctx, src, x.from.(evaluated), y) || !leq(ctx, src, y, x.to.(evaluated)) {
292292+ return errInRange(ctx, src.Pos(), x, y)
293293+ }
294294+ if y.k != k {
295295+ n := *y
296296+ n.k = k
297297+ return &n
298298+ }
299299+ return other
300300+301301+ case *durationLit, *stringLit:
302302+ if !leq(ctx, src, x.from.(evaluated), y) || !leq(ctx, src, y, x.to.(evaluated)) {
303303+ return errInRange(ctx, src.Pos(), x, y)
304304+ }
305305+ return other
306306+ }
307307+ }
308308+ // See https://en.wikipedia.org/wiki/Interval_arithmetic.
309309+ case opAdd:
310310+ switch x.kind() & typeKinds {
311311+ case stringKind:
312312+ if !x.from.kind().isGround() || !x.to.kind().isGround() {
313313+ // TODO: return regexp
314314+ return ctx.mkErr(newSrc, codeIncomplete, "cannot add incomplete values")
315315+ }
316316+ combine := func(x, y evaluated) evaluated {
317317+ if _, ok := x.(*basicType); ok {
318318+ return ctx.mkErr(newSrc, "adding string to non-concrete type")
319319+ }
320320+ if _, ok := y.(*basicType); ok {
321321+ return x
322322+ }
323323+ return binOp(ctx, src, opAdd, x, y)
324324+ }
325325+ return &rangeLit{
326326+ baseValue: binSrc(src.Pos(), op, x, other),
327327+ from: combine(minNum(from), minNum(other)),
328328+ to: combine(maxNum(to), maxNum(other)),
329329+ }
330330+331331+ case intKind, numKind, floatKind:
332332+ return &rangeLit{
333333+ baseValue: binSrc(src.Pos(), op, x, other),
334334+ from: combine(minNum(from), minNum(other)),
335335+ to: combine(maxNum(to), maxNum(other)),
336336+ }
337337+338338+ default:
339339+ return ctx.mkErrUnify(src, x, other)
340340+ }
341341+342342+ case opSub:
343343+ return &rangeLit{
344344+ baseValue: binSrc(src.Pos(), op, x, other),
345345+ from: combine(minNum(from), maxNum(other)),
346346+ to: combine(maxNum(to), minNum(other)),
347347+ }
348348+349349+ case opQuo:
350350+ // See https://en.wikipedia.org/wiki/Interval_arithmetic.
351351+ // TODO: all this is strictly not correct. To do it right we need to
352352+ // have non-inclusive ranges at the least. So for now we just do this.
353353+ var from, to evaluated
354354+ if max := maxNum(other); !max.kind().isGround() {
355355+ from = newNum(other, max.kind()) // 1/infinity is 0
356356+ } else if num, ok := max.(*numLit); ok && num.v.IsZero() {
357357+ from = &basicType{num.baseValue, num.kind()} // div by 0
358358+ } else {
359359+ one := newNum(other, max.kind())
360360+ one.v.SetInt64(1)
361361+ from = combine(one, max)
362362+ }
363363+364364+ if _, ok := other.(*rangeLit); !ok {
365365+ other = from
366366+ } else {
367367+ if min := minNum(other); !min.kind().isGround() {
368368+ to = newNum(other, min.kind()) // 1/infinity is 0
369369+ } else if num, ok := min.(*numLit); ok && num.v.IsZero() {
370370+ to = &basicType{num.baseValue, num.kind()} // div by 0
371371+ } else {
372372+ one := newNum(other, min.kind())
373373+ one.v.SetInt64(1)
374374+ to = combine(one, min)
375375+ }
376376+377377+ if !from.kind().isGround() && !to.kind().isGround() {
378378+ other = from
379379+ } else if leq(ctx, src, from, to) && leq(ctx, src, to, from) {
380380+ other = from
381381+ } else {
382382+ other = &rangeLit{newSrc.base(), from, to}
383383+ }
384384+ }
385385+ fallthrough
386386+387387+ case opMul:
388388+ xMin, xMax := minNum(from), maxNum(to)
389389+ yMin, yMax := minNum(other), maxNum(other)
390390+391391+ var from, to evaluated
392392+ negMax := func(from, to *evaluated, val, sign evaluated) {
393393+ if !val.kind().isGround() {
394394+ *from = val
395395+ if num, ok := sign.(*numLit); ok && num.v.Negative {
396396+ *to = val
397397+ }
398398+ }
399399+ }
400400+ negMax(&from, &to, yMin, xMax)
401401+ negMax(&to, &from, yMax, xMin)
402402+ negMax(&from, &to, xMin, yMax)
403403+ negMax(&to, &from, xMax, yMin)
404404+ if from != nil && to != nil {
405405+ return binOp(ctx, src, opUnify, from, to)
406406+ }
407407+408408+ values := []evaluated{}
409409+ add := func(a, b evaluated) {
410410+ if a.kind().isGround() && b.kind().isGround() {
411411+ values = append(values, combine(a, b))
412412+ }
413413+ }
414414+ add(xMin, yMin)
415415+ add(xMax, yMin)
416416+ add(xMin, yMax)
417417+ add(xMax, yMax)
418418+ sort.Slice(values, func(i, j int) bool {
419419+ return !leq(ctx, src, values[j], values[i])
420420+ })
421421+422422+ r := &rangeLit{baseValue: binSrc(src.Pos(), op, x, other), from: from, to: to}
423423+ if from == nil {
424424+ r.from = values[0]
425425+ }
426426+ if to == nil {
427427+ r.to = values[len(values)-1]
428428+ }
429429+ return r
430430+ }
431431+ return ctx.mkIncompatible(src, op, x, other)
432432+}
433433+434434+func evalLambda(ctx *context, a value) (l *lambdaExpr, err evaluated) {
435435+ if a == nil {
436436+ return nil, nil
437437+ }
438438+ // NOTE: the values of a lambda might still be a disjunction
439439+ e := ctx.manifest(a)
440440+ if isBottom(e) {
441441+ return nil, e
442442+ }
443443+ l, ok := e.(*lambdaExpr)
444444+ if !ok {
445445+ return nil, ctx.mkErr(a, "value must be lambda")
446446+ }
447447+ return ctx.deref(l).(*lambdaExpr), nil
448448+}
449449+450450+func (x *structLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
451451+ y, ok := other.(*structLit)
452452+ if !ok || op != opUnify {
453453+ return ctx.mkIncompatible(src, op, x, other)
454454+ }
455455+456456+ // TODO: unify emit
457457+458458+ x = ctx.deref(x).(*structLit)
459459+ y = ctx.deref(y).(*structLit)
460460+ if x == y {
461461+ return x
462462+ }
463463+ arcs := make(arcs, 0, len(x.arcs)+len(y.arcs))
464464+ obj := &structLit{binSrc(src.Pos(), op, x, other), x.emit, nil, arcs}
465465+ defer ctx.pushForwards(x, obj, y, obj).popForwards()
466466+467467+ tx, ex := evalLambda(ctx, x.template)
468468+ ty, ey := evalLambda(ctx, y.template)
469469+470470+ var t *lambdaExpr
471471+ switch {
472472+ case ex != nil:
473473+ return ex
474474+ case ey != nil:
475475+ return ey
476476+ case tx != nil:
477477+ t = tx
478478+ case ty != nil:
479479+ t = ty
480480+ }
481481+ if tx != ty && tx != nil && ty != nil {
482482+ v := binOp(ctx, src, opUnify, tx, ty)
483483+ if isBottom(v) {
484484+ return v
485485+ }
486486+ t = v.(*lambdaExpr)
487487+ }
488488+ if t != nil {
489489+ obj.template = ctx.copy(t).(*lambdaExpr)
490490+ }
491491+492492+ for _, a := range x.arcs {
493493+ cp := ctx.copy(a.v)
494494+ obj.arcs = append(obj.arcs, arc{a.feature, cp, nil})
495495+ }
496496+outer:
497497+ for _, a := range y.arcs {
498498+ v := ctx.copy(a.v)
499499+ for i, b := range obj.arcs {
500500+ if a.feature == b.feature && a.v != b.v {
501501+ v = mkBin(ctx, src.Pos(), opUnify, b.v, v)
502502+ obj.arcs[i].v = v
503503+ continue outer
504504+ }
505505+ }
506506+ obj.arcs = append(obj.arcs, arc{feature: a.feature, v: v})
507507+ }
508508+ sort.Stable(obj)
509509+510510+ return obj
511511+}
512512+513513+func (x *nullLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
514514+ // TODO: consider using binSrc instead of src.base() for better traceability.
515515+ switch op {
516516+ case opEql:
517517+ return &boolLit{baseValue: src.base(), b: true}
518518+ case opNeq:
519519+ return &boolLit{baseValue: src.base(), b: false}
520520+ case opUnify:
521521+ return x
522522+ default:
523523+ panic("unimplemented")
524524+ }
525525+}
526526+527527+func (x *boolLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
528528+ switch y := other.(type) {
529529+ case *basicType:
530530+ // range math
531531+ return x
532532+533533+ case *boolLit:
534534+ switch op {
535535+ case opUnify:
536536+ if x.b != y.b {
537537+ return ctx.mkErr(x, "failed to unify: %v != %v", x.b, y.b)
538538+ }
539539+ return x
540540+ case opLand:
541541+ return boolTonode(src, x.b && y.b)
542542+ case opLor:
543543+ return boolTonode(src, x.b || y.b)
544544+ case opEql:
545545+ return boolTonode(src, x.b == y.b)
546546+ case opNeq:
547547+ return boolTonode(src, x.b != y.b)
548548+ }
549549+ }
550550+ return ctx.mkIncompatible(src, op, x, other)
551551+}
552552+553553+func (x *stringLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
554554+ switch other.(type) {
555555+ // case *basicType:
556556+ // return x
557557+558558+ // TODO: rangelit
559559+560560+ case *stringLit:
561561+ str := other.strValue()
562562+ switch op {
563563+ case opUnify:
564564+ str := other.strValue()
565565+ if x.str != str {
566566+ src := mkBin(ctx, src.Pos(), op, x, other)
567567+ return ctx.mkErr(src, "failed to unify: %v != %v", x.str, str)
568568+ }
569569+ return x
570570+ case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
571571+ return cmpTonode(src, op, strings.Compare(string(x.str), string(str)))
572572+ case opAdd:
573573+ return &stringLit{binSrc(src.Pos(), op, x, other), x.str + str}
574574+ }
575575+ }
576576+ return ctx.mkIncompatible(src, op, x, other)
577577+}
578578+579579+func (x *bytesLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
580580+ switch y := other.(type) {
581581+ // case *basicType:
582582+ // return x
583583+584584+ // TODO: rangelit
585585+586586+ case *bytesLit:
587587+ b := y.b
588588+ switch op {
589589+ case opUnify:
590590+ if !bytes.Equal(x.b, b) {
591591+ return ctx.mkErr(x, "failed to unify: %v != %v", x.b, b)
592592+ }
593593+ return x
594594+ case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
595595+ return cmpTonode(src, op, bytes.Compare(x.b, b))
596596+ case opAdd:
597597+ copy := append([]byte(nil), x.b...)
598598+ copy = append(copy, b...)
599599+ return &bytesLit{binSrc(src.Pos(), op, x, other), copy}
600600+ }
601601+ }
602602+ return ctx.mkIncompatible(src, op, x, other)
603603+}
604604+605605+func leq(ctx *context, src source, a, b evaluated) bool {
606606+ if isTop(a) || isTop(b) {
607607+ return true
608608+ }
609609+ v := binOp(ctx, src, opLeq, a, b)
610610+ if isBottom(v) {
611611+ return false
612612+ }
613613+ return v.(*boolLit).b
614614+}
615615+616616+func maxNum(v evaluated) evaluated {
617617+ switch x := v.(type) {
618618+ case *numLit:
619619+ return x
620620+ case *rangeLit:
621621+ return maxNum(x.to.(evaluated))
622622+ }
623623+ return v
624624+}
625625+626626+func minNum(v evaluated) evaluated {
627627+ switch x := v.(type) {
628628+ case *numLit:
629629+ return x
630630+ case *rangeLit:
631631+ return minNum(x.from.(evaluated))
632632+ }
633633+ return v
634634+}
635635+636636+func maxNumRaw(v value) value {
637637+ switch x := v.(type) {
638638+ case *numLit:
639639+ return x
640640+ case *rangeLit:
641641+ return maxNumRaw(x.to)
642642+ }
643643+ return v
644644+}
645645+646646+func minNumRaw(v value) value {
647647+ switch x := v.(type) {
648648+ case *numLit:
649649+ return x
650650+ case *rangeLit:
651651+ return minNumRaw(x.from)
652652+ }
653653+ return v
654654+}
655655+656656+func cmpTonode(src source, op op, r int) evaluated {
657657+ result := false
658658+ switch op {
659659+ case opLss:
660660+ result = r == -1
661661+ case opLeq:
662662+ result = r != 1
663663+ case opEql, opUnify:
664664+ result = r == 0
665665+ case opNeq:
666666+ result = r != 0
667667+ case opGeq:
668668+ result = r != -1
669669+ case opGtr:
670670+ result = r == 1
671671+ }
672672+ return boolTonode(src, result)
673673+}
674674+675675+func (x *numLit) updateNumInfo(a, b *numLit) {
676676+ x.numInfo = unifyNuminfo(a.numInfo, b.numInfo)
677677+}
678678+679679+func (x *numLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
680680+ switch y := other.(type) {
681681+ case *basicType:
682682+ if op == opUnify {
683683+ return y.binOp(ctx, src, op, x)
684684+ }
685685+ // infinity math
686686+ // 4 * int = int
687687+ case *rangeLit:
688688+ if op == opUnify {
689689+ return y.binOp(ctx, src, op, x)
690690+ }
691691+ // 5..7 - 8 = -3..4
692692+ case *numLit:
693693+ k := unifyType(x.kind(), y.kind())
694694+ n := newNumBin(k, x, y)
695695+ switch op {
696696+ case opUnify:
697697+ if x.v.Cmp(&y.v) != 0 {
698698+ src = mkBin(ctx, src.Pos(), op, x, other)
699699+ return ctx.mkErr(src, "cannot unify numbers %v and %v", x.strValue(), y.strValue())
700700+ }
701701+ if k != x.k {
702702+ n.v = x.v
703703+ return n
704704+ }
705705+ return x
706706+ case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
707707+ return cmpTonode(src, op, x.v.Cmp(&y.v))
708708+ case opAdd:
709709+ ctx.Add(&n.v, &x.v, &y.v)
710710+ case opSub:
711711+ ctx.Sub(&n.v, &x.v, &y.v)
712712+ case opMul:
713713+ ctx.Mul(&n.v, &x.v, &y.v)
714714+ case opQuo:
715715+ ctx.Quo(&n.v, &x.v, &y.v)
716716+ ctx.Reduce(&n.v, &n.v)
717717+ n.k = floatKind
718718+ case opRem:
719719+ ctx.Rem(&n.v, &x.v, &y.v)
720720+ n.k = floatKind
721721+ case opIDiv:
722722+ intOp(ctx, n, (*big.Int).Div, x, y)
723723+ case opIMod:
724724+ intOp(ctx, n, (*big.Int).Mod, x, y)
725725+ case opIQuo:
726726+ intOp(ctx, n, (*big.Int).Quo, x, y)
727727+ case opIRem:
728728+ intOp(ctx, n, (*big.Int).Rem, x, y)
729729+ }
730730+ return n
731731+732732+ case *durationLit:
733733+ if op == opMul {
734734+ fd := float64(y.d)
735735+ // TODO: check range
736736+ f, _ := x.v.Float64()
737737+ d := time.Duration(f * fd)
738738+ return &durationLit{binSrc(src.Pos(), op, x, other), d}
739739+ }
740740+ }
741741+ return ctx.mkIncompatible(src, op, x, other)
742742+}
743743+744744+type intFunc func(z, x, y *big.Int) *big.Int
745745+746746+func intOp(ctx *context, n *numLit, fn intFunc, a, b *numLit) {
747747+ var x, y apd.Decimal
748748+ ctx.RoundToIntegralValue(&x, &a.v)
749749+ if x.Negative {
750750+ x.Coeff.Neg(&x.Coeff)
751751+ }
752752+ ctx.RoundToIntegralValue(&y, &b.v)
753753+ if y.Negative {
754754+ y.Coeff.Neg(&y.Coeff)
755755+ }
756756+ fn(&n.v.Coeff, &x.Coeff, &y.Coeff)
757757+ if n.v.Coeff.Sign() < 0 {
758758+ n.v.Coeff.Neg(&n.v.Coeff)
759759+ n.v.Negative = true
760760+ }
761761+ n.k = intKind
762762+}
763763+764764+// TODO: check overflow
765765+766766+func (x *durationLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
767767+ switch y := other.(type) {
768768+ case *basicType:
769769+ // infinity math
770770+771771+ case *durationLit:
772772+ switch op {
773773+ case opUnify:
774774+ if x.d != y.d {
775775+ return ctx.mkIncompatible(src, op, x, other)
776776+ }
777777+ return other
778778+ case opLss:
779779+ return boolTonode(src, x.d < y.d)
780780+ case opLeq:
781781+ return boolTonode(src, x.d <= y.d)
782782+ case opEql:
783783+ return boolTonode(src, x.d == y.d)
784784+ case opNeq:
785785+ return boolTonode(src, x.d != y.d)
786786+ case opGeq:
787787+ return boolTonode(src, x.d >= y.d)
788788+ case opGtr:
789789+ return boolTonode(src, x.d > y.d)
790790+ case opAdd:
791791+ return &durationLit{binSrc(src.Pos(), op, x, other), x.d + y.d}
792792+ case opSub:
793793+ return &durationLit{binSrc(src.Pos(), op, x, other), x.d - y.d}
794794+ case opQuo:
795795+ n := &numLit{
796796+ numBase: newNumBase(nil, newNumInfo(floatKind, 0, 10, false)),
797797+ }
798798+ n.v.SetInt64(int64(x.d))
799799+ d := apd.New(int64(y.d), 0)
800800+ ctx.Quo(&n.v, &n.v, d)
801801+ return n
802802+ case opRem:
803803+ n := &numLit{
804804+ numBase: newNumBase(nil, newNumInfo(intKind, 0, 10, false)),
805805+ }
806806+ n.v.SetInt64(int64(x.d % y.d))
807807+ n.v.Exponent = -9
808808+ return n
809809+ }
810810+811811+ case *numLit:
812812+ switch op {
813813+ case opMul:
814814+ // TODO: check range
815815+ f, _ := y.v.Float64()
816816+ d := time.Duration(float64(x.d) * f)
817817+ return &durationLit{binSrc(src.Pos(), op, x, other), d}
818818+ case opQuo:
819819+ // TODO: check range
820820+ f, _ := y.v.Float64()
821821+ d := time.Duration(float64(x.d) * f)
822822+ return &durationLit{binSrc(src.Pos(), op, x, other), d}
823823+ case opRem:
824824+ d := x.d % time.Duration(y.intValue(ctx))
825825+ return &durationLit{binSrc(src.Pos(), op, x, other), d}
826826+ }
827827+ }
828828+ return ctx.mkIncompatible(src, op, x, other)
829829+}
830830+831831+func (x *list) binOp(ctx *context, src source, op op, other evaluated) evaluated {
832832+ switch op {
833833+ case opUnify:
834834+ y, ok := other.(*list)
835835+ if !ok {
836836+ break
837837+ }
838838+ n := unify(ctx, src, x.len.(evaluated), y.len.(evaluated))
839839+ if isBottom(n) {
840840+ src = mkBin(ctx, src.Pos(), op, x, other)
841841+ return ctx.mkErr(src, "incompatible list lengths: %v", n)
842842+ }
843843+ var a, rest []value
844844+ var rtyp value
845845+ nx, ny := len(x.a), len(y.a)
846846+ if nx < ny {
847847+ a = make([]value, nx, ny)
848848+ rest = y.a[nx:]
849849+ rtyp = x.typ
850850+851851+ } else {
852852+ a = make([]value, ny, nx)
853853+ rest = x.a[ny:]
854854+ rtyp = y.typ
855855+ }
856856+ typ := x.typ
857857+ max, ok := n.(*numLit)
858858+ if !ok || len(a)+len(rest) < max.intValue(ctx) {
859859+ typ = unify(ctx, src, x.typ.(evaluated), y.typ.(evaluated))
860860+ if isBottom(typ) {
861861+ src = mkBin(ctx, src.Pos(), op, x, other)
862862+ return ctx.mkErr(src, "incompatible list types: %v: ", typ)
863863+ }
864864+ }
865865+866866+ for i := range a {
867867+ ai := unify(ctx, src, x.at(ctx, i).evalPartial(ctx), y.at(ctx, i).evalPartial(ctx))
868868+ if isBottom(ai) {
869869+ return ai
870870+ }
871871+ a[i] = ai
872872+ }
873873+ for _, n := range rest {
874874+ an := unify(ctx, src, n.evalPartial(ctx), rtyp.(evaluated))
875875+ if isBottom(an) {
876876+ return an
877877+ }
878878+ a = append(a, an)
879879+ }
880880+ return &list{baseValue: binSrc(src.Pos(), op, x, other), a: a, typ: typ, len: n}
881881+882882+ case opMul:
883883+ k := other.kind()
884884+ if !k.isAnyOf(intKind) {
885885+ panic("multiplication must be int type")
886886+ }
887887+ typ := x.typ.(evaluated)
888888+ ln := x.len.(evaluated)
889889+ n := &list{baseValue: binSrc(src.Pos(), op, x, other), typ: x.typ}
890890+ switch len(x.a) {
891891+ case 0:
892892+ case 1:
893893+ n.typ = binOp(ctx, src, opUnify, typ, x.a[0].evalPartial(ctx))
894894+ default:
895895+ if !k.isGround() {
896896+ return x
897897+ }
898898+ if ln := other.(*numLit).intValue(ctx); ln > 0 {
899899+ // TODO: check error
900900+ for i := 0; i < ln; i++ {
901901+ // TODO: copy values
902902+ n.a = append(n.a, x.a...)
903903+ }
904904+ }
905905+ }
906906+ switch v := x.len.(type) {
907907+ case *top, *basicType:
908908+ n.len = other
909909+ case *numLit:
910910+ switch v.intValue(ctx) {
911911+ case 0:
912912+ n.len = x.len
913913+ case 1:
914914+ n.len = other
915915+ default:
916916+ n.len = binOp(ctx, src, opMul, ln, other)
917917+ }
918918+ default:
919919+ n.len = binOp(ctx, src, opMul, ln, other)
920920+ }
921921+ return n
922922+ }
923923+ return ctx.mkIncompatible(src, op, x, other)
924924+}
925925+926926+func (x *lambdaExpr) binOp(ctx *context, src source, op op, other evaluated) evaluated {
927927+ if y, ok := other.(*lambdaExpr); ok && op == opUnify {
928928+ x = ctx.deref(x).(*lambdaExpr)
929929+ y = ctx.deref(y).(*lambdaExpr)
930930+ n, m := len(x.params.arcs), len(y.params.arcs)
931931+ if n != m {
932932+ src = mkBin(ctx, src.Pos(), op, x, other)
933933+ return ctx.mkErr(src, "number of params of params should match in unification (%d != %d)", n, m)
934934+ }
935935+ arcs := make([]arc, len(x.arcs))
936936+ lambda := &lambdaExpr{binSrc(src.Pos(), op, x, other), ¶ms{arcs}, nil}
937937+ defer ctx.pushForwards(x, lambda, y, lambda).popForwards()
938938+939939+ xVal := ctx.copy(x.value)
940940+ yVal := ctx.copy(y.value)
941941+ lambda.value = mkBin(ctx, src.Pos(), opUnify, xVal, yVal)
942942+943943+ for i := range arcs {
944944+ xArg := ctx.copy(x.at(ctx, i)).(evaluated)
945945+ yArg := ctx.copy(y.at(ctx, i)).(evaluated)
946946+ v := binOp(ctx, src, op, xArg, yArg)
947947+ if isBottom(v) {
948948+ return v
949949+ }
950950+ arcs[i] = arc{x.arcs[i].feature, v, nil}
951951+ }
952952+953953+ return lambda
954954+ }
955955+ return ctx.mkIncompatible(src, op, x, other)
956956+}
957957+958958+func (x *builtin) binOp(ctx *context, src source, op op, other evaluated) evaluated {
959959+ if op == opUnify && evaluated(x) == other {
960960+ return x
961961+ }
962962+ return ctx.mkIncompatible(src, op, x, other)
963963+}
964964+965965+func (x *feed) binOp(ctx *context, src source, op op, other evaluated) evaluated {
966966+ return ctx.mkIncompatible(src, op, x, other)
967967+}
968968+969969+func (x *guard) binOp(ctx *context, src source, op op, other evaluated) evaluated {
970970+ return ctx.mkIncompatible(src, op, x, other)
971971+}
972972+973973+func (x *yield) binOp(ctx *context, src source, op op, other evaluated) evaluated {
974974+ return ctx.mkIncompatible(src, op, x, other)
975975+}
+245
cue/build.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "path"
1919+ "strconv"
2020+2121+ "cuelang.org/go/cue/ast"
2222+ build "cuelang.org/go/cue/build"
2323+ "cuelang.org/go/cue/token"
2424+)
2525+2626+// Build creates one Instance for each build.Instance. A returned Instance
2727+// may be incomplete, in which case its Err field is set.
2828+//
2929+// Example:
3030+// inst := cue.Build(load.Load(args))
3131+//
3232+func Build(instances []*build.Instance) []*Instance {
3333+ if len(instances) == 0 {
3434+ panic("cue: list of instances must not be empty")
3535+ }
3636+ index := newIndex(instances[0].Context().FileSet())
3737+3838+ loaded := []*Instance{}
3939+4040+ for _, p := range instances {
4141+ p.Complete()
4242+4343+ loaded = append(loaded, index.loadInstance(p))
4444+ }
4545+ // TODO: insert imports
4646+ return loaded
4747+}
4848+4949+// FromExpr creates anb instance from an expression.
5050+// Any references must be resolved beforehand.
5151+func FromExpr(fset *token.FileSet, expr ast.Expr) (*Instance, error) {
5252+ i := newIndex(fset).NewInstance(nil)
5353+ err := i.insertFile(&ast.File{
5454+ Decls: []ast.Decl{&ast.EmitDecl{Expr: expr}},
5555+ })
5656+ if err != nil {
5757+ return nil, err
5858+ }
5959+ return i, nil
6060+}
6161+6262+// index maps conversions from label names to internal codes.
6363+//
6464+// All instances belonging to the same package should share this index.
6565+type index struct {
6666+ fset *token.FileSet
6767+6868+ labelMap map[string]label
6969+ labels []string
7070+7171+ loaded map[*build.Instance]*Instance
7272+}
7373+7474+// newIndex creates a new index.
7575+func newIndex(f *token.FileSet) *index {
7676+ i := &index{
7777+ fset: f,
7878+ labelMap: map[string]label{"": 0},
7979+ labels: []string{""},
8080+ loaded: map[*build.Instance]*Instance{},
8181+ }
8282+ return i
8383+}
8484+8585+func (idx *index) strLabel(str string) label {
8686+ return idx.label(str, false)
8787+}
8888+8989+func (idx *index) nodeLabel(n ast.Node) (f label, ok bool) {
9090+ switch x := n.(type) {
9191+ case *ast.BasicLit:
9292+ name, ok := ast.LabelName(x)
9393+ return idx.label(name, false), ok
9494+ case *ast.Ident:
9595+ return idx.label(x.Name, true), true
9696+ }
9797+ return 0, false
9898+}
9999+100100+func (idx *index) label(s string, isIdent bool) label {
101101+ f, ok := idx.labelMap[s]
102102+ if !ok {
103103+ f = label(len(idx.labelMap))
104104+ idx.labelMap[s] = f
105105+ idx.labels = append(idx.labels, s)
106106+ }
107107+ f <<= 1
108108+ if isIdent && s != "" && s[0] == '_' {
109109+ f |= 1
110110+ }
111111+ return f
112112+}
113113+114114+func (idx *index) labelStr(l label) string {
115115+ return idx.labels[l>>1]
116116+}
117117+118118+func (idx *index) loadInstance(p *build.Instance) *Instance {
119119+ if inst := idx.loaded[p]; inst != nil {
120120+ if !inst.complete {
121121+ // cycles should be detected by the builder and it should not be
122122+ // possible to construct a build.Instance that has them.
123123+ panic("cue: cycle")
124124+ }
125125+ return inst
126126+ }
127127+ files := p.Files
128128+ inst := idx.NewInstance(p)
129129+ if inst.Err == nil {
130130+ // inst.instance.index.state = s
131131+ // inst.instance.inst = p
132132+ inst.Err = resolveFiles(idx, p)
133133+ for _, f := range files {
134134+ inst.insertFile(f)
135135+ }
136136+ }
137137+ inst.complete = true
138138+ return inst
139139+}
140140+141141+func lineStr(idx *index, n ast.Node) string {
142142+ return idx.fset.Position(n.Pos()).String()
143143+}
144144+145145+func resolveFiles(idx *index, p *build.Instance) error {
146146+ // Link top-level declarations. As top-level entries get unified, an entry
147147+ // may be linked to any top-level entry of any of the files.
148148+ allFields := map[string]ast.Node{}
149149+ for _, file := range p.Files {
150150+ for _, d := range file.Decls {
151151+ if f, ok := d.(*ast.Field); ok && f.Value != nil {
152152+ if ident, ok := f.Label.(*ast.Ident); ok {
153153+ allFields[ident.Name] = f.Value
154154+ }
155155+ }
156156+ }
157157+ }
158158+ for _, f := range p.Files {
159159+ if err := resolveFile(idx, f, p, allFields); err != nil {
160160+ return err
161161+ }
162162+ }
163163+ return nil
164164+}
165165+166166+func resolveFile(idx *index, f *ast.File, p *build.Instance, allFields map[string]ast.Node) error {
167167+ type importInfo struct {
168168+ node ast.Node
169169+ inst *Instance
170170+ used bool // TODO: use a more general unresolved value technique
171171+ }
172172+ index := map[string][]*ast.Ident{}
173173+ for _, u := range f.Unresolved {
174174+ index[u.Name] = append(index[u.Name], u)
175175+ }
176176+ fields := map[string]ast.Node{}
177177+ for _, d := range f.Decls {
178178+ if f, ok := d.(*ast.Field); ok && f.Value != nil {
179179+ if ident, ok := f.Label.(*ast.Ident); ok {
180180+ fields[ident.Name] = d
181181+ }
182182+ }
183183+ }
184184+ var errUnused error
185185+186186+ for _, spec := range f.Imports {
187187+ id, err := strconv.Unquote(spec.Path.Value)
188188+ if err != nil {
189189+ continue // quietly ignore the error
190190+ }
191191+ name := path.Base(id)
192192+ if _, ok := builtins[id]; ok {
193193+ } else if imp := p.LookupImport(id); imp != nil {
194194+ name = imp.PkgName
195195+ if spec.Name != nil {
196196+ name = spec.Name.Name
197197+ }
198198+ } else {
199199+ // continue
200200+ return idx.mkErr(newNode(spec), "package %q not found", id)
201201+ }
202202+ if n, ok := fields[name]; ok {
203203+ return idx.mkErr(newNode(spec),
204204+ "%s redeclared as imported package name\n"+
205205+ "\tprevious declaration at %v", name, lineStr(idx, n))
206206+ }
207207+ used := false
208208+ for _, u := range index[name] {
209209+ used = true
210210+ u.Node = spec
211211+ }
212212+ if !used {
213213+ if spec.Name == nil {
214214+ errUnused = idx.mkErr(newNode(spec),
215215+ "imported and not used: %s", spec.Path.Value)
216216+ } else {
217217+ errUnused = idx.mkErr(newNode(spec),
218218+ "imported and not used: %s as %s", spec.Path.Value, spec.Name)
219219+ }
220220+ }
221221+ }
222222+ i := 0
223223+ for _, u := range f.Unresolved {
224224+ if u.Node != nil {
225225+ continue
226226+ }
227227+ if n, ok := allFields[u.Name]; ok {
228228+ u.Node = n
229229+ u.Scope = f
230230+ continue
231231+ }
232232+ f.Unresolved[i] = u
233233+ i++
234234+ }
235235+ f.Unresolved = f.Unresolved[:i]
236236+ // TODO: also need to resolve types.
237237+ // if len(f.Unresolved) > 0 {
238238+ // n := f.Unresolved[0]
239239+ // return ctx.mkErr(newBase(n), "unresolved reference %s", n.Name)
240240+ // }
241241+ if errUnused != nil {
242242+ return errUnused
243243+ }
244244+ return nil
245245+}
+207
cue/build_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "strings"
2020+ "testing"
2121+2222+ "cuelang.org/go/cue/ast"
2323+ "cuelang.org/go/cue/build"
2424+ "cuelang.org/go/cue/token"
2525+)
2626+2727+func TestFromExpr(t *testing.T) {
2828+ testCases := []struct {
2929+ expr ast.Expr
3030+ out string
3131+ }{{
3232+ expr: &ast.BasicLit{Kind: token.STRING, Value: `"Hello"`},
3333+ out: `"Hello"`,
3434+ }, {
3535+ expr: &ast.ListLit{Elts: []ast.Expr{
3636+ &ast.BasicLit{Kind: token.STRING, Value: `"Hello"`},
3737+ &ast.BasicLit{Kind: token.STRING, Value: `"World"`},
3838+ }},
3939+ out: `["Hello","World"]`,
4040+ }}
4141+ for _, tc := range testCases {
4242+ t.Run("", func(t *testing.T) {
4343+ inst, err := FromExpr(nil, tc.expr)
4444+ if err != nil {
4545+ t.Fatal(err)
4646+ }
4747+ ctx := inst.newContext()
4848+ if got := debugStr(ctx, inst.eval(ctx)); got != tc.out {
4949+ t.Errorf("\n got: %v; want %v", got, tc.out)
5050+ }
5151+ })
5252+ }
5353+}
5454+5555+func TestBuild(t *testing.T) {
5656+ files := func(s ...string) []string { return s }
5757+ insts := func(i ...*bimport) []*bimport { return i }
5858+ pkg1 := &bimport{
5959+ "pkg1",
6060+ files(`
6161+ package pkg1
6262+6363+ Object: "World"
6464+ `),
6565+ }
6666+ pkg2 := &bimport{
6767+ "example.com/foo/pkg2",
6868+ files(`
6969+ package pkg
7070+7171+ Number: 12
7272+ `),
7373+ }
7474+ insts(pkg1, pkg2)
7575+7676+ testCases := []struct {
7777+ instances []*bimport
7878+ emit string
7979+ }{{
8080+ insts(&bimport{"", files(`test: "ok"`)}),
8181+ `<0>{test: "ok"}`,
8282+ // }, {
8383+ // insts(pkg1, &bimport{"",
8484+ // files(
8585+ // `package test
8686+8787+ // import "math"
8888+8989+ // "Pi: \(math.Pi)!"`)}),
9090+ // `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
9191+ }, {
9292+ insts(pkg1, &bimport{"",
9393+ files(
9494+ `package test
9595+9696+ import "pkg1"
9797+9898+ "Hello \(pkg1.Object)!"`),
9999+ }),
100100+ `"Hello World!"`,
101101+ }, {
102102+ insts(pkg1, &bimport{"",
103103+ files(
104104+ `package test
105105+106106+ import "pkg1"
107107+ pkg1: 1
108108+109109+ "Hello \(pkg1.Object)!"`),
110110+ }),
111111+ `pkg1 redeclared as imported package name
112112+ previous declaration at file0.cue:4:5`,
113113+ }, {
114114+ insts(pkg1, &bimport{"",
115115+ files(
116116+ `package test
117117+118118+ import bar "pkg1"
119119+120120+ pkg1 Object: 3
121121+ "Hello \(pkg1.Object)!"`),
122122+ }),
123123+ `imported and not used: "pkg1" as bar`,
124124+ }, {
125125+ insts(pkg2, &bimport{"",
126126+ files(
127127+ `package test
128128+129129+ import "example.com/foo/pkg2"
130130+131131+ "Hello \(pkg2.Number)!"`),
132132+ }),
133133+ `imported and not used: "example.com/foo/pkg2"`,
134134+ // `file0.cue:5:14: unresolved reference pkg2`,
135135+ }, {
136136+ insts(pkg2, &bimport{"",
137137+ files(
138138+ `package test
139139+140140+ import "example.com/foo/pkg2"
141141+142142+ "Hello \(pkg.Number)!"`),
143143+ }),
144144+ `"Hello 12!"`,
145145+ }}
146146+ for _, tc := range testCases {
147147+ t.Run("", func(t *testing.T) {
148148+ insts := Build(makeInstances(tc.instances))
149149+ var got string
150150+ if err := insts[0].Err; err != nil {
151151+ got = err.Error()
152152+ } else {
153153+ got = strings.TrimSpace(fmt.Sprintf("%s\n", insts[0].Value()))
154154+ }
155155+ if got != tc.emit {
156156+ t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
157157+ }
158158+ })
159159+ }
160160+}
161161+162162+type builder struct {
163163+ ctxt *build.Context
164164+ imports map[string]*bimport
165165+}
166166+167167+func (b *builder) load(path string) *build.Instance {
168168+ p := b.ctxt.NewInstance(path, b.load)
169169+ bi := b.imports[path]
170170+ if bi == nil {
171171+ return nil
172172+ }
173173+ buildInstance(b.imports[path], p)
174174+ return p
175175+}
176176+177177+type bimport struct {
178178+ path string // "" means top-level
179179+ files []string
180180+}
181181+182182+func makeInstances(insts []*bimport) (instances []*build.Instance) {
183183+ b := builder{
184184+ ctxt: build.NewContext(),
185185+ imports: map[string]*bimport{},
186186+ }
187187+ for _, bi := range insts {
188188+ if bi.path != "" {
189189+ b.imports[bi.path] = bi
190190+ }
191191+ }
192192+ for _, bi := range insts {
193193+ if bi.path == "" {
194194+ p := b.ctxt.NewInstance("dir", b.load)
195195+ buildInstance(bi, p)
196196+ instances = append(instances, p)
197197+ }
198198+ }
199199+ return
200200+}
201201+202202+func buildInstance(bi *bimport, p *build.Instance) {
203203+ for i, f := range bi.files {
204204+ p.AddFile(fmt.Sprintf("file%d.cue", i), f)
205205+ }
206206+ p.Complete()
207207+}
+519
cue/builtin.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "io"
2020+ "math/big"
2121+ "path"
2222+ "reflect"
2323+ "sort"
2424+ "strconv"
2525+ "strings"
2626+2727+ "cuelang.org/go/cue/ast"
2828+ "github.com/cockroachdb/apd"
2929+)
3030+3131+// A builtin is a builtin function or constant.
3232+//
3333+// A function may return and a constant may be any of the following types:
3434+//
3535+// error (translates to bottom)
3636+// nil (translates to null)
3737+// bool
3838+// int*
3939+// uint*
4040+// float64
4141+// string
4242+// *big.Float
4343+// *big.Int
4444+//
4545+// For any of the above, including interface{} and these types recursively:
4646+// []T
4747+// map[string]T
4848+//
4949+type builtin struct {
5050+ baseValue
5151+ Name string
5252+ Params []kind
5353+ Result kind
5454+ Func func(c *callCtxt)
5555+ // Const interface{}
5656+ Const evaluated
5757+}
5858+5959+var _ caller = &builtin{}
6060+6161+var lenBuiltin = &builtin{
6262+ Name: "len",
6363+ Params: []kind{stringKind | bytesKind | listKind | structKind},
6464+ Result: intKind,
6565+ Func: func(c *callCtxt) {
6666+ v := c.value(0)
6767+ switch v.Kind() {
6868+ case StructKind:
6969+ s, _ := v.structVal(c.ctx)
7070+ c.ret = s.Len()
7171+ case ListKind:
7272+ i := 0
7373+ iter, _ := v.List()
7474+ for ; iter.Next(); i++ {
7575+ }
7676+ c.ret = i
7777+ case BytesKind:
7878+ b, _ := v.Bytes()
7979+ c.ret = len(b)
8080+ case StringKind:
8181+ s, _ := v.String()
8282+ c.ret = len(s)
8383+ }
8484+ },
8585+}
8686+8787+func (x *builtin) kind() kind {
8888+ if x.Const != nil {
8989+ return x.Const.kind()
9090+ }
9191+ return lambdaKind
9292+}
9393+9494+func (x *builtin) evalPartial(ctx *context) evaluated {
9595+ if x.Const != nil {
9696+ return x.Const
9797+ }
9898+ return x
9999+}
100100+101101+func (x *builtin) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
102102+ if y, ok := v.(*builtin); ok {
103103+ return x == y
104104+ }
105105+ return false
106106+}
107107+108108+func (x *builtin) call(ctx *context, src source, args ...evaluated) (ret value) {
109109+ if x.Func == nil {
110110+ return ctx.mkErr(x, "Builtin %q is not a function", x.Name)
111111+ }
112112+ if len(x.Params) != len(args) {
113113+ return ctx.mkErr(src, x, "number of arguments does not match (%d vs %d)",
114114+ len(x.Params), len(args))
115115+ }
116116+ for i, a := range args {
117117+ if x.Params[i] != bottomKind {
118118+ if unifyType(x.Params[i], a.kind()) == bottomKind {
119119+ return ctx.mkErr(src, x, "argument %d requires type %v, found %v", i+1, x.Params[i], a.kind())
120120+ }
121121+ }
122122+ }
123123+ call := callCtxt{src: src, ctx: ctx, args: args}
124124+ defer func() {
125125+ var errVal interface{} = call.err
126126+ if err := recover(); err != nil {
127127+ errVal = err
128128+ }
129129+ switch err := errVal.(type) {
130130+ case nil:
131131+ case *bottom:
132132+ ret = err
133133+ default:
134134+ ret = ctx.mkErr(src, x, "call error: %v", err)
135135+ }
136136+ }()
137137+ x.Func(&call)
138138+ return convert(ctx, x, call.ret)
139139+}
140140+141141+// callCtxt is passed to builtin implementations.
142142+type callCtxt struct {
143143+ src source
144144+ ctx *context
145145+ args []evaluated
146146+ err error
147147+ ret interface{}
148148+}
149149+150150+var builtins map[string][]*builtin
151151+152152+func initBuiltins(pkgs map[string][]*builtin) {
153153+ builtins = pkgs
154154+ for k, b := range pkgs {
155155+ builtins["-/"+path.Base(k)] = b
156156+ }
157157+}
158158+159159+func getBuiltinShorthandPkg(ctx *context, shorthand string) *structLit {
160160+ return getBuiltinPkg(ctx, "-/"+shorthand)
161161+}
162162+163163+func getBuiltinPkg(ctx *context, path string) *structLit {
164164+ p, ok := builtins[path]
165165+ if !ok {
166166+ return nil
167167+ }
168168+169169+ // TODO(perf): store in index
170170+171171+ obj := &structLit{}
172172+ for _, b := range p {
173173+ f := ctx.label(b.Name, false) // never starts with _
174174+ // n := &node{baseValue: newBase(imp.Path)}
175175+ obj.arcs = append(obj.arcs, arc{feature: f, v: b})
176176+ }
177177+ sort.Sort(obj)
178178+ return obj
179179+}
180180+181181+// do returns whether the call should be done.
182182+func (c *callCtxt) do() bool {
183183+ return c.err == nil
184184+}
185185+186186+func (c *callCtxt) value(i int) Value {
187187+ return newValueRoot(c.ctx, c.args[i])
188188+}
189189+190190+func (c *callCtxt) int(i int) int { return int(c.intValue(i, 64)) }
191191+func (c *callCtxt) int8(i int) int8 { return int8(c.intValue(i, 8)) }
192192+func (c *callCtxt) int16(i int) int16 { return int16(c.intValue(i, 16)) }
193193+func (c *callCtxt) int32(i int) int32 { return int32(c.intValue(i, 32)) }
194194+func (c *callCtxt) rune(i int) rune { return rune(c.intValue(i, 32)) }
195195+func (c *callCtxt) int64(i int) int64 { return int64(c.intValue(i, 64)) }
196196+197197+func (c *callCtxt) intValue(i, bits int) int64 {
198198+ x := newValueRoot(c.ctx, c.args[i])
199199+ n, err := x.Int(nil)
200200+ if err != nil {
201201+ c.err = c.ctx.mkErr(c.src, "argument %d must be in int, found number", i)
202202+ return 0
203203+ }
204204+ if n.BitLen() > bits {
205205+ c.err = c.ctx.mkErr(c.src, err, "argument %d out of range: has %d > %d bits", n.BitLen(), bits)
206206+ }
207207+ res, _ := x.Int64()
208208+ return res
209209+}
210210+211211+func (c *callCtxt) uint(i int) uint { return uint(c.uintValue(i, 64)) }
212212+func (c *callCtxt) uint8(i int) uint8 { return uint8(c.uintValue(i, 8)) }
213213+func (c *callCtxt) byte(i int) uint8 { return byte(c.uintValue(i, 8)) }
214214+func (c *callCtxt) uint16(i int) uint16 { return uint16(c.uintValue(i, 16)) }
215215+func (c *callCtxt) uint32(i int) uint32 { return uint32(c.uintValue(i, 32)) }
216216+func (c *callCtxt) uint64(i int) uint64 { return uint64(c.uintValue(i, 64)) }
217217+218218+func (c *callCtxt) uintValue(i, bits int) uint64 {
219219+ x := newValueRoot(c.ctx, c.args[i])
220220+ n, err := x.Int(nil)
221221+ if err != nil {
222222+ c.err = c.ctx.mkErr(c.src, "argument %d must be an integer", i)
223223+ return 0
224224+ }
225225+ if n.Sign() < 0 {
226226+ c.err = c.ctx.mkErr(c.src, "argument %d must be a positive integer", i)
227227+ return 0
228228+ }
229229+ if n.BitLen() > bits {
230230+ c.err = c.ctx.mkErr(c.src, err, "argument %d out of range: has %d > %d bits", i, n.BitLen(), bits)
231231+ }
232232+ res, _ := x.Uint64()
233233+ return res
234234+}
235235+236236+func (c *callCtxt) float64(i int) float64 {
237237+ x := newValueRoot(c.ctx, c.args[i])
238238+ res, err := x.Float64()
239239+ if err != nil {
240240+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
241241+ return 0
242242+ }
243243+ return res
244244+}
245245+246246+func (c *callCtxt) bigInt(i int) *big.Int {
247247+ x := newValueRoot(c.ctx, c.args[i])
248248+ n, err := x.Int(nil)
249249+ if err != nil {
250250+ c.err = c.ctx.mkErr(c.src, "argument %d must be in int, found number", i)
251251+ return nil
252252+ }
253253+ return n
254254+}
255255+256256+func (c *callCtxt) bigFloat(i int) *big.Float {
257257+ x := newValueRoot(c.ctx, c.args[i])
258258+ var mant big.Int
259259+ exp, err := x.MantExp(&mant)
260260+ if err != nil {
261261+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
262262+ return nil
263263+ }
264264+ f := &big.Float{}
265265+ f.SetInt(&mant)
266266+ if exp != 0 {
267267+ var g big.Float
268268+ e := big.NewInt(int64(exp))
269269+ f.Mul(f, g.SetInt(e.Exp(ten, e, nil)))
270270+ }
271271+ return f
272272+}
273273+274274+func (c *callCtxt) string(i int) string {
275275+ x := newValueRoot(c.ctx, c.args[i])
276276+ v, err := x.String()
277277+ if err != nil {
278278+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
279279+ return ""
280280+ }
281281+ return v
282282+}
283283+284284+func (c *callCtxt) bytes(i int) []byte {
285285+ x := newValueRoot(c.ctx, c.args[i])
286286+ v, err := x.Bytes()
287287+ if err != nil {
288288+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
289289+ return nil
290290+ }
291291+ return v
292292+}
293293+294294+func (c *callCtxt) reader(i int) io.Reader {
295295+ x := newValueRoot(c.ctx, c.args[i])
296296+ // TODO: optimize for string and bytes cases
297297+ r, err := x.Reader()
298298+ if err != nil {
299299+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
300300+ return nil
301301+ }
302302+ return r
303303+}
304304+305305+func (c *callCtxt) bool(i int) bool {
306306+ x := newValueRoot(c.ctx, c.args[i])
307307+ b, err := x.Bool()
308308+ if err != nil {
309309+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
310310+ return false
311311+ }
312312+ return b
313313+}
314314+315315+func (c *callCtxt) error(i int) error {
316316+ x := newValueRoot(c.ctx, c.args[i])
317317+ return x.Err()
318318+}
319319+320320+func (c *callCtxt) list(i int) (a Iterator) {
321321+ x := newValueRoot(c.ctx, c.args[i])
322322+ v, err := x.List()
323323+ if err != nil {
324324+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
325325+ return Iterator{ctx: c.ctx}
326326+ }
327327+ return v
328328+}
329329+330330+func (c *callCtxt) strList(i int) (a []string) {
331331+ x := newValueRoot(c.ctx, c.args[i])
332332+ v, err := x.List()
333333+ if err != nil {
334334+ c.err = c.ctx.mkErr(c.src, err, "invalid argument %d: %v", i, err)
335335+ return nil
336336+ }
337337+ for i := 0; v.Next(); i++ {
338338+ str, err := v.Value().String()
339339+ if err != nil {
340340+ c.err = c.ctx.mkErr(c.src, err, "list element %d: %v", i, err)
341341+ }
342342+ a = append(a, str)
343343+ }
344344+ return a
345345+}
346346+347347+// lookupBuiltinPkg returns the builtin package for the given path if it exists.
348348+func lookupBuiltinPkg(ctx *context, imp *ast.ImportSpec) evaluated {
349349+ path, err := strconv.Unquote(imp.Path.Value)
350350+ if err != nil {
351351+ return ctx.mkErr(newNode(imp), "illformed import spec")
352352+ }
353353+354354+ p := getBuiltinPkg(ctx, path)
355355+ if p == nil {
356356+ return ctx.mkErr(newNode(imp), "package %q not found", path)
357357+ }
358358+ return p
359359+}
360360+361361+func convert(ctx *context, src source, x interface{}) evaluated {
362362+ switch v := x.(type) {
363363+ case evaluated:
364364+ return v
365365+ case nil:
366366+ return &nullLit{src.base()}
367367+ case *Instance:
368368+ return v.eval(ctx)
369369+ case error:
370370+ return ctx.mkErr(src, v.Error())
371371+ case bool:
372372+ return &boolLit{src.base(), v}
373373+ case string:
374374+ return &stringLit{src.base(), v}
375375+ case []byte:
376376+ return &bytesLit{src.base(), v}
377377+ case int:
378378+ return toInt(ctx, src, int64(v))
379379+ case int8:
380380+ return toInt(ctx, src, int64(v))
381381+ case int16:
382382+ return toInt(ctx, src, int64(v))
383383+ case int32:
384384+ return toInt(ctx, src, int64(v))
385385+ case int64:
386386+ return toInt(ctx, src, int64(v))
387387+ case uint:
388388+ return toUint(ctx, src, uint64(v))
389389+ case uint8:
390390+ return toUint(ctx, src, uint64(v))
391391+ case uint16:
392392+ return toUint(ctx, src, uint64(v))
393393+ case uint32:
394394+ return toUint(ctx, src, uint64(v))
395395+ case uint64:
396396+ return toUint(ctx, src, uint64(v))
397397+ case float64:
398398+ r := newNum(src, floatKind)
399399+ r.v.SetString(fmt.Sprintf("%g", v))
400400+ return r
401401+ case *big.Int:
402402+ n := newNum(src, intKind)
403403+ n.v.Coeff.Set(v)
404404+ if v.Sign() < 0 {
405405+ n.v.Coeff.Neg(&n.v.Coeff)
406406+ n.v.Negative = true
407407+ }
408408+ return n
409409+ case *big.Rat:
410410+ n := newNum(src, numKind)
411411+ ctx.Quo(&n.v, apd.NewWithBigInt(v.Num(), 0), apd.NewWithBigInt(v.Denom(), 0))
412412+ if !v.IsInt() {
413413+ n.k = floatKind
414414+ }
415415+ return n
416416+ case *big.Float:
417417+ n := newNum(src, floatKind)
418418+ n.v.SetString(v.String())
419419+ return n
420420+ case *apd.Decimal:
421421+ n := newNum(src, floatKind|intKind)
422422+ n.v.Set(v)
423423+ if !n.isInt(ctx) {
424424+ n.k = floatKind
425425+ }
426426+ return n
427427+ case reflect.Value:
428428+ if v.CanInterface() {
429429+ return convert(ctx, src, v.Interface())
430430+ }
431431+432432+ default:
433433+ value := reflect.ValueOf(v)
434434+ switch value.Kind() {
435435+ case reflect.Ptr:
436436+ if value.IsNil() {
437437+ return &nullLit{src.base()}
438438+ }
439439+ return convert(ctx, src, value.Elem().Interface())
440440+ case reflect.Struct:
441441+ obj := newStruct(src)
442442+ t := value.Type()
443443+ for i := 0; i < value.NumField(); i++ {
444444+ t := t.Field(i)
445445+ if t.PkgPath != "" {
446446+ continue
447447+ }
448448+ sub := convert(ctx, src, value.Field(i).Interface())
449449+ // leave errors like we do during normal evaluation or do we
450450+ // want to return the error?
451451+ name := t.Name
452452+ for _, s := range []string{"cue", "json", "protobuf"} {
453453+ if tag, ok := t.Tag.Lookup(s); ok {
454454+ if p := strings.Index(tag, ","); p >= 0 {
455455+ tag = tag[:p]
456456+ }
457457+ if tag != "" {
458458+ name = tag
459459+ break
460460+ }
461461+ }
462462+ }
463463+ f := ctx.strLabel(name)
464464+ obj.arcs = append(obj.arcs, arc{feature: f, v: sub})
465465+ }
466466+ sort.Sort(obj)
467467+ return obj
468468+469469+ case reflect.Map:
470470+ obj := newStruct(src)
471471+ t := value.Type()
472472+ if t.Key().Kind() != reflect.String {
473473+ return ctx.mkErr(src, "builtin map key not a string, but unsupported type %s", t.Key().String())
474474+ }
475475+ keys := []string{}
476476+ for _, k := range value.MapKeys() {
477477+ keys = append(keys, k.String())
478478+ }
479479+ sort.Strings(keys)
480480+ for _, k := range keys {
481481+ sub := convert(ctx, src, value.MapIndex(reflect.ValueOf(k)).Interface())
482482+ // leave errors like we do during normal evaluation or do we
483483+ // want to return the error?
484484+ f := ctx.strLabel(k)
485485+ obj.arcs = append(obj.arcs, arc{feature: f, v: sub})
486486+ }
487487+ sort.Sort(obj)
488488+ return obj
489489+490490+ case reflect.Slice, reflect.Array:
491491+ list := &list{baseValue: src.base()}
492492+ for i := 0; i < value.Len(); i++ {
493493+ x := convert(ctx, src, value.Index(i).Interface())
494494+ if isBottom(x) {
495495+ return x
496496+ }
497497+ list.a = append(list.a, x)
498498+ }
499499+ list.initLit()
500500+ // There is no need to set the type of the list, as the list will
501501+ // be of fixed size and all elements will already have a defined
502502+ // value.
503503+ return list
504504+ }
505505+ }
506506+ return ctx.mkErr(src, "builtin returned unsupported type %T", x)
507507+}
508508+509509+func toInt(ctx *context, src source, x int64) evaluated {
510510+ n := newNum(src, intKind)
511511+ n.v.SetInt64(x)
512512+ return n
513513+}
514514+515515+func toUint(ctx *context, src source, x uint64) evaluated {
516516+ n := newNum(src, floatKind)
517517+ n.v.Coeff.SetUint64(x)
518518+ return n
519519+}
+127
cue/builtin_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "math/big"
1919+ "reflect"
2020+ "testing"
2121+2222+ "cuelang.org/go/cue/ast"
2323+ "cuelang.org/go/cue/errors"
2424+)
2525+2626+func TestConvert(t *testing.T) {
2727+ i34 := big.NewInt(34)
2828+ d34 := mkBigInt(34)
2929+ f34 := big.NewFloat(34.0000)
3030+ testCases := []struct {
3131+ goVal interface{}
3232+ want string
3333+ }{{
3434+ nil, "null",
3535+ }, {
3636+ true, "true",
3737+ }, {
3838+ false, "false",
3939+ }, {
4040+ errors.New("oh noes"), "_|_(oh noes)",
4141+ }, {
4242+ "foo", `"foo"`,
4343+ }, {
4444+ 3, "3",
4545+ }, {
4646+ uint(3), "3",
4747+ }, {
4848+ uint8(3), "3",
4949+ }, {
5050+ uint16(3), "3",
5151+ }, {
5252+ uint32(3), "3",
5353+ }, {
5454+ uint64(3), "3",
5555+ }, {
5656+ int8(-3), "-3",
5757+ }, {
5858+ int16(-3), "-3",
5959+ }, {
6060+ int32(-3), "-3",
6161+ }, {
6262+ int64(-3), "-3",
6363+ }, {
6464+ float64(3.1), "3.1",
6565+ }, {
6666+ &i34, "34",
6767+ }, {
6868+ &f34, "34",
6969+ }, {
7070+ &d34, "34",
7171+ }, {
7272+ []int{1, 2, 3, 4}, "[1,2,3,4]",
7373+ }, {
7474+ []interface{}{}, "[]",
7575+ }, {
7676+ map[string][]int{
7777+ "a": []int{1},
7878+ "b": []int{3, 4},
7979+ }, "<0>{a: [1], b: [3,4]}",
8080+ }, {
8181+ map[int]int{}, "_|_(builtin map key not a string, but unsupported type int)",
8282+ }, {
8383+ map[int]int{1: 2}, "_|_(builtin map key not a string, but unsupported type int)",
8484+ }, {
8585+ struct {
8686+ a int
8787+ b int
8888+ }{3, 4},
8989+ "<0>{}",
9090+ }, {
9191+ struct {
9292+ A int
9393+ B int
9494+ }{3, 4},
9595+ "<0>{A: 3, B: 4}",
9696+ }, {
9797+ struct {
9898+ A int `json:"a"`
9999+ B int `cue:"b"`
100100+ }{3, 4},
101101+ "<0>{a: 3, b: 4}",
102102+ }, {
103103+ struct {
104104+ A int `json:",bb" cue:"" protobuf:"aa"`
105105+ B int `json:"cc" cue:"bb" protobuf:"aa"`
106106+ }{3, 4},
107107+ "<0>{aa: 3, bb: 4}",
108108+ }, {
109109+ &struct{ A int }{3}, "<0>{A: 3}",
110110+ }, {
111111+ (*struct{ A int })(nil), "null",
112112+ }, {
113113+ reflect.ValueOf(3), "3",
114114+ }}
115115+ inst := getInstance(t, "foo")
116116+ b := ast.NewIdent("dummy")
117117+ for _, tc := range testCases {
118118+ ctx := inst.newContext()
119119+ t.Run("", func(t *testing.T) {
120120+ v := convert(ctx, newNode(b), tc.goVal)
121121+ got := debugStr(ctx, v)
122122+ if got != tc.want {
123123+ t.Errorf("got %q; want %q", got, tc.want)
124124+ }
125125+ })
126126+ }
127127+}
+105
cue/context.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "github.com/cockroachdb/apd"
1919+)
2020+2121+// context manages evaluation state.
2222+type context struct {
2323+ *apd.Context
2424+2525+ *index
2626+2727+ forwardMap []scope // pairs
2828+ oldSize []int
2929+3030+ // constraints are to be evaluated at the end values to be evaluated later.
3131+ constraints []value
3232+ noDelay bool
3333+3434+ // for debug strings
3535+ nodeRefs map[scope]string
3636+3737+ // tracing
3838+ trace bool
3939+ level int
4040+}
4141+4242+var baseContext apd.Context
4343+4444+func init() {
4545+ baseContext = apd.BaseContext
4646+ baseContext.Precision = 24
4747+}
4848+4949+// newContext returns a new evaluation context.
5050+func (idx *index) newContext() *context {
5151+ c := &context{
5252+ Context: &baseContext,
5353+ index: idx,
5454+ }
5555+ return c
5656+}
5757+5858+// delayConstraint schedules constraint to be evaluated and returns ret. If
5959+// delaying constraints is currently not allowed, it returns an error instead.
6060+func (c *context) delayConstraint(ret evaluated, constraint value) evaluated {
6161+ if c.noDelay {
6262+ return c.mkErr(ret, "delayed constraint %v violated", debugStr(c, constraint))
6363+ }
6464+ c.constraints = append(c.constraints, constraint)
6565+ return ret
6666+}
6767+6868+func (c *context) processDelayedConstraints() evaluated {
6969+ cons := c.constraints
7070+ c.constraints = c.constraints[:0]
7171+ for _, dc := range cons {
7272+ c.noDelay = true
7373+ v := c.manifest(dc)
7474+ c.noDelay = false
7575+ if isBottom(v) {
7676+ return c.mkErr(dc, "constraint violated: %v", debugStr(c, v))
7777+ }
7878+ }
7979+ return nil
8080+}
8181+8282+func (c *context) deref(f scope) scope {
8383+outer:
8484+ for {
8585+ for i := 0; i < len(c.forwardMap); i += 2 {
8686+ if c.forwardMap[i] == f {
8787+ f = c.forwardMap[i+1]
8888+ continue outer
8989+ }
9090+ }
9191+ return f
9292+ }
9393+}
9494+9595+func (c *context) pushForwards(pairs ...scope) *context {
9696+ c.oldSize = append(c.oldSize, len(c.forwardMap))
9797+ c.forwardMap = append(c.forwardMap, pairs...)
9898+ return c
9999+}
100100+101101+func (c *context) popForwards() {
102102+ last := len(c.oldSize) - 1
103103+ c.forwardMap = c.forwardMap[:c.oldSize[last]]
104104+ c.oldSize = c.oldSize[:last]
105105+}
+66
cue/copy.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+func (c *context) copy(v value) value {
1818+ // return v.copy(c)
1919+ return rewrite(c, v, rewriteCopy)
2020+}
2121+2222+func rewriteCopy(ctx *context, v value) (value, bool) {
2323+ switch x := v.(type) {
2424+ case *nodeRef:
2525+ node := ctx.deref(x.node)
2626+ if node == x.node {
2727+ return x, false
2828+ }
2929+ return &nodeRef{x.baseValue, node}, false
3030+3131+ case *structLit:
3232+ arcs := make(arcs, len(x.arcs))
3333+ emit := x.emit
3434+ if emit != nil {
3535+ emit = ctx.copy(x.emit)
3636+ }
3737+ t := x.template
3838+ if t != nil {
3939+ v := ctx.copy(t)
4040+ if isBottom(v) {
4141+ return t, false
4242+ }
4343+ t = v.(*lambdaExpr)
4444+ }
4545+ obj := &structLit{x.baseValue, emit, t, arcs}
4646+4747+ defer ctx.pushForwards(x, obj).popForwards()
4848+ for i, a := range x.arcs {
4949+ v := ctx.copy(a.v)
5050+ arcs[i] = arc{a.feature, v, nil}
5151+ }
5252+ return obj, false
5353+5454+ case *lambdaExpr:
5555+ arcs := make([]arc, len(x.arcs))
5656+ for i, a := range x.arcs {
5757+ arcs[i] = arc{feature: a.feature, v: ctx.copy(a.v)}
5858+ }
5959+ lambda := &lambdaExpr{x.baseValue, ¶ms{arcs}, nil}
6060+ defer ctx.pushForwards(x, lambda).popForwards()
6161+6262+ lambda.value = ctx.copy(x.value)
6363+ return lambda, false
6464+ }
6565+ return v, true
6666+}
+390
cue/debug.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+ "fmt"
2020+ "strconv"
2121+ "strings"
2222+)
2323+2424+func debugStr(ctx *context, v value) string {
2525+ p := &printer{
2626+ ctx: ctx,
2727+ w: &bytes.Buffer{},
2828+ }
2929+ p.debugStr(v)
3030+ return p.w.String()
3131+}
3232+3333+func (c *context) ref(v scope) string {
3434+ v = c.deref(v)
3535+ if c.nodeRefs == nil {
3636+ c.nodeRefs = map[scope]string{}
3737+ }
3838+ ref, ok := c.nodeRefs[v]
3939+ if ok {
4040+ return ref
4141+ }
4242+ ref = strconv.Itoa(len(c.nodeRefs))
4343+ c.nodeRefs[v] = ref
4444+ return ref
4545+}
4646+4747+func (c *context) indent() {
4848+ fmt.Print(strings.Repeat(" ", c.level))
4949+}
5050+5151+func (c *context) debugPrint(args ...interface{}) {
5252+ if c.trace {
5353+ c.indent()
5454+ c.println(args...)
5555+ }
5656+}
5757+5858+func (c *context) println(args ...interface{}) {
5959+ for i, a := range args {
6060+ if i != 0 {
6161+ fmt.Print(" ")
6262+ }
6363+ switch x := a.(type) {
6464+ case value:
6565+ fmt.Print(debugStr(c, x))
6666+ default:
6767+ fmt.Print(x)
6868+ }
6969+ }
7070+ fmt.Println()
7171+}
7272+7373+// func trace(c *context, r rewriter, n *node) (*context, rewriter, *node) {
7474+// n = derefNode(n)
7575+// name := "evaluate"
7676+// if r != nil {
7777+// name = fmt.Sprintf("%T", r)
7878+// }
7979+// c.debugPrint("---", name, c.ref(n))
8080+// if n.obj != nil {
8181+// c.debugPrint("<<< node: ", debugStr(c, n.obj))
8282+// }
8383+// if n.expr != nil {
8484+// c.debugPrint("<<< expr: ", debugStr(c, n.expr))
8585+// }
8686+// if n.value != nil {
8787+// c.debugPrint("<<< value:", debugStr(c, n.value))
8888+// }
8989+// c.level++
9090+// return c, r, n
9191+// }
9292+9393+// func un(c *context, r rewriter, n *node) {
9494+// n = derefNode(n)
9595+// c.level--
9696+// if n.expr != nil {
9797+// c.debugPrint(">>> expr:", debugStr(c, n.expr))
9898+// }
9999+// if n.value != nil {
100100+// c.debugPrint(">>> value:", debugStr(c, n.value))
101101+// }
102102+// if n.obj != nil {
103103+// c.debugPrint(">>> node: ", debugStr(c, n.obj))
104104+// }
105105+// }
106106+107107+func indent(c *context, msg string, x value) (_ *context, m, v string) {
108108+ str := debugStr(c, x)
109109+ c.debugPrint("...", msg)
110110+ c.level++
111111+ c.debugPrint("in:", str)
112112+ return c, msg, str
113113+}
114114+115115+func uni(c *context, msg, oldValue string) {
116116+ c.debugPrint("was: ", oldValue)
117117+ c.level--
118118+ c.debugPrint("...", msg)
119119+}
120120+121121+func newPrinter(ctx *context) *printer {
122122+ return &printer{
123123+ ctx: ctx,
124124+ w: &bytes.Buffer{},
125125+ }
126126+}
127127+128128+type printer struct {
129129+ ctx *context
130130+ w *bytes.Buffer
131131+}
132132+133133+func (p *printer) str(v value) string {
134134+ p.debugStr(v)
135135+ str := p.w.String()
136136+ p.w.Reset()
137137+ return str
138138+}
139139+140140+func (p *printer) label(f label) string {
141141+ if p.ctx == nil {
142142+ return strconv.Itoa(int(f))
143143+ }
144144+ return p.ctx.labelStr(f)
145145+}
146146+147147+func (p *printer) writef(format string, args ...interface{}) {
148148+ fmt.Fprintf(p.w, format, args...)
149149+}
150150+151151+func (p *printer) write(args ...interface{}) {
152152+ fmt.Fprint(p.w, args...)
153153+}
154154+155155+func (p *printer) debugStr(v interface{}) {
156156+ writef := p.writef
157157+ write := p.write
158158+ switch x := v.(type) {
159159+ case nil:
160160+ write("*nil*")
161161+ case string:
162162+ write(x)
163163+ case *builtin:
164164+ write("builtin:")
165165+ p.debugStr(x.Name)
166166+ case *nodeRef:
167167+ writef("<%s>", p.ctx.ref(x.node))
168168+ // p.debugStr(x.node)
169169+ case *selectorExpr:
170170+ p.debugStr(x.x)
171171+ writef(".%v", p.label(x.feature))
172172+ case *indexExpr:
173173+ p.debugStr(x.x)
174174+ write("[")
175175+ p.debugStr(x.index)
176176+ write("]")
177177+ case *sliceExpr:
178178+ p.debugStr(x.x)
179179+ write("[")
180180+ if x.lo != nil {
181181+ p.debugStr(x.lo)
182182+ }
183183+ write(":")
184184+ if x.hi != nil {
185185+ p.debugStr(x.hi)
186186+ }
187187+ write("]")
188188+ case *callExpr:
189189+ p.debugStr(x.x)
190190+ write(" (")
191191+ for i, a := range x.args {
192192+ p.debugStr(a)
193193+ if i < len(x.args)-1 {
194194+ write(",")
195195+ }
196196+ }
197197+ write(")")
198198+ case *unaryExpr:
199199+ write(x.op)
200200+ p.debugStr(x.x)
201201+ case *binaryExpr:
202202+ write("(")
203203+ p.debugStr(x.left)
204204+ writef(" %v ", x.op)
205205+ p.debugStr(x.right)
206206+ write(")")
207207+ case *disjunction:
208208+ write("(")
209209+ for i, v := range x.values {
210210+ if i != 0 {
211211+ writef(" | ")
212212+ }
213213+ p.debugStr(v.val)
214214+ if v.ambiguous {
215215+ writef("!")
216216+ }
217217+ }
218218+ write(")")
219219+ case *lambdaExpr:
220220+ writef("<%s>(", p.ctx.ref(x))
221221+ p.debugStr(x.params.arcs)
222222+ write(")->")
223223+ p.debugStr(x.value)
224224+225225+ case *structLit:
226226+ if x == nil {
227227+ write("*nil node*")
228228+ break
229229+ }
230230+ p.writef("<%s>", p.ctx.ref(x))
231231+ writef("{")
232232+ if x.template != nil {
233233+ write("<>: ")
234234+ p.debugStr(x.template)
235235+ write(", ")
236236+ }
237237+ p.debugStr(x.arcs)
238238+ write("}")
239239+240240+ case []arc:
241241+ for i, a := range x {
242242+ p.debugStr(a)
243243+244244+ if i < len(x)-1 {
245245+ p.write(", ")
246246+ }
247247+ }
248248+249249+ case arc:
250250+ n := x.v
251251+ orig := p.label(x.feature)
252252+ str := strconv.Quote(orig)
253253+ if len(orig)+2 == len(str) {
254254+ str = str[1 : len(str)-1]
255255+ }
256256+ p.writef(str)
257257+ p.write(": ")
258258+ p.debugStr(n)
259259+260260+ case *structComprehension:
261261+ writef("{")
262262+ p.debugStr(x.clauses)
263263+ write(" }")
264264+265265+ case *listComprehension:
266266+ writef("[")
267267+ p.debugStr(x.clauses)
268268+ write(" ]")
269269+270270+ case *yield:
271271+ writef(" yield ")
272272+ writef("(")
273273+ p.debugStr(x.key)
274274+ writef("): ")
275275+ p.debugStr(x.value)
276276+277277+ case *feed:
278278+ writef(" <%s>for ", p.ctx.ref(x.fn))
279279+ a := x.fn.params.arcs[0]
280280+ p.writef(p.label(a.feature))
281281+ writef(", ")
282282+ a = x.fn.params.arcs[1]
283283+ p.writef(p.label(a.feature))
284284+ writef(" in ")
285285+ p.debugStr(x.source)
286286+ p.debugStr(x.fn.value)
287287+288288+ case *guard:
289289+ writef(" if ")
290290+ p.debugStr(x.condition)
291291+ p.debugStr(x.value)
292292+293293+ case *nullLit:
294294+ write("null")
295295+ case *boolLit:
296296+ writef("%v", x.b)
297297+ case *stringLit:
298298+ writef("%q", x.str)
299299+ case *bytesLit:
300300+ str := strconv.Quote(string(x.b))
301301+ str = str[1 : len(str)-1]
302302+ writef("'%s'", str)
303303+ case *numLit:
304304+ if x.k&intKind != 0 {
305305+ write(x.v.Text('f')) // also render info
306306+ } else {
307307+ write(x.v.Text('g')) // also render info
308308+ }
309309+ case *durationLit:
310310+ write(x.d.String())
311311+ case *rangeLit:
312312+ write("(")
313313+ p.debugStr(x.from)
314314+ write("..")
315315+ p.debugStr(x.to)
316316+ write(")")
317317+ case *interpolation:
318318+ for i, e := range x.parts {
319319+ if i != 0 {
320320+ write("+")
321321+ }
322322+ p.debugStr(e)
323323+ }
324324+ case *list:
325325+ // TODO: do not evaluate
326326+ max := maxNum(x.len.evalPartial(p.ctx))
327327+ inCast := false
328328+ ellipsis := false
329329+ n, ok := max.(*numLit)
330330+ if !ok {
331331+ // TODO: do not evaluate
332332+ min := minNum(x.len.evalPartial(p.ctx))
333333+ n, _ = min.(*numLit)
334334+ }
335335+ ln := 0
336336+ if n != nil {
337337+ x, _ := n.v.Int64()
338338+ ln = int(x)
339339+ }
340340+ if !ok || ln > len(x.a) {
341341+ if !isTop(max) && !isTop(x.typ) {
342342+ p.debugStr(x.len)
343343+ write("*[")
344344+ p.debugStr(x.typ)
345345+ write("]")
346346+ if len(x.a) == 0 {
347347+ break
348348+ }
349349+ write("(")
350350+ inCast = true
351351+ }
352352+ ellipsis = true
353353+ }
354354+ write("[")
355355+ for i, a := range x.a {
356356+ p.debugStr(a)
357357+ if i < len(x.a)-1 {
358358+ write(",")
359359+ }
360360+ }
361361+ if ellipsis {
362362+ write(", ...")
363363+ if !isTop(x.typ) {
364364+ p.debugStr(x.typ)
365365+ }
366366+ }
367367+ write("]")
368368+ if inCast {
369369+ write(")")
370370+ }
371371+372372+ case *bottom:
373373+ write("_|_")
374374+ if x.value != nil || x.msg != "" {
375375+ write("(")
376376+ if x.value != nil {
377377+ writef("%s:", debugStr(p.ctx, x.value))
378378+ }
379379+ write(x.msg)
380380+ write(")")
381381+ }
382382+ case *top:
383383+ write("_") // ⊤
384384+ case *basicType:
385385+ write(x.k.String())
386386+387387+ default:
388388+ panic(fmt.Sprintf("unimplemented type %T", x))
389389+ }
390390+}
+16
cue/doc.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+// Package cue creates, evaluates and manipulates CUE configurations.
1616+package cue // import "cuelang.org/go/cue"
+219
cue/errors.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "sort"
1919+2020+ "cuelang.org/go/cue/token"
2121+ "golang.org/x/exp/errors"
2222+ "golang.org/x/exp/errors/fmt"
2323+)
2424+2525+type errCode int
2626+2727+const (
2828+ codeNone errCode = iota
2929+ codeFatal
3030+ codeNotExist
3131+ codeTypeError
3232+ codeIncomplete
3333+ codeCycle
3434+)
3535+3636+func isIncomplete(v value) bool {
3737+ if err, ok := v.(*bottom); ok {
3838+ return err.code == codeIncomplete
3939+ }
4040+ return false
4141+}
4242+4343+func recoverable(v value) bool {
4444+ if err, ok := v.(*bottom); ok {
4545+ switch err.code {
4646+ case codeFatal,
4747+ codeCycle: // only recoverable when explicitly handled and discarded
4848+ return false
4949+ }
5050+ }
5151+ return true
5252+}
5353+5454+var errNotExists = &bottom{code: codeNotExist, msg: "undefined value"}
5555+5656+func exists(v value) bool {
5757+ if err, ok := v.(*bottom); ok {
5858+ return err.code != codeNotExist
5959+ }
6060+ return true
6161+}
6262+6363+// bottom is the bottom of the value lattice. It is subsumed by all values.
6464+type bottom struct {
6565+ baseValue
6666+6767+ index *index
6868+ code errCode
6969+ value value
7070+ offendingValue value
7171+ replacement evaluated // for cycle resolution
7272+ pos source
7373+ msg string
7474+7575+ wrapped *bottom
7676+7777+ // TODO: file at which the error was generated in the code.
7878+ // File positions of where the error occurred.
7979+}
8080+8181+func (x *bottom) kind() kind { return bottomKind }
8282+8383+func (x *bottom) Position() []token.Position {
8484+ if x.index != nil && x.index.fset != nil {
8585+ return appendPositions(nil, x.index.fset, x.pos)
8686+ }
8787+ return nil
8888+}
8989+9090+func appendPositions(pos []token.Position, fset *token.FileSet, src source) []token.Position {
9191+ if src != nil {
9292+ if src.Pos() != token.NoPos {
9393+ return append(pos, fset.Position(src.Pos()))
9494+ }
9595+ if c := src.computed(); c != nil {
9696+ pos = appendPositions(pos, fset, c.x)
9797+ pos = appendPositions(pos, fset, c.y)
9898+ }
9999+ }
100100+ return pos
101101+}
102102+103103+func (x *bottom) Error() string { return fmt.Sprint(x) }
104104+105105+func (x *bottom) Format(p errors.Printer) error {
106106+ p.Print(x.msg)
107107+ if p.Detail() && x.index != nil && x.index.fset != nil {
108108+ locs := appendLocations(nil, x.index.fset, x.pos)
109109+ sort.Strings(locs)
110110+ for _, l := range locs {
111111+ p.Printf("%s\n", l)
112112+ }
113113+ }
114114+ if x.wrapped != nil {
115115+ return x.wrapped // nil interface
116116+ }
117117+ return nil
118118+}
119119+120120+func appendLocations(locs []string, fset *token.FileSet, src source) []string {
121121+ if src != nil {
122122+ if src.Pos() != token.NoPos {
123123+ return append(locs, fset.Position(src.Pos()).String())
124124+ }
125125+ if c := src.computed(); c != nil {
126126+ locs = appendLocations(locs, fset, c.x)
127127+ locs = appendLocations(locs, fset, c.y)
128128+ }
129129+ }
130130+ return locs
131131+}
132132+133133+func cycleError(v evaluated) *bottom {
134134+ if err, ok := v.(*bottom); ok && err.code == codeCycle {
135135+ return err
136136+ }
137137+ return nil
138138+}
139139+140140+// sentinel values used for signalling a type of error.
141141+var (
142142+ // errNonGround = // values are not compatible
143143+ cycleSentinel = &bottom{
144144+ code: codeCycle,
145145+ msg: "cycle detected",
146146+ }
147147+148148+ // unifyNotSupported may be returned when a node implementation cannot
149149+ // handle the other type. In this case it may still be the case that the
150150+ // converse can be implemented.
151151+ // unifyNotSupported node = &bottom{}
152152+)
153153+154154+func (idx *index) mkErrUnify(src source, a, b evaluated) evaluated {
155155+ if err := firstBottom(a, b); err != nil {
156156+ return err
157157+ }
158158+ e := binSrc(src.Pos(), opUnify, a, b)
159159+ // TODO: show string of values and show location of both values.
160160+ return idx.mkErr(e, "incompatible values &(%s, %s)", a.kind(), b.kind())
161161+}
162162+163163+func (c *context) mkIncompatible(src source, op op, a, b evaluated) evaluated {
164164+ if err := firstBottom(a, b); err != nil {
165165+ return err
166166+ }
167167+ e := mkBin(c, src.Pos(), op, a, b)
168168+ return c.mkErr(e, "unsupported op %s(%s, %s)", op, a.kind(), b.kind())
169169+}
170170+171171+func (idx *index) mkErr(src source, args ...interface{}) *bottom {
172172+ e := &bottom{baseValue: src.base(), index: idx, pos: src}
173173+174174+ if v, ok := src.(value); ok {
175175+ e.value = v
176176+ }
177177+ for i, a := range args {
178178+ switch x := a.(type) {
179179+ case errCode:
180180+ e.code = x
181181+ case *bottom:
182182+ e.wrapped = x
183183+ e.offendingValue = x
184184+ case value:
185185+ e.offendingValue = x
186186+ case op:
187187+ panic("no longer using offending value and op")
188188+ case string:
189189+ e.msg += fmt.Sprintf(x, args[i+1:]...)
190190+ return e
191191+ }
192192+ }
193193+ if e.code == codeNone && e.wrapped != nil {
194194+ e.code = e.wrapped.code
195195+ }
196196+ return e
197197+}
198198+199199+func isBottom(n value) bool {
200200+ return n.kind() == bottomKind
201201+}
202202+203203+func firstBottom(v ...value) evaluated {
204204+ for _, b := range v {
205205+ if isBottom(b) {
206206+ return b.(*bottom)
207207+ }
208208+ }
209209+ return nil
210210+}
211211+212212+func expectType(idx *index, t kind, n evaluated) value {
213213+ if isBottom(n) {
214214+ return n
215215+ }
216216+ return idx.mkErr(n, "value should of type %s, found %s", n.kind(), t)
217217+}
218218+219219+// TODO: consider returning a type or subsuption error for op != opUnify
+490
cue/eval.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+ "sort"
2020+)
2121+2222+func eval(idx *index, v value) evaluated {
2323+ ctx := idx.newContext()
2424+ return v.evalPartial(ctx)
2525+}
2626+2727+func (x *nodeRef) evalPartial(ctx *context) (result evaluated) {
2828+ return x.node.evalPartial(ctx)
2929+}
3030+3131+// Atoms
3232+3333+func (x *top) evalPartial(ctx *context) evaluated { return x }
3434+func (x *bottom) evalPartial(ctx *context) evaluated { return x }
3535+3636+func (x *basicType) evalPartial(ctx *context) evaluated { return x }
3737+func (x *nullLit) evalPartial(ctx *context) evaluated { return x }
3838+func (x *boolLit) evalPartial(ctx *context) evaluated { return x }
3939+func (x *stringLit) evalPartial(ctx *context) evaluated { return x }
4040+func (x *bytesLit) evalPartial(ctx *context) evaluated { return x }
4141+func (x *numLit) evalPartial(ctx *context) evaluated { return x }
4242+func (x *durationLit) evalPartial(ctx *context) evaluated { return x }
4343+4444+func (x *lambdaExpr) evalPartial(ctx *context) evaluated {
4545+ return ctx.deref(x).(*lambdaExpr)
4646+}
4747+4848+func (x *selectorExpr) evalPartial(ctx *context) (result evaluated) {
4949+ if ctx.trace {
5050+ defer uni(indent(ctx, "selectorExpr", x))
5151+ defer func() { ctx.debugPrint("result:", result) }()
5252+ }
5353+5454+ e := newEval(ctx, true)
5555+5656+ const msgType = "invalid operation: %[5]s (type %[3]s does not support selection)"
5757+ v := e.eval(x.x, structKind|lambdaKind, msgType, x)
5858+5959+ if e.is(v, structKind|lambdaKind, "") {
6060+ n, _ := v.(scope).lookup(ctx, x.feature)
6161+ if n == nil {
6262+ field := ctx.labelStr(x.feature)
6363+ // m.foo undefined (type map[string]bool has no field or method foo)
6464+ return ctx.mkErr(x, "undefined field %q", field)
6565+ }
6666+ return n.evalPartial(ctx)
6767+ }
6868+ return e.err(&selectorExpr{x.baseValue, v, x.feature})
6969+}
7070+7171+func (x *indexExpr) evalPartial(ctx *context) (result evaluated) {
7272+ if ctx.trace {
7373+ defer uni(indent(ctx, "indexExpr", x))
7474+ defer func() { ctx.debugPrint("result:", result) }()
7575+ }
7676+7777+ e := newEval(ctx, true)
7878+7979+ const msgType = "invalid operation: %[5]s (type %[3]s does not support indexing)"
8080+ const msgIndexType = "invalid %[5]s index %[1]s (type %[3]s)"
8181+8282+ val := e.eval(x.x, listKind|structKind|stringKind|bytesKind, msgType, x)
8383+ k := val.kind()
8484+ index := e.eval(x.index, stringKind|intKind, msgIndexType, k)
8585+8686+ switch v := val.(type) {
8787+ case *structLit:
8888+ if e.is(index, stringKind, msgIndexType, k) {
8989+ s := index.strValue()
9090+ // TODO: must lookup
9191+ n, _ := v.lookup(ctx, ctx.strLabel(s))
9292+ if n == nil {
9393+ return ctx.mkErr(x, index, "undefined field %q", s)
9494+ }
9595+ return n
9696+ }
9797+ case atter:
9898+ if e.is(index, intKind, msgIndexType, k) {
9999+ i := index.(*numLit).intValue(ctx)
100100+ if i < 0 {
101101+ const msg = "invalid %[4]s index %[1]s (index must be non-negative)"
102102+ return e.mkErr(x.index, index, 0, k, msg)
103103+ }
104104+ return v.at(ctx, i)
105105+ }
106106+ }
107107+ return e.err(&indexExpr{x.baseValue, val, index})
108108+}
109109+110110+// Composit
111111+112112+func (x *sliceExpr) evalPartial(ctx *context) (result evaluated) {
113113+ if ctx.trace {
114114+ defer uni(indent(ctx, "sliceExpr", x))
115115+ defer func() { ctx.debugPrint("result:", result) }()
116116+ }
117117+118118+ e := newEval(ctx, true)
119119+ const msgType = "cannot slice %[2]s (type %[3]s)"
120120+ const msgInvalidIndex = "invalid slice index %[1]s (type %[3]s)"
121121+ val := e.eval(x.x, listKind|stringKind, msgType)
122122+ lo := e.evalAllowNil(x.lo, intKind, msgInvalidIndex)
123123+ hi := e.evalAllowNil(x.hi, intKind, msgInvalidIndex)
124124+ var low, high *numLit
125125+ if lo != nil && e.is(lo, intKind, msgInvalidIndex) {
126126+ low = lo.(*numLit)
127127+ }
128128+ if hi != nil && e.is(hi, intKind, msgInvalidIndex) {
129129+ high = hi.(*numLit)
130130+ }
131131+ if !e.hasErr() {
132132+ switch x := val.(type) {
133133+ case *list:
134134+ return x.slice(ctx, low, high)
135135+ case *stringLit:
136136+ return x.slice(ctx, low, high)
137137+ }
138138+ }
139139+ return e.err(&sliceExpr{x.baseValue, val, lo, hi})
140140+}
141141+142142+// TODO: make a callExpr a binary expression
143143+func (x *callExpr) evalPartial(ctx *context) (result evaluated) {
144144+ if ctx.trace {
145145+ defer uni(indent(ctx, "callExpr", x))
146146+ defer func() {
147147+ ctx.debugPrint("result:", result)
148148+ }()
149149+ }
150150+151151+ e := newEval(ctx, true)
152152+153153+ fn := e.eval(x.x, lambdaKind, "cannot call non-function %[1]s (type %[3]s)")
154154+ args := make([]evaluated, len(x.args))
155155+ for i, a := range x.args {
156156+ args[i] = e.evalPartial(a, typeKinds, "never triggers")
157157+ }
158158+ if !e.hasErr() {
159159+ // If we have a template expression, it is either already copied it as
160160+ // result of a references, or it is a literal, in which case it is
161161+ // trivially fully evaluated.
162162+ return fn.(caller).call(ctx, x, args...).evalPartial(ctx)
163163+ }
164164+ // Construct a simplified call for reporting purposes.
165165+ err := &callExpr{x.baseValue, fn, nil}
166166+ for _, a := range args {
167167+ err.args = append(err.args, a)
168168+ }
169169+ return e.err(err)
170170+}
171171+172172+func (x *rangeLit) evalPartial(ctx *context) (result evaluated) {
173173+ if ctx.trace {
174174+ defer uni(indent(ctx, "rangeLit", x))
175175+ defer func() { ctx.debugPrint("result:", result) }()
176176+ }
177177+ rngFrom := x.from.evalPartial(ctx)
178178+ rngTo := x.to.evalPartial(ctx)
179179+ // rngFrom := ctx.manifest(x.from)
180180+ // rngTo := ctx.manifest(x.to)
181181+ // kind := unifyType(rngFrom.kind(), rngTo.kind())
182182+ // TODO: sufficient to do just this?
183183+ kind, _ := matchBinOpKind(opLeq, rngFrom.kind(), rngTo.kind())
184184+ if kind&comparableKind == bottomKind {
185185+ return ctx.mkErr(x, "invalid range: must be defined for strings or numbers")
186186+ }
187187+ // Collapse evaluated nested ranges
188188+ if from, ok := rngFrom.(*rangeLit); ok {
189189+ rngFrom = from.from.(evaluated)
190190+ }
191191+ if to, ok := rngTo.(*rangeLit); ok {
192192+ rngTo = to.to.(evaluated)
193193+ }
194194+ rng := &rangeLit{x.baseValue, rngFrom, rngTo}
195195+ if !rngFrom.kind().isGround() || !rngTo.kind().isGround() {
196196+ return rng
197197+ }
198198+ // validate range
199199+ comp := binOp(ctx, x, opLeq, rngFrom, rngTo)
200200+ if isBottom(comp) {
201201+ return ctx.mkErr(comp, "invalid range")
202202+ }
203203+ if !comp.(*boolLit).b {
204204+ return ctx.mkErr(x, "for ranges from <= to, found %v > %v", rngFrom, rngTo)
205205+ }
206206+ if binOp(ctx, x, opEql, rngFrom, rngTo).(*boolLit).b {
207207+ return rngFrom
208208+ }
209209+ return rng
210210+}
211211+212212+func (x *interpolation) evalPartial(ctx *context) (result evaluated) {
213213+ if ctx.trace {
214214+ defer uni(indent(ctx, "interpolation", x))
215215+ defer func() { ctx.debugPrint("result:", result) }()
216216+ }
217217+ buf := bytes.Buffer{}
218218+ for _, v := range x.parts {
219219+ switch e := ctx.manifest(v).(type) {
220220+ case *bottom:
221221+ return e
222222+ case *stringLit, *numLit, *durationLit:
223223+ buf.WriteString(e.strValue())
224224+ default:
225225+ k := e.kind()
226226+ if k&stringableKind == bottomKind {
227227+ return ctx.mkErr(e, "expression in interpolation must evaluate to a number kind or string (found %v)", k)
228228+ }
229229+ if !k.isGround() {
230230+ return ctx.mkErr(e, codeIncomplete, "incomplete")
231231+ }
232232+ }
233233+ }
234234+ return &stringLit{x.baseValue, buf.String()}
235235+}
236236+237237+func (x *list) evalPartial(ctx *context) (result evaluated) {
238238+ if ctx.trace {
239239+ defer uni(indent(ctx, "list", x))
240240+ defer func() { ctx.debugPrint("result:", result) }()
241241+ }
242242+ n := x.len.evalPartial(ctx)
243243+ t := x.typ.evalPartial(ctx)
244244+ if err := firstBottom(n, t); err != nil {
245245+ return err
246246+ }
247247+ a := make([]value, len(x.a))
248248+ changed := false
249249+ for i, v := range x.a {
250250+ // TODO: don't evaluate now. List elements may refer to other list
251251+ // elements. Evaluating them here will cause a cycle evaluating the
252252+ // struct field.
253253+ e := v.evalPartial(ctx)
254254+ changed = changed || e != v
255255+ switch e.(type) {
256256+ case *bottom:
257257+ return e
258258+ case value:
259259+ a[i] = e
260260+ }
261261+ }
262262+ if !changed && n == x.len && t == x.typ {
263263+ return x
264264+ }
265265+ return &list{x.baseValue, a, t, n}
266266+}
267267+268268+func (x *structComprehension) evalPartial(ctx *context) evaluated {
269269+ obj := &structLit{baseValue: x.baseValue}
270270+ result := x.clauses.yield(ctx, func(k, v evaluated) *bottom {
271271+ if !k.kind().isAnyOf(stringKind) {
272272+ return ctx.mkErr(k, "key must be of type string")
273273+ }
274274+ if x.isTemplate {
275275+ if obj.template == nil {
276276+ obj.template = v
277277+ } else {
278278+ obj.template = mkBin(ctx, x.Pos(), opUnify, obj.template, v)
279279+ }
280280+ return nil
281281+ }
282282+ // TODO: improve big O
283283+ f := ctx.label(k.strValue(), true)
284284+ for i, a := range obj.arcs {
285285+ if a.feature == f {
286286+ obj.arcs[i].v = mkBin(ctx, x.Pos(), opUnify, a.v, v)
287287+ return nil
288288+ }
289289+ }
290290+ obj.arcs = append(obj.arcs, arc{feature: f, v: v})
291291+ return nil
292292+ })
293293+ switch {
294294+ case result == nil:
295295+ case isBottom(result):
296296+ return result
297297+ default:
298298+ panic("should not happen")
299299+ }
300300+ sort.Stable(obj)
301301+ return obj
302302+}
303303+304304+func (x *listComprehension) evalPartial(ctx *context) evaluated {
305305+ list := &list{baseValue: x.baseValue}
306306+ result := x.clauses.yield(ctx, func(k, v evaluated) *bottom {
307307+ if !k.kind().isAnyOf(intKind) {
308308+ return ctx.mkErr(k, "key must be of type int")
309309+ }
310310+ list.a = append(list.a, v.evalPartial(ctx))
311311+ return nil
312312+ })
313313+ switch {
314314+ case result == nil:
315315+ case isBottom(result):
316316+ return result
317317+ default:
318318+ panic("should not happen")
319319+ }
320320+ list.initLit()
321321+ return list
322322+}
323323+324324+func (x *feed) evalPartial(ctx *context) evaluated { return x }
325325+func (x *guard) evalPartial(ctx *context) evaluated { return x }
326326+func (x *yield) evalPartial(ctx *context) evaluated { return x }
327327+328328+func (x *structLit) evalPartial(ctx *context) (result evaluated) {
329329+ if ctx.trace {
330330+ defer uni(indent(ctx, "struct eval", x))
331331+ defer func() { ctx.debugPrint("result:", result) }()
332332+ }
333333+ x = ctx.deref(x).(*structLit)
334334+335335+ // TODO: Handle cycle?
336336+ return x
337337+}
338338+339339+func (x *disjunction) evalPartial(ctx *context) (result evaluated) {
340340+ if ctx.trace {
341341+ defer uni(indent(ctx, "disjunction", x))
342342+ defer func() { ctx.debugPrint("result:", result) }()
343343+ }
344344+345345+ dn := &disjunction{x.baseValue, make([]dValue, 0, len(x.values))}
346346+ changed := false
347347+ for _, v := range x.values {
348348+ n := v.val.evalPartial(ctx)
349349+ changed = changed || n != v.val
350350+ dn.add(ctx, n, v.ambiguous)
351351+ }
352352+ // TODO: move to evaluator
353353+ if !changed {
354354+ return x
355355+ }
356356+ return dn.simplify(ctx, x).(evaluated)
357357+}
358358+359359+func (x *disjunction) manifest(ctx *context) (result evaluated) {
360360+ switch len(x.values) {
361361+ case 0:
362362+ return x.simplify(ctx, x).(evaluated) // force error
363363+ case 1:
364364+ return x.values[0].val.(evaluated)
365365+ default:
366366+ for _, d := range x.values {
367367+ if validate(ctx, d.val) != nil {
368368+ continue
369369+ }
370370+ if d.ambiguous {
371371+ // better error
372372+ return ctx.mkErr(x, "ambiguous disjunction")
373373+ }
374374+ return d.val.(evaluated)
375375+ }
376376+ return ctx.mkErr(x, "empty disjunction after evaluation")
377377+ }
378378+}
379379+380380+func (x *binaryExpr) evalPartial(ctx *context) (result evaluated) {
381381+ if ctx.trace {
382382+ defer uni(indent(ctx, "binaryExpr", x))
383383+ defer func() { ctx.debugPrint("result:", result) }()
384384+ }
385385+ var left, right evaluated
386386+387387+ if x.op != opUnify {
388388+ left = ctx.manifest(x.left)
389389+ right = ctx.manifest(x.right)
390390+391391+ // TODO: allow comparing to a literal bottom only. Find something more
392392+ // principled perhaps. One should especially take care that two values
393393+ // evaluating to bottom don't evaluate to true. For now we check for
394394+ // bottom here and require that one of the values be a bottom literal.
395395+ if l, r := isBottom(x.left), isBottom(x.right); l || r {
396396+ leftBottom := isBottom(left)
397397+ rightBottom := isBottom(right)
398398+ switch x.op {
399399+ case opEql:
400400+ return &boolLit{x.baseValue, leftBottom == rightBottom}
401401+ case opNeq:
402402+ return &boolLit{x.baseValue, leftBottom != rightBottom}
403403+ }
404404+ }
405405+ } else {
406406+ left = x.left.evalPartial(ctx)
407407+ right = x.right.evalPartial(ctx)
408408+409409+ if err := cycleError(left); err != nil && right.kind().isAtom() {
410410+ return ctx.delayConstraint(right,
411411+ mkBin(ctx, x.Pos(), opUnify, x.left, right))
412412+ }
413413+ if err := cycleError(right); err != nil && left.kind().isAtom() {
414414+ return ctx.delayConstraint(left,
415415+ mkBin(ctx, x.Pos(), opUnify, left, x.right))
416416+ }
417417+418418+ // check if it is a cycle that can be unwrapped.
419419+ // If other value is a cycle or list, return the original forwarded,
420420+ // but ensure the value is not cached. Object/list error?
421421+ }
422422+ return binOp(ctx, x, x.op, left, right)
423423+}
424424+425425+func (x *unaryExpr) evalPartial(ctx *context) (result evaluated) {
426426+ if ctx.trace {
427427+ defer uni(indent(ctx, "unaryExpr", x))
428428+ defer func() { ctx.debugPrint("result:", result) }()
429429+ }
430430+431431+ return evalUnary(ctx, x, x.op, x.x)
432432+}
433433+434434+func evalUnary(ctx *context, src source, op op, x value) evaluated {
435435+ v := ctx.manifest(x)
436436+437437+ const numeric = numKind | durationKind
438438+ kind := v.kind()
439439+ switch op {
440440+ case opSub:
441441+ if kind&numeric == bottomKind {
442442+ return ctx.mkErr(src, "unary '-' requires numeric value, found %s", kind)
443443+ }
444444+ switch v := v.(type) {
445445+ case *numLit:
446446+ f := *v
447447+ f.v.Neg(&v.v)
448448+ return &f
449449+ case *durationLit:
450450+ d := *v
451451+ d.d = -d.d
452452+ return &d
453453+ }
454454+ fallthrough
455455+456456+ case opAdd:
457457+ if kind&numeric == bottomKind {
458458+ return ctx.mkErr(src, "unary '+' requires numeric value, found %s", kind)
459459+ }
460460+ if kind&^(numeric|nonGround|referenceKind) == bottomKind {
461461+ return v
462462+ }
463463+ switch v := v.(type) {
464464+ case *numLit, *durationLit:
465465+ return v
466466+ case *top:
467467+ return &basicType{v.baseValue, numeric | nonGround}
468468+ case *basicType:
469469+ return &basicType{v.baseValue, (v.k & numeric) | nonGround}
470470+ case *rangeLit:
471471+ from := evalUnary(ctx, src, op, v.from)
472472+ to := evalUnary(ctx, src, op, v.to)
473473+ return &rangeLit{src.base(), from, to}
474474+ }
475475+476476+ case opNot:
477477+ if kind&boolKind == bottomKind {
478478+ return ctx.mkErr(src, "unary '!' requires bool value, found %s", kind)
479479+ }
480480+ switch v := v.(type) {
481481+ case *top:
482482+ return &basicType{v.baseValue, boolKind | nonGround}
483483+ case *basicType:
484484+ return v
485485+ case *boolLit:
486486+ return &boolLit{src.base(), !v.b}
487487+ }
488488+ }
489489+ return ctx.mkErr(src, "invalid operand type %v for unary operator %v", v, op)
490490+}
+140
cue/evaluator.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+func (c *context) manifest(v value) evaluated {
1818+ evaluated := v.evalPartial(c)
1919+ for {
2020+ x, ok := evaluated.(*disjunction)
2121+ if !ok {
2222+ break
2323+ }
2424+ evaluated = x.manifest(c)
2525+ }
2626+ return evaluated
2727+}
2828+2929+type evaluator struct {
3030+ ctx *context
3131+ bottom []*bottom
3232+}
3333+3434+const (
3535+ // (fmt, evaluated, orig, gotKind, wantKind)
3636+ // "invalid [string index] -1 (index must be non-negative)"
3737+ // "invalid operation: %[1]s (type %[3] does not support indexing)"
3838+ // msgType = "invalid %s %s (must be type %s)"
3939+ msgGround = "invalid non-ground value %[1]s (must be concrete %[4]s)"
4040+)
4141+4242+func newEval(ctx *context, manifest bool) evaluator {
4343+ return evaluator{ctx: ctx}
4444+}
4545+4646+func (e *evaluator) hasErr() bool {
4747+ return len(e.bottom) > 0
4848+}
4949+5050+func (e *evaluator) mkErr(orig, eval value, code errCode, want kind, desc string, args ...interface{}) (err *bottom) {
5151+ args = append([]interface{}{
5252+ eval,
5353+ code,
5454+ desc, // format string
5555+ eval, // 1
5656+ orig, // 2
5757+ eval.kind(), // 3
5858+ want}, // 4
5959+ args...)
6060+ for i := 3; i < len(args); i++ {
6161+ switch v := args[i].(type) {
6262+ case value:
6363+ args[i] = debugStr(e.ctx, v)
6464+ }
6565+ }
6666+ err = e.ctx.mkErr(orig, args...)
6767+ // TODO: maybe replace with more specific type error.
6868+ for i, old := range e.bottom {
6969+ if old == eval {
7070+ e.bottom[i] = err
7171+ return err
7272+ }
7373+ }
7474+ e.bottom = append(e.bottom, err)
7575+ return err
7676+}
7777+7878+func (e *evaluator) eval(v value, want kind, desc string, extraArgs ...interface{}) evaluated {
7979+ eval := e.ctx.manifest(v)
8080+8181+ if isBottom(eval) {
8282+ e.bottom = append(e.bottom, eval.(*bottom))
8383+ return eval
8484+ }
8585+ got := eval.kind()
8686+ if got&want == bottomKind {
8787+ return e.mkErr(v, eval, codeTypeError, want, desc, extraArgs...)
8888+ }
8989+ if !got.isGround() {
9090+ return e.mkErr(v, eval, codeIncomplete, want, msgGround, extraArgs...)
9191+ }
9292+ return eval
9393+}
9494+9595+func (e *evaluator) evalPartial(v value, want kind, desc string, extraArgs ...interface{}) evaluated {
9696+ eval := v.evalPartial(e.ctx)
9797+ if isBottom(eval) {
9898+ // handle incomplete errors separately?
9999+ e.bottom = append(e.bottom, eval.(*bottom))
100100+ return eval
101101+ }
102102+ got := eval.kind()
103103+ if got&want == bottomKind {
104104+ return e.mkErr(v, eval, codeTypeError, want, desc, extraArgs...)
105105+ }
106106+ return eval
107107+}
108108+109109+func (e *evaluator) evalAllowNil(v value, want kind, desc string, extraArgs ...interface{}) evaluated {
110110+ if v == nil {
111111+ return nil
112112+ }
113113+ return e.eval(v, want, desc, extraArgs...)
114114+}
115115+116116+func (e *evaluator) is(v value, want kind, desc string, args ...interface{}) bool {
117117+ if isBottom(v) {
118118+ // Even though errors are ground, we treat them as not allowed.
119119+ return false
120120+ }
121121+ got := v.kind()
122122+ if got&want == bottomKind {
123123+ e.mkErr(v, v, codeTypeError, want, desc, args...)
124124+ return false
125125+ }
126126+ // groundness must already have been checked.
127127+ return true
128128+}
129129+130130+func (e *evaluator) err(v value) evaluated {
131131+ // if bottom is a fatal (not incomplete) error, return that.
132132+ // otherwise, try to extract a fatal error from the given value.
133133+ // otherwise return an incomplete error with the given value as offending.
134134+ for _, b := range e.bottom {
135135+ if b.code != codeIncomplete {
136136+ return b
137137+ }
138138+ }
139139+ return e.ctx.mkErr(v, codeIncomplete, e.bottom[0])
140140+}
+403
cue/export.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "strconv"
2020+ "strings"
2121+ "unicode/utf8"
2222+2323+ "cuelang.org/go/cue/ast"
2424+ "cuelang.org/go/cue/token"
2525+)
2626+2727+func export(ctx *context, v value) ast.Expr {
2828+ e := exporter{ctx}
2929+ return e.expr(v)
3030+}
3131+3232+type exporter struct {
3333+ ctx *context
3434+}
3535+3636+func (p *exporter) label(f label) *ast.Ident {
3737+ orig := p.ctx.labelStr(f)
3838+ str := strconv.Quote(orig)
3939+ if len(orig)+2 == len(str) {
4040+ str = str[1 : len(str)-1]
4141+ }
4242+ return &ast.Ident{Name: str}
4343+}
4444+4545+func (p *exporter) ident(str string) *ast.Ident {
4646+ return &ast.Ident{Name: str}
4747+}
4848+4949+func (p *exporter) clause(v value) (n ast.Clause, next yielder) {
5050+ switch x := v.(type) {
5151+ case *feed:
5252+ feed := &ast.ForClause{
5353+ Value: p.label(x.fn.params.arcs[1].feature),
5454+ Source: p.expr(x.source),
5555+ }
5656+ key := x.fn.params.arcs[0]
5757+ if p.ctx.labelStr(key.feature) != "_" {
5858+ feed.Key = p.label(key.feature)
5959+ }
6060+ return feed, x.fn.value.(yielder)
6161+6262+ case *guard:
6363+ return &ast.IfClause{Condition: p.expr(x.condition)}, x.value
6464+ }
6565+ panic(fmt.Sprintf("unsupported clause type %T", v))
6666+}
6767+6868+func (p *exporter) expr(v value) ast.Expr {
6969+ // TODO: also add position information.
7070+ switch x := v.(type) {
7171+ case *builtin:
7272+ return &ast.Ident{Name: x.Name}
7373+ case *nodeRef:
7474+ return nil
7575+ case *selectorExpr:
7676+ n := p.expr(x.x)
7777+ if n == nil {
7878+ return p.label(x.feature)
7979+ }
8080+ return &ast.SelectorExpr{X: n, Sel: p.label(x.feature)}
8181+ case *indexExpr:
8282+ return &ast.IndexExpr{X: p.expr(x.x), Index: p.expr(x.index)}
8383+ case *sliceExpr:
8484+ return &ast.SliceExpr{
8585+ X: p.expr(x.x),
8686+ Low: p.expr(x.lo),
8787+ High: p.expr(x.hi),
8888+ }
8989+ case *callExpr:
9090+ call := &ast.CallExpr{Fun: p.expr(x.x)}
9191+ for _, a := range x.args {
9292+ call.Args = append(call.Args, p.expr(a))
9393+ }
9494+ return call
9595+ case *unaryExpr:
9696+ return &ast.UnaryExpr{Op: opMap[x.op], X: p.expr(x.x)}
9797+ case *binaryExpr:
9898+ return &ast.BinaryExpr{
9999+ X: p.expr(x.left),
100100+ Op: opMap[x.op], Y: p.expr(x.right),
101101+ }
102102+ case *disjunction:
103103+ if len(x.values) == 1 {
104104+ return p.expr(x.values[0].val)
105105+ }
106106+ bin := &ast.BinaryExpr{
107107+ X: p.expr(x.values[0].val),
108108+ Op: token.DISJUNCTION,
109109+ Y: p.expr(x.values[1].val),
110110+ }
111111+ for _, v := range x.values[2:] {
112112+ bin = &ast.BinaryExpr{X: bin, Op: token.DISJUNCTION, Y: p.expr(v.val)}
113113+ }
114114+ return bin
115115+ // case *lambdaExpr:
116116+117117+ // p.debugStr(x.params.arcs)
118118+ // write(")->")
119119+ // p.debugStr(x.value)
120120+121121+ case *structLit:
122122+ obj := &ast.StructLit{}
123123+ if x.emit != nil {
124124+ obj.Elts = append(obj.Elts, &ast.EmitDecl{Expr: p.expr(x.emit)})
125125+ }
126126+ for _, a := range x.arcs {
127127+ obj.Elts = append(obj.Elts, &ast.Field{
128128+ Label: p.label(a.feature),
129129+ Value: p.expr(a.v),
130130+ })
131131+ }
132132+ return obj
133133+134134+ case *structComprehension:
135135+ var clauses []ast.Clause
136136+ for y, next := p.clause(x.clauses); ; y, next = p.clause(next) {
137137+ clauses = append(clauses, y)
138138+ if yield, ok := next.(*yield); ok {
139139+ return &ast.StructLit{Elts: []ast.Decl{
140140+ &ast.ComprehensionDecl{
141141+ Field: &ast.Field{
142142+ Label: p.expr(yield.key).(ast.Label),
143143+ Value: p.expr(yield.value),
144144+ },
145145+ Clauses: clauses,
146146+ },
147147+ }}
148148+ }
149149+ }
150150+151151+ case *listComprehension:
152152+ var clauses []ast.Clause
153153+ for y, next := p.clause(x.clauses); ; y, next = p.clause(next) {
154154+ clauses = append(clauses, y)
155155+ if yield, ok := next.(*yield); ok {
156156+ return &ast.ListComprehension{
157157+ Expr: p.expr(yield.value),
158158+ Clauses: clauses,
159159+ }
160160+ }
161161+ }
162162+163163+ case *nullLit:
164164+ return p.ident("null")
165165+166166+ case *boolLit:
167167+ return p.ident(fmt.Sprint(x.b))
168168+169169+ case *stringLit:
170170+ return &ast.BasicLit{
171171+ Kind: token.STRING,
172172+ Value: quote(x.str, '"'),
173173+ }
174174+175175+ case *bytesLit:
176176+ return &ast.BasicLit{
177177+ Kind: token.STRING,
178178+ Value: quote(string(x.b), '\''),
179179+ }
180180+181181+ case *numLit:
182182+ if x.k&intKind != 0 {
183183+ return &ast.BasicLit{
184184+ Kind: token.INT,
185185+ Value: x.v.Text('f'),
186186+ }
187187+ }
188188+ return &ast.BasicLit{
189189+ Kind: token.FLOAT,
190190+ Value: x.v.Text('g'),
191191+ }
192192+193193+ case *durationLit:
194194+ panic("unimplemented")
195195+196196+ case *rangeLit:
197197+ return &ast.BinaryExpr{
198198+ X: p.expr(x.from),
199199+ Op: token.RANGE,
200200+ Y: p.expr(x.to),
201201+ }
202202+203203+ case *interpolation:
204204+ t := &ast.Interpolation{}
205205+ multiline := false
206206+ // TODO: mark formatting in interpolation itself.
207207+ for i := 0; i < len(x.parts); i += 2 {
208208+ str := x.parts[i].(*stringLit).str
209209+ if strings.IndexByte(str, '\n') >= 0 {
210210+ multiline = true
211211+ break
212212+ }
213213+ }
214214+ quote := `"`
215215+ if multiline {
216216+ quote = `"""`
217217+ }
218218+ prefix := quote
219219+ suffix := `\(`
220220+ for i, e := range x.parts {
221221+ if i%2 == 1 {
222222+ t.Elts = append(t.Elts, p.expr(e))
223223+ } else {
224224+ buf := []byte(prefix)
225225+ if i == len(x.parts)-1 {
226226+ suffix = quote
227227+ }
228228+ str := e.(*stringLit).str
229229+ if multiline {
230230+ buf = appendEscapeMulti(buf, str, '"')
231231+ } else {
232232+ buf = appendEscaped(buf, str, '"', true)
233233+ }
234234+ buf = append(buf, suffix...)
235235+ t.Elts = append(t.Elts, &ast.BasicLit{
236236+ Kind: token.STRING,
237237+ Value: string(buf),
238238+ })
239239+ }
240240+ prefix = ")"
241241+ }
242242+ return t
243243+244244+ case *list:
245245+ list := &ast.ListLit{}
246246+ var expr ast.Expr = list
247247+ for _, e := range x.a {
248248+ list.Elts = append(list.Elts, p.expr(e))
249249+ }
250250+ max := maxNumRaw(x.len)
251251+ num, ok := max.(*numLit)
252252+ if !ok {
253253+ min := minNumRaw(x.len)
254254+ num, _ = min.(*numLit)
255255+ }
256256+ ln := 0
257257+ if num != nil {
258258+ x, _ := num.v.Int64()
259259+ ln = int(x)
260260+ }
261261+ if !ok || ln > len(x.a) {
262262+ list.Type = p.expr(x.typ)
263263+ if !isTop(max) && !isTop(x.typ) {
264264+ expr = &ast.BinaryExpr{
265265+ X: &ast.BinaryExpr{
266266+ X: p.expr(x.len),
267267+ Op: token.MUL,
268268+ Y: &ast.ListLit{Elts: []ast.Expr{
269269+ p.expr(x.typ),
270270+ }},
271271+ },
272272+ Op: token.UNIFY,
273273+ Y: list,
274274+ }
275275+276276+ }
277277+ }
278278+ return expr
279279+280280+ case *bottom:
281281+ err := &ast.BottomLit{}
282282+ comment := &ast.Comment{Text: "// " + x.msg}
283283+ err.AddComment(&ast.CommentGroup{
284284+ Line: true,
285285+ Position: 1,
286286+ List: []*ast.Comment{comment},
287287+ })
288288+ return err
289289+290290+ case *top:
291291+ return p.ident("_")
292292+293293+ case *basicType:
294294+ return p.ident(x.k.String())
295295+296296+ case *lambdaExpr:
297297+ return p.ident("TODO: LAMBDA")
298298+299299+ default:
300300+ panic(fmt.Sprintf("unimplemented type %T", x))
301301+ }
302302+}
303303+304304+// quote quotes the given string.
305305+func quote(str string, quote byte) string {
306306+ if strings.IndexByte(str, '\n') < 0 {
307307+ buf := []byte{quote}
308308+ buf = appendEscaped(buf, str, quote, true)
309309+ buf = append(buf, quote)
310310+ return string(buf)
311311+ }
312312+ buf := []byte{quote, quote, quote}
313313+ buf = append(buf, multiSep...)
314314+ buf = appendEscapeMulti(buf, str, quote)
315315+ buf = append(buf, quote, quote, quote)
316316+ return string(buf)
317317+}
318318+319319+// TODO: consider the best indent strategy.
320320+const multiSep = "\n "
321321+322322+func appendEscapeMulti(buf []byte, str string, quote byte) []byte {
323323+ // TODO(perf)
324324+ a := strings.Split(str, "\n")
325325+ for _, s := range a {
326326+ buf = appendEscaped(buf, s, quote, true)
327327+ buf = append(buf, multiSep...)
328328+ }
329329+ return buf
330330+}
331331+332332+const lowerhex = "0123456789abcdef"
333333+334334+func appendEscaped(buf []byte, s string, quote byte, graphicOnly bool) []byte {
335335+ for width := 0; len(s) > 0; s = s[width:] {
336336+ r := rune(s[0])
337337+ width = 1
338338+ if r >= utf8.RuneSelf {
339339+ r, width = utf8.DecodeRuneInString(s)
340340+ }
341341+ if width == 1 && r == utf8.RuneError {
342342+ buf = append(buf, `\x`...)
343343+ buf = append(buf, lowerhex[s[0]>>4])
344344+ buf = append(buf, lowerhex[s[0]&0xF])
345345+ continue
346346+ }
347347+ buf = appendEscapedRune(buf, r, quote, graphicOnly)
348348+ }
349349+ return buf
350350+}
351351+352352+func appendEscapedRune(buf []byte, r rune, quote byte, graphicOnly bool) []byte {
353353+ var runeTmp [utf8.UTFMax]byte
354354+ if r == rune(quote) || r == '\\' { // always backslashed
355355+ buf = append(buf, '\\')
356356+ buf = append(buf, byte(r))
357357+ return buf
358358+ }
359359+ // TODO(perf): IsGraphic calls IsPrint.
360360+ if strconv.IsPrint(r) || graphicOnly && strconv.IsGraphic(r) {
361361+ n := utf8.EncodeRune(runeTmp[:], r)
362362+ buf = append(buf, runeTmp[:n]...)
363363+ return buf
364364+ }
365365+ switch r {
366366+ case '\a':
367367+ buf = append(buf, `\a`...)
368368+ case '\b':
369369+ buf = append(buf, `\b`...)
370370+ case '\f':
371371+ buf = append(buf, `\f`...)
372372+ case '\n':
373373+ buf = append(buf, `\n`...)
374374+ case '\r':
375375+ buf = append(buf, `\r`...)
376376+ case '\t':
377377+ buf = append(buf, `\t`...)
378378+ case '\v':
379379+ buf = append(buf, `\v`...)
380380+ default:
381381+ switch {
382382+ case r < ' ':
383383+ // Invalid for strings, only bytes.
384384+ buf = append(buf, `\x`...)
385385+ buf = append(buf, lowerhex[byte(r)>>4])
386386+ buf = append(buf, lowerhex[byte(r)&0xF])
387387+ case r > utf8.MaxRune:
388388+ r = 0xFFFD
389389+ fallthrough
390390+ case r < 0x10000:
391391+ buf = append(buf, `\u`...)
392392+ for s := 12; s >= 0; s -= 4 {
393393+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
394394+ }
395395+ default:
396396+ buf = append(buf, `\U`...)
397397+ for s := 28; s >= 0; s -= 4 {
398398+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
399399+ }
400400+ }
401401+ }
402402+ return buf
403403+}
+188
cue/export_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+ "fmt"
2020+ "log"
2121+ "strings"
2222+ "testing"
2323+2424+ "cuelang.org/go/cue/format"
2525+)
2626+2727+func TestExport(t *testing.T) {
2828+ testCases := []struct {
2929+ raw bool
3030+ in, out string
3131+ }{{
3232+ in: `"hello"`,
3333+ out: `"hello"`,
3434+ }, {
3535+ in: `'hello'`,
3636+ out: `'hello'`,
3737+ }, {
3838+ in: `'hello\nworld'`,
3939+ out: "'''" +
4040+ multiSep + "hello" +
4141+ multiSep + "world" +
4242+ multiSep + "'''",
4343+ }, {
4444+ in: `"hello\nworld"`,
4545+ out: `"""` +
4646+ multiSep + "hello" +
4747+ multiSep + "world" +
4848+ multiSep + `"""`,
4949+ }, {
5050+ in: "{ a: 1, b: a + 2, c: null, d: true, e: _, f: string }",
5151+ out: unindent(`
5252+ {
5353+ a: 1
5454+ b: 3
5555+ c: null
5656+ d: true
5757+ e: _
5858+ f: string
5959+ }`),
6060+ }, {
6161+ in: `{ a: { b: 2.0, s: "abc" }, b: a.b, c: a.c, d: a["d"], e: a.t[2:3] }`,
6262+ out: unindent(`
6363+ {
6464+ a: {
6565+ b: 2.0
6666+ s: "abc"
6767+ }
6868+ b: 2.0
6969+ c: _|_ // undefined field "c"
7070+ d: _|_ // undefined field "d"
7171+ e: _|_ // undefined field "t"
7272+ }`),
7373+ }, {
7474+ in: `{
7575+ a: 5*[int]
7676+ a: [1, 2, ...]
7777+ b: 0..5*[int]
7878+ b: [1, 2, ...]
7979+ c: 3..5*[int]
8080+ c: [1, 2, ...]
8181+ d: 2.._*[int]
8282+ d: [1, 2, ...]
8383+ e: [...int]
8484+ e: [1, 2, ...]
8585+ f: [1, 2, ...]
8686+ }`,
8787+ out: unindent(`
8888+ {
8989+ a: 5*[int] & [1, 2, ...int]
9090+ b: 2..5*[int] & [1, 2, ...int]
9191+ c: 3..5*[int] & [1, 2, ...int]
9292+ d: [1, 2, ...int]
9393+ e: [1, 2, ...int]
9494+ f: [1, 2, ...]
9595+ }`),
9696+ }, {
9797+ in: `{
9898+ a: (0.._)*[int]
9999+ a: (0.._)*[...int]
100100+ }`,
101101+ out: unindent(`
102102+ {
103103+ a: [...int]
104104+ }`),
105105+ }, {
106106+ raw: true,
107107+ in: `{ a: { b: [] }, c: a.b, d: a["b"] }`,
108108+ out: unindent(`
109109+ {
110110+ a b: []
111111+ c: a.b
112112+ d: a["b"]
113113+ }`),
114114+ }, {
115115+ raw: true,
116116+ in: `{ a: "foo" | "bar" | string, b: a[2:3] }`,
117117+ out: unindent(`
118118+ {
119119+ a: "foo" | "bar" | string
120120+ b: a[2:3]
121121+ }`),
122122+ }, {
123123+ raw: true,
124124+ in: `{ a: [1, 2], b: { "\(k)": v for k, v in a if a > 1 } }`,
125125+ out: unindent(`
126126+ {
127127+ a: [1, 2]
128128+ b: {
129129+ "\(k)": v for k, v in a if a > 1
130130+ }
131131+ }`),
132132+ }, {
133133+ raw: true,
134134+ in: `{ a: [1, 2], b: [ v for k, v in a ] }`,
135135+ out: unindent(`
136136+ {
137137+ a: [1, 2]
138138+ b: [ v for k, v in a ]
139139+ }`),
140140+ }, {
141141+ raw: true,
142142+ in: `{ a: 0..10, b: "Count: \(a) times" }`,
143143+ out: unindent(`
144144+ {
145145+ a: 0..10
146146+ b: "Count: \(a) times"
147147+ }`),
148148+ }}
149149+ for _, tc := range testCases {
150150+ t.Run("", func(t *testing.T) {
151151+ body := fmt.Sprintf("Test: %s", tc.in)
152152+ ctx, obj := compileFile(t, body)
153153+ ctx.trace = *traceOn
154154+ var root value = obj
155155+ if !tc.raw {
156156+ root = testResolve(ctx, obj, evalFull)
157157+ }
158158+ t.Log(debugStr(ctx, root))
159159+160160+ n := root.(*structLit).arcs[0].v
161161+ v := newValueRoot(ctx, n)
162162+163163+ buf := &bytes.Buffer{}
164164+ err := format.Node(buf, export(ctx, v.eval(ctx)))
165165+ if err != nil {
166166+ log.Fatal(err)
167167+ }
168168+ if got := buf.String(); got != tc.out {
169169+ t.Errorf("\ngot %v;\nwant %v", got, tc.out)
170170+ }
171171+ })
172172+ }
173173+}
174174+175175+func unindent(s string) string {
176176+ lines := strings.Split(s, "\n")[1:]
177177+ ws := lines[0][:len(lines[0])-len(strings.TrimLeft(lines[0], " \t"))]
178178+ for i, s := range lines {
179179+ if s == "" {
180180+ continue
181181+ }
182182+ if !strings.HasPrefix(s, ws) {
183183+ panic("invalid indentation")
184184+ }
185185+ lines[i] = lines[i][len(ws):]
186186+ }
187187+ return strings.Join(lines, "\n")
188188+}
+251
cue/instance.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "cuelang.org/go/cue/ast"
1919+ "cuelang.org/go/cue/build"
2020+ "cuelang.org/go/cue/token"
2121+ "cuelang.org/go/internal"
2222+)
2323+2424+// An Instance defines a single configuration based on a collection of
2525+// underlying CUE files.
2626+type Instance struct {
2727+ *index
2828+2929+ rootStruct *structLit // the struct to insert root values into
3030+ rootValue value // the value to evaluate: may add comprehensions
3131+3232+ // scope is used as an additional top-level scope between the package scope
3333+ // and the predeclared identifiers.
3434+ scope *structLit
3535+3636+ ImportPath string
3737+ Dir string
3838+ Name string
3939+4040+ Incomplete bool // true if Pkg and all its dependencies are free of errors
4141+ Err error // non-nil if the package had errors
4242+4343+ inst *build.Instance
4444+4545+ complete bool // for cycle detection
4646+}
4747+4848+// NewInstance creates a new instance. Use Insert to populate the instance.
4949+func (x *index) NewInstance(p *build.Instance) *Instance {
5050+ st := &structLit{baseValue: baseValue{nil}}
5151+ i := &Instance{
5252+ index: x,
5353+ rootStruct: st,
5454+ rootValue: st,
5555+ inst: p,
5656+ }
5757+ if p != nil {
5858+ i.ImportPath = p.ImportPath
5959+ i.Dir = p.Dir
6060+ i.Name = p.PkgName
6161+ if p.Err != nil {
6262+ i.setError(p.Err)
6363+ }
6464+ }
6565+ return i
6666+}
6767+6868+func (inst *Instance) setError(err error) {
6969+ inst.Err = err
7070+ inst.Incomplete = true
7171+}
7272+7373+func (inst *Instance) eval(ctx *context) evaluated {
7474+ v := ctx.manifest(inst.rootValue)
7575+ if s, ok := v.(*structLit); ok && s.emit != nil {
7676+ v = ctx.manifest(s.emit)
7777+ }
7878+ // manifest to benefit from validation step.
7979+ // TODO: consider not doing manifest.
8080+ return ctx.manifest(v)
8181+}
8282+8383+func init() {
8484+ internal.EvalExpr = func(value, expr interface{}) interface{} {
8585+ v := value.(Value)
8686+ e := expr.(ast.Expr)
8787+ ctx := v.idx.newContext()
8888+ return newValueRoot(ctx, evalExpr(v.idx, v.eval(ctx), e))
8989+ }
9090+}
9191+9292+func evalExpr(idx *index, x value, expr ast.Expr) evaluated {
9393+ if isBottom(x) {
9494+ return idx.mkErr(x, "error evaluating instance: %v", x)
9595+ }
9696+ obj, ok := x.(*structLit)
9797+ if !ok {
9898+ return idx.mkErr(obj, "instance is not a struct")
9999+ }
100100+101101+ v := newVisitor(idx, nil, nil, obj)
102102+ return eval(idx, v.walk(expr))
103103+}
104104+105105+func (inst *Instance) evalExpr(ctx *context, expr ast.Expr) evaluated {
106106+ root := inst.eval(ctx)
107107+ if isBottom(root) {
108108+ return ctx.mkErr(root, "error evaluating instance")
109109+ }
110110+ obj, ok := root.(*structLit)
111111+ if !ok {
112112+ return ctx.mkErr(obj, "instance is not a struct")
113113+ }
114114+ v := newVisitor(ctx.index, inst.inst, nil, obj)
115115+ return v.walk(expr).evalPartial(ctx)
116116+}
117117+118118+// Value returns the root value of the configuration. If the configuration
119119+// defines in emit value, it will be that value. Otherwise it will be all
120120+// top-level values.
121121+func (inst *Instance) Value() Value {
122122+ ctx := inst.newContext()
123123+ return newValueRoot(ctx, inst.eval(ctx))
124124+}
125125+126126+// Eval evaluates an expression within an existing instance.
127127+//
128128+// Expressions may refer to builtin packages if they can be uniquely identified.
129129+func (inst *Instance) Eval(expr ast.Expr) Value {
130130+ ctx := inst.newContext()
131131+ result := inst.evalExpr(ctx, expr)
132132+ return newValueRoot(ctx, result)
133133+}
134134+135135+// Merge unifies the given instances into a single one.
136136+//
137137+// Errors regarding conflicts are included in the result, but not reported, so
138138+// that these will only surface during manifestation. This allows
139139+func Merge(inst ...*Instance) *Instance {
140140+ switch len(inst) {
141141+ case 0:
142142+ return nil
143143+ case 1:
144144+ return inst[0]
145145+ }
146146+147147+ for _, i := range inst {
148148+ if i.Err != nil {
149149+ return i
150150+ }
151151+ }
152152+153153+ ctx := inst[0].newContext()
154154+155155+ merged := stripTemplates(ctx, inst[0].rootValue)
156156+157157+ for _, i := range inst[1:] {
158158+ x := stripTemplates(ctx, i.rootValue)
159159+ merged = mkBin(ctx, token.NoPos, opUnify, merged, x)
160160+ }
161161+162162+ st, ok := ctx.manifest(merged).(*structLit)
163163+ if !ok {
164164+ return nil
165165+ }
166166+167167+ p := &Instance{
168168+ rootStruct: st,
169169+ rootValue: merged,
170170+ index: ctx.index,
171171+ complete: true,
172172+ }
173173+ return p
174174+}
175175+176176+// Build creates a new instance from the build instances, allowing unbound
177177+// identifier to bind to the top-level field in inst. The top-level fields in
178178+// inst take precedence over predeclared identifier and builtin functions.
179179+func (inst *Instance) Build(p *build.Instance) *Instance {
180180+ p.Complete()
181181+182182+ idx := inst.index
183183+184184+ i := idx.NewInstance(p)
185185+ if i.Err != nil {
186186+ return i
187187+ }
188188+189189+ ctx := inst.newContext()
190190+ v, err := newValueRoot(ctx, inst.rootValue).structVal(ctx)
191191+ if err != nil {
192192+ i.setError(err)
193193+ return i
194194+ }
195195+ i.scope = v.n
196196+197197+ i.Err = resolveFiles(idx, p)
198198+ for _, f := range p.Files {
199199+ i.insertFile(f)
200200+ }
201201+ i.complete = true
202202+203203+ return i
204204+}
205205+206206+// Lookup reports the value starting from the top level struct (not the emitted
207207+// value), or an error if the path is not found.
208208+// The empty path returns the top-level configuration struct, regardless of
209209+// whether an emit value was specified.
210210+func (inst *Instance) Lookup(path ...string) Value {
211211+ idx := inst.index
212212+ ctx := idx.newContext()
213213+ v := newValueRoot(ctx, inst.rootValue)
214214+ for _, k := range path {
215215+ obj, err := v.structVal(ctx)
216216+ if err != nil {
217217+ v := err.(*bottom)
218218+ return Value{idx, &valueData{v: v, raw: v}}
219219+ }
220220+ v = obj.Lookup(k)
221221+ }
222222+ return v
223223+}
224224+225225+// Fill creates a new instance with the values of the old instance unified with
226226+// the given value. It is not possible to update the emit value.
227227+func (inst *Instance) Fill(x interface{}, path ...string) (*Instance, error) {
228228+ ctx := inst.newContext()
229229+ root := ctx.manifest(inst.rootValue)
230230+ for i := len(path) - 1; i >= 0; i-- {
231231+ x = map[string]interface{}{path[i]: x}
232232+ }
233233+ value := convert(ctx, root, x)
234234+ eval := binOp(ctx, baseValue{}, opUnify, root, value)
235235+ // TODO: validate recursively?
236236+ st := eval.(*structLit)
237237+ inst = &Instance{
238238+ rootStruct: st,
239239+ rootValue: st,
240240+ index: inst.index,
241241+ inst: nil,
242242+243243+ ImportPath: inst.ImportPath,
244244+ Name: inst.Name,
245245+ Incomplete: inst.Incomplete,
246246+ Err: inst.Err,
247247+248248+ complete: true,
249249+ }
250250+ return inst, nil
251251+}
+148
cue/instance_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "strings"
1919+ "testing"
2020+2121+ "cuelang.org/go/cue/build"
2222+)
2323+2424+func toString(t *testing.T, v Value) string {
2525+ t.Helper()
2626+2727+ b, err := v.MarshalJSON()
2828+ if err != nil {
2929+ t.Fatal(err)
3030+ }
3131+3232+ return strings.Replace(string(b), `"`, "", -1)
3333+}
3434+3535+func TestMerge(t *testing.T) {
3636+ insts := func(s ...string) []string { return s }
3737+ testCases := []struct {
3838+ desc string
3939+ instances []string
4040+ out string
4141+ isErr bool
4242+ }{{
4343+ desc: "single",
4444+ instances: insts(`a: 1, b: 2`),
4545+ out: `{a:1,b:2}`,
4646+ }, {
4747+ desc: "multiple",
4848+ instances: insts(
4949+ `a: 1`,
5050+ `b: 2`,
5151+ `a: int`,
5252+ ),
5353+ out: `{a:1,b:2}`,
5454+ }, {
5555+ desc: "templates",
5656+ instances: insts(`
5757+ obj <X>: { a: "A" }
5858+ obj alpha: { b: 2 }
5959+ `,
6060+ `
6161+ obj <X>: { a: "B" }
6262+ obj beta: { b: 3 }
6363+ `,
6464+ ),
6565+ out: `{obj:{alpha:{a:A,b:2},beta:{a:B,b:3}}}`,
6666+ }, {
6767+ // Structs that are shared in templates may have conflicting results.
6868+ // However, this is not an issue as long as these value are not
6969+ // referenced during evaluation. For generating JSON this is not an
7070+ // issue as such fields are typically hidden.
7171+ desc: "shared struct",
7272+ instances: insts(`
7373+ _shared: { a: "A" }
7474+ obj <X>: _shared & {}
7575+ obj alpha: { b: 2 }
7676+ `,
7777+ `
7878+ _shared: { a: "B" }
7979+ obj <X>: _shared & {}
8080+ obj beta: { b: 3 }
8181+ `,
8282+ ),
8383+ out: `{obj:{alpha:{a:A,b:2},beta:{a:B,b:3}}}`,
8484+ }, {
8585+ desc: "error",
8686+ instances: insts(`a:`),
8787+ out: `{}`,
8888+ isErr: true,
8989+ }}
9090+9191+ for _, tc := range testCases {
9292+ t.Run(tc.desc, func(t *testing.T) {
9393+ ctx := build.NewContext()
9494+ in := []*build.Instance{}
9595+ for _, str := range tc.instances {
9696+ bi := ctx.NewInstance("dir", nil) // no packages
9797+ bi.AddFile("file", str)
9898+ in = append(in, bi)
9999+ }
100100+ merged := Merge(Build(in)...)
101101+ if err := merged.Err; err != nil {
102102+ if !tc.isErr {
103103+ t.Fatal(err)
104104+ }
105105+ }
106106+107107+ if got := toString(t, merged.Value()); got != tc.out {
108108+ t.Errorf("\n got: %s\nwant: %s", got, tc.out)
109109+ }
110110+ })
111111+ }
112112+}
113113+114114+func TestInstance_Build(t *testing.T) {
115115+ testCases := []struct {
116116+ desc string
117117+ instance string
118118+ overlay string
119119+ out string
120120+ }{{
121121+ desc: "single",
122122+ instance: `a: {b: 1, c: 2}`,
123123+ overlay: `res: a`,
124124+ out: `{res:{b:1,c:2}}`,
125125+ }}
126126+127127+ for _, tc := range testCases {
128128+ t.Run(tc.desc, func(t *testing.T) {
129129+ ctx := build.NewContext()
130130+131131+ bi := ctx.NewInstance("main", nil) // no packages
132132+ bi.AddFile("file", tc.instance)
133133+ main := Build([]*build.Instance{bi})
134134+ if err := main[0].Err; err != nil {
135135+ t.Fatal(err)
136136+ }
137137+138138+ bi = ctx.NewInstance("overlay", nil) // no packages
139139+ bi.AddFile("file", tc.overlay)
140140+141141+ overlay := main[0].Build(bi)
142142+143143+ if got := toString(t, overlay.Value()); got != tc.out {
144144+ t.Errorf("\n got: %s\nwant: %s", got, tc.out)
145145+ }
146146+ })
147147+ }
148148+}
+281
cue/kind.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+2020+ "cuelang.org/go/cue/token"
2121+)
2222+2323+func unifyType(a, b kind) kind {
2424+ const mask = topKind
2525+ isRef := (a &^ mask) | (b &^ mask)
2626+ return isRef | (a & b)
2727+}
2828+2929+type kind uint16
3030+3131+const (
3232+ unknownKind kind = (1 << iota)
3333+ nullKind
3434+ boolKind
3535+ intKind
3636+ floatKind
3737+ stringKind
3838+ bytesKind
3939+ durationKind
4040+ listKind
4141+ structKind
4242+4343+ lambdaKind
4444+ // customKind
4545+4646+ // nonGround means that a value is not specific enough to be emitted.
4747+ // Structs and lists are indicated as ground even when their values are not.
4848+ nonGround
4949+5050+ // TODO: distinguish beteween nonGround and disjunctions?
5151+5252+ // a referenceKind is typically top and nonGround, but is indicated with an
5353+ // additional bit. If reference is set and nonGround is not, it is possible
5454+ // to move the reference to an assertion clause.
5555+ referenceKind
5656+5757+ atomKind = (listKind - 1)
5858+ concreteKind = (lambdaKind - 1)
5959+6060+ // doneKind indicates a value can not further develop on its own (i.e. not a
6161+ // reference). If doneKind is not set, but the result is ground, it
6262+ // typically possible to hoist the reference out of a unification operation.
6363+6464+ // For rational numbers, typically both intKind and floatKind are set,
6565+ // unless the range is restricted by a root type.
6666+ numKind = intKind | floatKind
6767+6868+ comparableKind = listKind - 1
6969+ stringableKind = scalarKinds | stringKind
7070+ topKind = (referenceKind - 1) // all kinds, but not references
7171+ typeKinds = nonGround - 1
7272+ okKinds = typeKinds &^ bottomKind
7373+ fixedKinds = okKinds &^ (structKind | lambdaKind)
7474+ scalarKinds = numKind | durationKind
7575+7676+ bottomKind = 0
7777+)
7878+7979+func isTop(v value) bool {
8080+ return v.kind() == topKind
8181+}
8282+8383+// isDone means that the value will not evaluate further.
8484+func (k kind) isDone() bool { return k&referenceKind == bottomKind }
8585+func (k kind) hasReferences() bool { return k&referenceKind != bottomKind }
8686+func (k kind) isGround() bool { return k&nonGround == bottomKind }
8787+func (k kind) isAtom() bool { return k.isGround() && k&atomKind != bottomKind }
8888+func (k kind) isAnyOf(of kind) bool {
8989+ return k&of != bottomKind
9090+}
9191+func (k kind) stringable() bool {
9292+ return k.isGround() && k&stringKind|scalarKinds != bottomKind
9393+}
9494+9595+func (k kind) String() string {
9696+ str := ""
9797+ if k&topKind == topKind {
9898+ str = "_"
9999+ goto finalize
100100+ }
101101+ for i := kind(1); i < referenceKind; i <<= 1 {
102102+ t := ""
103103+ switch k & i {
104104+ case bottomKind:
105105+ continue
106106+ case nullKind:
107107+ t = "null"
108108+ case boolKind:
109109+ t = "bool"
110110+ case intKind:
111111+ if k&floatKind != 0 {
112112+ t = "number"
113113+ } else {
114114+ t = "int"
115115+ }
116116+ case floatKind:
117117+ if k&intKind != 0 {
118118+ continue
119119+ }
120120+ t = "float"
121121+ case stringKind:
122122+ t = "string"
123123+ case bytesKind:
124124+ t = "bytes"
125125+ case durationKind:
126126+ t = "duration"
127127+ case listKind:
128128+ t = "list"
129129+ case structKind:
130130+ t = "struct"
131131+ case lambdaKind:
132132+ t = "lambda"
133133+ case nonGround, referenceKind:
134134+ continue
135135+ default:
136136+ t = fmt.Sprintf("<unknown> %x", int(i))
137137+ }
138138+ if str != "" {
139139+ str += "|"
140140+ }
141141+ str += t
142142+ }
143143+finalize:
144144+ if str == "" {
145145+ return "_|_"
146146+ }
147147+ if k&nonGround != 0 {
148148+ str = "(" + str + ")*"
149149+ }
150150+ if k&referenceKind != 0 {
151151+ str = "&" + str
152152+ }
153153+ return str
154154+}
155155+156156+type kindInfo struct {
157157+ kind
158158+ subsumes []*kindInfo
159159+ subsumedBy []*kindInfo
160160+ unary []token.Token
161161+ binary []token.Token
162162+}
163163+164164+var toKindInfo = map[kind]*kindInfo{}
165165+166166+// matchBinOpKind reports whether the given op is possible for the given kinds
167167+// and what the result will be. Evaluating binary expressions uses this to
168168+// - fail incompatible operations early, even if the concrete types are
169169+// not known,
170170+// - check the result type of unification,
171171+//
172172+// Secondary goals:
173173+// - keep type compatibility mapped at a central place
174174+// - reduce the amount op type switching.
175175+// - simplifies testing
176176+func matchBinOpKind(op op, a, b kind) (k kind, invert bool) {
177177+ if op == opDisjunction {
178178+ return a | b, false
179179+ }
180180+ u := unifyType(a, b)
181181+ valBits := u & typeKinds
182182+ catBits := u &^ typeKinds
183183+ a = a & typeKinds
184184+ b = b & typeKinds
185185+ if valBits == bottomKind {
186186+ if op == opEql || op == opNeq {
187187+ return bottomKind, false
188188+ }
189189+ if a.isAnyOf(listKind) && b.isAnyOf(intKind) {
190190+ return a, false
191191+ }
192192+ if b.isAnyOf(listKind) && a.isAnyOf(intKind) {
193193+ return b, true
194194+ }
195195+ // non-overlapping types
196196+ if a&scalarKinds == 0 || b&scalarKinds == 0 {
197197+ return bottomKind, false
198198+ }
199199+ // a and b have different numeric types.
200200+ switch {
201201+ case b.isAnyOf(durationKind):
202202+ // a must be a numeric, non-duration type.
203203+ if op == opMul {
204204+ return durationKind | catBits, true
205205+ }
206206+ case a.isAnyOf(durationKind):
207207+ if opIn(op, opMul, opQuo, opRem) {
208208+ return durationKind | catBits, false
209209+ }
210210+ case op.isCmp():
211211+ return boolKind, false
212212+ case op.allowImplicitNumCast():
213213+ if a.isAnyOf(intKind) ||
214214+ (a.isAnyOf(floatKind) && !b.isAnyOf(intKind)) {
215215+ return b | catBits, false
216216+ }
217217+ return a | catBits, false
218218+ }
219219+ return bottomKind, false
220220+ }
221221+ switch {
222222+ case a&nonGround == 0 && b&nonGround == 0:
223223+ // both ground values: nothing to do
224224+225225+ case op != opUnify && op != opLand && op != opLor:
226226+227227+ default:
228228+ invert = a&nonGround == 0 && b&nonGround != 0
229229+ }
230230+ // a and b have overlapping types.
231231+ switch op {
232232+ case opUnify:
233233+ // Increase likelihood of unification succeeding on first try.
234234+ return u, invert
235235+236236+ case opLand, opLor:
237237+ if u.isAnyOf(boolKind) {
238238+ return boolKind | catBits, invert
239239+ }
240240+ case opEql, opNeq:
241241+ if u.isAnyOf(fixedKinds) {
242242+ return boolKind | catBits, false
243243+ }
244244+ case opLss, opLeq, opGeq, opGtr:
245245+ if u.isAnyOf(fixedKinds) {
246246+ return boolKind | catBits, false
247247+ }
248248+ case opAdd:
249249+ if u.isAnyOf(atomKind) {
250250+ return u&(atomKind) | catBits, false
251251+ // u&(durationKind|intKind)
252252+ }
253253+ case opSub:
254254+ if u.isAnyOf(scalarKinds) {
255255+ return u&scalarKinds | catBits, false
256256+ }
257257+ case opRem:
258258+ if u.isAnyOf(durationKind | intKind) {
259259+ return u&(durationKind|intKind) | catBits, false
260260+ }
261261+ case opQuo:
262262+ if u.isAnyOf(durationKind | numKind) {
263263+ return floatKind | catBits, false
264264+ }
265265+ case opIRem, opIMod:
266266+ if u.isAnyOf(intKind) {
267267+ return u&(intKind) | catBits, false
268268+ }
269269+ case opIQuo, opIDiv:
270270+ if u.isAnyOf(intKind) {
271271+ return intKind | catBits, false
272272+ }
273273+ case opMul:
274274+ if u.isAnyOf(numKind) {
275275+ return u&numKind | catBits, false
276276+ }
277277+ default:
278278+ panic("unimplemented")
279279+ }
280280+ return bottomKind, false
281281+}
+53
cue/kind_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "testing"
2020+)
2121+2222+func TestMatchBinOpKind(t *testing.T) {
2323+ testCases := []struct {
2424+ op op
2525+ a kind
2626+ b kind
2727+ want kind
2828+ }{{
2929+ op: opMul,
3030+ a: floatKind,
3131+ b: intKind,
3232+ want: floatKind,
3333+ }, {
3434+ op: opMul,
3535+ a: listKind,
3636+ b: intKind,
3737+ want: listKind,
3838+ }, {
3939+ op: opMul,
4040+ a: intKind,
4141+ b: listKind,
4242+ want: listKind,
4343+ }}
4444+ for _, tc := range testCases {
4545+ key := fmt.Sprintf("%s(%v, %v)", tc.op, tc.a, tc.b)
4646+ t.Run(key, func(t *testing.T) {
4747+ got, _ := matchBinOpKind(tc.op, tc.a, tc.b)
4848+ if got != tc.want {
4949+ t.Errorf("got %v, want %v", got, tc.want)
5050+ }
5151+ })
5252+ }
5353+}
+687
cue/lit.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "math/big"
1919+ "strings"
2020+ "unicode"
2121+ "unicode/utf8"
2222+2323+ "cuelang.org/go/cue/ast"
2424+ "cuelang.org/go/cue/errors"
2525+ "github.com/cockroachdb/apd"
2626+)
2727+2828+// errRange indicates that a value is out of range for the target type.
2929+var errRange = errors.New("value out of range")
3030+3131+// errSyntax indicates that a value does not have the right syntax for the
3232+// target type.
3333+var errSyntax = errors.New("invalid syntax")
3434+3535+var errInvalidString = errors.New("invalid string")
3636+3737+// Unquote interprets s as a single-quoted, double-quoted, or backquoted CUE
3838+// string literal, returning the string value that s quotes.
3939+func Unquote(s string) (string, error) {
4040+ quote, err := stringType(s)
4141+ if err != nil {
4242+ return "", err
4343+ }
4444+ prefix, err := wsPrefix(s, quote)
4545+ if err != nil {
4646+ return "", err
4747+ }
4848+ s = s[len(quote) : len(s)-len(quote)]
4949+ return unquote(quote[0], len(quote) == 3, true, prefix, s)
5050+}
5151+5252+// unquote interprets s as a CUE string, where quote identifies the string type:
5353+// s: Unicode string (normal double quoted strings)
5454+// b: Binary strings: allows escape sequences that may result in invalid
5555+// Unicode.
5656+// r: raw strings.
5757+//
5858+// quote indicates the quote used. This is relevant for raw strings, as they
5959+// may not contain the quoting character itself.
6060+func unquote(quote byte, multiline, first bool, wsPrefix, s string) (string, error) {
6161+ if quote == '`' {
6262+ if contains(s, quote) {
6363+ return "", errSyntax
6464+ }
6565+ if contains(s, '\r') {
6666+ // -1 because we know there is at least one \r to remove.
6767+ buf := make([]byte, 0, len(s)-1)
6868+ for i := 0; i < len(s); i++ {
6969+ if s[i] != '\r' {
7070+ buf = append(buf, s[i])
7171+ }
7272+ }
7373+ return string(buf), nil
7474+ }
7575+ return s, nil
7676+ }
7777+ if !multiline {
7878+ if contains(s, '\n') {
7979+ return "", errSyntax
8080+ }
8181+ // Is it trivial? Avoid allocation.
8282+ if !contains(s, '\\') && !contains(s, quote) {
8383+ return s, nil
8484+ }
8585+ }
8686+8787+ var runeTmp [utf8.UTFMax]byte
8888+ buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
8989+ for len(s) > 0 {
9090+ switch s[0] {
9191+ case '\r':
9292+ s = s[1:]
9393+ continue
9494+ case '\n':
9595+ switch {
9696+ case !multiline:
9797+ fallthrough
9898+ default:
9999+ return "", errSyntax
100100+ case strings.HasPrefix(s[1:], wsPrefix):
101101+ s = s[1+len(wsPrefix):]
102102+ case strings.HasPrefix(s[1:], "\n"):
103103+ s = s[1:]
104104+ }
105105+ if !first && len(s) > 0 {
106106+ buf = append(buf, '\n')
107107+ }
108108+ first = false
109109+ continue
110110+ }
111111+ c, multibyte, ss, err := unquoteChar(s, quote)
112112+ if err != nil {
113113+ return "", err
114114+ }
115115+ // TODO: handle surrogates: if we have a left-surrogate, expect the
116116+ // next value to be a right surrogate. Otherwise this is an error.
117117+ s = ss
118118+ if c < utf8.RuneSelf || !multibyte {
119119+ buf = append(buf, byte(c))
120120+ } else {
121121+ n := utf8.EncodeRune(runeTmp[:], c)
122122+ buf = append(buf, runeTmp[:n]...)
123123+ }
124124+ }
125125+ return string(buf), nil
126126+}
127127+128128+// contains reports whether the string contains the byte c.
129129+func contains(s string, c byte) bool {
130130+ for i := 0; i < len(s); i++ {
131131+ if s[i] == c {
132132+ return true
133133+ }
134134+ }
135135+ return false
136136+}
137137+138138+// unquoteChar decodes the first character or byte in the escaped string.
139139+// It returns four values:
140140+//
141141+// 1) value, the decoded Unicode code point or byte value;
142142+// 2) multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation;
143143+// 3) tail, the remainder of the string after the character; and
144144+// 4) an error that will be nil if the character is syntactically valid.
145145+//
146146+// The second argument, kind, specifies the type of literal being parsed
147147+// and therefore which kind of escape sequences are permitted.
148148+// For kind 's' only JSON escapes and \u{ are permitted.
149149+// For kind 'b' also hexadecimal and octal escape sequences are permitted.
150150+//
151151+// The third argument, quote, specifies that an ASCII quoting character that
152152+// is not permitted in the output.
153153+func unquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
154154+ // easy cases
155155+ switch c := s[0]; {
156156+ case c == quote && quote != 0:
157157+ err = errSyntax
158158+ return
159159+ case c >= utf8.RuneSelf:
160160+ r, size := utf8.DecodeRuneInString(s)
161161+ return r, true, s[size:], nil
162162+ case c != '\\':
163163+ return rune(s[0]), false, s[1:], nil
164164+ }
165165+166166+ // hard case: c is backslash
167167+ if len(s) <= 1 {
168168+ err = errSyntax
169169+ return
170170+ }
171171+ c := s[1]
172172+ s = s[2:]
173173+174174+ switch c {
175175+ case 'a':
176176+ value = '\a'
177177+ case 'b':
178178+ value = '\b'
179179+ case 'f':
180180+ value = '\f'
181181+ case 'n':
182182+ value = '\n'
183183+ case 'r':
184184+ value = '\r'
185185+ case 't':
186186+ value = '\t'
187187+ case 'v':
188188+ value = '\v'
189189+ case 'x', 'u', 'U':
190190+ n := 0
191191+ switch c {
192192+ case 'x':
193193+ n = 2
194194+ case 'u':
195195+ n = 4
196196+ case 'U':
197197+ n = 8
198198+ }
199199+ var v rune
200200+ if len(s) < n {
201201+ err = errSyntax
202202+ return
203203+ }
204204+ for j := 0; j < n; j++ {
205205+ x, ok := unhex(s[j])
206206+ if !ok {
207207+ err = errSyntax
208208+ return
209209+ }
210210+ v = v<<4 | x
211211+ }
212212+ s = s[n:]
213213+ if c == 'x' {
214214+ if quote == '"' {
215215+ err = errSyntax
216216+ return
217217+ }
218218+ // single-byte string, possibly not UTF-8
219219+ value = v
220220+ break
221221+ }
222222+ if v > utf8.MaxRune {
223223+ err = errSyntax
224224+ return
225225+ }
226226+ value = v
227227+ multibyte = true
228228+ case '0', '1', '2', '3', '4', '5', '6', '7':
229229+ if quote == '"' {
230230+ err = errSyntax
231231+ return
232232+ }
233233+ v := rune(c) - '0'
234234+ if len(s) < 2 {
235235+ err = errSyntax
236236+ return
237237+ }
238238+ for j := 0; j < 2; j++ { // one digit already; two more
239239+ x := rune(s[j]) - '0'
240240+ if x < 0 || x > 7 {
241241+ err = errSyntax
242242+ return
243243+ }
244244+ v = (v << 3) | x
245245+ }
246246+ s = s[2:]
247247+ if v > 255 {
248248+ err = errSyntax
249249+ return
250250+ }
251251+ value = v
252252+ case '\\':
253253+ value = '\\'
254254+ case '\'', '"':
255255+ // TODO: should we allow escaping of quotes regardless?
256256+ if c != quote {
257257+ err = errSyntax
258258+ return
259259+ }
260260+ value = rune(c)
261261+ default:
262262+ err = errSyntax
263263+ return
264264+ }
265265+ tail = s
266266+ return
267267+}
268268+269269+func unhex(b byte) (v rune, ok bool) {
270270+ c := rune(b)
271271+ switch {
272272+ case '0' <= c && c <= '9':
273273+ return c - '0', true
274274+ case 'a' <= c && c <= 'f':
275275+ return c - 'a' + 10, true
276276+ case 'A' <= c && c <= 'F':
277277+ return c - 'A' + 10, true
278278+ }
279279+ return
280280+}
281281+282282+type numInfo struct {
283283+ rep multiplier
284284+ k kind
285285+}
286286+287287+func newNumInfo(k kind, m multiplier, base int, sep bool) numInfo {
288288+ switch base {
289289+ case 10:
290290+ m |= base10
291291+ case 2:
292292+ m |= base2
293293+ k = intKind
294294+ case 8:
295295+ m |= base8
296296+ k = intKind
297297+ case 16:
298298+ m |= base16
299299+ k = intKind
300300+ }
301301+ if sep {
302302+ m |= hasSeparators
303303+ }
304304+ return numInfo{m, k}
305305+}
306306+307307+func unifyNuminfo(a, b numInfo) numInfo {
308308+ k := unifyType(a.k, b.k)
309309+ return numInfo{a.rep | b.rep, k}
310310+}
311311+312312+func (n numInfo) isValid() bool { return n.k != bottomKind }
313313+func (n numInfo) multiplier() multiplier { return n.rep & (hasSeparators - 1) }
314314+315315+type multiplier uint16
316316+317317+const (
318318+ mul1 multiplier = 1 << iota
319319+ mul2
320320+ mul3
321321+ mul4
322322+ mul5
323323+ mul6
324324+ mul7
325325+ mul8
326326+327327+ mulBin
328328+ mulDec
329329+330330+ // _ 3 for dec, 4 for hex. Maybe support first and rest, like CLDR.
331331+ hasSeparators
332332+333333+ base2
334334+ base8
335335+ base10
336336+ base16
337337+338338+ mulK = mulDec | mul1
339339+ mulM = mulDec | mul2
340340+ mulG = mulDec | mul3
341341+ mulT = mulDec | mul4
342342+ mulP = mulDec | mul5
343343+ mulE = mulDec | mul6
344344+ mulZ = mulDec | mul7
345345+ mulY = mulDec | mul8
346346+347347+ mulKi = mulBin | mul1
348348+ mulMi = mulBin | mul2
349349+ mulGi = mulBin | mul3
350350+ mulTi = mulBin | mul4
351351+ mulPi = mulBin | mul5
352352+ mulEi = mulBin | mul6
353353+ mulZi = mulBin | mul7
354354+ mulYi = mulBin | mul8
355355+)
356356+357357+type litParser struct {
358358+ ctx *context
359359+ node *ast.BasicLit
360360+ src string
361361+ p int
362362+ // pDot int // first position after the dot, if any
363363+ ch byte
364364+ useSep bool
365365+ buf []byte
366366+ err value
367367+}
368368+369369+func (p *litParser) error(l ast.Node, args ...interface{}) value {
370370+ return p.ctx.mkErr(newNode(l), args...)
371371+}
372372+373373+func (p *litParser) next() bool {
374374+ if p.p >= len(p.src) {
375375+ p.ch = 0
376376+ return false
377377+ }
378378+ p.ch = p.src[p.p]
379379+ p.p++
380380+ if p.ch == '.' {
381381+ p.buf = append(p.buf, '.')
382382+383383+ }
384384+ return true
385385+}
386386+387387+func (p *litParser) init(l *ast.BasicLit) (err value) {
388388+ s := l.Value
389389+ b := p.buf
390390+ *p = litParser{ctx: p.ctx, node: l, src: s}
391391+ p.buf = b[:0]
392392+ if !p.next() {
393393+ return p.error(l, "invalid literal %q", s)
394394+ }
395395+ return nil
396396+}
397397+398398+func (p *litParser) parse(l *ast.BasicLit) (n value) {
399399+ s := l.Value
400400+ switch s {
401401+ case "null":
402402+ return &nullLit{newExpr(l)}
403403+ case "true":
404404+ return &boolLit{newExpr(l), true}
405405+ case "false":
406406+ return &boolLit{newExpr(l), false}
407407+ }
408408+ if err := p.init(l); err != nil {
409409+ return err
410410+ }
411411+ switch p.ch {
412412+ case '"', '\'', '`':
413413+ quote, err := stringType(l.Value)
414414+ if err != nil {
415415+ return p.error(l, err.Error())
416416+ }
417417+ ws, err := wsPrefix(l.Value, quote)
418418+ if err != nil {
419419+ return p.error(l, err.Error())
420420+ }
421421+ return p.parseString(quote, quote, ws, len(quote) == 3, quote[0])
422422+ case '.':
423423+ p.next()
424424+ n = p.scanNumber(true)
425425+ default:
426426+ n = p.scanNumber(false)
427427+ }
428428+ if p.err != nil {
429429+ return p.err
430430+ }
431431+ if p.p < len(p.src) {
432432+ return p.error(l, "invalid number")
433433+ }
434434+ return n
435435+}
436436+437437+var (
438438+ errStringTooShort = errors.New("invalid string: too short")
439439+ errMissingNewline = errors.New(
440440+ "invalid string: opening quote of multiline string must be followed by newline")
441441+ errUnmatchedQuote = errors.New("invalid string: unmatched quote")
442442+)
443443+444444+// stringType reports the type of quoting used, being ther a ", ', """, or ''',
445445+// or `.
446446+func stringType(s string) (quote string, err error) {
447447+ if len(s) < 2 {
448448+ return "", errStringTooShort
449449+ }
450450+ switch s[0] {
451451+ case '"', '\'':
452452+ if len(s) > 3 && s[1] == s[0] && s[2] == s[0] {
453453+ if s[3] != '\n' {
454454+ return "", errMissingNewline
455455+ }
456456+ return s[:3], nil
457457+ }
458458+ case '`':
459459+ default:
460460+ return "", errSyntax
461461+ }
462462+ return s[:1], nil
463463+}
464464+465465+func wsPrefix(s, quote string) (ws string, err error) {
466466+ for i := 0; i < len(quote); i++ {
467467+ if j := len(s) - i - 1; j < 0 || quote[i] != s[j] {
468468+ return "", errUnmatchedQuote
469469+ }
470470+ }
471471+ i := len(s) - len(quote)
472472+ for i > 0 {
473473+ r, size := utf8.DecodeLastRuneInString(s[:i])
474474+ if r == '\n' || !unicode.IsSpace(r) {
475475+ break
476476+ }
477477+ i -= size
478478+ }
479479+ return s[i : len(s)-len(quote)], nil
480480+}
481481+482482+func (p *litParser) parseString(prefix, suffix, ws string, multi bool, quote byte) (n value) {
483483+ if len(p.src) < len(prefix)+len(suffix) {
484484+ return p.error(p.node, "invalid string: too short")
485485+ }
486486+ for _, r := range prefix {
487487+ if byte(r) != p.ch {
488488+ return p.error(p.node, "invalid interpolation: expected %q", prefix)
489489+ }
490490+ p.next()
491491+ }
492492+ if !strings.HasSuffix(p.src, suffix) {
493493+ return p.error(p.node, "invalid interpolation: unmatched ')'", suffix)
494494+ }
495495+ start, end := len(prefix), len(p.src)-len(suffix)
496496+ str, err := unquote(quote, multi, len(prefix) == 3, ws, p.src[start:end])
497497+ if err != nil {
498498+ return p.error(p.node, err, "invalid string: %v", err)
499499+ }
500500+ if quote == '"' {
501501+ return &stringLit{newExpr(p.node), str}
502502+ }
503503+ return &bytesLit{newExpr(p.node), []byte(str)}
504504+}
505505+506506+func (p *litParser) digitVal(ch byte) (d int) {
507507+ switch {
508508+ case '0' <= ch && ch <= '9':
509509+ d = int(ch - '0')
510510+ case ch == '_':
511511+ p.useSep = true
512512+ return 0
513513+ case 'a' <= ch && ch <= 'f':
514514+ d = int(ch - 'a' + 10)
515515+ case 'A' <= ch && ch <= 'F':
516516+ d = int(ch - 'A' + 10)
517517+ default:
518518+ return 16 // larger than any legal digit val
519519+ }
520520+ return d
521521+}
522522+523523+func (p *litParser) scanMantissa(base int) {
524524+ var last byte
525525+ for p.digitVal(p.ch) < base {
526526+ if p.ch != '_' {
527527+ p.buf = append(p.buf, p.ch)
528528+ }
529529+ last = p.ch
530530+ p.next()
531531+ }
532532+ if last == '_' {
533533+ p.err = p.error(p.node, "illegal '_' in number")
534534+ }
535535+}
536536+537537+func (p *litParser) scanNumber(seenDecimalPoint bool) value {
538538+ // digitVal(s.ch) < 10
539539+ isFloat := false
540540+ base := 10
541541+542542+ if seenDecimalPoint {
543543+ isFloat = true
544544+ p.scanMantissa(10)
545545+ goto exponent
546546+ }
547547+548548+ if p.ch == '0' {
549549+ // int or float
550550+ p.next()
551551+ if p.ch == 'x' || p.ch == 'X' {
552552+ base = 16
553553+ // hexadecimal int
554554+ p.next()
555555+ p.scanMantissa(16)
556556+ if p.p <= 2 {
557557+ // only scanned "0x" or "0X"
558558+ return p.error(p.node, "illegal hexadecimal number %q", p.src)
559559+ }
560560+ } else if p.ch == 'b' || p.ch == 'B' {
561561+ base = 2
562562+ // binary int
563563+ p.next()
564564+ p.scanMantissa(2)
565565+ if p.p <= 2 {
566566+ // only scanned "0b" or "0B"
567567+ return p.error(p.node, "illegal binary number %q", p.src)
568568+ }
569569+ } else {
570570+ base = 8
571571+ // octal int or float
572572+ seenDecimalDigit := false
573573+ p.scanMantissa(8)
574574+ if p.ch == '8' || p.ch == '9' {
575575+ // illegal octal int or float
576576+ seenDecimalDigit = true
577577+ p.scanMantissa(10)
578578+ }
579579+ // TODO: disallow complex
580580+ if p.ch == '.' || p.ch == 'e' {
581581+ goto fraction
582582+ }
583583+ // octal int
584584+ if seenDecimalDigit {
585585+ return p.error(p.node, "illegal octal number %q", p.src)
586586+ }
587587+ }
588588+ goto exit
589589+ }
590590+591591+ // decimal int or float
592592+ p.scanMantissa(10)
593593+594594+ // TODO: allow 3h4s, etc.
595595+ // switch p.ch {
596596+ // case 'h', 'm', 's', "µ"[0], 'u', 'n':
597597+ // }
598598+599599+fraction:
600600+ if p.ch == '.' {
601601+ isFloat = true
602602+ p.next()
603603+ p.scanMantissa(10)
604604+ }
605605+606606+exponent:
607607+ switch p.ch {
608608+ case 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y':
609609+ mul := charToMul[p.ch]
610610+ p.next()
611611+ if p.ch == 'i' {
612612+ mul |= mulBin
613613+ p.next()
614614+ } else {
615615+ mul |= mulDec
616616+ }
617617+ n := &numLit{
618618+ numBase: newNumBase(p.node, newNumInfo(numKind, mul, 10, p.useSep)),
619619+ }
620620+ n.v.UnmarshalText(p.buf)
621621+ p.ctx.Mul(&n.v, &n.v, mulToRat[mul])
622622+ cond, _ := p.ctx.RoundToIntegralExact(&n.v, &n.v)
623623+ if cond.Inexact() {
624624+ return p.error(p.node, "number cannot be represented as int")
625625+ }
626626+ return n
627627+628628+ case 'e':
629629+ isFloat = true
630630+ p.next()
631631+ p.buf = append(p.buf, 'e')
632632+ if p.ch == '-' || p.ch == '+' {
633633+ p.buf = append(p.buf, p.ch)
634634+ p.next()
635635+ }
636636+ p.scanMantissa(10)
637637+ }
638638+639639+exit:
640640+ if isFloat {
641641+ f := &numLit{
642642+ numBase: newNumBase(p.node, newNumInfo(floatKind, 0, 10, p.useSep)),
643643+ }
644644+ f.v.UnmarshalText(p.buf)
645645+ return f
646646+ }
647647+ i := &numLit{numBase: newNumBase(p.node, newNumInfo(numKind, 0, base, p.useSep))}
648648+ i.v.Coeff.SetString(string(p.buf), base)
649649+ return i
650650+}
651651+652652+type mulInfo struct {
653653+ fact *big.Rat
654654+ mul multiplier
655655+}
656656+657657+var charToMul = map[byte]multiplier{
658658+ 'K': mul1,
659659+ 'M': mul2,
660660+ 'G': mul3,
661661+ 'T': mul4,
662662+ 'P': mul5,
663663+ 'E': mul6,
664664+ 'Z': mul7,
665665+ 'Y': mul8,
666666+}
667667+668668+var mulToRat = map[multiplier]*apd.Decimal{}
669669+670670+func init() {
671671+ d := apd.New(1, 0)
672672+ b := apd.New(1, 0)
673673+ dm := apd.New(1000, 0)
674674+ bm := apd.New(1024, 0)
675675+676676+ c := apd.BaseContext
677677+ for i := uint(0); int(i) < len(charToMul); i++ {
678678+ // TODO: may we write to one of the sources?
679679+ var bn, dn apd.Decimal
680680+ c.Mul(&dn, d, dm)
681681+ d = &dn
682682+ c.Mul(&bn, b, bm)
683683+ b = &bn
684684+ mulToRat[mulDec|1<<i] = d
685685+ mulToRat[mulBin|1<<i] = b
686686+ }
687687+}
+228
cue/lit_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "math/big"
2020+ "testing"
2121+2222+ "cuelang.org/go/cue/ast"
2323+ "github.com/cockroachdb/apd"
2424+ "github.com/google/go-cmp/cmp"
2525+ "github.com/google/go-cmp/cmp/cmpopts"
2626+)
2727+2828+func TestUnquote(t *testing.T) {
2929+ testCases := []struct {
3030+ in, out string
3131+ err error
3232+ }{
3333+ {`"Hello"`, "Hello", nil},
3434+ {`'Hello'`, "Hello", nil},
3535+ {"`Hello`", "Hello", nil},
3636+ {`"""` + "\n\t\tHello\n\t\t" + `"""`, "Hello", nil},
3737+ {"'''\n\t\tHello\n\t\t'''", "Hello", nil},
3838+ {"'''\n\t\tHello\n\n\t\t'''", "Hello\n", nil},
3939+ {"'''\n\n\t\tHello\n\t\t'''", "\nHello", nil},
4040+ {"'''\n\n\n\n\t\t'''", "\n\n", nil},
4141+ {"'''\n\t\t'''", "", nil},
4242+ {"`\n\tHello`", "\n\tHello", nil},
4343+ {"`aaa\n\rbbb`", "aaa\nbbb", nil},
4444+ {`"""` + "\n\raaa\n\rbbb\n\r" + `"""`, "aaa\nbbb", nil},
4545+4646+ {"```", "", errSyntax},
4747+ {"Hello", "", errSyntax},
4848+ {`"Hello`, "", errUnmatchedQuote},
4949+ {`"""Hello"""`, "", errMissingNewline},
5050+ {`"Hello""`, "", errSyntax},
5151+ }
5252+ for _, tc := range testCases {
5353+ t.Run(tc.in, func(t *testing.T) {
5454+ if got, err := Unquote(tc.in); err != tc.err {
5555+ t.Errorf("error: got %q; want %q", err, tc.err)
5656+ } else if got != tc.out {
5757+ t.Errorf("value: got %q; want %q", got, tc.out)
5858+ }
5959+ })
6060+ }
6161+}
6262+6363+var defIntBase = newNumBase(&ast.BasicLit{}, newNumInfo(numKind, 0, 10, false))
6464+var defRatBase = newNumBase(&ast.BasicLit{}, newNumInfo(floatKind, 0, 10, false))
6565+6666+func mkInt(a int64) *numLit {
6767+ x := &numLit{numBase: defIntBase}
6868+ x.v.SetInt64(a)
6969+ return x
7070+}
7171+func mkIntString(a string) *numLit {
7272+ x := &numLit{numBase: defIntBase}
7373+ x.v.SetString(a)
7474+ return x
7575+}
7676+func mkFloat(a string) *numLit {
7777+ x := &numLit{numBase: defRatBase}
7878+ x.v.SetString(a)
7979+ return x
8080+}
8181+func mkBigInt(a int64) (v apd.Decimal) { v.SetInt64(a); return }
8282+8383+func mkBigFloat(a string) (v apd.Decimal) { v.SetString(a); return }
8484+8585+var diffOpts = []cmp.Option{
8686+ cmp.Comparer(func(x, y big.Rat) bool {
8787+ return x.String() == y.String()
8888+ }),
8989+ cmp.Comparer(func(x, y big.Int) bool {
9090+ return x.String() == y.String()
9191+ }),
9292+ cmp.AllowUnexported(
9393+ nullLit{},
9494+ boolLit{},
9595+ stringLit{},
9696+ bytesLit{},
9797+ numLit{},
9898+ numBase{},
9999+ numInfo{},
100100+ ),
101101+ cmpopts.IgnoreUnexported(
102102+ bottom{},
103103+ baseValue{},
104104+ baseValue{},
105105+ ),
106106+}
107107+108108+var (
109109+ nullSentinel = &nullLit{}
110110+ trueSentinel = &boolLit{b: true}
111111+ falseSentinel = &boolLit{b: false}
112112+)
113113+114114+func TestLiterals(t *testing.T) {
115115+ mkMul := func(x int64, m multiplier, base int) *numLit {
116116+ return &numLit{
117117+ newNumBase(&ast.BasicLit{}, newNumInfo(numKind, m, base, false)),
118118+ mkBigInt(x),
119119+ }
120120+ }
121121+ hk := &numLit{
122122+ newNumBase(&ast.BasicLit{}, newNumInfo(numKind, 0, 10, true)),
123123+ mkBigInt(100000),
124124+ }
125125+ testCases := []struct {
126126+ lit string
127127+ node value
128128+ }{
129129+ {"null", nullSentinel},
130130+ {"true", trueSentinel},
131131+ {"false", falseSentinel},
132132+ {"fls", &bottom{}},
133133+ {`"foo"`, &stringLit{str: "foo"}},
134134+ {`"\"foo\""`, &stringLit{str: `"foo"`}},
135135+ {`"foo\u0032"`, &stringLit{str: `foo2`}},
136136+ {`"foo\U00000033"`, &stringLit{str: `foo3`}},
137137+ {`"foo\U0001f499"`, &stringLit{str: `foo💙`}},
138138+ {`"\a\b\f\n\r\t\v"`, &stringLit{str: "\a\b\f\n\r\t\v"}},
139139+ {`"""
140140+ """`, &stringLit{str: ""}},
141141+ {`"""
142142+ abc
143143+ """`, &stringLit{str: "abc"}},
144144+ {`"""
145145+ abc
146146+ def
147147+ """`, &stringLit{str: "abc\ndef"}},
148148+ {`"""
149149+ abc
150150+ def
151151+ """`, &stringLit{str: "abc\n\tdef"}},
152152+ {`'\xff'`, &bytesLit{b: []byte("\xff")}},
153153+ {"1", mkInt(1)},
154154+ {"100_000", hk},
155155+ {"1.", mkFloat("1")},
156156+ {".0", mkFloat(".0")},
157157+ {"1K", mkMul(1000, mulK, 10)},
158158+ {"1Mi", mkMul(1024*1024, mulMi, 10)},
159159+ {"1.5Mi", mkMul((1024+512)*1024, mulMi, 10)},
160160+ {"1.3Mi", &bottom{}}, // Cannot be accurately represented.
161161+ {"1.3G", mkMul(1300000000, mulG, 10)},
162162+ {"1.3e+20", mkFloat("1.3e+20")},
163163+ {"1.3e20", mkFloat("1.3e+20")},
164164+ {"1.3e-5", mkFloat("1.3e-5")},
165165+ {"0x1234", mkMul(0x1234, 0, 16)},
166166+ {"0xABCD", mkMul(0xABCD, 0, 16)},
167167+ {"0b11001000", mkMul(0xc8, 0, 2)},
168168+ {"0b1", mkMul(1, 0, 2)},
169169+ {"0755", mkMul(0755, 0, 8)},
170170+ }
171171+ p := litParser{
172172+ ctx: &context{Context: &apd.BaseContext},
173173+ }
174174+ for i, tc := range testCases {
175175+ t.Run(fmt.Sprintf("%d/%+q", i, tc.lit), func(t *testing.T) {
176176+ got := p.parse(&ast.BasicLit{Value: tc.lit})
177177+ if !cmp.Equal(got, tc.node, diffOpts...) {
178178+ t.Error(cmp.Diff(got, tc.node, diffOpts...))
179179+ t.Errorf("%#v, %#v\n", got, tc.node)
180180+ }
181181+ })
182182+ }
183183+}
184184+185185+func TestLiteralErrors(t *testing.T) {
186186+ testCases := []struct {
187187+ lit string
188188+ }{
189189+ {`"foo\u"`},
190190+ {`"foo\u003"`},
191191+ {`"foo\U1234567"`},
192192+ {`"foo\U12345678"`},
193193+ {`"foo\Ug"`},
194194+ {`"\xff"`},
195195+ // not allowed in string literal, only binary
196196+ {`"foo\x00"`},
197197+ {`0x`},
198198+ {`09`},
199199+ {`0_`},
200200+ {``},
201201+ {`"`},
202202+ {`"a`},
203203+ // wrong indentation
204204+ {`"""
205205+ abc
206206+ def
207207+ """`},
208208+ // non-matching quotes
209209+ {`"""
210210+ abc
211211+ '''`},
212212+ {`"""
213213+ abc
214214+ "`},
215215+ {`"abc \( foo "`},
216216+ }
217217+ p := litParser{
218218+ ctx: &context{Context: &apd.BaseContext},
219219+ }
220220+ for _, tc := range testCases {
221221+ t.Run(fmt.Sprintf("%+q", tc.lit), func(t *testing.T) {
222222+ got := p.parse(&ast.BasicLit{Value: tc.lit})
223223+ if _, ok := got.(*bottom); !ok {
224224+ t.Fatalf("expected error but found none")
225225+ }
226226+ })
227227+ }
228228+}
+144
cue/op.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import "cuelang.org/go/cue/token"
1818+1919+func opIn(op op, anyOf ...op) bool {
2020+ for _, o := range anyOf {
2121+ if o == op {
2222+ return true
2323+ }
2424+ }
2525+ return false
2626+}
2727+2828+// isCmp reports whether an op is a comparator.
2929+func (op op) isCmp() bool {
3030+ return opEql <= op && op <= opGeq
3131+}
3232+3333+// allowImplicitNumCast returns whether an operator is allowed between two
3434+// different kind of numeric types without an explicit cast.
3535+// TODO: remove
3636+func (op op) allowImplicitNumCast() bool {
3737+ return opAdd <= op && op <= opQuo
3838+}
3939+4040+type op uint16
4141+4242+const (
4343+ opUnknown op = iota
4444+4545+ opUnify
4646+ opDisjunction
4747+4848+ opLand
4949+ opLor
5050+ opNot
5151+5252+ opEql
5353+ opNeq
5454+5555+ opLss
5656+ opGtr
5757+ opLeq
5858+ opGeq
5959+6060+ opAdd
6161+ opSub
6262+ opMul
6363+ opQuo
6464+ opRem
6565+6666+ opIDiv
6767+ opIMod
6868+ opIQuo
6969+ opIRem
7070+7171+ opRange // Used in computedSource
7272+)
7373+7474+var opStrings = []string{
7575+ opUnknown: "??",
7676+7777+ opUnify: "&",
7878+ opDisjunction: "|",
7979+8080+ opLand: "&&",
8181+ opLor: "||",
8282+ opNot: "!",
8383+8484+ opEql: "==",
8585+ opNeq: "!=",
8686+8787+ opLss: "<",
8888+ opGtr: ">",
8989+ opLeq: "<=",
9090+ opGeq: ">=",
9191+9292+ opAdd: "+",
9393+ opSub: "-",
9494+ opMul: "*",
9595+ opQuo: "/",
9696+ opRem: "%",
9797+9898+ opIDiv: "div",
9999+ opIMod: "mod",
100100+ opIQuo: "quo",
101101+ opIRem: "rem",
102102+103103+ opRange: "..",
104104+}
105105+106106+func (op op) String() string { return opStrings[op] }
107107+108108+var tokenMap = map[token.Token]op{
109109+ token.DISJUNCTION: opDisjunction, // |
110110+ token.UNIFY: opUnify, // &
111111+112112+ token.ADD: opAdd, // +
113113+ token.SUB: opSub, // -
114114+ token.MUL: opMul, // *
115115+ token.QUO: opQuo, // /
116116+ token.REM: opRem, // %
117117+118118+ token.IDIV: opIDiv, // div
119119+ token.IMOD: opIMod, // mod
120120+ token.IQUO: opIQuo, // quo
121121+ token.IREM: opIRem, // rem
122122+123123+ token.LAND: opLand, // &&
124124+ token.LOR: opLor, // ||
125125+126126+ token.EQL: opEql, // ==
127127+ token.LSS: opLss, // <
128128+ token.GTR: opGtr, // >
129129+ token.NOT: opNot, // !
130130+131131+ token.NEQ: opNeq, // !=
132132+ token.LEQ: opLeq, // <=
133133+ token.GEQ: opGeq, // >=
134134+135135+ token.RANGE: opRange, // ..
136136+}
137137+138138+var opMap = map[op]token.Token{}
139139+140140+func init() {
141141+ for t, o := range tokenMap {
142142+ opMap[o] = t
143143+ }
144144+}
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+// TODO: nodeRefs are currently not updated if the structs they point to are
1818+// updated. Handing this in uses of rewrite is tedious and hard to get correct.
1919+// Make this a general mechanism. This can be done using a Tomabechi-like
2020+// approach of associating copies with nodes in one pass, and then make a
2121+// complete copy in a second.
2222+2323+type rewriteFunc func(ctx *context, v value) (value, bool)
2424+2525+func rewrite(ctx *context, v value, fn rewriteFunc) value {
2626+ v, descend := fn(ctx, v)
2727+ if !descend {
2828+ return v
2929+ }
3030+ return v.rewrite(ctx, fn)
3131+}
3232+3333+func (x *nodeRef) rewrite(ctx *context, fn rewriteFunc) value {
3434+ return x
3535+}
3636+3737+func (x *structLit) rewrite(ctx *context, fn rewriteFunc) value {
3838+ emit := x.emit
3939+ if emit != nil {
4040+ emit = rewrite(ctx, x.emit, fn)
4141+ }
4242+ arcs := make(arcs, len(x.arcs))
4343+ obj := &structLit{baseValue: x.baseValue, emit: emit, arcs: arcs}
4444+ changed := emit == x.emit
4545+ for i, a := range x.arcs {
4646+ v := rewrite(ctx, a.v, fn)
4747+ arcs[i] = arc{a.feature, v, nil}
4848+ changed = changed || arcs[i].v != v
4949+ }
5050+ if !changed {
5151+ return x
5252+ }
5353+ return obj
5454+}
5555+5656+func (x *selectorExpr) rewrite(ctx *context, fn rewriteFunc) value {
5757+ v := rewrite(ctx, x.x, fn)
5858+ if v == x.x {
5959+ return x
6060+ }
6161+ return &selectorExpr{x.baseValue, v, x.feature}
6262+}
6363+6464+func (x *indexExpr) rewrite(ctx *context, fn rewriteFunc) value {
6565+ v := rewrite(ctx, x.x, fn)
6666+ index := rewrite(ctx, x.index, fn)
6767+ if v == x.x && index == x.index {
6868+ return x
6969+ }
7070+ return &indexExpr{x.baseValue, v, index}
7171+}
7272+7373+// Even more boring stuff below.
7474+7575+func (x *builtin) rewrite(ctx *context, fn rewriteFunc) value { return x }
7676+func (x *top) rewrite(ctx *context, fn rewriteFunc) value { return x }
7777+func (x *bottom) rewrite(ctx *context, fn rewriteFunc) value { return x }
7878+func (x *basicType) rewrite(ctx *context, fn rewriteFunc) value { return x }
7979+func (x *nullLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
8080+func (x *boolLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
8181+func (x *stringLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
8282+func (x *bytesLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
8383+func (x *numLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
8484+func (x *durationLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
8585+8686+func (x *rangeLit) rewrite(ctx *context, fn rewriteFunc) value {
8787+ from := rewrite(ctx, x.from, fn)
8888+ to := rewrite(ctx, x.to, fn)
8989+ if from == x.from && to == x.to {
9090+ return x
9191+ }
9292+ return &rangeLit{x.baseValue, from, to}
9393+}
9494+9595+func (x *interpolation) rewrite(ctx *context, fn rewriteFunc) value {
9696+ parts := make([]value, len(x.parts))
9797+ changed := false
9898+ for i, p := range x.parts {
9999+ parts[i] = rewrite(ctx, p, fn)
100100+ changed = changed || parts[i] != p
101101+ }
102102+ if !changed {
103103+ return x
104104+ }
105105+ return &interpolation{x.baseValue, x.k, parts}
106106+}
107107+108108+func (x *list) rewrite(ctx *context, fn rewriteFunc) value {
109109+ a := make([]value, len(x.a))
110110+ changed := false
111111+ for i, e := range x.a {
112112+ a[i] = rewrite(ctx, e, fn)
113113+ changed = changed || a[i] != e
114114+ }
115115+ typ := rewrite(ctx, x.typ, fn)
116116+ len := rewrite(ctx, x.len, fn)
117117+ if !changed && typ == x.typ && len == x.len {
118118+ return x
119119+ }
120120+ return &list{x.baseValue, a, typ, len}
121121+}
122122+123123+func (x *sliceExpr) rewrite(ctx *context, fn rewriteFunc) value {
124124+ v := rewrite(ctx, x.x, fn)
125125+ lo := rewrite(ctx, x.lo, fn)
126126+ hi := rewrite(ctx, x.hi, fn)
127127+ if v == x.x && lo == x.lo && hi == x.hi {
128128+ return x
129129+ }
130130+ return &sliceExpr{x.baseValue, v, lo, hi}
131131+}
132132+133133+func (x *callExpr) rewrite(ctx *context, fn rewriteFunc) value {
134134+ args := make([]value, len(x.args))
135135+ changed := false
136136+ for i, a := range x.args {
137137+ v := rewrite(ctx, a, fn)
138138+ args[i] = v
139139+ changed = changed || v != a
140140+ }
141141+ v := rewrite(ctx, x.x, fn)
142142+ if !changed && v == x.x {
143143+ return x
144144+ }
145145+ return &callExpr{baseValue: x.baseValue, x: v, args: args}
146146+}
147147+148148+func (x *lambdaExpr) rewrite(ctx *context, fn rewriteFunc) value {
149149+ arcs := make([]arc, len(x.arcs))
150150+ changed := false
151151+ for i, a := range x.arcs {
152152+ v := rewrite(ctx, a.v, fn)
153153+ arcs[i] = arc{feature: a.feature, v: v}
154154+ changed = changed || v != a.v
155155+ }
156156+ value := rewrite(ctx, x.value, fn)
157157+ if !changed && value == x.value {
158158+ return x
159159+ }
160160+ return &lambdaExpr{x.baseValue, ¶ms{arcs}, value}
161161+}
162162+163163+func (x *unaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
164164+ v := rewrite(ctx, x.x, fn)
165165+ if v == x.x {
166166+ return x
167167+ }
168168+ return &unaryExpr{x.baseValue, x.op, v}
169169+}
170170+171171+func (x *binaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
172172+ left := rewrite(ctx, x.left, fn)
173173+ right := rewrite(ctx, x.right, fn)
174174+ if left == x.left && right == x.right {
175175+ return x
176176+ }
177177+ return &binaryExpr{x.baseValue, x.op, left, right}
178178+}
179179+180180+func (x *disjunction) rewrite(ctx *context, fn rewriteFunc) value {
181181+ values := make([]dValue, len(x.values))
182182+ changed := false
183183+ for i, d := range x.values {
184184+ v := rewrite(ctx, d.val, fn)
185185+ values[i] = dValue{v, d.ambiguous}
186186+ changed = changed || v != d.val
187187+ }
188188+ if !changed {
189189+ return x
190190+ }
191191+ return &disjunction{x.baseValue, values}
192192+}
193193+194194+func (x *listComprehension) rewrite(ctx *context, fn rewriteFunc) value {
195195+ clauses := rewrite(ctx, x.clauses, fn).(yielder)
196196+ if clauses == x.clauses {
197197+ return x
198198+ }
199199+ return &listComprehension{x.baseValue, clauses}
200200+}
201201+202202+func (x *structComprehension) rewrite(ctx *context, fn rewriteFunc) value {
203203+ clauses := rewrite(ctx, x.clauses, fn).(yielder)
204204+ if clauses == x.clauses {
205205+ return x
206206+ }
207207+ return &structComprehension{x.baseValue, clauses, x.isTemplate}
208208+}
209209+210210+func (x *yield) rewrite(ctx *context, fn rewriteFunc) value {
211211+ key := x.key
212212+ if key != nil {
213213+ key = rewrite(ctx, x.key, fn)
214214+ }
215215+ value := rewrite(ctx, x.value, fn)
216216+ if key == x.key && value == x.value {
217217+ return x
218218+ }
219219+ return &yield{x.baseValue, key, value}
220220+}
221221+222222+func (x *guard) rewrite(ctx *context, fn rewriteFunc) value {
223223+ condition := rewrite(ctx, x.condition, fn)
224224+ value := rewrite(ctx, x.value, fn).(yielder)
225225+ if condition == x.condition && value == x.value {
226226+ return x
227227+ }
228228+ return &guard{x.baseValue, condition, value}
229229+}
230230+231231+func (x *feed) rewrite(ctx *context, fn rewriteFunc) value {
232232+ source := rewrite(ctx, x.source, fn)
233233+ lambda := rewrite(ctx, x.fn, fn).(*lambdaExpr)
234234+ if source == x.source && lambda == x.fn {
235235+ return x
236236+ }
237237+ return &feed{x.baseValue, source, lambda}
238238+}
+104
cue/rewrite_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "strings"
2020+)
2121+2222+type rewriteMode int
2323+2424+const (
2525+ evalRaw rewriteMode = iota
2626+ evalSimplify
2727+ evalPartial // all but disjunctions
2828+ evalFull
2929+)
3030+3131+// testResolve recursively
3232+func testResolve(ctx *context, v value, m rewriteMode) (result value) {
3333+ if m == evalRaw || v == nil {
3434+ return v
3535+ }
3636+ return rewriteRec(ctx, v, v.evalPartial(ctx), m)
3737+}
3838+3939+var indentLevel int
4040+4141+func (c *context) ind() int {
4242+ old := indentLevel
4343+ indentLevel += 2
4444+ return old
4545+}
4646+4747+func (c *context) unindent(old int) {
4848+ indentLevel = old
4949+}
5050+5151+func (c *context) printIndent(args ...interface{}) {
5252+ fmt.Print(strings.Repeat(" ", indentLevel))
5353+ c.println(args...)
5454+}
5555+5656+func rewriteRec(ctx *context, raw value, eval evaluated, m rewriteMode) (result value) {
5757+ if m >= evalPartial {
5858+ if isIncomplete(eval) {
5959+ return raw
6060+ }
6161+ if m == evalFull {
6262+ eval = ctx.manifest(eval)
6363+ if isBottom(eval) {
6464+ return eval
6565+ }
6666+ }
6767+ }
6868+ switch x := eval.(type) {
6969+ case *structLit:
7070+ if m == evalFull {
7171+ e := ctx.manifest(x)
7272+ if isBottom(e) {
7373+ return e
7474+ }
7575+ x = e.(*structLit)
7676+ }
7777+ arcs := make(arcs, len(x.arcs))
7878+ for i, a := range x.arcs {
7979+ v := x.at(ctx, i)
8080+ arcs[i] = arc{a.feature, rewriteRec(ctx, a.v, v, m), nil}
8181+ }
8282+ t := x.template
8383+ if t != nil {
8484+ v := rewriteRec(ctx, t, t.evalPartial(ctx), m)
8585+ if isBottom(v) {
8686+ return v
8787+ }
8888+ t = v.(*lambdaExpr)
8989+ }
9090+ emit := testResolve(ctx, x.emit, m)
9191+ obj := &structLit{x.baseValue, emit, t, arcs}
9292+ return obj
9393+ case *list:
9494+ a := make([]value, len(x.a))
9595+ for i := range x.a {
9696+ a[i] = rewriteRec(ctx, x.a[i], x.at(ctx, i), m)
9797+ }
9898+ len := rewriteRec(ctx, x.len, x.len.(evaluated), m)
9999+ typ := rewriteRec(ctx, x.typ, x.typ.(evaluated), m)
100100+ return &list{x.baseValue, a, typ, len}
101101+ default:
102102+ return eval
103103+ }
104104+}
+43
cue/strip.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+// This file defines a rewriter that strips a fully evaluated value of its
1818+// template.
1919+2020+// TODO: currently strip templates does a full evaluation as it is hard to keep
2121+// nodeRef and copied structs in sync. This is far from efficient, but it is the
2222+// easiest to get correct.
2323+2424+// stripTemplates evaluates v and strips the result of templates.
2525+func stripTemplates(ctx *context, v value) value {
2626+ return rewrite(ctx, v, stripRewriter)
2727+}
2828+2929+func stripRewriter(ctx *context, v value) (value, bool) {
3030+ eval := ctx.manifest(v)
3131+ switch x := eval.(type) {
3232+ case *structLit:
3333+ if x.template != nil {
3434+ arcs := make(arcs, len(x.arcs))
3535+ for i, a := range x.arcs {
3636+ v := rewrite(ctx, x.at(ctx, i), stripRewriter)
3737+ arcs[i] = arc{a.feature, v, nil}
3838+ }
3939+ return &structLit{x.baseValue, x.emit, nil, arcs}, false
4040+ }
4141+ }
4242+ return eval, true
4343+}
+61
cue/strip_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import "testing"
1818+1919+func TestStripTemplates(t *testing.T) {
2020+ testCases := []testCase{{
2121+ desc: "basic",
2222+ in: `
2323+ foo <Name>: { name: Name }
2424+ foo bar: { units: 5 }
2525+ `,
2626+ out: `<0>{foo: <1>{bar: <2>{name: "bar", units: 5}}}`,
2727+ }, {
2828+ desc: "top-level template",
2929+ in: `
3030+ <Name>: { name: Name }
3131+ bar: { units: 5 }
3232+ `,
3333+ out: `<0>{bar: <1>{name: "bar", units: 5}}`,
3434+ }, {
3535+ desc: "with reference",
3636+ in: `
3737+ before: foo.bar
3838+ foo <Name>: { name: Name }
3939+ foo bar: { units: 5 }
4040+ after: foo.bar
4141+ `,
4242+ out: `<0>{before: <1>{name: "bar", units: 5}, foo: <2>{bar: <3>{name: "bar", units: 5}}, after: <4>{name: "bar", units: 5}}`,
4343+ }, {
4444+ desc: "nested",
4545+ in: `
4646+ <X1> foo <X2> bar <X3>: { name: X1+X2+X3 }
4747+ a foo b bar c: { morning: true }
4848+ `,
4949+ out: `<0>{a: <1>{foo: <2>{b: <3>{bar: <4>{c: <5>{name: "abc", morning: true}}}}}}`}}
5050+ for _, tc := range testCases {
5151+ t.Run("", func(t *testing.T) {
5252+ ctx, obj := compileFile(t, tc.in)
5353+5454+ v := stripTemplates(ctx, obj)
5555+5656+ if got := debugStr(ctx, v); got != tc.out {
5757+ t.Errorf("output differs:\ngot %s\nwant %s", got, tc.out)
5858+ }
5959+ })
6060+ }
6161+}
+370
cue/subsume.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+)
2020+2121+type valueSubsumer interface {
2222+ subsumesImpl(ctx *context, v value) bool
2323+}
2424+2525+type subsumeMode int
2626+2727+const (
2828+ // subChoose ensures values are elected before doing a subsumption. This
2929+ // feature is on the conservative side and may result in false negatives.
3030+ subChoose subsumeMode = 1 << iota
3131+)
3232+3333+// subsumes checks gt subsumes lt. If any of the values contains references or
3434+// unevaluated expressions, structural subsumption is performed. This means
3535+// subsumption is conservative; it may return false when a guarantee for
3636+// subsumption could be proven. For concreted values it returns the exact
3737+// relation. It never returns a false positive.
3838+func subsumes(ctx *context, gt, lt value, mode subsumeMode) bool {
3939+ var v, w value
4040+ if mode&subChoose == 0 {
4141+ v = gt.evalPartial(ctx)
4242+ w = lt.evalPartial(ctx)
4343+ } else {
4444+ v = ctx.manifest(gt)
4545+ w = ctx.manifest(lt)
4646+ }
4747+ if !isIncomplete(v) && !isIncomplete(w) {
4848+ gt = v
4949+ lt = w
5050+ }
5151+ a := gt.kind()
5252+ b := lt.kind()
5353+ switch {
5454+ case b == bottomKind:
5555+ return true
5656+ case b&^(a&b) != 0:
5757+ // a does not have strictly more bits. This implies any ground kind
5858+ // subsuming a non-ground type.
5959+ return false
6060+ // TODO: consider not supporting references.
6161+ // case (a|b)&(referenceKind) != 0:
6262+ // // no resolution if references are in play.
6363+ // return false, false
6464+ }
6565+ return gt.subsumesImpl(ctx, lt, mode)
6666+}
6767+6868+func (x *structLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
6969+ if o, ok := v.(*structLit); ok {
7070+ // all arcs in n must exist in v and its values must subsume.
7171+ for _, a := range x.arcs {
7272+ b, _ := o.lookup(ctx, a.feature)
7373+ if b == nil || !subsumes(ctx, a.v, b, mode) {
7474+ return false
7575+ }
7676+ }
7777+ }
7878+ return !isBottom(v)
7979+}
8080+8181+func (*top) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
8282+ return true
8383+}
8484+8585+func (x *bottom) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
8686+ // never called.
8787+ return v.kind() == bottomKind
8888+}
8989+9090+func (x *basicType) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
9191+ return true
9292+}
9393+9494+func (x *rangeLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
9595+ k := unifyType(x.from.kind(), x.to.kind())
9696+ if k.isDone() && k.isGround() {
9797+ switch y := v.(type) {
9898+ case *rangeLit:
9999+ // structural equivalence
100100+ return subsumes(ctx, x.from, y.from, 0) && subsumes(ctx, x.to, y.to, 0)
101101+ case *numLit, *stringLit, *durationLit:
102102+ kv := v.kind()
103103+ k, _ := matchBinOpKind(opAdd, k, kv)
104104+ if k != kv {
105105+ return false
106106+ }
107107+ v := v.(evaluated)
108108+ if x.from != nil {
109109+ from := minNumRaw(x.from)
110110+ if !from.kind().isGround() {
111111+ return subsumes(ctx, from, v, 0) // false negative is okay
112112+ }
113113+ return leq(ctx, x, x.from.(evaluated), v)
114114+ }
115115+ if x.to != nil {
116116+ to := minNumRaw(x.to)
117117+ if !to.kind().isGround() {
118118+ return subsumes(ctx, to, v, 0) // false negative is okay
119119+ }
120120+ return leq(ctx, x, v, x.to.(evaluated))
121121+ }
122122+ return true
123123+ }
124124+ }
125125+ return isBottom(v)
126126+}
127127+128128+func (x *nullLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
129129+ return true
130130+}
131131+132132+func (x *boolLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
133133+ return x.b == v.(*boolLit).b
134134+}
135135+136136+func (x *stringLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
137137+ return x.str == v.(*stringLit).str
138138+}
139139+140140+func (x *bytesLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
141141+ return bytes.Equal(x.b, v.(*bytesLit).b)
142142+}
143143+144144+func (x *numLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
145145+ b := v.(*numLit)
146146+ return x.v.Cmp(&b.v) == 0
147147+}
148148+149149+func (x *durationLit) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
150150+ return x.d == v.(*durationLit).d
151151+}
152152+153153+func (x *list) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
154154+ switch y := v.(type) {
155155+ case *list:
156156+ if !subsumes(ctx, x.len, y.len, mode) {
157157+ return false
158158+ }
159159+ n := len(x.a)
160160+ if len(y.a) < n {
161161+ n = len(y.a)
162162+ }
163163+ for i, a := range x.a[:n] {
164164+ if !subsumes(ctx, a, y.a[i], mode) {
165165+ return false
166166+ }
167167+ }
168168+ if y.isOpen() {
169169+ return subsumes(ctx, x.typ, y.typ, 0)
170170+ }
171171+ for i := range y.a[n:] {
172172+ if !subsumes(ctx, x.typ, y.a[i], mode) {
173173+ return false
174174+ }
175175+ }
176176+ return true
177177+ }
178178+ return isBottom(v)
179179+}
180180+181181+func (x *params) subsumes(ctx *context, y *params, mode subsumeMode) bool {
182182+ // structural equivalence
183183+ // TODO: make agnostic to argument names.
184184+ if len(y.arcs) != len(x.arcs) {
185185+ return false
186186+ }
187187+ for i, a := range x.arcs {
188188+ if !subsumes(ctx, a.v, y.arcs[i].v, 0) {
189189+ return false
190190+ }
191191+ }
192192+ return true
193193+}
194194+195195+func (x *lambdaExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
196196+ // structural equivalence
197197+ if y, ok := v.(*lambdaExpr); ok {
198198+ return x.params.subsumes(ctx, y.params, 0) &&
199199+ subsumes(ctx, x.value, y.value, 0)
200200+ }
201201+ return isBottom(v)
202202+}
203203+204204+// subsumes for disjunction is logically precise. However, just like with
205205+// structural subsumption, it should not have to be called after evaluation.
206206+func (x *disjunction) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
207207+ if d, ok := v.(*disjunction); ok {
208208+ // TODO: the result of subsuming a value by a disjunction is logically
209209+ // the subsumed value. However, since we have default semantics, we
210210+ // should mark a resulting subsumed value as ambiguous if necessary.
211211+ // Also, prove that the returned subsumed single value is always the
212212+ // left-most matching value.
213213+ return false
214214+ // at least one value in x should subsume each value in d.
215215+ for _, vd := range d.values {
216216+ if !subsumes(ctx, x, vd.val, 0) {
217217+ return false
218218+ }
219219+ }
220220+ return true
221221+ }
222222+ // v is subsumed if any value in x subsumes v.
223223+ for _, vx := range x.values {
224224+ if subsumes(ctx, vx.val, v, 0) {
225225+ return true
226226+ }
227227+ }
228228+ return false
229229+}
230230+231231+// Structural subsumption operations. Should never have to be called after
232232+// evaluation.
233233+234234+// structural equivalence
235235+func (x *nodeRef) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
236236+ if r, ok := v.(*nodeRef); ok {
237237+ return x.node == r.node
238238+ }
239239+ return isBottom(v)
240240+}
241241+242242+// structural equivalence
243243+func (x *selectorExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
244244+ if r, ok := v.(*selectorExpr); ok {
245245+ return x.feature == r.feature && subsumes(ctx, x.x, r.x, subChoose)
246246+ }
247247+ return isBottom(v)
248248+}
249249+250250+func (x *interpolation) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
251251+ switch v := v.(type) {
252252+ case *stringLit:
253253+ // Be conservative if not ground.
254254+ return false
255255+256256+ case *interpolation:
257257+ // structural equivalence
258258+ if len(x.parts) != len(v.parts) {
259259+ return false
260260+ }
261261+ for i, p := range x.parts {
262262+ if !subsumes(ctx, p, v.parts[i], 0) {
263263+ return false
264264+ }
265265+ }
266266+ return true
267267+ }
268268+ return false
269269+}
270270+271271+// structural equivalence
272272+func (x *indexExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
273273+ // TODO: what does it mean to subsume if the index value is not known?
274274+ if r, ok := v.(*indexExpr); ok {
275275+ // TODO: could be narrowed down if we know the exact value of the index
276276+ // and referenced value.
277277+ return subsumes(ctx, x.x, r.x, mode) && subsumes(ctx, x.index, r.index, 0)
278278+ }
279279+ return isBottom(v)
280280+}
281281+282282+// structural equivalence
283283+func (x *sliceExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
284284+ // TODO: what does it mean to subsume if the index value is not known?
285285+ if r, ok := v.(*sliceExpr); ok {
286286+ // TODO: could be narrowed down if we know the exact value of the index
287287+ // and referenced value.
288288+ return subsumes(ctx, x.x, r.x, 0) &&
289289+ subsumes(ctx, x.lo, r.lo, 0) &&
290290+ subsumes(ctx, x.hi, r.hi, 0)
291291+ }
292292+ return isBottom(v)
293293+}
294294+295295+// structural equivalence
296296+func (x *callExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
297297+ if c, ok := v.(*callExpr); ok {
298298+ if len(x.args) != len(c.args) {
299299+ return false
300300+ }
301301+ for i, a := range x.args {
302302+ if !subsumes(ctx, a, c.args[i], 0) {
303303+ return false
304304+ }
305305+ }
306306+ return subsumes(ctx, x.x, c.x, 0)
307307+ }
308308+ return isBottom(v)
309309+}
310310+311311+// structural equivalence
312312+func (x *unaryExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
313313+ if b, ok := v.(*unaryExpr); ok {
314314+ return x.op == b.op && subsumes(ctx, x.x, b.x, 0)
315315+ }
316316+ return isBottom(v)
317317+}
318318+319319+// structural equivalence
320320+func (x *binaryExpr) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
321321+ if b, ok := v.(*binaryExpr); ok {
322322+ return x.op == b.op &&
323323+ subsumes(ctx, x.left, b.left, 0) &&
324324+ subsumes(ctx, x.right, b.right, 0)
325325+ }
326326+ return isBottom(v)
327327+}
328328+329329+// structural equivalence
330330+func (x *listComprehension) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
331331+ if b, ok := v.(*listComprehension); ok {
332332+ return subsumes(ctx, x.clauses, b.clauses, 0)
333333+ }
334334+ return isBottom(v)
335335+}
336336+337337+// structural equivalence
338338+func (x *structComprehension) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
339339+ if b, ok := v.(*structComprehension); ok {
340340+ return subsumes(ctx, x.clauses, b.clauses, 0)
341341+ }
342342+ return isBottom(v)
343343+}
344344+345345+// structural equivalence
346346+func (x *yield) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
347347+ if b, ok := v.(*yield); ok {
348348+ return subsumes(ctx, x.key, b.key, 0) &&
349349+ subsumes(ctx, x.value, b.value, 0)
350350+ }
351351+ return isBottom(v)
352352+}
353353+354354+// structural equivalence
355355+func (x *feed) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
356356+ if b, ok := v.(*feed); ok {
357357+ return subsumes(ctx, x.source, b.source, 0) &&
358358+ subsumes(ctx, x.fn, b.fn, 0)
359359+ }
360360+ return isBottom(v)
361361+}
362362+363363+// structural equivalence
364364+func (x *guard) subsumesImpl(ctx *context, v value, mode subsumeMode) bool {
365365+ if b, ok := v.(*guard); ok {
366366+ return subsumes(ctx, x.condition, b.condition, 0) &&
367367+ subsumes(ctx, x.value, b.value, 0)
368368+ }
369369+ return isBottom(v)
370370+}
+350
cue/subsume_test.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "regexp"
1919+ "strconv"
2020+ "strings"
2121+ "testing"
2222+)
2323+2424+func TestSubsume(t *testing.T) {
2525+ testCases := []struct {
2626+ // the result of a ⊑ b, where a and b are defined in "in"
2727+ subsumes bool
2828+ in string
2929+ mode subsumeMode
3030+ }{
3131+ // Top subsumes everything
3232+ 0: {subsumes: true, in: `a: _, b: _ `},
3333+ 1: {subsumes: true, in: `a: _, b: null `},
3434+ 2: {subsumes: true, in: `a: _, b: int `},
3535+ 3: {subsumes: true, in: `a: _, b: 1 `},
3636+ 4: {subsumes: true, in: `a: _, b: float `},
3737+ 5: {subsumes: true, in: `a: _, b: "s" `},
3838+ 6: {subsumes: true, in: `a: _, b: {} `},
3939+ 7: {subsumes: true, in: `a: _, b: []`},
4040+ 8: {subsumes: true, in: `a: _, b: _|_ `},
4141+4242+ // Nothing besides top subsumed top
4343+ 9: {subsumes: false, in: `a: null, b: _`},
4444+ 10: {subsumes: false, in: `a: int, b: _`},
4545+ 11: {subsumes: false, in: `a: 1, b: _`},
4646+ 12: {subsumes: false, in: `a: float, b: _`},
4747+ 13: {subsumes: false, in: `a: "s", b: _`},
4848+ 14: {subsumes: false, in: `a: {}, b: _`},
4949+ 15: {subsumes: false, in: `a: [], b: _`},
5050+ 16: {subsumes: false, in: `a: _|_ , b: _`},
5151+5252+ // Bottom subsumes nothing except bottom itself.
5353+ 17: {subsumes: false, in: `a: _|_, b: null `},
5454+ 18: {subsumes: false, in: `a: _|_, b: int `},
5555+ 19: {subsumes: false, in: `a: _|_, b: 1 `},
5656+ 20: {subsumes: false, in: `a: _|_, b: float `},
5757+ 21: {subsumes: false, in: `a: _|_, b: "s" `},
5858+ 22: {subsumes: false, in: `a: _|_, b: {} `},
5959+ 23: {subsumes: false, in: `a: _|_, b: [] `},
6060+ 24: {subsumes: true, in: ` a: _|_, b: _|_ `},
6161+6262+ // All values subsume bottom
6363+ 25: {subsumes: true, in: `a: null, b: _|_`},
6464+ 26: {subsumes: true, in: `a: int, b: _|_`},
6565+ 27: {subsumes: true, in: `a: 1, b: _|_`},
6666+ 28: {subsumes: true, in: `a: float, b: _|_`},
6767+ 29: {subsumes: true, in: `a: "s", b: _|_`},
6868+ 30: {subsumes: true, in: `a: {}, b: _|_`},
6969+ 31: {subsumes: true, in: `a: [], b: _|_`},
7070+ 32: {subsumes: true, in: `a: true, b: _|_`},
7171+ 33: {subsumes: true, in: `a: _|_, b: _|_`},
7272+7373+ // null subsumes only null
7474+ 34: {subsumes: true, in: ` a: null, b: null `},
7575+ 35: {subsumes: false, in: `a: null, b: 1 `},
7676+ 36: {subsumes: false, in: `a: 1, b: null `},
7777+7878+ 37: {subsumes: true, in: ` a: true, b: true `},
7979+ 38: {subsumes: false, in: `a: true, b: false `},
8080+8181+ 39: {subsumes: true, in: ` a: "a", b: "a" `},
8282+ 40: {subsumes: false, in: `a: "a", b: "b" `},
8383+ 41: {subsumes: true, in: ` a: string, b: "a" `},
8484+ 42: {subsumes: false, in: `a: "a", b: string `},
8585+8686+ // Number typing (TODO)
8787+ //
8888+ // In principle, an "int" cannot assume an untyped "1", as "1" may
8989+ // still by typed as a float. They are two different type aspects. When
9090+ // considering, keep in mind that:
9191+ // Key requirement: if A subsumes B, it must not be possible to
9292+ // specialize B further such that A does not subsume B. HOWEVER,
9393+ // The type conversion rules for conversion are INDEPENDENT of the
9494+ // rules for subsumption!
9595+ // Consider:
9696+ // - only having number, but allowing user-defined types.
9797+ // Subsumption would still work the same, but it may be somewhat
9898+ // less weird.
9999+ // - making 1 always an int and 1.0 always a float.
100100+ // - the int type would subsume any derived type from int.
101101+ // - arithmetic would allow implicit conversions, but maybe not for
102102+ // types.
103103+ //
104104+ // TODO: irrational numbers: allow untyped, but require explicit
105105+ // trunking when assigning to float.
106106+ //
107107+ // a: number; cue.IsInteger(a) && a > 0
108108+ // t: (x) -> number; cue.IsInteger(a) && a > 0
109109+ // type x number: cue.IsInteger(x) && x > 0
110110+ // x: typeOf(number); cue.IsInteger(x) && x > 0
111111+ 43: {subsumes: true, in: `a: 1, b: 1 `},
112112+ 44: {subsumes: true, in: `a: 1.0, b: 1.0 `},
113113+ 45: {subsumes: true, in: `a: 3.0, b: 3.0 `},
114114+ 46: {subsumes: false, in: `a: 1.0, b: 1 `},
115115+ 47: {subsumes: true, in: `a: 1, b: 1.0 `},
116116+ 48: {subsumes: true, in: `a: 3, b: 3.0`},
117117+ 49: {subsumes: false, in: `a: int, b: 1`},
118118+ 50: {subsumes: true, in: `a: int, b: int & 1`},
119119+ 51: {subsumes: true, in: `a: float, b: 1.0`},
120120+ 52: {subsumes: false, in: `a: float, b: 1`},
121121+ 53: {subsumes: false, in: `a: int, b: 1.0`},
122122+ 54: {subsumes: true, in: `a: int, b: int`},
123123+ 55: {subsumes: true, in: `a: number, b: int`},
124124+125125+ // Lists
126126+ 56: {subsumes: true, in: `a: [], b: [] `},
127127+ 57: {subsumes: true, in: `a: [1], b: [1] `},
128128+ 58: {subsumes: false, in: `a: [1], b: [2] `},
129129+ 59: {subsumes: false, in: `a: [1], b: [2, 3] `},
130130+ 60: {subsumes: true, in: `a: [{b: string}], b: [{b: "foo"}] `},
131131+ 61: {subsumes: true, in: `a: [...{b: string}], b: [{b: "foo"}] `},
132132+ 62: {subsumes: false, in: `a: [{b: "foo"}], b: [{b: string}] `},
133133+ 63: {subsumes: false, in: `a: [{b: string}], b: [{b: "foo"}, ...{b: "foo"}] `},
134134+135135+ // Structs
136136+ 64: {subsumes: true, in: `a: {}, b: {}`},
137137+ 65: {subsumes: true, in: `a: {}, b: {a: 1}`},
138138+ 66: {subsumes: true, in: `a: {a:1}, b: {a:1, b:1}`},
139139+ 67: {subsumes: true, in: `a: {s: { a:1} }, b: { s: { a:1, b:2 }}`},
140140+ // TODO: allow subsumption of unevaluated values?
141141+ 68: {subsumes: true, in: `a: {}, b: c(), c: () -> {}`},
142142+ // TODO: allow subsumption of unevaluated values?
143143+ // ref not yet evaluated and not structurally equivalent
144144+ 69: {subsumes: true, in: `a: {}, b: {} & c, c: {}`},
145145+146146+ 70: {subsumes: false, in: `a: {a:1}, b: {}`},
147147+ 71: {subsumes: false, in: `a: {a:1, b:1}, b: {a:1}`},
148148+ 72: {subsumes: false, in: `a: {s: { a:1} }, b: { s: {}}`},
149149+150150+ // Lambda
151151+ 73: {subsumes: true, in: `a: (x: _) -> {}, b: (x: _) -> {}`},
152152+ 74: {subsumes: true, in: `a: (x: int) -> {}, b: (x: int) -> {}`},
153153+ 75: {subsumes: true, in: `a: (x: {}) -> {}, b: (x: {}) -> {}`},
154154+ 76: {subsumes: false, in: `a: (x: _) -> {}, b: (x: _, y:_) -> {}`},
155155+ 77: {subsumes: true, in: `a: (x: _) -> {}, b: (x: 1) -> { a: 1 }`},
156156+ 78: {subsumes: false, in: `a: (x: 1) -> {}, b: (x: _) -> {}`},
157157+ 79: {subsumes: false, in: `a: (x: _) -> {}, b: () -> {}`},
158158+159159+ 80: {subsumes: true, in: `a: (x: _) -> {}, b: (y: _) -> {}`},
160160+ 81: {subsumes: true, in: `a: (x) -> {}, b: (y) -> {}`},
161161+162162+ 82: {subsumes: true, in: `a: (x: {a:1}) -> {f:2}, b: (x: {a:1, b:1}) -> {f:2, g:3}`},
163163+ 83: {subsumes: false, in: `a: (x: {a:1, b:1}) -> {f:2}, b: (x: {a:1}) -> {f:2, g:3}`},
164164+165165+ // Disjunction TODO: for now these two are false: unifying may result in
166166+ // an ambiguity that we are currently not handling, so safer to not
167167+ // unify.
168168+ 84: {subsumes: false, in: `a: 1 | 2, b: 2 | 1`},
169169+ 85: {subsumes: false, in: `a: 1 | 2, b: 1 | 2`},
170170+171171+ 86: {subsumes: true, in: `a: number, b: 2 | 1`},
172172+ 87: {subsumes: true, in: `a: number, b: 2 | 1`},
173173+ 88: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
174174+175175+ // Disjunction TODO: for now these two are false: unifying may result in
176176+ // an ambiguity that we are currently not handling, so safer to not
177177+ // unify.
178178+ 89: {subsumes: false, in: `a: float | number, b: 1 | 2 | 3.1`},
179179+180180+ 90: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
181181+ 91: {subsumes: true, in: `a: 1 | 2, b: 1`},
182182+ 92: {subsumes: true, in: `a: 1 | 2, b: 2`},
183183+ 93: {subsumes: false, in: `a: 1 | 2, b: 3`},
184184+185185+ // Structural
186186+ 94: {subsumes: false, in: `a: int + int, b: int`},
187187+ 95: {subsumes: true, in: `a: int + int, b: int + int`},
188188+ 96: {subsumes: true, in: `a: int + number, b: int + int`},
189189+ 97: {subsumes: true, in: `a: number + number, b: int + int`},
190190+ // TODO: allow subsumption of unevaluated values?
191191+ // TODO: may be false if we allow arithmetic on incomplete values.
192192+ 98: {subsumes: true, in: `a: int + int, b: int * int`},
193193+194194+ 99: {subsumes: true, in: `a: !int, b: !int`},
195195+ 100: {subsumes: true, in: `a: !number, b: !int`},
196196+ // TODO: allow subsumption of unevaluated values?
197197+ // true because both evaluate to bottom
198198+ 101: {subsumes: true, in: `a: !int, b: !number`},
199199+ // TODO: allow subsumption of unevaluated values?
200200+ // true because both evaluate to bottom
201201+ 102: {subsumes: true, in: `a: int + int, b: !number`},
202202+ // TODO: allow subsumption of unevaluated values?
203203+ // true because both evaluate to bool
204204+ 103: {subsumes: true, in: `a: !bool, b: bool`},
205205+206206+ 104: {subsumes: true, in: `
207207+ a: () -> 2
208208+ b: () -> 2`},
209209+ 105: {subsumes: true, in: `
210210+ a: () -> number
211211+ b: () -> 2`},
212212+ 106: {subsumes: true, in: `
213213+ a: (a: number) -> 2
214214+ b: (a: number) -> 2`},
215215+ 107: {subsumes: true, in: `
216216+ a: (a: number) -> 2
217217+ b: (a: 2) -> 2`},
218218+ 108: {subsumes: false, in: `
219219+ a: (a: 2) -> 2
220220+ b: (a: 2, b: 2) -> 2`},
221221+ 109: {subsumes: false, in: `
222222+ a: (a: number) -> 2,
223223+ b: (a: number, b: number) -> 2`},
224224+ 110: {subsumes: false, in: `
225225+ a: () -> 3
226226+ b: () -> number`},
227227+ 111: {subsumes: false, in: `
228228+ a: (a: 3) -> 2
229229+ b: (a: number) -> 2`},
230230+ 112: {subsumes: false, in: `
231231+ a: (a: 3, b: 3) -> 2
232232+ b: (a: 3) -> 2`},
233233+234234+ // Call
235235+ 113: {subsumes: true, in: `
236236+ a: (() -> 2)(),
237237+ b: (() -> 2)()`,
238238+ },
239239+ // TODO: allow subsumption of unevaluated values?
240240+ 114: {subsumes: true, in: `
241241+ a: (() -> 2)(),
242242+ b: ((a) -> 2)(1)`,
243243+ },
244244+ 115: {subsumes: true, in: `
245245+ a: ((a: number) -> [2])(2)
246246+ b: ((a: number) -> [2])(2)`,
247247+ },
248248+ // TODO: allow subsumption of unevaluated values?
249249+ 116: {subsumes: true, in: `
250250+ a: ((a: number) -> [2])(number)
251251+ b: ((a: number) -> [2])(2)`,
252252+ },
253253+ // TODO: allow subsumption of unevaluated values?
254254+ 117: {subsumes: true, in: `
255255+ a: ((a: number) -> [2])(2)
256256+ b: ((a: number) -> [2])(number)`,
257257+ },
258258+ 118: {subsumes: true, in: `
259259+ a: ((a) -> number)(2)
260260+ b: ((a) -> 2)(2)`,
261261+ },
262262+ 119: {subsumes: false, in: `
263263+ a: ((a) -> 2)(2)
264264+ b: ((a) -> number)(2)`,
265265+ },
266266+ // purely structural:
267267+ // TODO: allow subsumption of unevaluated values?
268268+ 120: {subsumes: true, in: `
269269+ a: ((a) -> int)(2)
270270+ b: int`,
271271+ },
272272+273273+ // TODO: allow subsumption of unevaluated values?
274274+ // TODO: okay, but why false?
275275+ 121: {subsumes: false, in: `a: c + d, b: int, c: int, d: int`},
276276+ // TODO: allow subsumption of unevaluated values?
277277+ 122: {subsumes: true, in: `a: {}, b: c & {}, c: {}`},
278278+279279+ // references
280280+ 123: {subsumes: true, in: `a: c, b: c, c: {}`},
281281+ // TODO: allow subsumption of unevaluated values?
282282+ 124: {subsumes: true, in: `a: c, b: d, c: {}, d: {}`},
283283+ 125: {subsumes: false, in: `a: c, b: d, c: {a:1}, d: {}`},
284284+ // TODO: allow subsumption of unevaluated values?
285285+ 126: {subsumes: true, in: `a: c, b: d, c: {a:1}, d: c & {b:1}`},
286286+ 127: {subsumes: false, in: `a: d, b: c, c: {a:1}, d: c & {b:1}`},
287287+ 128: {subsumes: false, in: `a: c.c, b: c, c: { d: number}`},
288288+289289+ // type unification catches a reference error.
290290+ 129: {subsumes: false, in: `a: c, b: d, c: 1, d: 2`},
291291+292292+ 130: {subsumes: true, in: ` a: [1][1], b: [1][1]`},
293293+ 131: {subsumes: true, in: ` a: [1][number], b: [1][1]`},
294294+ 132: {subsumes: true, in: ` a: [number][1], b: [1][1]`},
295295+ 133: {subsumes: true, in: ` a: [number][number], b: [1][1]`},
296296+ 134: {subsumes: false, in: ` a: [1][0], b: [1][number]`},
297297+ 135: {subsumes: false, in: ` a: [1][0], b: [number][0]`},
298298+ 136: {subsumes: true, in: ` a: [number][number], b: [1][number]`},
299299+ 137: {subsumes: true, in: ` a: [number][number], b: [number][1]`},
300300+ // purely structural:
301301+ 138: {subsumes: false, in: ` a: [number][number], b: number`},
302302+303303+ // interpolations
304304+ 139: {subsumes: true, in: ` a: "\(d)", b: "\(d)", d: _`},
305305+ // TODO: allow subsumption of unevaluated values?
306306+ 140: {subsumes: true, in: ` a: "\(d)", b: "\(e)", d: _, e: _`},
307307+308308+ 141: {subsumes: true, in: ` a: "\(string)", b: "\("foo")"`},
309309+ // TODO: allow subsumption of unevaluated values?
310310+ 142: {subsumes: true, in: ` a: "\(string)", b: "\(d)", d: "foo"`},
311311+ 143: {subsumes: true, in: ` a: "\("foo")", b: "\("foo")"`},
312312+ 144: {subsumes: false, in: ` a: "\("foo")", b: "\(1) \(2)"`},
313313+314314+ 145: {subsumes: false, in: ` a: "s \(d) e", b: "s a e", d: _`},
315315+ 146: {subsumes: false, in: ` a: "s \(d)m\(d) e", b: "s a e", d: _`},
316316+317317+ 147: {subsumes: true, in: ` a: 7080, b: 7080 | int`, mode: subChoose},
318318+ }
319319+320320+ re := regexp.MustCompile(`a: (.*).*b: ([^\n]*)`)
321321+ for i, tc := range testCases {
322322+ m := re.FindStringSubmatch(strings.Join(strings.Split(tc.in, "\n"), ""))
323323+ const cutset = "\n ,"
324324+ key := strings.Trim(m[1], cutset) + " ⊑ " + strings.Trim(m[2], cutset)
325325+326326+ t.Run(strconv.Itoa(i)+"/"+key, func(t *testing.T) {
327327+ ctx, root := compileFile(t, tc.in)
328328+329329+ // Use low-level lookup to avoid evaluation.
330330+ var a, b value
331331+ for _, arc := range root.arcs {
332332+ switch arc.feature {
333333+ case ctx.strLabel("a"):
334334+ a = arc.v
335335+ case ctx.strLabel("b"):
336336+ b = arc.v
337337+ }
338338+ }
339339+ if got := subsumes(ctx, a, b, tc.mode); got != tc.subsumes {
340340+ t.Errorf("got %v; want %v (%v vs %v)", got, tc.subsumes, a.kind(), b.kind())
341341+ }
342342+ })
343343+ }
344344+}
345345+346346+func TestTouchBottom(t *testing.T) {
347347+ // Just call this function to mark coverage. It is otherwise never called.
348348+ var x bottom
349349+ x.subsumesImpl(nil, &bottom{}, 0)
350350+}
+1034
cue/types.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "bytes"
1919+ "encoding/json"
2020+ "fmt"
2121+ "io"
2222+ "math"
2323+ "math/big"
2424+ "strings"
2525+2626+ "cuelang.org/go/cue/ast"
2727+ "cuelang.org/go/cue/errors"
2828+ "cuelang.org/go/cue/token"
2929+ "github.com/cockroachdb/apd"
3030+)
3131+3232+// Kind determines the underlying type of a Value.
3333+type Kind int
3434+3535+const (
3636+ // BottomKind is the error value.
3737+ BottomKind Kind = 1 << iota
3838+3939+ // NullKind indicates a null value.
4040+ NullKind
4141+4242+ // BoolKind indicates a boolean value.
4343+ BoolKind
4444+4545+ // NumberKind represents any kind of number.
4646+ NumberKind
4747+4848+ // StringKind indicates any kind of string.
4949+ StringKind
5050+5151+ // BytesKind is a blob of data.
5252+ BytesKind
5353+5454+ // StructKind is a kev-value map.
5555+ StructKind
5656+5757+ // ListKind indicates a list of values.
5858+ ListKind
5959+6060+ nextKind
6161+)
6262+6363+// An structValue represents a JSON object.
6464+//
6565+// TODO: remove
6666+type structValue struct {
6767+ ctx *context
6868+ path *valueData
6969+ n *structLit
7070+}
7171+7272+// Len reports the number of fields in this struct.
7373+func (o *structValue) Len() int {
7474+ return len(o.n.arcs)
7575+}
7676+7777+// At reports the key and value of the ith field, i < o.Len().
7878+func (o *structValue) At(i int) (key string, v Value) {
7979+ a := o.n.arcs[i]
8080+ v = newChildValue(o, i)
8181+ return o.ctx.labelStr(a.feature), v
8282+}
8383+8484+// Lookup reports the field for the given key. The returned Value is invalid
8585+// if it does not exist.
8686+func (o *structValue) Lookup(key string) Value {
8787+ f := o.ctx.strLabel(key)
8888+ i := 0
8989+ for ; i < len(o.n.arcs); i++ {
9090+ if o.n.arcs[i].feature == f {
9191+ break
9292+ }
9393+ }
9494+ if i == len(o.n.arcs) {
9595+ // TODO: better message.
9696+ return newValueRoot(o.ctx, o.ctx.mkErr(o.n, codeNotExist,
9797+ "value %q not found", key))
9898+ }
9999+ // v, _ := o.n.lookup(o.ctx, f)
100100+ // v = o.ctx.manifest(v)
101101+ return newChildValue(o, i)
102102+}
103103+104104+// MarshalJSON returns a valid JSON encoding or reports an error if any of the
105105+// fields is invalid.
106106+func (o *structValue) MarshalJSON() (b []byte, err error) {
107107+ b = append(b, '{')
108108+ n := o.Len()
109109+ for i := 0; i < n; i++ {
110110+ k, v := o.At(i)
111111+ s, err := json.Marshal(k)
112112+ if err != nil {
113113+ return nil, err
114114+ }
115115+ b = append(b, s...)
116116+ b = append(b, ':')
117117+ bb, err := json.Marshal(v)
118118+ if err != nil {
119119+ return nil, err
120120+ }
121121+ b = append(b, bb...)
122122+ if i < n-1 {
123123+ b = append(b, ',')
124124+ }
125125+ }
126126+ b = append(b, '}')
127127+ return b, nil
128128+}
129129+130130+// An Iterator iterates over values.
131131+//
132132+type Iterator struct {
133133+ val Value
134134+ ctx *context
135135+ iter iterAtter
136136+ len int
137137+ p int
138138+ cur Value
139139+ f label
140140+}
141141+142142+// Next advances the iterator to the next value and reports whether there was
143143+// any. It must be called before the first call to Value or Key.
144144+func (i *Iterator) Next() bool {
145145+ if i.p >= i.len {
146146+ i.cur = Value{}
147147+ return false
148148+ }
149149+ eval, orig, f := i.iter.iterAt(i.ctx, i.p)
150150+ i.cur = i.val.makeChild(i.ctx, uint32(i.p), f, eval, orig)
151151+ i.f = f
152152+ i.p++
153153+ return true
154154+}
155155+156156+// Value returns the current value in the list. It will panic if Next advanced
157157+// past the last entry.
158158+func (i *Iterator) Value() Value {
159159+ return i.cur
160160+}
161161+162162+// Label reports the label of the value if i iterates over struct fields and
163163+// "" otherwise.
164164+func (i *Iterator) Label() string {
165165+ if i.f == 0 {
166166+ return ""
167167+ }
168168+ return i.ctx.labelStr(i.f)
169169+}
170170+171171+// IsHidden reports if a field is hidden from the data model. This may only
172172+// be true if the field was obtained using AllFields.
173173+func (i *Iterator) IsHidden() bool {
174174+ return i.f&hidden != 0
175175+}
176176+177177+// marshalJSON iterates over the list and generates JSON output. HasNext
178178+// will return false after this operation.
179179+func marshalList(l *Iterator) (b []byte, err error) {
180180+ b = append(b, '[')
181181+ if l.Next() {
182182+ for {
183183+ x, err := json.Marshal(l.Value())
184184+ if err != nil {
185185+ return nil, err
186186+ }
187187+ b = append(b, x...)
188188+ if !l.Next() {
189189+ break
190190+ }
191191+ b = append(b, ',')
192192+ }
193193+ }
194194+ b = append(b, ']')
195195+ return b, nil
196196+}
197197+198198+func (v Value) getNum(k kind) (*numLit, error) {
199199+ if err := v.checkKind(v.ctx(), k); err != nil {
200200+ return nil, err
201201+ }
202202+ n, _ := v.path.v.(*numLit)
203203+ return n, nil
204204+}
205205+206206+// MantExp breaks x into its mantissa and exponent components and returns the
207207+// exponent. If a non-nil mant argument is provided its value is set to the
208208+// mantissa of x. The components satisfy x == mant × 10**exp. It returns an
209209+// error if v is not a number.
210210+//
211211+// The components are not normalized. For instance, 2.00 is represented mant ==
212212+// 200 and exp == -2. Calling MantExp with a nil argument is an efficient way to
213213+// get the exponent of the receiver.
214214+func (v Value) MantExp(mant *big.Int) (exp int, err error) {
215215+ n, err := v.getNum(numKind)
216216+ if err != nil {
217217+ return 0, err
218218+ }
219219+ if n.v.Form != 0 {
220220+ return 0, ErrInfinite
221221+ }
222222+ if mant != nil {
223223+ mant.Set(&n.v.Coeff)
224224+ if n.v.Negative {
225225+ mant.Neg(mant)
226226+ }
227227+ }
228228+ return int(n.v.Exponent), nil
229229+}
230230+231231+// AppendInt appends the string representation of x in the given base to buf and
232232+// returns the extended buffer, or an error if the underlying number was not
233233+// an integer.
234234+func (v Value) AppendInt(buf []byte, base int) ([]byte, error) {
235235+ i, err := v.Int(nil)
236236+ if err != nil {
237237+ return nil, err
238238+ }
239239+ return i.Append(buf, base), nil
240240+}
241241+242242+// AppendFloat appends to buf the string form of the floating-point number x.
243243+// It returns an error if v is not a number.
244244+func (v Value) AppendFloat(buf []byte, fmt byte, prec int) ([]byte, error) {
245245+ n, err := v.getNum(numKind)
246246+ if err != nil {
247247+ return nil, err
248248+ }
249249+ ctx := apd.BaseContext
250250+ nd := int(apd.NumDigits(&n.v.Coeff)) + int(n.v.Exponent)
251251+ if n.v.Form == apd.Infinite {
252252+ if n.v.Negative {
253253+ buf = append(buf, '-')
254254+ }
255255+ return append(buf, string('∞')...), nil
256256+ }
257257+ if fmt == 'f' && nd > 0 {
258258+ ctx.Precision = uint32(nd + prec)
259259+ } else {
260260+ ctx.Precision = uint32(prec)
261261+ }
262262+ var d apd.Decimal
263263+ ctx.Round(&d, &n.v)
264264+ return d.Append(buf, fmt), nil
265265+}
266266+267267+var (
268268+ // ErrBelow indicates that a value was rounded down in a conversion.
269269+ ErrBelow = errors.New("cue: value was rounded down")
270270+271271+ // ErrAbove indicates that a value was rounded up in a conversion.
272272+ ErrAbove = errors.New("cue: value was rounded up")
273273+274274+ // ErrInfinite indicates that a value is infinite.
275275+ ErrInfinite = errors.New("cue: infinite")
276276+)
277277+278278+// IsInt reports whether n is a integral number type.
279279+func (v Value) IsInt() bool {
280280+ _, err := v.getNum(intKind) // TODO: make more efficient.
281281+ return err == nil
282282+}
283283+284284+// IsUint reports whether n is a positive integral number type.
285285+func (v Value) IsUint() bool {
286286+ if !v.IsInt() {
287287+ return false
288288+ }
289289+ n, _ := v.path.v.(*numLit)
290290+ return n.v.Sign() >= 0
291291+}
292292+293293+// Int converts the underlying integral number to an big.Int. It reports an
294294+// error if the underlying value is not an integer type. If a non-nil *Int
295295+// argument z is provided, Int stores the result in z instead of allocating a
296296+// new Int.
297297+func (v Value) Int(z *big.Int) (*big.Int, error) {
298298+ n, err := v.getNum(intKind)
299299+ if err != nil {
300300+ return nil, err
301301+ }
302302+ if z == nil {
303303+ z = &big.Int{}
304304+ }
305305+ if n.v.Exponent != 0 {
306306+ panic("cue: exponent should always be nil for integer types")
307307+ }
308308+ z.Set(&n.v.Coeff)
309309+ if n.v.Negative {
310310+ z.Neg(z)
311311+ }
312312+ return z, nil
313313+}
314314+315315+// Int64 converts the underlying integral number to int64. It reports an
316316+// error if the underlying value is not an integer type or cannot be represented
317317+// as an int64. The result is (math.MinInt64, ErrAbove) for x < math.MinInt64,
318318+// and (math.MaxInt64, ErrBelow) for x > math.MaxInt64.
319319+func (v Value) Int64() (int64, error) {
320320+ n, err := v.getNum(intKind)
321321+ if err != nil {
322322+ return 0, err
323323+ }
324324+ if !n.v.Coeff.IsInt64() {
325325+ if n.v.Negative {
326326+ return math.MinInt64, ErrAbove
327327+ }
328328+ return math.MaxInt64, ErrBelow
329329+ }
330330+ i := n.v.Coeff.Int64()
331331+ if n.v.Negative {
332332+ i = -i
333333+ }
334334+ return i, nil
335335+}
336336+337337+// Uint64 converts the underlying integral number to uint64. It reports an
338338+// error if the underlying value is not an integer type or cannot be represented
339339+// as a uint64. The result is (0, ErrAbove) for x < 0, and
340340+// (math.MaxUint64, ErrBelow) for x > math.MaxUint64.
341341+func (v Value) Uint64() (uint64, error) {
342342+ n, err := v.getNum(intKind)
343343+ if err != nil {
344344+ return 0, err
345345+ }
346346+ if n.v.Negative {
347347+ return 0, ErrAbove
348348+ }
349349+ if !n.v.Coeff.IsUint64() {
350350+ return math.MaxUint64, ErrBelow
351351+ }
352352+ i := n.v.Coeff.Uint64()
353353+ return i, nil
354354+}
355355+356356+// trimZeros trims 0's for better JSON respresentations.
357357+func trimZeros(s string) string {
358358+ n1 := len(s)
359359+ s2 := strings.TrimRight(s, "0")
360360+ n2 := len(s2)
361361+ if p := strings.IndexByte(s2, '.'); p != -1 {
362362+ if p == n2-1 {
363363+ return s[:len(s2)+1]
364364+ }
365365+ return s2
366366+ }
367367+ if n1-n2 <= 4 {
368368+ return s
369369+ }
370370+ return fmt.Sprint(s2, "e+", n1-n2)
371371+}
372372+373373+var (
374374+ smallestPosFloat64 *apd.Decimal
375375+ smallestNegFloat64 *apd.Decimal
376376+ maxPosFloat64 *apd.Decimal
377377+ maxNegFloat64 *apd.Decimal
378378+)
379379+380380+func init() {
381381+ const (
382382+ // math.SmallestNonzeroFloat64: 1 / 2**(1023 - 1 + 52)
383383+ smallest = "4.940656458412465441765687928682213723651e-324"
384384+ // math.MaxFloat64: 2**1023 * (2**53 - 1) / 2**52
385385+ max = "1.797693134862315708145274237317043567981e+308"
386386+ )
387387+ ctx := apd.BaseContext
388388+ ctx.Precision = 40
389389+390390+ var err error
391391+ smallestPosFloat64, _, err = ctx.NewFromString(smallest)
392392+ if err != nil {
393393+ panic(err)
394394+ }
395395+ smallestNegFloat64, _, err = ctx.NewFromString("-" + smallest)
396396+ if err != nil {
397397+ panic(err)
398398+ }
399399+ maxPosFloat64, _, err = ctx.NewFromString(max)
400400+ if err != nil {
401401+ panic(err)
402402+ }
403403+ maxNegFloat64, _, err = ctx.NewFromString("-" + max)
404404+ if err != nil {
405405+ panic(err)
406406+ }
407407+}
408408+409409+// Float64 returns the float64 value nearest to x. It reports an error if v is
410410+// not a number. If x is too small to be represented by a float64 (|x| <
411411+// math.SmallestNonzeroFloat64), the result is (0, ErrBelow) or (-0, ErrAbove),
412412+// respectively, depending on the sign of x. If x is too large to be represented
413413+// by a float64 (|x| > math.MaxFloat64), the result is (+Inf, ErrAbove) or
414414+// (-Inf, ErrBelow), depending on the sign of x.
415415+func (v Value) Float64() (float64, error) {
416416+ n, err := v.getNum(numKind)
417417+ if err != nil {
418418+ return 0, err
419419+ }
420420+ if n.v.Negative {
421421+ if n.v.Cmp(smallestNegFloat64) == 1 {
422422+ return -0, ErrAbove
423423+ }
424424+ if n.v.Cmp(maxNegFloat64) == -1 {
425425+ return math.Inf(-1), ErrBelow
426426+ }
427427+ } else {
428428+ if n.v.Cmp(smallestPosFloat64) == -1 {
429429+ return 0, ErrBelow
430430+ }
431431+ if n.v.Cmp(maxPosFloat64) == 1 {
432432+ return math.Inf(1), ErrAbove
433433+ }
434434+ }
435435+ f, _ := n.v.Float64()
436436+ return f, nil
437437+}
438438+439439+type valueData struct {
440440+ parent *valueData
441441+ feature label
442442+ index uint32
443443+ v evaluated
444444+ raw value
445445+}
446446+447447+// Value holds any value, which may be a Boolean, Error, List, Null, Number,
448448+// Struct, or String.
449449+type Value struct {
450450+ idx *index
451451+ path *valueData
452452+}
453453+454454+func newValueRoot(ctx *context, x value) Value {
455455+ v := x.evalPartial(ctx)
456456+ return Value{ctx.index, &valueData{nil, 0, 0, v, x}}
457457+}
458458+459459+func newChildValue(obj *structValue, i int) Value {
460460+ eval := obj.ctx.manifest(obj.n.at(obj.ctx, i))
461461+ a := obj.n.arcs[i]
462462+ return Value{obj.ctx.index, &valueData{obj.path, a.feature, uint32(i), eval, a.v}}
463463+}
464464+465465+func (v Value) ctx() *context {
466466+ return v.idx.newContext()
467467+}
468468+469469+func (v Value) makeChild(ctx *context, i uint32, f label, eval evaluated, raw value) Value {
470470+ eval = ctx.manifest(eval)
471471+ return Value{v.idx, &valueData{v.path, f, i, eval, raw}}
472472+}
473473+474474+func (v Value) eval(ctx *context) value {
475475+ if v.path == nil || v.path.v == nil {
476476+ panic("undefined value")
477477+ }
478478+ return ctx.manifest(v.path.v)
479479+}
480480+481481+// Default returs v if v.Exists or a value converted from x otherwise.
482482+func (v Value) Default(x interface{}) Value {
483483+ return v
484484+}
485485+486486+// Label reports he label used to obtain this value from the enclosing struct.
487487+//
488488+// TODO: get rid of this somehow. Maybe by passing it to walk
489489+func (v Value) Label() (string, bool) {
490490+ if v.path.feature == 0 {
491491+ return "", false
492492+ }
493493+ return v.idx.labelStr(v.path.feature), true
494494+}
495495+496496+// Kind returns the kind of value. It returns BottomKind for atomic values that
497497+// are not concrete. For instance, it will return BottomKind for the range
498498+// 0..5.
499499+func (v Value) Kind() Kind {
500500+ k := v.eval(v.ctx()).kind()
501501+ if k.isGround() {
502502+ switch {
503503+ case k.isAnyOf(nullKind):
504504+ return NullKind
505505+ case k.isAnyOf(boolKind):
506506+ return BoolKind
507507+ case k.isAnyOf(numKind):
508508+ return NumberKind
509509+ case k.isAnyOf(bytesKind):
510510+ return BytesKind
511511+ case k.isAnyOf(stringKind):
512512+ return StringKind
513513+ case k.isAnyOf(structKind):
514514+ return StructKind
515515+ case k.isAnyOf(listKind):
516516+ return ListKind
517517+ }
518518+ }
519519+ return BottomKind
520520+}
521521+522522+// IncompleteKind returns a mask of all kinds that this value may be.
523523+func (v Value) IncompleteKind() Kind {
524524+ k := v.eval(v.ctx()).kind()
525525+ vk := BottomKind // Everything is a bottom kind.
526526+ for i := kind(1); i < nonGround; i <<= 1 {
527527+ if k&i != 0 {
528528+ switch i {
529529+ case nullKind:
530530+ vk |= NullKind
531531+ case boolKind:
532532+ vk |= BoolKind
533533+ case intKind, floatKind:
534534+ vk |= NumberKind
535535+ case stringKind:
536536+ vk |= StringKind
537537+ case bytesKind:
538538+ vk |= BytesKind
539539+ case structKind:
540540+ vk |= StructKind
541541+ case listKind:
542542+ vk |= ListKind
543543+ }
544544+ }
545545+ }
546546+ return vk
547547+}
548548+549549+// MarshalJSON marshalls this value into valid JSON.
550550+func (v Value) MarshalJSON() (b []byte, err error) {
551551+ if v.path == nil {
552552+ return json.Marshal(nil)
553553+ }
554554+ ctx := v.idx.newContext()
555555+ x := v.eval(ctx)
556556+ // TODO: implement marshalles in value.
557557+ switch k := x.kind(); k {
558558+ case nullKind:
559559+ return json.Marshal(nil)
560560+ case boolKind:
561561+ return json.Marshal(x.(*boolLit).b)
562562+ case intKind, floatKind, numKind:
563563+ return x.(*numLit).v.MarshalText()
564564+ case stringKind:
565565+ return json.Marshal(x.(*stringLit).str)
566566+ case bytesKind:
567567+ return json.Marshal(x.(*bytesLit).b)
568568+ case listKind:
569569+ l := x.(*list)
570570+ i := Iterator{ctx: ctx, val: v, iter: l, len: len(l.a)}
571571+ return marshalList(&i)
572572+ case structKind:
573573+ obj, _ := v.structVal(ctx)
574574+ return obj.MarshalJSON()
575575+ case bottomKind:
576576+ return nil, x.(*bottom)
577577+ default:
578578+ if k.hasReferences() {
579579+ return nil, v.idx.mkErr(x, "value %q contains unresolved references", debugStr(ctx, x))
580580+ }
581581+ if !k.isGround() {
582582+ return nil, v.idx.mkErr(x, "cannot convert incomplete value %q to JSON", debugStr(ctx, x))
583583+ }
584584+ return nil, v.idx.mkErr(x, "cannot convert value %q of type %T to JSON", debugStr(ctx, x), x)
585585+ }
586586+}
587587+588588+// Syntax converts the possibly partially evaluated value into syntax. This
589589+// can use used to print the value with package format.
590590+func (v Value) Syntax() ast.Expr {
591591+ if v.path == nil || v.path.v == nil {
592592+ return nil
593593+ }
594594+ ctx := v.ctx()
595595+ return export(ctx, v.eval(ctx))
596596+}
597597+598598+// Decode initializes x with Value v. If x is a struct, it will validate the
599599+// constraints specified in the field tags.
600600+func (v Value) Decode(x interface{}) error {
601601+ // TODO: optimize
602602+ b, err := v.MarshalJSON()
603603+ if err != nil {
604604+ return err
605605+ }
606606+ return json.Unmarshal(b, x)
607607+}
608608+609609+// // EncodeJSON generates JSON for the given value.
610610+// func (v Value) EncodeJSON(w io.Writer, v Value) error {
611611+// return nil
612612+// }
613613+614614+// Split returns a list of values from which v originated such that
615615+// the unification of all these values equals v and for all returned values
616616+// Source returns a non-nil value.
617617+func (v Value) Split() []Value {
618618+ if v.path == nil {
619619+ return nil
620620+ }
621621+ ctx := v.ctx()
622622+ a := []Value{}
623623+ for _, x := range separate(v.path.raw) {
624624+ path := *v.path
625625+ path.v = x.evalPartial(ctx)
626626+ path.raw = x
627627+ a = append(a, Value{v.idx, &path})
628628+ }
629629+ return a
630630+}
631631+632632+func separate(v value) (a []value) {
633633+ c := v.computed()
634634+ if c == nil {
635635+ return []value{v}
636636+ }
637637+ if c.x != nil {
638638+ a = append(a, separate(c.x)...)
639639+ }
640640+ if c.y != nil {
641641+ a = append(a, separate(c.y)...)
642642+ }
643643+ return a
644644+}
645645+646646+// Source returns the original node for this value. The return value may not
647647+// be a syntax.Expr. For instance, a struct kind may be represented by a
648648+// struct literal, a field comprehension, or a file. It returns nil for
649649+// computed nodes. Use Split to get all source values that apply to a field.
650650+func (v Value) Source() ast.Node {
651651+ if v.path == nil {
652652+ return nil
653653+ }
654654+ return v.path.raw.syntax()
655655+}
656656+657657+// Err returns the error represented by v or nil v is not an error.
658658+func (v Value) Err() error {
659659+ if err := v.checkKind(v.ctx(), bottomKind); err != nil {
660660+ return err
661661+ }
662662+ return nil
663663+}
664664+665665+// Pos returns position information.
666666+func (v Value) Pos() token.Position {
667667+ if v.path == nil || v.Source() == nil {
668668+ return token.Position{}
669669+ }
670670+ pos := v.Source().Pos()
671671+ return v.idx.fset.Position(pos)
672672+}
673673+674674+// IsIncomplete indicates that the value cannot be fully evaluated due to
675675+// insufficient information.
676676+func (v Value) IsIncomplete() bool {
677677+ x := v.eval(v.ctx())
678678+ if x.kind().hasReferences() || !x.kind().isGround() {
679679+ return true
680680+ }
681681+ return isIncomplete(x)
682682+}
683683+684684+// IsValid reports whether this value is defined and evaluates to something
685685+// other than an error.
686686+func (v Value) IsValid() bool {
687687+ if v.path == nil || v.path.v == nil {
688688+ return false
689689+ }
690690+ k := v.eval(v.ctx()).kind()
691691+ return k != bottomKind && !v.IsIncomplete()
692692+}
693693+694694+// Exists reports whether this value existed in the configuration.
695695+func (v Value) Exists() bool {
696696+ if v.path == nil {
697697+ return false
698698+ }
699699+ return exists(v.eval(v.ctx()))
700700+}
701701+702702+func (v Value) checkKind(ctx *context, want kind) *bottom {
703703+ if v.path == nil {
704704+ return errNotExists
705705+ }
706706+ // TODO: use checkKind
707707+ x := v.eval(ctx)
708708+ if b, ok := x.(*bottom); ok {
709709+ return b
710710+ }
711711+ got := x.kind()
712712+ if got&want&concreteKind == bottomKind && want != bottomKind {
713713+ return ctx.mkErr(x, "not of right kind (%v vs %v)", got, want)
714714+ }
715715+ if !got.isGround() {
716716+ return ctx.mkErr(x, codeIncomplete,
717717+ "non-concrete value %v when evaluating config file", got)
718718+ }
719719+ return nil
720720+}
721721+722722+// List creates an iterator over the values of a list or reports an error if
723723+// v is not a list.
724724+func (v Value) List() (Iterator, error) {
725725+ ctx := v.ctx()
726726+ if err := v.checkKind(ctx, listKind); err != nil {
727727+ return Iterator{ctx: ctx}, err
728728+ }
729729+ l := v.eval(ctx).(*list)
730730+ return Iterator{ctx: ctx, val: v, iter: l, len: len(l.a)}, nil
731731+}
732732+733733+// Null reports an error if v is not null.
734734+func (v Value) Null() error {
735735+ if err := v.checkKind(v.ctx(), nullKind); err != nil {
736736+ return err
737737+ }
738738+ return nil
739739+}
740740+741741+// IsNull reports whether v is null.
742742+func (v Value) IsNull() bool {
743743+ return v.Null() == nil
744744+}
745745+746746+// Bool returns the bool value of v or false and an error if v is not a boolean.
747747+func (v Value) Bool() (bool, error) {
748748+ ctx := v.ctx()
749749+ if err := v.checkKind(ctx, boolKind); err != nil {
750750+ return false, err
751751+ }
752752+ return v.eval(ctx).(*boolLit).b, nil
753753+}
754754+755755+// String returns the string value if v is a string or an error otherwise.
756756+func (v Value) String() (string, error) {
757757+ ctx := v.ctx()
758758+ if err := v.checkKind(ctx, stringKind); err != nil {
759759+ return "", err
760760+ }
761761+ return v.eval(ctx).(*stringLit).str, nil
762762+}
763763+764764+// Bytes returns a byte slice if v represents a list of bytes or an error
765765+// otherwise.
766766+func (v Value) Bytes() ([]byte, error) {
767767+ ctx := v.ctx()
768768+ switch x := v.eval(ctx).(type) {
769769+ case *bytesLit:
770770+ return append([]byte(nil), x.b...), nil
771771+ case *stringLit:
772772+ return []byte(x.str), nil
773773+ }
774774+ return nil, v.checkKind(ctx, bytesKind|stringKind)
775775+}
776776+777777+// Reader returns a new Reader if v is a string or bytes type and an error
778778+// otherwise.
779779+func (v Value) Reader() (io.Reader, error) {
780780+ ctx := v.ctx()
781781+ switch x := v.eval(ctx).(type) {
782782+ case *bytesLit:
783783+ return bytes.NewReader(x.b), nil
784784+ case *stringLit:
785785+ return strings.NewReader(x.str), nil
786786+ }
787787+ return nil, v.checkKind(ctx, stringKind|bytesKind)
788788+}
789789+790790+// structVal returns an structVal or an error if v is not a struct.
791791+func (v Value) structVal(ctx *context) (structValue, error) {
792792+ if err := v.checkKind(ctx, structKind); err != nil {
793793+ return structValue{}, err
794794+ }
795795+ obj := v.eval(ctx).(*structLit)
796796+797797+ // check if any labels are hidden
798798+ f := label(0)
799799+ for _, a := range obj.arcs {
800800+ f |= a.feature
801801+ }
802802+803803+ if f&hidden != 0 {
804804+ arcs := make([]arc, len(obj.arcs))
805805+ k := 0
806806+ for _, a := range obj.arcs {
807807+ if a.feature&hidden == 0 {
808808+ arcs[k] = a
809809+ k++
810810+ }
811811+ }
812812+ arcs = arcs[:k]
813813+ obj = &structLit{
814814+ obj.baseValue,
815815+ obj.emit,
816816+ obj.template,
817817+ arcs,
818818+ }
819819+820820+ }
821821+ return structValue{ctx, v.path, obj}, nil
822822+}
823823+824824+func (v Value) structValWithHidden(ctx *context) (structValue, error) {
825825+ if err := v.checkKind(ctx, structKind); err != nil {
826826+ return structValue{}, err
827827+ }
828828+ obj := v.eval(ctx).(*structLit)
829829+830830+ return structValue{ctx, v.path, obj}, nil
831831+}
832832+833833+// Fields creates an iterator over v's fields if v is a struct or an error
834834+// otherwise.
835835+func (v Value) Fields() (Iterator, error) {
836836+ ctx := v.ctx()
837837+ obj, err := v.structVal(ctx)
838838+ if err != nil {
839839+ return Iterator{ctx: ctx}, err
840840+ }
841841+ return Iterator{ctx: ctx, val: v, iter: obj.n, len: len(obj.n.arcs)}, nil
842842+}
843843+844844+// AllFields creates an iterator over all of v's fields, including the hidden
845845+// ones, if v is a struct or an error otherwise.
846846+func (v Value) AllFields() (Iterator, error) {
847847+ ctx := v.ctx()
848848+ obj, err := v.structValWithHidden(ctx)
849849+ if err != nil {
850850+ return Iterator{ctx: ctx}, err
851851+ }
852852+ return Iterator{ctx: ctx, val: v, iter: obj.n, len: len(obj.n.arcs)}, nil
853853+}
854854+855855+// Lookup reports the value starting from v, or an error if the path is not
856856+// found. The empty path returns v itself.
857857+//
858858+// Lookup cannot be used to look up hidden fields.
859859+func (v Value) Lookup(path ...string) Value {
860860+ ctx := v.ctx()
861861+ for _, k := range path {
862862+ obj, err := v.structVal(ctx)
863863+ if err != nil {
864864+ return newValueRoot(ctx, err.(*bottom))
865865+ }
866866+ v = obj.Lookup(k)
867867+ }
868868+ return v
869869+}
870870+871871+// Template returns a function that represents the template definition for a
872872+// struct in a configuration file. It returns nil if v is not a struct kind or
873873+// if there is no template associated with the struct.
874874+//
875875+// The returned function returns the value that would be unified with field
876876+// given its name.
877877+func (v Value) Template() func(label string) Value {
878878+ ctx := v.ctx()
879879+ x, ok := v.path.v.(*structLit)
880880+ if !ok || x.template == nil {
881881+ return nil
882882+ }
883883+ fn, ok := ctx.manifest(x.template).(*lambdaExpr)
884884+ if !ok {
885885+ return nil
886886+ }
887887+ return func(label string) Value {
888888+ arg := &stringLit{x.baseValue, label}
889889+ y := fn.call(ctx, x, arg)
890890+ return newValueRoot(ctx, y)
891891+ }
892892+}
893893+894894+// Subsumes reports whether w is an instance of v.
895895+//
896896+// Value v and w must be obtained from the same build.
897897+// TODO: remove this requirement.
898898+func (v Value) Subsumes(w Value) bool {
899899+ ctx := v.ctx()
900900+ return subsumes(ctx, v.eval(ctx), w.eval(ctx), subChoose)
901901+}
902902+903903+// Unify reports the greatest lower bound of v and w.
904904+//
905905+// Value v and w must be obtained from the same build.
906906+// TODO: remove this requirement.
907907+func (v Value) Unify(w Value) Value {
908908+ ctx := v.ctx()
909909+ if v.path == nil {
910910+ return w
911911+ }
912912+ if w.path == nil {
913913+ return v
914914+ }
915915+ a := v.eval(ctx)
916916+ b := w.eval(ctx)
917917+ val := ctx.manifest(mkBin(ctx, token.NoPos, opUnify, a, b))
918918+ if err := validate(ctx, val); err != nil {
919919+ val = err
920920+ }
921921+ return newValueRoot(ctx, val)
922922+}
923923+924924+// Format prints a debug version of a value.
925925+func (v Value) Format(state fmt.State, verb rune) {
926926+ ctx := v.ctx()
927927+ if v.path == nil {
928928+ fmt.Fprint(state, "<nil>")
929929+ return
930930+ }
931931+ io.WriteString(state, debugStr(ctx, v.path.v))
932932+}
933933+934934+// References reports all references used to evaluate this value. It does not
935935+// report references for sub fields if v is a struct.
936936+func (v Value) References() [][]string {
937937+ ctx := v.ctx()
938938+ pf := pathFinder{up: v.path}
939939+ raw := v.path.raw
940940+ if raw == nil {
941941+ return nil
942942+ }
943943+ rewrite(ctx, raw, pf.find)
944944+ return pf.paths
945945+}
946946+947947+type pathFinder struct {
948948+ paths [][]string
949949+ stack []string
950950+ up *valueData
951951+}
952952+953953+func (p *pathFinder) find(ctx *context, v value) (value, bool) {
954954+ switch x := v.(type) {
955955+ case *selectorExpr:
956956+ i := len(p.stack)
957957+ p.stack = append(p.stack, ctx.labelStr(x.feature))
958958+ rewrite(ctx, x.x, p.find)
959959+ p.stack = p.stack[:i]
960960+ return v, false
961961+ case *nodeRef:
962962+ i := len(p.stack)
963963+ up := p.up
964964+ for ; up != nil && up.v != x.node.(value); up = up.parent {
965965+ }
966966+ for ; up != nil && up.feature > 0; up = up.parent {
967967+ p.stack = append(p.stack, ctx.labelStr(up.feature))
968968+ }
969969+ path := make([]string, len(p.stack))
970970+ for i, v := range p.stack {
971971+ path[len(path)-1-i] = v
972972+ }
973973+ p.paths = append(p.paths, path)
974974+ p.stack = p.stack[:i]
975975+ return v, false
976976+ case *structLit: // handled in sub fields
977977+ return v, false
978978+ }
979979+ return v, true
980980+}
981981+982982+// Validate reports any errors, recursively. The returned error may be an
983983+// errors.List reporting multiple errors, where the total number of errors
984984+// reported may be less than the actual number.
985985+func (v Value) Validate() error {
986986+ list := errors.List{}
987987+ v.Walk(func(v Value) bool {
988988+ if err := v.Err(); err != nil {
989989+ list.Add(err)
990990+ if len(list) > 50 {
991991+ return false // mostly to avoid some hypothetical cycle issue
992992+ }
993993+ }
994994+ return true
995995+ }, nil)
996996+ if len(list) > 0 {
997997+ list.Sort()
998998+ // list.RemoveMultiples() // TODO: use RemoveMultiples when it is fixed
999999+ return list
10001000+ }
10011001+ return nil
10021002+}
10031003+10041004+// Walk descends into all values of v, calling f. If f returns false, Walk
10051005+// will not descent further.
10061006+func (v Value) Walk(before func(Value) bool, after func(Value)) {
10071007+ ctx := v.ctx()
10081008+ switch v.Kind() {
10091009+ case StructKind:
10101010+ if before != nil && !before(v) {
10111011+ return
10121012+ }
10131013+ obj, _ := v.structVal(ctx)
10141014+ for i := 0; i < obj.Len(); i++ {
10151015+ _, v := obj.At(i)
10161016+ v.Walk(before, after)
10171017+ }
10181018+ case ListKind:
10191019+ if before != nil && !before(v) {
10201020+ return
10211021+ }
10221022+ list, _ := v.List()
10231023+ for list.Next() {
10241024+ list.Value().Walk(before, after)
10251025+ }
10261026+ default:
10271027+ if before != nil {
10281028+ before(v)
10291029+ }
10301030+ }
10311031+ if after != nil {
10321032+ after(v)
10331033+ }
10341034+}
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+// validate returns whether there is any error, recursively.
1818+func validate(ctx *context, v value) *bottom {
1919+ eval := v.evalPartial(ctx)
2020+ if err, ok := eval.(*bottom); ok && err.code != codeIncomplete {
2121+ return eval.(*bottom)
2222+ }
2323+ switch x := eval.(type) {
2424+ case *structLit:
2525+ for i := range x.arcs {
2626+ if err := validate(ctx, x.at(ctx, i)); err != nil {
2727+ return err
2828+ }
2929+ }
3030+ case *list:
3131+ for _, v := range x.a {
3232+ if err := validate(ctx, v); err != nil {
3333+ return err
3434+ }
3535+ }
3636+ }
3737+ return nil
3838+}
+1145
cue/value.go
···11+// Copyright 2018 The CUE Authors
22+//
33+// Licensed under the Apache License, Version 2.0 (the "License");
44+// you may not use this file except in compliance with the License.
55+// You may obtain a copy of the License at
66+//
77+// http://www.apache.org/licenses/LICENSE-2.0
88+//
99+// Unless required by applicable law or agreed to in writing, software
1010+// distributed under the License is distributed on an "AS IS" BASIS,
1111+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212+// See the License for the specific language governing permissions and
1313+// limitations under the License.
1414+1515+package cue
1616+1717+import (
1818+ "fmt"
1919+ "math/big"
2020+ "sort"
2121+ "strconv"
2222+ "strings"
2323+ "time"
2424+2525+ "cuelang.org/go/cue/ast"
2626+ "cuelang.org/go/cue/token"
2727+ "github.com/cockroachdb/apd"
2828+)
2929+3030+type value interface {
3131+ source
3232+3333+ rewrite(*context, rewriteFunc) value
3434+3535+ // evalPartial evaluates a value without choosing default values.
3636+ evalPartial(*context) evaluated
3737+3838+ kind() kind
3939+4040+ // subsumesImpl is only defined for non-reference types.
4141+ // It should only be called by the subsumes function.
4242+ subsumesImpl(*context, value, subsumeMode) bool
4343+}
4444+4545+type evaluated interface {
4646+ value
4747+ binOp(*context, source, op, evaluated) evaluated
4848+ strValue() string
4949+}
5050+5151+type scope interface {
5252+ value
5353+ lookup(*context, label) (e evaluated, raw value)
5454+}
5555+5656+type atter interface {
5757+ // at returns the evaluated and its original value at the given position.
5858+ // If the original could not be found, it returns an error and nil.
5959+ at(*context, int) evaluated
6060+}
6161+6262+type iterAtter interface {
6363+ // at returns the evaluated and its original value at the given position.
6464+ // If the original could not be found, it returns an error and nil.
6565+ iterAt(*context, int) (evaluated, value, label)
6666+}
6767+6868+// caller must be implemented by any concrete lambdaKind
6969+type caller interface {
7070+ call(ctx *context, src source, args ...evaluated) value
7171+ returnKind() kind
7272+}
7373+7474+func checkKind(ctx *context, x value, want kind) *bottom {
7575+ if b, ok := x.(*bottom); ok {
7676+ return b
7777+ }
7878+ got := x.kind()
7979+ if got&want&concreteKind == bottomKind && want != bottomKind {
8080+ return ctx.mkErr(x, "not of right kind (%v vs %v)", got, want)
8181+ }
8282+ if !got.isGround() {
8383+ return ctx.mkErr(x, codeIncomplete,
8484+ "non-concrete value %v", got)
8585+ }
8686+ return nil
8787+}
8888+8989+func newDecl(n ast.Decl) baseValue {
9090+ if n == nil {
9191+ panic("empty node")
9292+ }
9393+ return baseValue{n}
9494+}
9595+9696+func newExpr(n ast.Expr) baseValue {
9797+ if n == nil {
9898+ panic("empty node")
9999+ }
100100+ return baseValue{n}
101101+}
102102+103103+func newNode(n ast.Node) baseValue {
104104+ if n == nil {
105105+ panic("empty node")
106106+ }
107107+ return baseValue{n}
108108+}
109109+110110+type source interface {
111111+ // syntax returns the parsed file of the underlying node or a computed
112112+ // node indicating that it is a computed binary expression.
113113+ syntax() ast.Node
114114+ computed() *computedSource
115115+ Pos() token.Pos
116116+ base() baseValue
117117+}
118118+119119+type computedSource struct {
120120+ pos token.Pos
121121+ op op
122122+ x value
123123+ y value
124124+}
125125+126126+func (s *computedSource) Pos() token.Pos {
127127+ return s.pos
128128+}
129129+130130+type posser interface {
131131+ Pos() token.Pos
132132+}
133133+134134+type baseValue struct {
135135+ pos posser
136136+}
137137+138138+func (b baseValue) Pos() token.Pos {
139139+ if b.pos == nil {
140140+ return token.NoPos
141141+ }
142142+ return b.pos.Pos()
143143+}
144144+145145+func (b baseValue) computed() *computedSource {
146146+ switch x := b.pos.(type) {
147147+ case *computedSource:
148148+ return x
149149+ }
150150+ return nil
151151+}
152152+153153+func (b baseValue) syntax() ast.Node {
154154+ switch x := b.pos.(type) {
155155+ case ast.Node:
156156+ return x
157157+ }
158158+ return nil
159159+}
160160+161161+func (b baseValue) base() baseValue {
162162+ return b
163163+}
164164+165165+func (x baseValue) strValue() string { panic("unimplemented") }
166166+func (x baseValue) returnKind() kind { panic("unimplemented") }
167167+168168+// top is the top of the value lattice. It subsumes all possible values.
169169+type top struct{ baseValue }
170170+171171+func (x *top) kind() kind { return topKind }
172172+173173+// basicType represents the root class of any specific type.
174174+type basicType struct {
175175+ baseValue
176176+ k kind
177177+}
178178+179179+func (x *basicType) kind() kind { return x.k | nonGround }
180180+181181+// Literals
182182+183183+type nullLit struct{ baseValue }
184184+185185+func (x *nullLit) kind() kind { return nullKind }
186186+187187+type boolLit struct {
188188+ baseValue
189189+ b bool
190190+}
191191+192192+func (x *boolLit) kind() kind { return boolKind }
193193+194194+func boolTonode(src source, b bool) evaluated {
195195+ return &boolLit{src.base(), b}
196196+}
197197+198198+type bytesLit struct {
199199+ baseValue
200200+ b []byte
201201+ // TODO: maintain extended grapheme index cache.
202202+}
203203+204204+func (x *bytesLit) kind() kind { return bytesKind }
205205+func (x *bytesLit) strValue() string { return string(x.b) }
206206+207207+func (x *bytesLit) iterAt(ctx *context, i int) (evaluated, value, label) {
208208+ if i >= len(x.b) {
209209+ return nil, nil, 0
210210+ }
211211+ v := x.at(ctx, i)
212212+ return v, v, 0
213213+}
214214+215215+func (x *bytesLit) at(ctx *context, i int) evaluated {
216216+ if i < 0 || i >= len(x.b) {
217217+ return ctx.mkErr(x, "index %d out of bounds", i)
218218+ }
219219+ // TODO: this is incorrect.
220220+ n := newNum(x, intKind)
221221+ n.v.SetInt64(int64(x.b[i]))
222222+ return n
223223+}
224224+225225+func (x *bytesLit) len() int { return len(x.b) }
226226+227227+func (x *bytesLit) slice(ctx *context, lo, hi *numLit) evaluated {
228228+ lox := 0
229229+ hix := len(x.b)
230230+ if lo != nil {
231231+ lox = lo.intValue(ctx)
232232+ }
233233+ if hi != nil {
234234+ hix = hi.intValue(ctx)
235235+ }
236236+ if lox < 0 {
237237+ return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", lox)
238238+ }
239239+ if hix < 0 {
240240+ return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", hix)
241241+ }
242242+ if hix < lox {
243243+ return ctx.mkErr(x, "invalid slice index: %d > %d", lox, hix)
244244+ }
245245+ if len(x.b) < hix {
246246+ return ctx.mkErr(hi, "slice bounds out of range")
247247+ }
248248+ return &bytesLit{x.baseValue, x.b[lox:hix]}
249249+}
250250+251251+type stringLit struct {
252252+ baseValue
253253+ str string
254254+255255+ // TODO: maintain extended grapheme index cache.
256256+}
257257+258258+func (x *stringLit) kind() kind { return stringKind }
259259+func (x *stringLit) strValue() string { return x.str }
260260+261261+func (x *stringLit) iterAt(ctx *context, i int) (evaluated, value, label) {
262262+ runes := []rune(x.str)
263263+ if i >= len(runes) {
264264+ return nil, nil, 0
265265+ }
266266+ v := x.at(ctx, i)
267267+ return v, v, 0
268268+}
269269+270270+func (x *stringLit) at(ctx *context, i int) evaluated {
271271+ runes := []rune(x.str)
272272+ if i < 0 || i >= len(runes) {
273273+ return ctx.mkErr(x, "index %d out of bounds", i)
274274+ }
275275+ // TODO: this is incorrect.
276276+ return &stringLit{x.baseValue, string(runes[i : i+1])}
277277+}
278278+func (x *stringLit) len() int { return len([]rune(x.str)) }
279279+280280+func (x *stringLit) slice(ctx *context, lo, hi *numLit) evaluated {
281281+ runes := []rune(x.str)
282282+ lox := 0
283283+ hix := len(runes)
284284+ if lo != nil {
285285+ lox = lo.intValue(ctx)
286286+ }
287287+ if hi != nil {
288288+ hix = hi.intValue(ctx)
289289+ }
290290+ if lox < 0 {
291291+ return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", lox)
292292+ }
293293+ if hix < 0 {
294294+ return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", hix)
295295+ }
296296+ if hix < lox {
297297+ return ctx.mkErr(x, "invalid slice index: %d > %d", lox, hix)
298298+ }
299299+ if len(runes) < hix {
300300+ return ctx.mkErr(hi, "slice bounds out of range")
301301+ }
302302+ return &stringLit{x.baseValue, string(runes[lox:hix])}
303303+}
304304+305305+type numBase struct {
306306+ baseValue
307307+ numInfo
308308+}
309309+310310+func newNumBase(n ast.Expr, info numInfo) numBase {
311311+ return numBase{newExpr(n), info}
312312+}
313313+314314+func newNumBin(k kind, a, b *numLit) *numLit {
315315+ n := &numLit{
316316+ numBase: numBase{
317317+ baseValue: a.baseValue,
318318+ numInfo: unifyNuminfo(a.numInfo, b.numInfo),
319319+ },
320320+ }
321321+ return n
322322+}
323323+324324+func resultNumBase(a, b numBase) numBase {
325325+ return numBase{
326326+ baseValue: a.baseValue,
327327+ numInfo: unifyNuminfo(a.numInfo, b.numInfo),
328328+ }
329329+}
330330+331331+type numLit struct {
332332+ numBase
333333+ v apd.Decimal
334334+}
335335+336336+func parseInt(k kind, s string) *numLit {
337337+ n := &ast.BasicLit{
338338+ Kind: token.INT,
339339+ Value: s,
340340+ }
341341+ num := newNum(newExpr(n), k)
342342+ _, _, err := num.v.SetString(s)
343343+ if err != nil {
344344+ panic(err)
345345+ }
346346+ return num
347347+}
348348+349349+func newNum(src source, k kind) *numLit {
350350+ n := &numLit{numBase: numBase{baseValue: src.base()}}
351351+ n.k = k
352352+ return n
353353+}
354354+355355+var ten = big.NewInt(10)
356356+357357+func (x *numLit) kind() kind { return x.k }
358358+func (x *numLit) strValue() string { return x.v.String() }
359359+360360+func (x *numLit) isInt(ctx *context) bool {
361361+ return x.kind()&intKind != 0
362362+}
363363+364364+func (x *numLit) intValue(ctx *context) int {
365365+ v, err := x.v.Int64()
366366+ if err != nil {
367367+ ctx.mkErr(x, "intValue: %v", err)
368368+ return 0
369369+ }
370370+ return int(v)
371371+}
372372+373373+func intFromGo(s string) *numLit {
374374+ num := &numLit{}
375375+ num.k = intKind
376376+ var ok bool
377377+ switch {
378378+ case strings.HasPrefix(s, "0x"), strings.HasPrefix(s, "0X"):
379379+ _, ok = num.v.Coeff.SetString(s, 16)
380380+ case strings.HasPrefix(s, "0"):
381381+ _, ok = num.v.Coeff.SetString(s, 16)
382382+ default:
383383+ _, cond, err := num.v.SetString(s)
384384+ ok = cond == 0 && err == nil
385385+ }
386386+ if !ok {
387387+ panic(fmt.Sprintf("could not parse number %q", s))
388388+ }
389389+ return num
390390+}
391391+392392+func floatFromGo(s string) *numLit {
393393+ num := &numLit{}
394394+ num.k = floatKind
395395+ num.v.SetString(s)
396396+ return num
397397+}
398398+399399+type durationLit struct {
400400+ baseValue
401401+ d time.Duration
402402+}
403403+404404+func (x *durationLit) kind() kind { return durationKind }
405405+func (x *durationLit) strValue() string { return x.d.String() }
406406+407407+type rangeLit struct {
408408+ baseValue
409409+ from, to value
410410+}
411411+412412+func (x *rangeLit) kind() kind {
413413+ return unifyType(x.from.kind(), x.to.kind()) | nonGround
414414+}
415415+416416+func mkIntRange(a, b string) *rangeLit {
417417+ from := parseInt(intKind, a)
418418+ to := parseInt(intKind, b)
419419+ return &rangeLit{
420420+ binSrc(token.NoPos, opRange, from, to),
421421+ from,
422422+ to,
423423+ }
424424+}
425425+426426+var predefinedRanges = map[string]*rangeLit{
427427+ "rune": mkIntRange("0", strconv.Itoa(0x10FFFF)),
428428+ "int8": mkIntRange("-128", "127"),
429429+ "int16": mkIntRange("-32768", "32767"),
430430+ "int32": mkIntRange("-2147483648", "2147483647"),
431431+ "int64": mkIntRange("-9223372036854775808", "9223372036854775807"),
432432+ "int128": mkIntRange(
433433+ "-170141183460469231731687303715884105728",
434434+ "170141183460469231731687303715884105727"),
435435+436436+ // Do not include an alias for "byte", as it would be too easily confused
437437+ // with the builtin "bytes".
438438+ "uint8": mkIntRange("0", "255"),
439439+ "uint16": mkIntRange("0", "65535"),
440440+ "uint32": mkIntRange("0", "4294967295"),
441441+ "uint64": mkIntRange("0", "18446744073709551615"),
442442+ "uint128": mkIntRange("0", "340282366920938463463374607431768211455"),
443443+}
444444+445445+type interpolation struct {
446446+ baseValue
447447+ k kind // string or bytes
448448+ parts []value // odd: strings, even expressions
449449+}
450450+451451+func (x *interpolation) kind() kind { return x.k | nonGround }
452452+453453+type list struct {
454454+ baseValue
455455+ // TODO: Elements in a list are nodes to allow for cycle detection.
456456+ a []value // TODO: could be arc?
457457+458458+ typ value
459459+ len value
460460+}
461461+462462+// initLit initializes a literal list.
463463+func (x *list) initLit() {
464464+ n := newNum(x, intKind)
465465+ n.v.SetInt64(int64(len(x.a)))
466466+ x.len = n
467467+ x.typ = &top{x.baseValue}
468468+}
469469+470470+func (x *list) kind() kind {
471471+ // Any open list has a default manifestation and can thus always be
472472+ // interpreted as ground (ignoring non-ground elements).
473473+ return listKind
474474+}
475475+476476+// at returns the evaluated and original value of position i. List x must
477477+// already have been evaluated. It returns an error and nil if there was an
478478+// issue evaluating the list itself.
479479+func (x *list) at(ctx *context, i int) evaluated {
480480+ e, _, _ := x.iterAt(ctx, i)
481481+ if e == nil {
482482+ return ctx.mkErr(x, "index %d out of bounds", i)
483483+ }
484484+ return e
485485+}
486486+487487+// iterAt returns the evaluated and original value of position i. List x must
488488+// already have been evaluated. It returns an error and nil if there was an
489489+// issue evaluating the list itself.
490490+func (x *list) iterAt(ctx *context, i int) (evaluated, value, label) {
491491+ if i < 0 {
492492+ return ctx.mkErr(x, "index %d out of bounds", i), nil, 0
493493+ }
494494+ if i < len(x.a) {
495495+ return x.a[i].evalPartial(ctx), x.a[i], 0
496496+ }
497497+ max := maxNum(x.len.(evaluated))
498498+ if max.kind().isGround() {
499499+ if max.kind()&intKind == bottomKind {
500500+ return ctx.mkErr(max, "length indicator of list not of type int"), nil, 0
501501+ }
502502+ n := max.(*numLit).intValue(ctx)
503503+ if i >= n {
504504+ return nil, nil, 0
505505+ }
506506+ }
507507+ return x.typ.(evaluated), x.typ, 0
508508+}
509509+510510+func (x *list) isOpen() bool {
511511+ return !x.len.kind().isGround()
512512+}
513513+514514+// lo and hi must be nil or a ground integer.
515515+func (x *list) slice(ctx *context, lo, hi *numLit) evaluated {
516516+ a := x.a
517517+ max := maxNum(x.len.(evaluated))
518518+ if hi != nil {
519519+ n := hi.intValue(ctx)
520520+ if n < 0 {
521521+ return ctx.mkErr(x, "negative slice index")
522522+ }
523523+ if max.kind().isGround() && !leq(ctx, hi, hi, max) {
524524+ return ctx.mkErr(hi, "slice bounds out of range")
525525+ }
526526+ max = hi
527527+ if n < len(a) {
528528+ a = a[:n]
529529+ }
530530+ }
531531+532532+ if lo != nil {
533533+ n := lo.intValue(ctx)
534534+ if n < 0 {
535535+ return ctx.mkErr(x, "negative slice index")
536536+ }
537537+ if n > 0 && max.kind().isGround() {
538538+ if !leq(ctx, lo, lo, max) {
539539+ max := max.(*numLit).intValue(ctx)
540540+ return ctx.mkErr(x, "invalid slice index: %v > %v", n, max)
541541+ }
542542+ max = binOp(ctx, lo, opSub, max, lo)
543543+ }
544544+ if n < len(a) {
545545+ a = a[n:]
546546+ } else {
547547+ a = []value{}
548548+ }
549549+ }
550550+ return &list{baseValue: x.baseValue, a: a, typ: x.typ, len: max}
551551+}
552552+553553+// An structLit is a single structLit in the configuration tree.
554554+//
555555+// An structLit may have multiple arcs. There may be only one arc per label. Use
556556+// insertRaw to insert arcs to ensure this invariant holds.
557557+type structLit struct {
558558+ baseValue
559559+ emit value // currently only supported at top level.
560560+561561+ template value
562562+ // TODO: consider hoisting the template arc to its own value.
563563+ arcs []arc
564564+}
565565+566566+func newStruct(src source) *structLit {
567567+ return &structLit{baseValue: src.base()}
568568+}
569569+570570+func (x *structLit) kind() kind { return structKind }
571571+572572+type arcs []arc
573573+574574+func (x *structLit) Len() int { return len(x.arcs) }
575575+func (x *structLit) Less(i, j int) bool { return x.arcs[i].feature < x.arcs[j].feature }
576576+func (x *structLit) Swap(i, j int) { x.arcs[i], x.arcs[j] = x.arcs[j], x.arcs[i] }
577577+578578+// lookup returns the node for the given label f, if present, or nil otherwise.
579579+func (x *structLit) lookup(ctx *context, f label) (v evaluated, raw value) {
580580+ // Lookup is done by selector or index references. Either this is done on
581581+ // literal nodes or nodes obtained from references. In the later case,
582582+ // noderef will have ensured that the ancestors were evaluated.
583583+ for i, a := range x.arcs {
584584+ if a.feature == f {
585585+ return x.at(ctx, i), a.v
586586+ }
587587+ }
588588+ return nil, nil
589589+}
590590+591591+func (x *structLit) iterAt(ctx *context, i int) (evaluated, value, label) {
592592+ if i >= len(x.arcs) {
593593+ return nil, nil, 0
594594+ }
595595+ v := x.at(ctx, i)
596596+ return v, x.arcs[i].v, x.arcs[i].feature // TODO: return template & v for original?
597597+}
598598+599599+// Cycle Handling
600600+//
601601+// Structs (and thus lists)
602602+//
603603+// Unresolved cycle
604604+// a: b // _|_
605605+// b: a // _|_
606606+//
607607+// a: b | {c:1} // _|_
608608+// b: a | {d:1} // _|_
609609+//
610610+// Resolved cycles
611611+// a: b // {c:1} : b -> a&{c:1} ->a&{c:1}[a:cycle error] -> {c:1}
612612+// b: a & { c: 1 } // {c:1}
613613+//
614614+// a: b & { d: 1 } // {c:1, d:1}
615615+// b: a & { c: 1 } // {c:1, d:1}
616616+//
617617+// To resolve cycles in disjunctions, the unification operations need to be
618618+// rewritten before that disjunction values are unified. This is optional for
619619+// CUE implementations.
620620+// a: b | {d:1} // {c:1} | {d:1}
621621+// b: a & {c:1} // b & {c:1} | {d:1}&{c:1} -> {c:1} | {c:1,d:1}
622622+//
623623+//
624624+// Atoms
625625+// a: b + 100 // _|_
626626+// b: a - 100 // _|_
627627+//
628628+// a: b + 100 // 200
629629+// b: a - 100 // 100 + check 100 & (a-100)
630630+// b: 100
631631+//
632632+// a: b+100 | b+50 // 200 | 150
633633+// b: a-100 | a-50 // 100 + check 100 & (a-100 | a-50)
634634+// b: 100
635635+636636+// TODO: Question: defining an interpration of a constraint structure with no
637637+// default resolution applied versus one there is. And given a substitution that
638638+// is valid for both interpretation, resulting in a an b, respectively. Is there
639639+// any expression in which a an b can be substituted for which the fully
640640+// evaluated interpretation can yield different results? If so, can we define
641641+// disjunction in a way that it does not?
642642+// ANSWER: NO. But is it sufficient to only require this for direct references?
643643+// Maybe, but at least it holds in that case.
644644+// f1: a1 | ... | an
645645+// f2: f1
646646+// f2: b1 | ... | bm | ... | bn
647647+// -- Suppose the element that unifies with a1 in f2 is bm.
648648+// Is a1 & bm the same answer if f2 referencing f1 referred to the
649649+// disjunction?
650650+// Assume that some ax, x > 1 unifies with a by, y < m.
651651+// This would be an ambiguous disjunction, and by definition invalid.
652652+// The first valid disjunction is one where bm is the first to match
653653+// any of the values in f1. The result will therefore be the same.
654654+//
655655+// Case 1
656656+// replicas: 1 | int
657657+//
658658+// foo: 1 | 2 // interpretations must be equal or else the value crosses
659659+// foo: replicas
660660+//
661661+// Case 2
662662+// a: {
663663+// replicas: 1 | int
664664+// b: {chk: 0, num: 4 } | { chk: int, e: 5, f: int } | { chk: 1, e: 6, f: 7 }
665665+// b chk: replicas // { chk: 1, num: 5 }
666666+// c: 1/(replicas-1) | 0 // 0
667667+// }
668668+//
669669+// b: {
670670+// b chk f: 7
671671+// }
672672+//
673673+// This may be an issue, but by defining all expressions to be lazily evaluated,
674674+// this is not a surprise. We could have a cue.Choose() builtin to pick
675675+// the disjunctions recursively. Note that within a single struct, though, the
676676+// selection for a field is always unique. It may only vary if a substructure
677677+// is referred to in a new substructure.
678678+679679+func (x *structLit) at(ctx *context, i int) evaluated {
680680+ // Lookup is done by selector or index references. Either this is done on
681681+ // literal nodes or nodes obtained from references. In the later case,
682682+ // noderef will have ensured that the ancestors were evaluated.
683683+ if x.arcs[i].cache == nil {
684684+685685+ // cycle detection
686686+ x.arcs[i].cache = cycleSentinel
687687+ v := x.arcs[i].v.evalPartial(ctx)
688688+689689+ if err := cycleError(v); err != nil {
690690+691691+ x.arcs[i].cache = nil
692692+ return err
693693+ }
694694+695695+ v = x.applyTemplate(ctx, i, v)
696696+ x.arcs[i].cache = v
697697+ }
698698+ return x.arcs[i].cache
699699+}
700700+701701+func (x *structLit) applyTemplate(ctx *context, i int, v evaluated) evaluated {
702702+ if x.template != nil {
703703+ e := ctx.manifest(x.template)
704704+ if isBottom(e) {
705705+ return e
706706+ }
707707+708708+ fn, ok := e.(*lambdaExpr)
709709+ if !ok {
710710+ return ctx.mkErr(e, "expected lambda expression")
711711+ }
712712+713713+ name := ctx.labelStr(x.arcs[i].feature)
714714+ arg := &stringLit{x.baseValue, name}
715715+ w := fn.call(ctx, x, arg).evalPartial(ctx)
716716+ v = binOp(ctx, x, opUnify, v, w)
717717+ }
718718+ return v
719719+}
720720+721721+// A label is a canonicalized feature name.
722722+type label uint32
723723+724724+const hidden label = 0x01 // only set iff identifier starting with $
725725+726726+// An arc holds the label-value pair.
727727+//
728728+// A fully evaluated arc has either a node or a value. An unevaluated arc,
729729+// however, may have both. In this case, the value must ultimately evaluate
730730+// to a node, which will then be merged with the existing one.
731731+type arc struct {
732732+ feature label
733733+734734+ v value
735735+ cache evaluated // also used as newValue during unification.
736736+}
737737+738738+type arcInfo struct {
739739+ hidden bool
740740+ tags []string // name:string
741741+}
742742+743743+var hiddenArc = &arcInfo{hidden: true}
744744+745745+// insertValue is used during initialization but never during evaluation.
746746+func (x *structLit) insertValue(ctx *context, f label, value value) {
747747+ for i, p := range x.arcs {
748748+ if f != p.feature {
749749+ continue
750750+ }
751751+ x.arcs[i].v = mkBin(ctx, token.NoPos, opUnify, p.v, value)
752752+ return
753753+ }
754754+ x.arcs = append(x.arcs, arc{feature: f, v: value})
755755+ sort.Stable(x)
756756+}
757757+758758+// A nodeRef is a reference to a node.
759759+type nodeRef struct {
760760+ baseValue
761761+ node scope
762762+}
763763+764764+func (x *nodeRef) kind() kind {
765765+ // TODO(REWORK): no context available
766766+ // n := x.node.deref(nil)
767767+ n := x.node
768768+ return n.kind() | nonGround | referenceKind
769769+}
770770+771771+type selectorExpr struct {
772772+ baseValue
773773+ x value
774774+ feature label
775775+}
776776+777777+// TODO: could this be narrowed down?
778778+func (x *selectorExpr) kind() kind {
779779+ isRef := x.x.kind() & referenceKind
780780+ return topKind | isRef
781781+}
782782+783783+type indexExpr struct {
784784+ baseValue
785785+ x value
786786+ index value
787787+}
788788+789789+// TODO: narrow this down when we have list types.
790790+func (x *indexExpr) kind() kind { return topKind | referenceKind }
791791+792792+type sliceExpr struct {
793793+ baseValue
794794+ x value
795795+ lo value
796796+ hi value
797797+}
798798+799799+// TODO: narrow this down when we have list types.
800800+func (x *sliceExpr) kind() kind { return topKind | referenceKind }
801801+802802+type callExpr struct {
803803+ baseValue
804804+ x value
805805+ args []value
806806+}
807807+808808+func (x *callExpr) kind() kind {
809809+ // TODO: could this be narrowed down?
810810+ if l, ok := x.x.(*lambdaExpr); ok {
811811+ return l.returnKind() | nonGround
812812+ }
813813+ return topKind | referenceKind
814814+}
815815+816816+type params struct {
817817+ arcs []arc
818818+}
819819+820820+func (x *params) add(f label, v value) {
821821+ if v == nil {
822822+ panic("nil node")
823823+ }
824824+ x.arcs = append(x.arcs, arc{f, v, nil})
825825+}
826826+827827+func (x *params) iterAt(ctx *context, i int) (evaluated, value) {
828828+ if i >= len(x.arcs) {
829829+ return nil, nil
830830+ }
831831+ return x.at(ctx, i), x.arcs[i].v
832832+}
833833+834834+// lookup returns the node for the given label f, if present, or nil otherwise.
835835+func (x *params) at(ctx *context, i int) evaluated {
836836+ // Lookup is done by selector or index references. Either this is done on
837837+ // literal nodes or nodes obtained from references. In the later case,
838838+ // noderef will have ensured that the ancestors were evaluated.
839839+ if x.arcs[i].cache == nil {
840840+ x.arcs[i].cache = x.arcs[i].v.evalPartial(ctx)
841841+ }
842842+ return x.arcs[i].cache
843843+}
844844+845845+// lookup returns the node for the given label f, if present, or nil otherwise.
846846+func (x *params) lookup(ctx *context, f label) (v evaluated, raw value) {
847847+ // Lookup is done by selector or index references. Either this is done on
848848+ // literal nodes or nodes obtained from references. In the later case,
849849+ // noderef will have ensured that the ancestors were evaluated.
850850+ for i, a := range x.arcs {
851851+ if a.feature == f {
852852+ return x.at(ctx, i), a.v
853853+ }
854854+ }
855855+ return nil, nil
856856+}
857857+858858+type lambdaExpr struct {
859859+ baseValue
860860+ *params
861861+ value value
862862+}
863863+864864+// TODO: could this be narrowed down?
865865+func (x *lambdaExpr) kind() kind { return lambdaKind }
866866+func (x *lambdaExpr) returnKind() kind { return x.value.kind() }
867867+868868+// call calls and evaluates a lambda expression. It is assumed that x may be
869869+// destroyed, either because it is copied as a result of a reference or because
870870+// it is invoked as a literal.
871871+func (x *lambdaExpr) call(ctx *context, p source, args ...evaluated) value {
872872+ // fully evaluated.
873873+ if len(x.params.arcs) != len(args) {
874874+ return ctx.mkErr(p, x, "number of arguments does not match (%d vs %d)",
875875+ len(x.params.arcs), len(args))
876876+ }
877877+878878+ // force parameter substitution. It is important that the result stands on
879879+ // its own and does not depend on its input parameters.
880880+ arcs := make(arcs, len(x.arcs))
881881+ for i, a := range x.arcs {
882882+ v := unify(ctx, p, a.v.evalPartial(ctx), args[i])
883883+ if isBottom(v) {
884884+ return v
885885+ }
886886+ arcs[i] = arc{a.feature, v, v}
887887+ }
888888+ lambda := &lambdaExpr{x.baseValue, ¶ms{arcs}, nil}
889889+ defer ctx.pushForwards(x, lambda).popForwards()
890890+ return ctx.copy(x.value)
891891+}
892892+893893+// Operations
894894+895895+type unaryExpr struct {
896896+ baseValue
897897+ op op
898898+ x value
899899+}
900900+901901+func (x *unaryExpr) kind() kind { return x.x.kind() }
902902+903903+type binaryExpr struct {
904904+ baseValue
905905+ op op
906906+ left value
907907+ right value
908908+}
909909+910910+func mkBin(ctx *context, pos token.Pos, op op, left, right value) value {
911911+ if left == nil || right == nil {
912912+ panic("operands may not be nil")
913913+ }
914914+ if op == opUnify {
915915+ if left == right {
916916+ return left
917917+ }
918918+ if _, ok := left.(*top); ok {
919919+ return right
920920+ }
921921+ if _, ok := right.(*top); ok {
922922+ return left
923923+ }
924924+ // TODO(perf): consider adding a subsumption filter.
925925+ // if subsumes(ctx, left, right) {
926926+ // return right
927927+ // }
928928+ // if subsumes(ctx, right, left) {
929929+ // return left
930930+ // }
931931+ }
932932+ return &binaryExpr{binSrc(pos, op, left, right), op, left, right}
933933+}
934934+935935+func (x *binaryExpr) kind() kind {
936936+ // TODO: cache results
937937+ kind, _ := matchBinOpKind(x.op, x.left.kind(), x.right.kind())
938938+ return kind | nonGround
939939+}
940940+941941+// TODO: make disjunction a binOp, but translate disjunctions into
942942+// arrays, or at least linked lists.
943943+944944+type disjunction struct {
945945+ baseValue
946946+947947+ values []dValue
948948+949949+ // bind is the node that a successful disjunction will bind to. This
950950+ // allows other arcs to point to this node before the disjunction is
951951+ // completed. For early failure, this node can be set to the glb of all
952952+ // disjunctions. Otherwise top will suffice.
953953+ // bind node
954954+}
955955+956956+type dValue struct {
957957+ val value
958958+ ambiguous bool
959959+}
960960+961961+// makeDisjunction constructs a disjunction linked list.
962962+func makeDisjunction(ctx *context, n ast.Expr, a, b value) *disjunction {
963963+ d, ok := a.(*disjunction)
964964+ if !ok {
965965+ d = &disjunction{newExpr(n), []dValue{{val: a}}}
966966+ }
967967+ if o, ok := b.(*disjunction); ok {
968968+ d.values = append(d.values, o.values...)
969969+ } else {
970970+ d.values = append(d.values, dValue{val: b})
971971+ }
972972+ return d
973973+}
974974+975975+func (x *disjunction) kind() kind {
976976+ k := kind(0)
977977+ for _, v := range x.values {
978978+ k |= v.val.kind()
979979+ }
980980+ if k != bottomKind {
981981+ k |= nonGround
982982+ }
983983+ return k
984984+}
985985+986986+func (x *disjunction) Pos() token.Pos { return x.values[0].val.Pos() }
987987+988988+// add add a value to the disjunction. It is assumed not to be a disjunction.
989989+func (x *disjunction) add(ctx *context, v value, ambiguous bool) {
990990+ if !isBottom(v) {
991991+ x.values = append(x.values, dValue{v, ambiguous})
992992+ }
993993+}
994994+995995+// simplify unwraps the disjunction if necessary.
996996+func (x *disjunction) simplify(ctx *context, src source) value {
997997+ switch len(x.values) {
998998+ case 0:
999999+ return ctx.mkErr(src, "empty disjunction after evaluation")
10001000+ case 1:
10011001+ return x.values[0].val
10021002+ }
10031003+ return x
10041004+}
10051005+10061006+type listComprehension struct {
10071007+ baseValue
10081008+ clauses yielder
10091009+}
10101010+10111011+func (x *listComprehension) kind() kind {
10121012+ return listKind | nonGround | referenceKind
10131013+}
10141014+10151015+// TODO: structComprehensions are a left-over from the past and are used to
10161016+// interpret field comprehensions. The resulting construction prohibits
10171017+// references in comprehension clauses to be able to reference values in
10181018+// the struct in which the field is defined. See the updater config in the
10191019+// kubernetes demo.
10201020+type structComprehension struct {
10211021+ baseValue
10221022+ clauses yielder
10231023+ isTemplate bool
10241024+}
10251025+10261026+func (x *structComprehension) kind() kind {
10271027+ return structKind | nonGround | referenceKind
10281028+}
10291029+10301030+type yieldFunc func(k, v evaluated) *bottom
10311031+10321032+type yielder interface {
10331033+ value
10341034+ yield(*context, yieldFunc) evaluated
10351035+}
10361036+10371037+type yield struct {
10381038+ baseValue
10391039+ key value
10401040+ value value
10411041+}
10421042+10431043+func (x *yield) kind() kind { return topKind | referenceKind }
10441044+10451045+func (x *yield) yield(ctx *context, fn yieldFunc) evaluated {
10461046+ var k evaluated
10471047+ if x.key != nil {
10481048+ k = ctx.manifest(x.key)
10491049+ if isBottom(k) {
10501050+ return k
10511051+ }
10521052+ } else {
10531053+ k = &top{}
10541054+ }
10551055+ v := x.value.evalPartial(ctx)
10561056+ if isBottom(v) {
10571057+ return v
10581058+ }
10591059+ if err := fn(k, v); err != nil {
10601060+ return err
10611061+ }
10621062+ return nil
10631063+}
10641064+10651065+type guard struct { // rename to guard
10661066+ baseValue
10671067+ condition value
10681068+ value yielder
10691069+}
10701070+10711071+func (x *guard) kind() kind { return topKind | referenceKind }
10721072+10731073+func (x *guard) yield(ctx *context, fn yieldFunc) evaluated {
10741074+ filter := ctx.manifest(x.condition)
10751075+ if isBottom(filter) {
10761076+ return filter
10771077+ }
10781078+ if err := checkKind(ctx, filter, boolKind); err != nil {
10791079+ return err
10801080+ }
10811081+ if filter.(*boolLit).b {
10821082+ if err := x.value.yield(ctx, fn); err != nil {
10831083+ return err
10841084+ }
10851085+ }
10861086+ return nil
10871087+}
10881088+10891089+type feed struct {
10901090+ baseValue
10911091+ source value
10921092+ fn *lambdaExpr
10931093+}
10941094+10951095+func (x *feed) kind() kind { return topKind | referenceKind }
10961096+10971097+func (x *feed) yield(ctx *context, yfn yieldFunc) (result evaluated) {
10981098+ if ctx.trace {
10991099+ defer uni(indent(ctx, "feed", x))
11001100+ }
11011101+ source := ctx.manifest(x.source)
11021102+ fn := x.fn // no need to evaluate eval
11031103+11041104+ switch src := source.(type) {
11051105+ case *structLit:
11061106+ for i, a := range src.arcs {
11071107+ key := &stringLit{
11081108+ x.baseValue,
11091109+ ctx.labelStr(a.feature),
11101110+ }
11111111+ val := src.at(ctx, i)
11121112+ v := fn.call(ctx, x, key, val)
11131113+ if isBottom(v) {
11141114+ return v.evalPartial(ctx)
11151115+ }
11161116+ if err := v.(yielder).yield(ctx, yfn); err != nil {
11171117+ return err
11181118+ }
11191119+ }
11201120+ return nil
11211121+11221122+ case *list:
11231123+ for i := range src.a {
11241124+ idx := newNum(x, intKind)
11251125+ idx.v.SetInt64(int64(i))
11261126+ v := fn.call(ctx, x, idx, src.at(ctx, i))
11271127+ if isBottom(v) {
11281128+ return v.evalPartial(ctx)
11291129+ }
11301130+ if err := v.(yielder).yield(ctx, yfn); err != nil {
11311131+ return err
11321132+ }
11331133+ }
11341134+ return nil
11351135+11361136+ default:
11371137+ if isBottom(source) {
11381138+ return source
11391139+ }
11401140+ if k := source.kind(); k&(structKind|listKind) == bottomKind {
11411141+ return ctx.mkErr(x, x.source, "feed source must be list or struct, found %s", k)
11421142+ }
11431143+ return ctx.mkErr(x, "feed source not fully evaluated to struct or list")
11441144+ }
11451145+}
+11
internal/internal.go
···18181919// DebugStr prints a syntax node.
2020var DebugStr func(x interface{}) string
2121+2222+// EvalExpr evaluates an expression within an existing struct value.
2323+// Identifiers only resolve to values defined within the struct.
2424+//
2525+// Expressions may refer to builtin packages if they can be uniquely identified
2626+//
2727+// Both value and result are of type cue.Value, but are an interface to prevent
2828+// cyclic dependencies.
2929+//
3030+// TODO: extract interface
3131+var EvalExpr func(value, expr interface{}) (result interface{})