blob: c4a236651f87b106dfdd169722c450b9ef0c7754 [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"
25)
26
27// insertFile inserts the given file at the root of the instance.
28//
29// The contents will be merged (unified) with any pre-existing value. In this
30// case an error may be reported, but only if the merge failed at the top-level.
31// Other errors will be recorded at the respective values in the tree.
32//
33// There should be no unresolved identifiers in file, meaning the Node field
34// of all identifiers should be set to a non-nil value.
35func (inst *Instance) insertFile(f *ast.File) error {
36 // TODO: insert by converting to value first so that the trim command can
37 // also remove top-level fields.
38 // First process single file.
39 v := newVisitor(inst.index, inst.inst, inst.rootStruct, inst.scope)
40 v.astState.astMap[f] = inst.rootStruct
41 result := v.walk(f)
42 if isBottom(result) {
43 return result.(*bottom)
44 }
45
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010046 return nil
47}
48
49type astVisitor struct {
50 *astState
Marcel van Lohuizen66db9202018-12-17 19:02:08 +010051 object *structLit
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010052
53 inSelector int
54}
55
56func (v *astVisitor) ctx() *context {
57 return v.astState.ctx
58}
59
60type astState struct {
61 ctx *context
62 *index
63 inst *build.Instance
64
65 litParser *litParser
66 resolveRoot *structLit
67
68 // make unique per level to avoid reuse of structs being an issue.
69 astMap map[ast.Node]scope
70}
71
72func (s *astState) mapScope(n ast.Node) (m scope) {
73 if m = s.astMap[n]; m == nil {
74 m = newStruct(newNode(n))
75 s.astMap[n] = m
76 }
77 return m
78}
79
80func (s *astState) setScope(n ast.Node, v scope) {
81 if m, ok := s.astMap[n]; ok && m != v {
82 panic("already defined")
83 }
84 s.astMap[n] = v
85}
86
87func newVisitor(idx *index, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
88 ctx := idx.newContext()
Marcel van Lohuizend4847d92019-02-18 23:27:34 +010089 return newVisitorCtx(ctx, inst, obj, resolveRoot)
90}
91
92func newVisitorCtx(ctx *context, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010093 v := &astVisitor{
94 object: obj,
95 }
96 v.astState = &astState{
97 ctx: ctx,
98 index: ctx.index,
99 inst: inst,
100 litParser: &litParser{ctx: ctx},
101 resolveRoot: resolveRoot,
102 astMap: map[ast.Node]scope{},
103 }
104 return v
105}
106
107func (v *astVisitor) error(n ast.Node, args ...interface{}) value {
108 return v.mkErr(newNode(n), args...)
109}
110
111func (v *astVisitor) resolve(n *ast.Ident) value {
112 ctx := v.ctx()
113 label := v.label(n.Name, true)
114 if r := v.resolveRoot; r != nil {
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200115 for _, a := range r.arcs {
116 if a.feature == label {
117 return &selectorExpr{newExpr(n),
118 &nodeRef{baseValue: newExpr(n), node: r}, label}
119 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100120 }
121 if v.inSelector > 0 {
122 if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
123 return &nodeRef{baseValue: newExpr(n), node: p}
124 }
125 }
126 }
127 return nil
128}
129
130func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
131 ctx := v.ctx()
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100132 path, err := literal.Unquote(imp.Path.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100133 if err != nil {
134 return ctx.mkErr(newNode(imp), "illformed import spec")
135 }
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200136 // TODO: allow builtin *and* imported package. The result is a unified
137 // struct.
Marcel van Lohuizen8bc02e52019-04-01 13:14:07 +0200138 if p := getBuiltinPkg(ctx, path); p != nil {
139 return p
140 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100141 bimp := v.inst.LookupImport(path)
142 if bimp == nil {
143 return ctx.mkErr(newNode(imp), "package %q not found", path)
144 }
145 impInst := v.index.loadInstance(bimp)
146 return impInst.rootValue.evalPartial(ctx)
147}
148
149// We probably don't need to call Walk.s
150func (v *astVisitor) walk(astNode ast.Node) (value value) {
151 switch n := astNode.(type) {
152 case *ast.File:
153 obj := v.object
154 v1 := &astVisitor{
155 astState: v.astState,
156 object: obj,
157 }
158 for _, e := range n.Decls {
159 switch x := e.(type) {
160 case *ast.EmitDecl:
161 if v1.object.emit == nil {
162 v1.object.emit = v1.walk(x.Expr)
163 } else {
164 v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
165 }
166 default:
167 v1.walk(e)
168 }
169 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100170 value = obj
171
172 case *ast.ImportDecl:
173 for _, s := range n.Specs {
174 v.walk(s)
175 }
176
177 case *ast.ImportSpec:
178 val := v.loadImport(n)
179 if !isBottom(val) {
180 v.setScope(n, val.(*structLit))
181 }
182
183 case *ast.StructLit:
184 obj := v.mapScope(n).(*structLit)
185 v1 := &astVisitor{
186 astState: v.astState,
187 object: obj,
188 }
189 for _, e := range n.Elts {
190 switch x := e.(type) {
191 case *ast.EmitDecl:
192 // Only allowed at top-level.
193 v1.error(x, "emitting values is only allowed at top level")
194 case *ast.Field, *ast.Alias:
195 v1.walk(e)
196 case *ast.ComprehensionDecl:
197 v1.walk(x)
198 }
199 }
200 value = obj
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100201
202 case *ast.ComprehensionDecl:
203 yielder := &yield{baseValue: newExpr(n.Field.Value)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100204 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100205 baseValue: newDecl(n),
206 clauses: wrapClauses(v, yielder, n.Clauses),
207 }
208 field := n.Field
209 switch x := field.Label.(type) {
210 case *ast.Interpolation:
211 yielder.key = v.walk(x)
212 yielder.value = v.walk(field.Value)
213
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100214 case *ast.TemplateLabel:
215 f := v.label(x.Ident.Name, true)
216
217 sig := &params{}
218 sig.add(f, &basicType{newNode(field.Label), stringKind})
219 template := &lambdaExpr{newExpr(field.Value), sig, nil}
220
221 v.setScope(field, template)
222 template.value = v.walk(field.Value)
223 yielder.value = template
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100224 fc.isTemplate = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100225
226 case *ast.BasicLit, *ast.Ident:
227 name, ok := ast.LabelName(x)
228 if !ok {
229 return v.error(x, "invalid field name: %v", x)
230 }
Marcel van Lohuizenf23fbff2018-12-20 12:23:16 +0100231
232 // TODO: if the clauses do not contain a guard, we know that this
233 // field will always be added and we can move the comprehension one
234 // level down. This, in turn, has the advantage that it is more
235 // likely that the cross-reference limitation for field
236 // comprehensions is not violated. To ensure compatibility between
237 // implementations, though, we should relax the spec as well.
238 // The cross-reference rule is simple and this relaxation seems a
239 // bit more complex.
240
241 // TODO: for now we can also consider making this an error if
242 // the list of clauses does not contain if and make a suggestion
243 // to rewrite it.
244
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100245 if name != "" {
246 yielder.key = &stringLit{newNode(x), name}
247 yielder.value = v.walk(field.Value)
248 }
249
250 default:
251 panic("cue: unknown label type")
252 }
253 // yielder.key = v.walk(n.Field.Label)
254 // yielder.value = v.walk(n.Field.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100255 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100256
257 case *ast.Field:
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100258 opt := n.Optional != token.NoPos
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100259 switch x := n.Label.(type) {
260 case *ast.Interpolation:
261 yielder := &yield{baseValue: newNode(x)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100262 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100263 baseValue: newDecl(n),
264 clauses: yielder,
265 }
266 yielder.key = v.walk(x)
267 yielder.value = v.walk(n.Value)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100268 yielder.opt = opt
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100269 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100270
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100271 case *ast.TemplateLabel:
272 f := v.label(x.Ident.Name, true)
273
274 sig := &params{}
275 sig.add(f, &basicType{newNode(n.Label), stringKind})
276 template := &lambdaExpr{newExpr(n.Value), sig, nil}
277
278 v.setScope(n, template)
279 template.value = v.walk(n.Value)
280
281 if v.object.template == nil {
282 v.object.template = template
283 } else {
284 v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
285 }
286
287 case *ast.BasicLit, *ast.Ident:
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +0100288 attrs, err := createAttrs(v.ctx(), newNode(n), n.Attrs)
289 if err != nil {
290 return err
291 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100292 f, ok := v.nodeLabel(x)
293 if !ok {
294 return v.error(n.Label, "invalid field name: %v", n.Label)
295 }
296 if f != 0 {
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100297 v.object.insertValue(v.ctx(), f, opt, v.walk(n.Value), attrs)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100298 }
299
300 default:
301 panic("cue: unknown label type")
302 }
303
304 case *ast.Alias:
305 // parsed verbatim at reference.
306
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100307 case *ast.ListComprehension:
308 yielder := &yield{baseValue: newExpr(n.Expr)}
309 lc := &listComprehension{
310 newExpr(n),
311 wrapClauses(v, yielder, n.Clauses),
312 }
313 // we don't support key for lists (yet?)
314 yielder.value = v.walk(n.Expr)
315 return lc
316
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100317 // Expressions
318 case *ast.Ident:
319 if n.Node == nil {
320 if value = v.resolve(n); value != nil {
321 break
322 }
323
324 switch n.Name {
325 case "_":
326 return &top{newExpr(n)}
327 case "string":
328 return &basicType{newExpr(n), stringKind}
329 case "bytes":
330 return &basicType{newExpr(n), bytesKind}
331 case "bool":
332 return &basicType{newExpr(n), boolKind}
333 case "int":
334 return &basicType{newExpr(n), intKind}
335 case "float":
336 return &basicType{newExpr(n), floatKind}
337 case "number":
338 return &basicType{newExpr(n), numKind}
339 case "duration":
340 return &basicType{newExpr(n), durationKind}
341
342 case "len":
343 return lenBuiltin
344 }
345 if r, ok := predefinedRanges[n.Name]; ok {
346 return r
347 }
348
349 value = v.error(n, "reference %q not found", n.Name)
350 break
351 }
352
353 if a, ok := n.Node.(*ast.Alias); ok {
354 value = v.walk(a.Expr)
355 break
356 }
357
358 label := v.label(n.Name, true)
359 if n.Scope != nil {
360 n2 := v.mapScope(n.Scope)
361 value = &nodeRef{baseValue: newExpr(n), node: n2}
362 value = &selectorExpr{newExpr(n), value, label}
363 } else {
364 n2 := v.mapScope(n.Node)
365 value = &nodeRef{baseValue: newExpr(n), node: n2}
366 }
367
368 case *ast.BottomLit:
369 value = v.error(n, "from source")
370
371 case *ast.BadDecl:
372 // nothing to do
373
374 case *ast.BadExpr:
375 value = v.error(n, "invalid expression")
376
377 case *ast.BasicLit:
378 value = v.litParser.parse(n)
379
380 case *ast.Interpolation:
381 if len(n.Elts) == 0 {
382 return v.error(n, "invalid interpolation")
383 }
384 first, ok1 := n.Elts[0].(*ast.BasicLit)
385 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
386 if !ok1 || !ok2 {
387 return v.error(n, "invalid interpolation")
388 }
389 if len(n.Elts) == 1 {
390 value = v.walk(n.Elts[0])
391 break
392 }
393 lit := &interpolation{baseValue: newExpr(n), k: stringKind}
394 value = lit
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100395 info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100396 if err != nil {
397 return v.error(n, "invalid interpolation: %v", err)
398 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400399 prefix := ""
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100400 for i := 0; i < len(n.Elts); i += 2 {
401 l, ok := n.Elts[i].(*ast.BasicLit)
402 if !ok {
403 return v.error(n, "invalid interpolation")
404 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400405 s := l.Value
406 if !strings.HasPrefix(s, prefix) {
407 return v.error(l, "invalid interpolation: unmatched ')'")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100408 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400409 s = l.Value[prefixLen:]
410 x := parseString(v.ctx(), l, info, s)
411 lit.parts = append(lit.parts, x)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100412 if i+1 < len(n.Elts) {
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400413 lit.parts = append(lit.parts, v.walk(n.Elts[i+1]))
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100414 }
415 prefix = ")"
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400416 prefixLen = 1
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100417 }
418
419 case *ast.ListLit:
420 list := &list{baseValue: newExpr(n)}
421 for _, e := range n.Elts {
422 list.a = append(list.a, v.walk(e))
423 }
424 list.initLit()
425 if n.Ellipsis != token.NoPos || n.Type != nil {
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100426 list.len = &bound{list.baseValue, opGeq, list.len}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100427 if n.Type != nil {
428 list.typ = v.walk(n.Type)
429 }
430 }
431 value = list
432
433 case *ast.ParenExpr:
434 value = v.walk(n.X)
435
436 case *ast.SelectorExpr:
437 v.inSelector++
438 value = &selectorExpr{
439 newExpr(n),
440 v.walk(n.X),
441 v.label(n.Sel.Name, true),
442 }
443 v.inSelector--
444
445 case *ast.IndexExpr:
446 value = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
447
448 case *ast.SliceExpr:
449 slice := &sliceExpr{baseValue: newExpr(n), x: v.walk(n.X)}
450 if n.Low != nil {
451 slice.lo = v.walk(n.Low)
452 }
453 if n.High != nil {
454 slice.hi = v.walk(n.High)
455 }
456 value = slice
457
458 case *ast.CallExpr:
459 call := &callExpr{baseValue: newExpr(n), x: v.walk(n.Fun)}
460 for _, a := range n.Args {
461 call.args = append(call.args, v.walk(a))
462 }
463 value = call
464
465 case *ast.UnaryExpr:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100466 switch n.Op {
467 case token.NOT, token.ADD, token.SUB:
468 value = &unaryExpr{
469 newExpr(n),
470 tokenMap[n.Op],
471 v.walk(n.X),
472 }
Marcel van Lohuizen706e69c2019-02-11 18:21:14 +0100473 case token.GEQ, token.GTR, token.LSS, token.LEQ,
474 token.NEQ, token.MAT, token.NMAT:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100475 value = &bound{
476 newExpr(n),
477 tokenMap[n.Op],
478 v.walk(n.X),
479 }
480
481 case token.MUL:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100482 return v.error(n, "preference mark not allowed at this position")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100483 default:
484 return v.error(n, "unsupported unary operator %q", n.Op)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100485 }
486
487 case *ast.BinaryExpr:
488 switch n.Op {
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100489 case token.OR:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100490 d := &disjunction{baseValue: newExpr(n)}
491 v.addDisjunctionElem(d, n.X, false)
492 v.addDisjunctionElem(d, n.Y, false)
493 value = d
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100494
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100495 default:
496 value = &binaryExpr{
497 newExpr(n),
498 tokenMap[n.Op], // op
499 v.walk(n.X), // left
500 v.walk(n.Y), // right
501 }
502 }
503
504 // nothing to do
505 // case *syntax.EmitDecl:
506 default:
507 // TODO: unhandled node.
508 // value = ctx.mkErr(n, "unknown node type %T", n)
509 panic(fmt.Sprintf("unimplemented %T", n))
510
511 }
512 return value
513}
514
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100515func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
516 switch x := n.(type) {
517 case *ast.BinaryExpr:
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100518 if x.Op == token.OR {
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100519 v.addDisjunctionElem(d, x.X, mark)
520 v.addDisjunctionElem(d, x.Y, mark)
521 return
522 }
523 case *ast.UnaryExpr:
524 if x.Op == token.MUL {
525 mark = true
526 n = x.X
527 }
528 }
529 d.values = append(d.values, dValue{v.walk(n), mark})
530}
531
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100532func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
533 for _, c := range clauses {
534 if n, ok := c.(*ast.ForClause); ok {
535 params := &params{}
536 fn := &lambdaExpr{newExpr(n.Source), params, nil}
537 v.setScope(n, fn)
538 }
539 }
540 for i := len(clauses) - 1; i >= 0; i-- {
541 switch n := clauses[i].(type) {
542 case *ast.ForClause:
543 fn := v.mapScope(n).(*lambdaExpr)
544 fn.value = y
545
546 key := "_"
547 if n.Key != nil {
548 key = n.Key.Name
549 }
550 f := v.label(key, true)
551 fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
552
553 f = v.label(n.Value.Name, true)
554 fn.add(f, &top{})
555
556 y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
557
558 case *ast.IfClause:
559 y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
560 }
561 }
562 return y
563}