blob: 9dbed65b0d1451f5fa2242bcc91e266d90e1b762 [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()
Marcel van Lohuizend4847d92019-02-18 23:27:34 +010088 return newVisitorCtx(ctx, inst, obj, resolveRoot)
89}
90
91func newVisitorCtx(ctx *context, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010092 v := &astVisitor{
93 object: obj,
94 }
95 v.astState = &astState{
96 ctx: ctx,
97 index: ctx.index,
98 inst: inst,
99 litParser: &litParser{ctx: ctx},
100 resolveRoot: resolveRoot,
101 astMap: map[ast.Node]scope{},
102 }
103 return v
104}
105
106func (v *astVisitor) error(n ast.Node, args ...interface{}) value {
107 return v.mkErr(newNode(n), args...)
108}
109
110func (v *astVisitor) resolve(n *ast.Ident) value {
111 ctx := v.ctx()
112 label := v.label(n.Name, true)
113 if r := v.resolveRoot; r != nil {
114 if value, _ := r.lookup(v.ctx(), label); value != nil {
115 return &selectorExpr{newExpr(n),
116 &nodeRef{baseValue: newExpr(n), node: r}, label}
117 }
118 if v.inSelector > 0 {
119 if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
120 return &nodeRef{baseValue: newExpr(n), node: p}
121 }
122 }
123 }
124 return nil
125}
126
127func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
128 ctx := v.ctx()
129 val := lookupBuiltinPkg(ctx, imp)
130 if !isBottom(val) {
131 return val
132 }
133 path, err := strconv.Unquote(imp.Path.Value)
134 if err != nil {
135 return ctx.mkErr(newNode(imp), "illformed import spec")
136 }
137 bimp := v.inst.LookupImport(path)
138 if bimp == nil {
139 return ctx.mkErr(newNode(imp), "package %q not found", path)
140 }
141 impInst := v.index.loadInstance(bimp)
142 return impInst.rootValue.evalPartial(ctx)
143}
144
145// We probably don't need to call Walk.s
146func (v *astVisitor) walk(astNode ast.Node) (value value) {
147 switch n := astNode.(type) {
148 case *ast.File:
149 obj := v.object
150 v1 := &astVisitor{
151 astState: v.astState,
152 object: obj,
153 }
154 for _, e := range n.Decls {
155 switch x := e.(type) {
156 case *ast.EmitDecl:
157 if v1.object.emit == nil {
158 v1.object.emit = v1.walk(x.Expr)
159 } else {
160 v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
161 }
162 default:
163 v1.walk(e)
164 }
165 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100166 value = obj
167
168 case *ast.ImportDecl:
169 for _, s := range n.Specs {
170 v.walk(s)
171 }
172
173 case *ast.ImportSpec:
174 val := v.loadImport(n)
175 if !isBottom(val) {
176 v.setScope(n, val.(*structLit))
177 }
178
179 case *ast.StructLit:
180 obj := v.mapScope(n).(*structLit)
181 v1 := &astVisitor{
182 astState: v.astState,
183 object: obj,
184 }
185 for _, e := range n.Elts {
186 switch x := e.(type) {
187 case *ast.EmitDecl:
188 // Only allowed at top-level.
189 v1.error(x, "emitting values is only allowed at top level")
190 case *ast.Field, *ast.Alias:
191 v1.walk(e)
192 case *ast.ComprehensionDecl:
193 v1.walk(x)
194 }
195 }
196 value = obj
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100197
198 case *ast.ComprehensionDecl:
199 yielder := &yield{baseValue: newExpr(n.Field.Value)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100200 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100201 baseValue: newDecl(n),
202 clauses: wrapClauses(v, yielder, n.Clauses),
203 }
204 field := n.Field
205 switch x := field.Label.(type) {
206 case *ast.Interpolation:
207 yielder.key = v.walk(x)
208 yielder.value = v.walk(field.Value)
209
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100210 case *ast.TemplateLabel:
211 f := v.label(x.Ident.Name, true)
212
213 sig := &params{}
214 sig.add(f, &basicType{newNode(field.Label), stringKind})
215 template := &lambdaExpr{newExpr(field.Value), sig, nil}
216
217 v.setScope(field, template)
218 template.value = v.walk(field.Value)
219 yielder.value = template
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100220 fc.isTemplate = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100221
222 case *ast.BasicLit, *ast.Ident:
223 name, ok := ast.LabelName(x)
224 if !ok {
225 return v.error(x, "invalid field name: %v", x)
226 }
Marcel van Lohuizenf23fbff2018-12-20 12:23:16 +0100227
228 // TODO: if the clauses do not contain a guard, we know that this
229 // field will always be added and we can move the comprehension one
230 // level down. This, in turn, has the advantage that it is more
231 // likely that the cross-reference limitation for field
232 // comprehensions is not violated. To ensure compatibility between
233 // implementations, though, we should relax the spec as well.
234 // The cross-reference rule is simple and this relaxation seems a
235 // bit more complex.
236
237 // TODO: for now we can also consider making this an error if
238 // the list of clauses does not contain if and make a suggestion
239 // to rewrite it.
240
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100241 if name != "" {
242 yielder.key = &stringLit{newNode(x), name}
243 yielder.value = v.walk(field.Value)
244 }
245
246 default:
247 panic("cue: unknown label type")
248 }
249 // yielder.key = v.walk(n.Field.Label)
250 // yielder.value = v.walk(n.Field.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100251 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100252
253 case *ast.Field:
254 switch x := n.Label.(type) {
255 case *ast.Interpolation:
256 yielder := &yield{baseValue: newNode(x)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100257 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100258 baseValue: newDecl(n),
259 clauses: yielder,
260 }
261 yielder.key = v.walk(x)
262 yielder.value = v.walk(n.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100263 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100264
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100265 case *ast.TemplateLabel:
266 f := v.label(x.Ident.Name, true)
267
268 sig := &params{}
269 sig.add(f, &basicType{newNode(n.Label), stringKind})
270 template := &lambdaExpr{newExpr(n.Value), sig, nil}
271
272 v.setScope(n, template)
273 template.value = v.walk(n.Value)
274
275 if v.object.template == nil {
276 v.object.template = template
277 } else {
278 v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
279 }
280
281 case *ast.BasicLit, *ast.Ident:
282 f, ok := v.nodeLabel(x)
283 if !ok {
284 return v.error(n.Label, "invalid field name: %v", n.Label)
285 }
286 if f != 0 {
287 v.object.insertValue(v.ctx(), f, v.walk(n.Value))
288 }
289
290 default:
291 panic("cue: unknown label type")
292 }
293
294 case *ast.Alias:
295 // parsed verbatim at reference.
296
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100297 case *ast.ListComprehension:
298 yielder := &yield{baseValue: newExpr(n.Expr)}
299 lc := &listComprehension{
300 newExpr(n),
301 wrapClauses(v, yielder, n.Clauses),
302 }
303 // we don't support key for lists (yet?)
304 yielder.value = v.walk(n.Expr)
305 return lc
306
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100307 // Expressions
308 case *ast.Ident:
309 if n.Node == nil {
310 if value = v.resolve(n); value != nil {
311 break
312 }
313
314 switch n.Name {
315 case "_":
316 return &top{newExpr(n)}
317 case "string":
318 return &basicType{newExpr(n), stringKind}
319 case "bytes":
320 return &basicType{newExpr(n), bytesKind}
321 case "bool":
322 return &basicType{newExpr(n), boolKind}
323 case "int":
324 return &basicType{newExpr(n), intKind}
325 case "float":
326 return &basicType{newExpr(n), floatKind}
327 case "number":
328 return &basicType{newExpr(n), numKind}
329 case "duration":
330 return &basicType{newExpr(n), durationKind}
331
332 case "len":
333 return lenBuiltin
334 }
335 if r, ok := predefinedRanges[n.Name]; ok {
336 return r
337 }
338
339 value = v.error(n, "reference %q not found", n.Name)
340 break
341 }
342
343 if a, ok := n.Node.(*ast.Alias); ok {
344 value = v.walk(a.Expr)
345 break
346 }
347
348 label := v.label(n.Name, true)
349 if n.Scope != nil {
350 n2 := v.mapScope(n.Scope)
351 value = &nodeRef{baseValue: newExpr(n), node: n2}
352 value = &selectorExpr{newExpr(n), value, label}
353 } else {
354 n2 := v.mapScope(n.Node)
355 value = &nodeRef{baseValue: newExpr(n), node: n2}
356 }
357
358 case *ast.BottomLit:
359 value = v.error(n, "from source")
360
361 case *ast.BadDecl:
362 // nothing to do
363
364 case *ast.BadExpr:
365 value = v.error(n, "invalid expression")
366
367 case *ast.BasicLit:
368 value = v.litParser.parse(n)
369
370 case *ast.Interpolation:
371 if len(n.Elts) == 0 {
372 return v.error(n, "invalid interpolation")
373 }
374 first, ok1 := n.Elts[0].(*ast.BasicLit)
375 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
376 if !ok1 || !ok2 {
377 return v.error(n, "invalid interpolation")
378 }
379 if len(n.Elts) == 1 {
380 value = v.walk(n.Elts[0])
381 break
382 }
383 lit := &interpolation{baseValue: newExpr(n), k: stringKind}
384 value = lit
385 quote, err := stringType(first.Value)
386 if err != nil {
387 return v.error(n, "invalid interpolation: %v", err)
388 }
389 if quote[0] == '\'' {
390 return v.error(n, "interpolation not implemented for bytes: %v", err)
391 }
392 ws, err := wsPrefix(last.Value, quote)
393 if err != nil {
394 return v.error(n, "invalid interpolation: %v", err)
395 }
396 prefix := quote
397 multi := len(quote) == 3
398 p := v.litParser
399 for i := 0; i < len(n.Elts); i += 2 {
400 l, ok := n.Elts[i].(*ast.BasicLit)
401 if !ok {
402 return v.error(n, "invalid interpolation")
403 }
404 if err := p.init(l); err != nil {
405 return v.error(n, "invalid interpolation: %v", err)
406 }
407 if i+1 < len(n.Elts) {
408 x := p.parseString(prefix, `\(`, ws, multi, quote[0])
409 lit.parts = append(lit.parts, x, v.walk(n.Elts[i+1]))
410 } else {
411 x := p.parseString(prefix, quote, ws, multi, quote[0])
412 lit.parts = append(lit.parts, x)
413 }
414 prefix = ")"
415 }
416
417 case *ast.ListLit:
418 list := &list{baseValue: newExpr(n)}
419 for _, e := range n.Elts {
420 list.a = append(list.a, v.walk(e))
421 }
422 list.initLit()
423 if n.Ellipsis != token.NoPos || n.Type != nil {
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100424 list.len = &bound{list.baseValue, opGeq, list.len}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100425 if n.Type != nil {
426 list.typ = v.walk(n.Type)
427 }
428 }
429 value = list
430
431 case *ast.ParenExpr:
432 value = v.walk(n.X)
433
434 case *ast.SelectorExpr:
435 v.inSelector++
436 value = &selectorExpr{
437 newExpr(n),
438 v.walk(n.X),
439 v.label(n.Sel.Name, true),
440 }
441 v.inSelector--
442
443 case *ast.IndexExpr:
444 value = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
445
446 case *ast.SliceExpr:
447 slice := &sliceExpr{baseValue: newExpr(n), x: v.walk(n.X)}
448 if n.Low != nil {
449 slice.lo = v.walk(n.Low)
450 }
451 if n.High != nil {
452 slice.hi = v.walk(n.High)
453 }
454 value = slice
455
456 case *ast.CallExpr:
457 call := &callExpr{baseValue: newExpr(n), x: v.walk(n.Fun)}
458 for _, a := range n.Args {
459 call.args = append(call.args, v.walk(a))
460 }
461 value = call
462
463 case *ast.UnaryExpr:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100464 switch n.Op {
465 case token.NOT, token.ADD, token.SUB:
466 value = &unaryExpr{
467 newExpr(n),
468 tokenMap[n.Op],
469 v.walk(n.X),
470 }
Marcel van Lohuizen706e69c2019-02-11 18:21:14 +0100471 case token.GEQ, token.GTR, token.LSS, token.LEQ,
472 token.NEQ, token.MAT, token.NMAT:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100473 value = &bound{
474 newExpr(n),
475 tokenMap[n.Op],
476 v.walk(n.X),
477 }
478
479 case token.MUL:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100480 return v.error(n, "preference mark not allowed at this position")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100481 default:
482 return v.error(n, "unsupported unary operator %q", n.Op)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100483 }
484
485 case *ast.BinaryExpr:
486 switch n.Op {
487 case token.DISJUNCTION:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100488 d := &disjunction{baseValue: newExpr(n)}
489 v.addDisjunctionElem(d, n.X, false)
490 v.addDisjunctionElem(d, n.Y, false)
491 value = d
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100492
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100493 default:
494 value = &binaryExpr{
495 newExpr(n),
496 tokenMap[n.Op], // op
497 v.walk(n.X), // left
498 v.walk(n.Y), // right
499 }
500 }
501
502 // nothing to do
503 // case *syntax.EmitDecl:
504 default:
505 // TODO: unhandled node.
506 // value = ctx.mkErr(n, "unknown node type %T", n)
507 panic(fmt.Sprintf("unimplemented %T", n))
508
509 }
510 return value
511}
512
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100513func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
514 switch x := n.(type) {
515 case *ast.BinaryExpr:
516 if x.Op == token.DISJUNCTION {
517 v.addDisjunctionElem(d, x.X, mark)
518 v.addDisjunctionElem(d, x.Y, mark)
519 return
520 }
521 case *ast.UnaryExpr:
522 if x.Op == token.MUL {
523 mark = true
524 n = x.X
525 }
526 }
527 d.values = append(d.values, dValue{v.walk(n), mark})
528}
529
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100530func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
531 for _, c := range clauses {
532 if n, ok := c.(*ast.ForClause); ok {
533 params := &params{}
534 fn := &lambdaExpr{newExpr(n.Source), params, nil}
535 v.setScope(n, fn)
536 }
537 }
538 for i := len(clauses) - 1; i >= 0; i-- {
539 switch n := clauses[i].(type) {
540 case *ast.ForClause:
541 fn := v.mapScope(n).(*lambdaExpr)
542 fn.value = y
543
544 key := "_"
545 if n.Key != nil {
546 key = n.Key.Name
547 }
548 f := v.label(key, true)
549 fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
550
551 f = v.label(n.Value.Name, true)
552 fn.add(f, &top{})
553
554 y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
555
556 case *ast.IfClause:
557 y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
558 }
559 }
560 return y
561}