blob: 5246b30ac4f3355ad64fd95271943d0b0fdea6d8 [file] [log] [blame]
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001// Copyright 2018 The CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cue
16
17import (
18 "fmt"
Marcel van Lohuizen369e4232019-02-15 10:59:29 +040019 "strings"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010020
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/build"
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +010023 "cuelang.org/go/cue/literal"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010024 "cuelang.org/go/cue/token"
Marcel van Lohuizene9fd2142019-04-12 15:46:31 +020025 "cuelang.org/go/internal"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010026)
27
28// insertFile inserts the given file at the root of the instance.
29//
30// The contents will be merged (unified) with any pre-existing value. In this
31// case an error may be reported, but only if the merge failed at the top-level.
32// Other errors will be recorded at the respective values in the tree.
33//
34// There should be no unresolved identifiers in file, meaning the Node field
35// of all identifiers should be set to a non-nil value.
36func (inst *Instance) insertFile(f *ast.File) error {
37 // TODO: insert by converting to value first so that the trim command can
38 // also remove top-level fields.
39 // First process single file.
40 v := newVisitor(inst.index, inst.inst, inst.rootStruct, inst.scope)
41 v.astState.astMap[f] = inst.rootStruct
42 result := v.walk(f)
43 if isBottom(result) {
44 return result.(*bottom)
45 }
46
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010047 return nil
48}
49
50type astVisitor struct {
51 *astState
Marcel van Lohuizen66db9202018-12-17 19:02:08 +010052 object *structLit
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010053
54 inSelector int
55}
56
57func (v *astVisitor) ctx() *context {
58 return v.astState.ctx
59}
60
61type astState struct {
62 ctx *context
63 *index
64 inst *build.Instance
65
66 litParser *litParser
67 resolveRoot *structLit
68
69 // make unique per level to avoid reuse of structs being an issue.
70 astMap map[ast.Node]scope
71}
72
73func (s *astState) mapScope(n ast.Node) (m scope) {
74 if m = s.astMap[n]; m == nil {
75 m = newStruct(newNode(n))
76 s.astMap[n] = m
77 }
78 return m
79}
80
81func (s *astState) setScope(n ast.Node, v scope) {
82 if m, ok := s.astMap[n]; ok && m != v {
83 panic("already defined")
84 }
85 s.astMap[n] = v
86}
87
88func newVisitor(idx *index, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
89 ctx := idx.newContext()
Marcel van Lohuizend4847d92019-02-18 23:27:34 +010090 return newVisitorCtx(ctx, inst, obj, resolveRoot)
91}
92
93func newVisitorCtx(ctx *context, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010094 v := &astVisitor{
95 object: obj,
96 }
97 v.astState = &astState{
98 ctx: ctx,
99 index: ctx.index,
100 inst: inst,
101 litParser: &litParser{ctx: ctx},
102 resolveRoot: resolveRoot,
103 astMap: map[ast.Node]scope{},
104 }
105 return v
106}
107
108func (v *astVisitor) error(n ast.Node, args ...interface{}) value {
109 return v.mkErr(newNode(n), args...)
110}
111
112func (v *astVisitor) resolve(n *ast.Ident) value {
113 ctx := v.ctx()
114 label := v.label(n.Name, true)
115 if r := v.resolveRoot; r != nil {
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200116 for _, a := range r.arcs {
117 if a.feature == label {
118 return &selectorExpr{newExpr(n),
119 &nodeRef{baseValue: newExpr(n), node: r}, label}
120 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100121 }
122 if v.inSelector > 0 {
123 if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
124 return &nodeRef{baseValue: newExpr(n), node: p}
125 }
126 }
127 }
128 return nil
129}
130
131func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
132 ctx := v.ctx()
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100133 path, err := literal.Unquote(imp.Path.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100134 if err != nil {
135 return ctx.mkErr(newNode(imp), "illformed import spec")
136 }
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200137 // TODO: allow builtin *and* imported package. The result is a unified
138 // struct.
Marcel van Lohuizen8bc02e52019-04-01 13:14:07 +0200139 if p := getBuiltinPkg(ctx, path); p != nil {
140 return p
141 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100142 bimp := v.inst.LookupImport(path)
143 if bimp == nil {
144 return ctx.mkErr(newNode(imp), "package %q not found", path)
145 }
146 impInst := v.index.loadInstance(bimp)
147 return impInst.rootValue.evalPartial(ctx)
148}
149
150// We probably don't need to call Walk.s
151func (v *astVisitor) walk(astNode ast.Node) (value value) {
152 switch n := astNode.(type) {
153 case *ast.File:
154 obj := v.object
155 v1 := &astVisitor{
156 astState: v.astState,
157 object: obj,
158 }
159 for _, e := range n.Decls {
160 switch x := e.(type) {
161 case *ast.EmitDecl:
162 if v1.object.emit == nil {
163 v1.object.emit = v1.walk(x.Expr)
164 } else {
165 v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
166 }
167 default:
168 v1.walk(e)
169 }
170 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100171 value = obj
172
173 case *ast.ImportDecl:
174 for _, s := range n.Specs {
175 v.walk(s)
176 }
177
178 case *ast.ImportSpec:
179 val := v.loadImport(n)
180 if !isBottom(val) {
181 v.setScope(n, val.(*structLit))
182 }
183
184 case *ast.StructLit:
185 obj := v.mapScope(n).(*structLit)
186 v1 := &astVisitor{
187 astState: v.astState,
188 object: obj,
189 }
190 for _, e := range n.Elts {
191 switch x := e.(type) {
192 case *ast.EmitDecl:
193 // Only allowed at top-level.
194 v1.error(x, "emitting values is only allowed at top level")
195 case *ast.Field, *ast.Alias:
196 v1.walk(e)
197 case *ast.ComprehensionDecl:
198 v1.walk(x)
199 }
200 }
201 value = obj
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100202
203 case *ast.ComprehensionDecl:
204 yielder := &yield{baseValue: newExpr(n.Field.Value)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100205 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100206 baseValue: newDecl(n),
207 clauses: wrapClauses(v, yielder, n.Clauses),
208 }
209 field := n.Field
210 switch x := field.Label.(type) {
211 case *ast.Interpolation:
212 yielder.key = v.walk(x)
213 yielder.value = v.walk(field.Value)
214
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100215 case *ast.TemplateLabel:
216 f := v.label(x.Ident.Name, true)
217
218 sig := &params{}
219 sig.add(f, &basicType{newNode(field.Label), stringKind})
220 template := &lambdaExpr{newExpr(field.Value), sig, nil}
221
222 v.setScope(field, template)
223 template.value = v.walk(field.Value)
224 yielder.value = template
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100225 fc.isTemplate = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100226
227 case *ast.BasicLit, *ast.Ident:
228 name, ok := ast.LabelName(x)
229 if !ok {
230 return v.error(x, "invalid field name: %v", x)
231 }
Marcel van Lohuizenf23fbff2018-12-20 12:23:16 +0100232
233 // TODO: if the clauses do not contain a guard, we know that this
234 // field will always be added and we can move the comprehension one
235 // level down. This, in turn, has the advantage that it is more
236 // likely that the cross-reference limitation for field
237 // comprehensions is not violated. To ensure compatibility between
238 // implementations, though, we should relax the spec as well.
239 // The cross-reference rule is simple and this relaxation seems a
240 // bit more complex.
241
242 // TODO: for now we can also consider making this an error if
243 // the list of clauses does not contain if and make a suggestion
244 // to rewrite it.
245
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100246 if name != "" {
247 yielder.key = &stringLit{newNode(x), name}
248 yielder.value = v.walk(field.Value)
249 }
250
251 default:
252 panic("cue: unknown label type")
253 }
254 // yielder.key = v.walk(n.Field.Label)
255 // yielder.value = v.walk(n.Field.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100256 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100257
258 case *ast.Field:
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100259 opt := n.Optional != token.NoPos
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100260 switch x := n.Label.(type) {
261 case *ast.Interpolation:
262 yielder := &yield{baseValue: newNode(x)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100263 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100264 baseValue: newDecl(n),
265 clauses: yielder,
266 }
267 yielder.key = v.walk(x)
268 yielder.value = v.walk(n.Value)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100269 yielder.opt = opt
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100270 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100271
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100272 case *ast.TemplateLabel:
273 f := v.label(x.Ident.Name, true)
274
275 sig := &params{}
276 sig.add(f, &basicType{newNode(n.Label), stringKind})
277 template := &lambdaExpr{newExpr(n.Value), sig, nil}
278
279 v.setScope(n, template)
280 template.value = v.walk(n.Value)
281
282 if v.object.template == nil {
283 v.object.template = template
284 } else {
285 v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
286 }
287
288 case *ast.BasicLit, *ast.Ident:
Marcel van Lohuizene9fd2142019-04-12 15:46:31 +0200289 if internal.DropOptional && opt {
290 break
291 }
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +0100292 attrs, err := createAttrs(v.ctx(), newNode(n), n.Attrs)
293 if err != nil {
294 return err
295 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100296 f, ok := v.nodeLabel(x)
297 if !ok {
298 return v.error(n.Label, "invalid field name: %v", n.Label)
299 }
300 if f != 0 {
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100301 v.object.insertValue(v.ctx(), f, opt, v.walk(n.Value), attrs)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100302 }
303
304 default:
305 panic("cue: unknown label type")
306 }
307
308 case *ast.Alias:
309 // parsed verbatim at reference.
310
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100311 case *ast.ListComprehension:
312 yielder := &yield{baseValue: newExpr(n.Expr)}
313 lc := &listComprehension{
314 newExpr(n),
315 wrapClauses(v, yielder, n.Clauses),
316 }
317 // we don't support key for lists (yet?)
318 yielder.value = v.walk(n.Expr)
319 return lc
320
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100321 // Expressions
322 case *ast.Ident:
323 if n.Node == nil {
324 if value = v.resolve(n); value != nil {
325 break
326 }
327
328 switch n.Name {
329 case "_":
330 return &top{newExpr(n)}
331 case "string":
332 return &basicType{newExpr(n), stringKind}
333 case "bytes":
334 return &basicType{newExpr(n), bytesKind}
335 case "bool":
336 return &basicType{newExpr(n), boolKind}
337 case "int":
338 return &basicType{newExpr(n), intKind}
339 case "float":
340 return &basicType{newExpr(n), floatKind}
341 case "number":
342 return &basicType{newExpr(n), numKind}
343 case "duration":
344 return &basicType{newExpr(n), durationKind}
345
346 case "len":
347 return lenBuiltin
348 }
349 if r, ok := predefinedRanges[n.Name]; ok {
350 return r
351 }
352
353 value = v.error(n, "reference %q not found", n.Name)
354 break
355 }
356
357 if a, ok := n.Node.(*ast.Alias); ok {
358 value = v.walk(a.Expr)
359 break
360 }
361
362 label := v.label(n.Name, true)
363 if n.Scope != nil {
364 n2 := v.mapScope(n.Scope)
365 value = &nodeRef{baseValue: newExpr(n), node: n2}
366 value = &selectorExpr{newExpr(n), value, label}
367 } else {
368 n2 := v.mapScope(n.Node)
369 value = &nodeRef{baseValue: newExpr(n), node: n2}
370 }
371
372 case *ast.BottomLit:
373 value = v.error(n, "from source")
374
375 case *ast.BadDecl:
376 // nothing to do
377
378 case *ast.BadExpr:
379 value = v.error(n, "invalid expression")
380
381 case *ast.BasicLit:
382 value = v.litParser.parse(n)
383
384 case *ast.Interpolation:
385 if len(n.Elts) == 0 {
386 return v.error(n, "invalid interpolation")
387 }
388 first, ok1 := n.Elts[0].(*ast.BasicLit)
389 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
390 if !ok1 || !ok2 {
391 return v.error(n, "invalid interpolation")
392 }
393 if len(n.Elts) == 1 {
394 value = v.walk(n.Elts[0])
395 break
396 }
397 lit := &interpolation{baseValue: newExpr(n), k: stringKind}
398 value = lit
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100399 info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100400 if err != nil {
401 return v.error(n, "invalid interpolation: %v", err)
402 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400403 prefix := ""
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100404 for i := 0; i < len(n.Elts); i += 2 {
405 l, ok := n.Elts[i].(*ast.BasicLit)
406 if !ok {
407 return v.error(n, "invalid interpolation")
408 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400409 s := l.Value
410 if !strings.HasPrefix(s, prefix) {
411 return v.error(l, "invalid interpolation: unmatched ')'")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100412 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400413 s = l.Value[prefixLen:]
414 x := parseString(v.ctx(), l, info, s)
415 lit.parts = append(lit.parts, x)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100416 if i+1 < len(n.Elts) {
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400417 lit.parts = append(lit.parts, v.walk(n.Elts[i+1]))
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100418 }
419 prefix = ")"
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400420 prefixLen = 1
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100421 }
422
423 case *ast.ListLit:
424 list := &list{baseValue: newExpr(n)}
425 for _, e := range n.Elts {
426 list.a = append(list.a, v.walk(e))
427 }
428 list.initLit()
429 if n.Ellipsis != token.NoPos || n.Type != nil {
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100430 list.len = &bound{list.baseValue, opGeq, list.len}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100431 if n.Type != nil {
432 list.typ = v.walk(n.Type)
433 }
434 }
435 value = list
436
437 case *ast.ParenExpr:
438 value = v.walk(n.X)
439
440 case *ast.SelectorExpr:
441 v.inSelector++
442 value = &selectorExpr{
443 newExpr(n),
444 v.walk(n.X),
445 v.label(n.Sel.Name, true),
446 }
447 v.inSelector--
448
449 case *ast.IndexExpr:
450 value = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
451
452 case *ast.SliceExpr:
453 slice := &sliceExpr{baseValue: newExpr(n), x: v.walk(n.X)}
454 if n.Low != nil {
455 slice.lo = v.walk(n.Low)
456 }
457 if n.High != nil {
458 slice.hi = v.walk(n.High)
459 }
460 value = slice
461
462 case *ast.CallExpr:
463 call := &callExpr{baseValue: newExpr(n), x: v.walk(n.Fun)}
464 for _, a := range n.Args {
465 call.args = append(call.args, v.walk(a))
466 }
467 value = call
468
469 case *ast.UnaryExpr:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100470 switch n.Op {
471 case token.NOT, token.ADD, token.SUB:
472 value = &unaryExpr{
473 newExpr(n),
474 tokenMap[n.Op],
475 v.walk(n.X),
476 }
Marcel van Lohuizen706e69c2019-02-11 18:21:14 +0100477 case token.GEQ, token.GTR, token.LSS, token.LEQ,
478 token.NEQ, token.MAT, token.NMAT:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100479 value = &bound{
480 newExpr(n),
481 tokenMap[n.Op],
482 v.walk(n.X),
483 }
484
485 case token.MUL:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100486 return v.error(n, "preference mark not allowed at this position")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100487 default:
488 return v.error(n, "unsupported unary operator %q", n.Op)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100489 }
490
491 case *ast.BinaryExpr:
492 switch n.Op {
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100493 case token.OR:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100494 d := &disjunction{baseValue: newExpr(n)}
495 v.addDisjunctionElem(d, n.X, false)
496 v.addDisjunctionElem(d, n.Y, false)
497 value = d
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100498
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100499 default:
500 value = &binaryExpr{
501 newExpr(n),
502 tokenMap[n.Op], // op
503 v.walk(n.X), // left
504 v.walk(n.Y), // right
505 }
506 }
507
508 // nothing to do
509 // case *syntax.EmitDecl:
510 default:
511 // TODO: unhandled node.
512 // value = ctx.mkErr(n, "unknown node type %T", n)
513 panic(fmt.Sprintf("unimplemented %T", n))
514
515 }
516 return value
517}
518
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100519func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
520 switch x := n.(type) {
521 case *ast.BinaryExpr:
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100522 if x.Op == token.OR {
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100523 v.addDisjunctionElem(d, x.X, mark)
524 v.addDisjunctionElem(d, x.Y, mark)
525 return
526 }
527 case *ast.UnaryExpr:
528 if x.Op == token.MUL {
529 mark = true
530 n = x.X
531 }
532 }
533 d.values = append(d.values, dValue{v.walk(n), mark})
534}
535
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100536func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
537 for _, c := range clauses {
538 if n, ok := c.(*ast.ForClause); ok {
539 params := &params{}
540 fn := &lambdaExpr{newExpr(n.Source), params, nil}
541 v.setScope(n, fn)
542 }
543 }
544 for i := len(clauses) - 1; i >= 0; i-- {
545 switch n := clauses[i].(type) {
546 case *ast.ForClause:
547 fn := v.mapScope(n).(*lambdaExpr)
548 fn.value = y
549
550 key := "_"
551 if n.Key != nil {
552 key = n.Key.Name
553 }
554 f := v.label(key, true)
555 fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
556
557 f = v.label(n.Value.Name, true)
558 fn.add(f, &top{})
559
560 y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
561
562 case *ast.IfClause:
563 y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
564 }
565 }
566 return y
567}