blob: e1303eaaae38429d3b6c5c06c54f1b52356090d6 [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"
19 "strconv"
20
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/build"
23 "cuelang.org/go/cue/token"
24)
25
26// insertFile inserts the given file at the root of the instance.
27//
28// The contents will be merged (unified) with any pre-existing value. In this
29// case an error may be reported, but only if the merge failed at the top-level.
30// Other errors will be recorded at the respective values in the tree.
31//
32// There should be no unresolved identifiers in file, meaning the Node field
33// of all identifiers should be set to a non-nil value.
34func (inst *Instance) insertFile(f *ast.File) error {
35 // TODO: insert by converting to value first so that the trim command can
36 // also remove top-level fields.
37 // First process single file.
38 v := newVisitor(inst.index, inst.inst, inst.rootStruct, inst.scope)
39 v.astState.astMap[f] = inst.rootStruct
40 result := v.walk(f)
41 if isBottom(result) {
42 return result.(*bottom)
43 }
44
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010045 return nil
46}
47
48type astVisitor struct {
49 *astState
Marcel van Lohuizen66db9202018-12-17 19:02:08 +010050 object *structLit
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010051
52 inSelector int
53}
54
55func (v *astVisitor) ctx() *context {
56 return v.astState.ctx
57}
58
59type astState struct {
60 ctx *context
61 *index
62 inst *build.Instance
63
64 litParser *litParser
65 resolveRoot *structLit
66
67 // make unique per level to avoid reuse of structs being an issue.
68 astMap map[ast.Node]scope
69}
70
71func (s *astState) mapScope(n ast.Node) (m scope) {
72 if m = s.astMap[n]; m == nil {
73 m = newStruct(newNode(n))
74 s.astMap[n] = m
75 }
76 return m
77}
78
79func (s *astState) setScope(n ast.Node, v scope) {
80 if m, ok := s.astMap[n]; ok && m != v {
81 panic("already defined")
82 }
83 s.astMap[n] = v
84}
85
86func newVisitor(idx *index, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
87 ctx := idx.newContext()
88 v := &astVisitor{
89 object: obj,
90 }
91 v.astState = &astState{
92 ctx: ctx,
93 index: ctx.index,
94 inst: inst,
95 litParser: &litParser{ctx: ctx},
96 resolveRoot: resolveRoot,
97 astMap: map[ast.Node]scope{},
98 }
99 return v
100}
101
102func (v *astVisitor) error(n ast.Node, args ...interface{}) value {
103 return v.mkErr(newNode(n), args...)
104}
105
106func (v *astVisitor) resolve(n *ast.Ident) value {
107 ctx := v.ctx()
108 label := v.label(n.Name, true)
109 if r := v.resolveRoot; r != nil {
110 if value, _ := r.lookup(v.ctx(), label); value != nil {
111 return &selectorExpr{newExpr(n),
112 &nodeRef{baseValue: newExpr(n), node: r}, label}
113 }
114 if v.inSelector > 0 {
115 if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
116 return &nodeRef{baseValue: newExpr(n), node: p}
117 }
118 }
119 }
120 return nil
121}
122
123func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
124 ctx := v.ctx()
125 val := lookupBuiltinPkg(ctx, imp)
126 if !isBottom(val) {
127 return val
128 }
129 path, err := strconv.Unquote(imp.Path.Value)
130 if err != nil {
131 return ctx.mkErr(newNode(imp), "illformed import spec")
132 }
133 bimp := v.inst.LookupImport(path)
134 if bimp == nil {
135 return ctx.mkErr(newNode(imp), "package %q not found", path)
136 }
137 impInst := v.index.loadInstance(bimp)
138 return impInst.rootValue.evalPartial(ctx)
139}
140
141// We probably don't need to call Walk.s
142func (v *astVisitor) walk(astNode ast.Node) (value value) {
143 switch n := astNode.(type) {
144 case *ast.File:
145 obj := v.object
146 v1 := &astVisitor{
147 astState: v.astState,
148 object: obj,
149 }
150 for _, e := range n.Decls {
151 switch x := e.(type) {
152 case *ast.EmitDecl:
153 if v1.object.emit == nil {
154 v1.object.emit = v1.walk(x.Expr)
155 } else {
156 v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
157 }
158 default:
159 v1.walk(e)
160 }
161 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100162 value = obj
163
164 case *ast.ImportDecl:
165 for _, s := range n.Specs {
166 v.walk(s)
167 }
168
169 case *ast.ImportSpec:
170 val := v.loadImport(n)
171 if !isBottom(val) {
172 v.setScope(n, val.(*structLit))
173 }
174
175 case *ast.StructLit:
176 obj := v.mapScope(n).(*structLit)
177 v1 := &astVisitor{
178 astState: v.astState,
179 object: obj,
180 }
181 for _, e := range n.Elts {
182 switch x := e.(type) {
183 case *ast.EmitDecl:
184 // Only allowed at top-level.
185 v1.error(x, "emitting values is only allowed at top level")
186 case *ast.Field, *ast.Alias:
187 v1.walk(e)
188 case *ast.ComprehensionDecl:
189 v1.walk(x)
190 }
191 }
192 value = obj
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100193
194 case *ast.ComprehensionDecl:
195 yielder := &yield{baseValue: newExpr(n.Field.Value)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100196 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100197 baseValue: newDecl(n),
198 clauses: wrapClauses(v, yielder, n.Clauses),
199 }
200 field := n.Field
201 switch x := field.Label.(type) {
202 case *ast.Interpolation:
203 yielder.key = v.walk(x)
204 yielder.value = v.walk(field.Value)
205
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100206 case *ast.TemplateLabel:
207 f := v.label(x.Ident.Name, true)
208
209 sig := &params{}
210 sig.add(f, &basicType{newNode(field.Label), stringKind})
211 template := &lambdaExpr{newExpr(field.Value), sig, nil}
212
213 v.setScope(field, template)
214 template.value = v.walk(field.Value)
215 yielder.value = template
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100216 fc.isTemplate = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100217
218 case *ast.BasicLit, *ast.Ident:
219 name, ok := ast.LabelName(x)
220 if !ok {
221 return v.error(x, "invalid field name: %v", x)
222 }
Marcel van Lohuizenf23fbff2018-12-20 12:23:16 +0100223
224 // TODO: if the clauses do not contain a guard, we know that this
225 // field will always be added and we can move the comprehension one
226 // level down. This, in turn, has the advantage that it is more
227 // likely that the cross-reference limitation for field
228 // comprehensions is not violated. To ensure compatibility between
229 // implementations, though, we should relax the spec as well.
230 // The cross-reference rule is simple and this relaxation seems a
231 // bit more complex.
232
233 // TODO: for now we can also consider making this an error if
234 // the list of clauses does not contain if and make a suggestion
235 // to rewrite it.
236
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100237 if name != "" {
238 yielder.key = &stringLit{newNode(x), name}
239 yielder.value = v.walk(field.Value)
240 }
241
242 default:
243 panic("cue: unknown label type")
244 }
245 // yielder.key = v.walk(n.Field.Label)
246 // yielder.value = v.walk(n.Field.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100247 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100248
249 case *ast.Field:
250 switch x := n.Label.(type) {
251 case *ast.Interpolation:
252 yielder := &yield{baseValue: newNode(x)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100253 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100254 baseValue: newDecl(n),
255 clauses: yielder,
256 }
257 yielder.key = v.walk(x)
258 yielder.value = v.walk(n.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100259 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100260
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100261 case *ast.TemplateLabel:
262 f := v.label(x.Ident.Name, true)
263
264 sig := &params{}
265 sig.add(f, &basicType{newNode(n.Label), stringKind})
266 template := &lambdaExpr{newExpr(n.Value), sig, nil}
267
268 v.setScope(n, template)
269 template.value = v.walk(n.Value)
270
271 if v.object.template == nil {
272 v.object.template = template
273 } else {
274 v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
275 }
276
277 case *ast.BasicLit, *ast.Ident:
278 f, ok := v.nodeLabel(x)
279 if !ok {
280 return v.error(n.Label, "invalid field name: %v", n.Label)
281 }
282 if f != 0 {
283 v.object.insertValue(v.ctx(), f, v.walk(n.Value))
284 }
285
286 default:
287 panic("cue: unknown label type")
288 }
289
290 case *ast.Alias:
291 // parsed verbatim at reference.
292
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100293 case *ast.ListComprehension:
294 yielder := &yield{baseValue: newExpr(n.Expr)}
295 lc := &listComprehension{
296 newExpr(n),
297 wrapClauses(v, yielder, n.Clauses),
298 }
299 // we don't support key for lists (yet?)
300 yielder.value = v.walk(n.Expr)
301 return lc
302
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100303 // Expressions
304 case *ast.Ident:
305 if n.Node == nil {
306 if value = v.resolve(n); value != nil {
307 break
308 }
309
310 switch n.Name {
311 case "_":
312 return &top{newExpr(n)}
313 case "string":
314 return &basicType{newExpr(n), stringKind}
315 case "bytes":
316 return &basicType{newExpr(n), bytesKind}
317 case "bool":
318 return &basicType{newExpr(n), boolKind}
319 case "int":
320 return &basicType{newExpr(n), intKind}
321 case "float":
322 return &basicType{newExpr(n), floatKind}
323 case "number":
324 return &basicType{newExpr(n), numKind}
325 case "duration":
326 return &basicType{newExpr(n), durationKind}
327
328 case "len":
329 return lenBuiltin
330 }
331 if r, ok := predefinedRanges[n.Name]; ok {
332 return r
333 }
334
335 value = v.error(n, "reference %q not found", n.Name)
336 break
337 }
338
339 if a, ok := n.Node.(*ast.Alias); ok {
340 value = v.walk(a.Expr)
341 break
342 }
343
344 label := v.label(n.Name, true)
345 if n.Scope != nil {
346 n2 := v.mapScope(n.Scope)
347 value = &nodeRef{baseValue: newExpr(n), node: n2}
348 value = &selectorExpr{newExpr(n), value, label}
349 } else {
350 n2 := v.mapScope(n.Node)
351 value = &nodeRef{baseValue: newExpr(n), node: n2}
352 }
353
354 case *ast.BottomLit:
355 value = v.error(n, "from source")
356
357 case *ast.BadDecl:
358 // nothing to do
359
360 case *ast.BadExpr:
361 value = v.error(n, "invalid expression")
362
363 case *ast.BasicLit:
364 value = v.litParser.parse(n)
365
366 case *ast.Interpolation:
367 if len(n.Elts) == 0 {
368 return v.error(n, "invalid interpolation")
369 }
370 first, ok1 := n.Elts[0].(*ast.BasicLit)
371 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
372 if !ok1 || !ok2 {
373 return v.error(n, "invalid interpolation")
374 }
375 if len(n.Elts) == 1 {
376 value = v.walk(n.Elts[0])
377 break
378 }
379 lit := &interpolation{baseValue: newExpr(n), k: stringKind}
380 value = lit
381 quote, err := stringType(first.Value)
382 if err != nil {
383 return v.error(n, "invalid interpolation: %v", err)
384 }
385 if quote[0] == '\'' {
386 return v.error(n, "interpolation not implemented for bytes: %v", err)
387 }
388 ws, err := wsPrefix(last.Value, quote)
389 if err != nil {
390 return v.error(n, "invalid interpolation: %v", err)
391 }
392 prefix := quote
393 multi := len(quote) == 3
394 p := v.litParser
395 for i := 0; i < len(n.Elts); i += 2 {
396 l, ok := n.Elts[i].(*ast.BasicLit)
397 if !ok {
398 return v.error(n, "invalid interpolation")
399 }
400 if err := p.init(l); err != nil {
401 return v.error(n, "invalid interpolation: %v", err)
402 }
403 if i+1 < len(n.Elts) {
404 x := p.parseString(prefix, `\(`, ws, multi, quote[0])
405 lit.parts = append(lit.parts, x, v.walk(n.Elts[i+1]))
406 } else {
407 x := p.parseString(prefix, quote, ws, multi, quote[0])
408 lit.parts = append(lit.parts, x)
409 }
410 prefix = ")"
411 }
412
413 case *ast.ListLit:
414 list := &list{baseValue: newExpr(n)}
415 for _, e := range n.Elts {
416 list.a = append(list.a, v.walk(e))
417 }
418 list.initLit()
419 if n.Ellipsis != token.NoPos || n.Type != nil {
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100420 list.len = &bound{list.baseValue, opGeq, list.len}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100421 if n.Type != nil {
422 list.typ = v.walk(n.Type)
423 }
424 }
425 value = list
426
427 case *ast.ParenExpr:
428 value = v.walk(n.X)
429
430 case *ast.SelectorExpr:
431 v.inSelector++
432 value = &selectorExpr{
433 newExpr(n),
434 v.walk(n.X),
435 v.label(n.Sel.Name, true),
436 }
437 v.inSelector--
438
439 case *ast.IndexExpr:
440 value = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
441
442 case *ast.SliceExpr:
443 slice := &sliceExpr{baseValue: newExpr(n), x: v.walk(n.X)}
444 if n.Low != nil {
445 slice.lo = v.walk(n.Low)
446 }
447 if n.High != nil {
448 slice.hi = v.walk(n.High)
449 }
450 value = slice
451
452 case *ast.CallExpr:
453 call := &callExpr{baseValue: newExpr(n), x: v.walk(n.Fun)}
454 for _, a := range n.Args {
455 call.args = append(call.args, v.walk(a))
456 }
457 value = call
458
459 case *ast.UnaryExpr:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100460 switch n.Op {
461 case token.NOT, token.ADD, token.SUB:
462 value = &unaryExpr{
463 newExpr(n),
464 tokenMap[n.Op],
465 v.walk(n.X),
466 }
Marcel van Lohuizen706e69c2019-02-11 18:21:14 +0100467 case token.GEQ, token.GTR, token.LSS, token.LEQ,
468 token.NEQ, token.MAT, token.NMAT:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100469 value = &bound{
470 newExpr(n),
471 tokenMap[n.Op],
472 v.walk(n.X),
473 }
474
475 case token.MUL:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100476 return v.error(n, "preference mark not allowed at this position")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100477 default:
478 return v.error(n, "unsupported unary operator %q", n.Op)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100479 }
480
481 case *ast.BinaryExpr:
482 switch n.Op {
483 case token.DISJUNCTION:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100484 d := &disjunction{baseValue: newExpr(n)}
485 v.addDisjunctionElem(d, n.X, false)
486 v.addDisjunctionElem(d, n.Y, false)
487 value = d
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100488
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100489 default:
490 value = &binaryExpr{
491 newExpr(n),
492 tokenMap[n.Op], // op
493 v.walk(n.X), // left
494 v.walk(n.Y), // right
495 }
496 }
497
498 // nothing to do
499 // case *syntax.EmitDecl:
500 default:
501 // TODO: unhandled node.
502 // value = ctx.mkErr(n, "unknown node type %T", n)
503 panic(fmt.Sprintf("unimplemented %T", n))
504
505 }
506 return value
507}
508
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100509func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
510 switch x := n.(type) {
511 case *ast.BinaryExpr:
512 if x.Op == token.DISJUNCTION {
513 v.addDisjunctionElem(d, x.X, mark)
514 v.addDisjunctionElem(d, x.Y, mark)
515 return
516 }
517 case *ast.UnaryExpr:
518 if x.Op == token.MUL {
519 mark = true
520 n = x.X
521 }
522 }
523 d.values = append(d.values, dValue{v.walk(n), mark})
524}
525
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100526func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
527 for _, c := range clauses {
528 if n, ok := c.(*ast.ForClause); ok {
529 params := &params{}
530 fn := &lambdaExpr{newExpr(n.Source), params, nil}
531 v.setScope(n, fn)
532 }
533 }
534 for i := len(clauses) - 1; i >= 0; i-- {
535 switch n := clauses[i].(type) {
536 case *ast.ForClause:
537 fn := v.mapScope(n).(*lambdaExpr)
538 fn.value = y
539
540 key := "_"
541 if n.Key != nil {
542 key = n.Key.Name
543 }
544 f := v.label(key, true)
545 fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
546
547 f = v.label(n.Value.Name, true)
548 fn.add(f, &top{})
549
550 y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
551
552 case *ast.IfClause:
553 y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
554 }
555 }
556 return y
557}