blob: 2b5bab48f99c2e7cdd51a52a9ac0b40c98d990a7 [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 Lohuizen52d4dd72019-06-09 11:53:40 +020019 "strconv"
Marcel van Lohuizen369e4232019-02-15 10:59:29 +040020 "strings"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010021
22 "cuelang.org/go/cue/ast"
23 "cuelang.org/go/cue/build"
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +020024 "cuelang.org/go/cue/errors"
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +010025 "cuelang.org/go/cue/literal"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010026 "cuelang.org/go/cue/token"
Marcel van Lohuizene9fd2142019-04-12 15:46:31 +020027 "cuelang.org/go/internal"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010028)
29
30// insertFile inserts the given file at the root of the instance.
31//
32// The contents will be merged (unified) with any pre-existing value. In this
33// case an error may be reported, but only if the merge failed at the top-level.
34// Other errors will be recorded at the respective values in the tree.
35//
36// There should be no unresolved identifiers in file, meaning the Node field
37// of all identifiers should be set to a non-nil value.
38func (inst *Instance) insertFile(f *ast.File) error {
39 // TODO: insert by converting to value first so that the trim command can
40 // also remove top-level fields.
41 // First process single file.
42 v := newVisitor(inst.index, inst.inst, inst.rootStruct, inst.scope)
43 v.astState.astMap[f] = inst.rootStruct
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +020044 // TODO: fix cmd/import to resolve references in the AST before
45 // inserting. For now, we accept errors that did not make it up to the tree.
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010046 result := v.walk(f)
47 if isBottom(result) {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +020048 if v.errors.Len() > 0 {
49 return v.errors
50 }
51 return &callError{result.(*bottom)}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010052 }
53
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010054 return nil
55}
56
57type astVisitor struct {
58 *astState
Marcel van Lohuizen66db9202018-12-17 19:02:08 +010059 object *structLit
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +020060
61 parent *astVisitor
62 sel string // label or index; may be '*'
Marcel van Lohuizen079451a2019-05-15 14:51:11 +020063 // For single line fields, the doc comment is applied to the inner-most
64 // field value.
65 //
66 // // This comment is for bar.
67 // foo bar: value
68 //
69 doc *docNode
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010070
71 inSelector int
72}
73
74func (v *astVisitor) ctx() *context {
75 return v.astState.ctx
76}
77
78type astState struct {
79 ctx *context
80 *index
81 inst *build.Instance
82
83 litParser *litParser
84 resolveRoot *structLit
85
86 // make unique per level to avoid reuse of structs being an issue.
87 astMap map[ast.Node]scope
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +020088
89 errors errors.List
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010090}
91
92func (s *astState) mapScope(n ast.Node) (m scope) {
93 if m = s.astMap[n]; m == nil {
94 m = newStruct(newNode(n))
95 s.astMap[n] = m
96 }
97 return m
98}
99
100func (s *astState) setScope(n ast.Node, v scope) {
101 if m, ok := s.astMap[n]; ok && m != v {
102 panic("already defined")
103 }
104 s.astMap[n] = v
105}
106
107func newVisitor(idx *index, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
108 ctx := idx.newContext()
Marcel van Lohuizend4847d92019-02-18 23:27:34 +0100109 return newVisitorCtx(ctx, inst, obj, resolveRoot)
110}
111
112func newVisitorCtx(ctx *context, inst *build.Instance, obj, resolveRoot *structLit) *astVisitor {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100113 v := &astVisitor{
114 object: obj,
115 }
116 v.astState = &astState{
117 ctx: ctx,
118 index: ctx.index,
119 inst: inst,
120 litParser: &litParser{ctx: ctx},
121 resolveRoot: resolveRoot,
122 astMap: map[ast.Node]scope{},
123 }
124 return v
125}
126
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200127func (v *astVisitor) errf(n ast.Node, format string, args ...interface{}) evaluated {
128 v.astState.errors.Add(&nodeError{
Marcel van Lohuizen8a3c35b2019-06-10 18:25:37 +0200129 path: v.appendPath(nil),
130 n: n,
131 Message: errors.NewMessage(format, args),
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200132 })
133 arguments := append([]interface{}{format}, args...)
134 return v.mkErr(newNode(n), arguments...)
135}
136
137func (v *astVisitor) appendPath(a []string) []string {
138 if v.parent != nil {
139 a = v.parent.appendPath(a)
140 }
141 if v.sel != "" {
142 a = append(a, v.sel)
143 }
144 return a
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100145}
146
147func (v *astVisitor) resolve(n *ast.Ident) value {
148 ctx := v.ctx()
149 label := v.label(n.Name, true)
150 if r := v.resolveRoot; r != nil {
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200151 for _, a := range r.arcs {
152 if a.feature == label {
153 return &selectorExpr{newExpr(n),
154 &nodeRef{baseValue: newExpr(n), node: r}, label}
155 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100156 }
157 if v.inSelector > 0 {
158 if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
159 return &nodeRef{baseValue: newExpr(n), node: p}
160 }
161 }
162 }
163 return nil
164}
165
166func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
167 ctx := v.ctx()
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100168 path, err := literal.Unquote(imp.Path.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100169 if err != nil {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200170 return v.errf(imp, "illformed import spec")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100171 }
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200172 // TODO: allow builtin *and* imported package. The result is a unified
173 // struct.
Marcel van Lohuizen8bc02e52019-04-01 13:14:07 +0200174 if p := getBuiltinPkg(ctx, path); p != nil {
175 return p
176 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100177 bimp := v.inst.LookupImport(path)
178 if bimp == nil {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200179 return v.errf(imp, "package %q not found", path)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100180 }
181 impInst := v.index.loadInstance(bimp)
182 return impInst.rootValue.evalPartial(ctx)
183}
184
185// We probably don't need to call Walk.s
186func (v *astVisitor) walk(astNode ast.Node) (value value) {
187 switch n := astNode.(type) {
188 case *ast.File:
189 obj := v.object
190 v1 := &astVisitor{
191 astState: v.astState,
192 object: obj,
193 }
194 for _, e := range n.Decls {
195 switch x := e.(type) {
196 case *ast.EmitDecl:
197 if v1.object.emit == nil {
198 v1.object.emit = v1.walk(x.Expr)
199 } else {
200 v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
201 }
202 default:
203 v1.walk(e)
204 }
205 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100206 value = obj
207
208 case *ast.ImportDecl:
209 for _, s := range n.Specs {
210 v.walk(s)
211 }
212
213 case *ast.ImportSpec:
214 val := v.loadImport(n)
215 if !isBottom(val) {
216 v.setScope(n, val.(*structLit))
217 }
218
219 case *ast.StructLit:
220 obj := v.mapScope(n).(*structLit)
221 v1 := &astVisitor{
222 astState: v.astState,
223 object: obj,
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200224 parent: v,
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100225 }
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200226 passDoc := len(n.Elts) == 1 && !n.Lbrace.IsValid() && v.doc != nil
227 if passDoc {
228 v1.doc = v.doc
229 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100230 for _, e := range n.Elts {
231 switch x := e.(type) {
232 case *ast.EmitDecl:
233 // Only allowed at top-level.
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200234 return v1.errf(x, "emitting values is only allowed at top level")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100235 case *ast.Field, *ast.Alias:
236 v1.walk(e)
237 case *ast.ComprehensionDecl:
238 v1.walk(x)
239 }
240 }
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200241 if passDoc {
242 v.doc = v1.doc // signal usage of document back to parent.
243 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100244 value = obj
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100245
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200246 case *ast.ListLit:
247 v1 := &astVisitor{
248 astState: v.astState,
249 object: v.object,
250 parent: v,
251 }
252 arcs := []arc{}
253 for i, e := range n.Elts {
254 v1.sel = strconv.Itoa(i)
255 arcs = append(arcs, arc{feature: label(i), v: v1.walk(e)})
256 }
257 s := &structLit{baseValue: newExpr(n), arcs: arcs}
258 list := &list{baseValue: newExpr(n), elem: s}
259 list.initLit()
260 if n.Ellipsis != token.NoPos || n.Type != nil {
Marcel van Lohuizen6767a012019-06-26 12:15:16 +0200261 list.len = newBound(v.ctx(), list.baseValue, opGeq, intKind, list.len)
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200262 if n.Type != nil {
263 list.typ = v1.walk(n.Type)
264 }
265 }
266 value = list
267
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100268 case *ast.ComprehensionDecl:
269 yielder := &yield{baseValue: newExpr(n.Field.Value)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100270 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100271 baseValue: newDecl(n),
272 clauses: wrapClauses(v, yielder, n.Clauses),
273 }
274 field := n.Field
275 switch x := field.Label.(type) {
276 case *ast.Interpolation:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200277 v.sel = "?"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100278 yielder.key = v.walk(x)
279 yielder.value = v.walk(field.Value)
280
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100281 case *ast.TemplateLabel:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200282 v.sel = "*"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100283 f := v.label(x.Ident.Name, true)
284
285 sig := &params{}
286 sig.add(f, &basicType{newNode(field.Label), stringKind})
287 template := &lambdaExpr{newExpr(field.Value), sig, nil}
288
289 v.setScope(field, template)
290 template.value = v.walk(field.Value)
291 yielder.value = template
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100292 fc.isTemplate = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100293
294 case *ast.BasicLit, *ast.Ident:
295 name, ok := ast.LabelName(x)
296 if !ok {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200297 return v.errf(x, "invalid field name: %v", x)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100298 }
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200299 // TODO: is this correct? Just for info, so not very important.
300 v.sel = name
Marcel van Lohuizenf23fbff2018-12-20 12:23:16 +0100301
302 // TODO: if the clauses do not contain a guard, we know that this
303 // field will always be added and we can move the comprehension one
304 // level down. This, in turn, has the advantage that it is more
305 // likely that the cross-reference limitation for field
306 // comprehensions is not violated. To ensure compatibility between
307 // implementations, though, we should relax the spec as well.
308 // The cross-reference rule is simple and this relaxation seems a
309 // bit more complex.
310
311 // TODO: for now we can also consider making this an error if
312 // the list of clauses does not contain if and make a suggestion
313 // to rewrite it.
314
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100315 if name != "" {
Marcel van Lohuizen6767a012019-06-26 12:15:16 +0200316 yielder.key = &stringLit{newNode(x), name, nil}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100317 yielder.value = v.walk(field.Value)
318 }
319
320 default:
321 panic("cue: unknown label type")
322 }
323 // yielder.key = v.walk(n.Field.Label)
324 // yielder.value = v.walk(n.Field.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100325 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100326
327 case *ast.Field:
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100328 opt := n.Optional != token.NoPos
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100329 switch x := n.Label.(type) {
330 case *ast.Interpolation:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200331 v.sel = "?"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100332 yielder := &yield{baseValue: newNode(x)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100333 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100334 baseValue: newDecl(n),
335 clauses: yielder,
336 }
337 yielder.key = v.walk(x)
338 yielder.value = v.walk(n.Value)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100339 yielder.opt = opt
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100340 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100341
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100342 case *ast.TemplateLabel:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200343 v.sel = "*"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100344 f := v.label(x.Ident.Name, true)
345
346 sig := &params{}
347 sig.add(f, &basicType{newNode(n.Label), stringKind})
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200348 template := &lambdaExpr{newNode(n), sig, nil}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100349
350 v.setScope(n, template)
351 template.value = v.walk(n.Value)
352
353 if v.object.template == nil {
354 v.object.template = template
355 } else {
356 v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
357 }
358
359 case *ast.BasicLit, *ast.Ident:
Marcel van Lohuizene9fd2142019-04-12 15:46:31 +0200360 if internal.DropOptional && opt {
361 break
362 }
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200363 v.sel, _ = ast.LabelName(x)
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +0100364 attrs, err := createAttrs(v.ctx(), newNode(n), n.Attrs)
365 if err != nil {
366 return err
367 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100368 f, ok := v.nodeLabel(x)
369 if !ok {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200370 return v.errf(n.Label, "invalid field name: %v", n.Label)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100371 }
372 if f != 0 {
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200373 var leftOverDoc *docNode
374 for _, c := range n.Comments() {
375 if c.Position == 0 {
376 leftOverDoc = v.doc
377 v.doc = &docNode{n: n}
378 break
379 }
380 }
381 val := v.walk(n.Value)
382 v.object.insertValue(v.ctx(), f, opt, val, attrs, v.doc)
383 v.doc = leftOverDoc
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100384 }
385
386 default:
387 panic("cue: unknown label type")
388 }
389
390 case *ast.Alias:
391 // parsed verbatim at reference.
392
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100393 case *ast.ListComprehension:
394 yielder := &yield{baseValue: newExpr(n.Expr)}
395 lc := &listComprehension{
396 newExpr(n),
397 wrapClauses(v, yielder, n.Clauses),
398 }
399 // we don't support key for lists (yet?)
400 yielder.value = v.walk(n.Expr)
401 return lc
402
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100403 // Expressions
404 case *ast.Ident:
405 if n.Node == nil {
406 if value = v.resolve(n); value != nil {
407 break
408 }
409
410 switch n.Name {
411 case "_":
412 return &top{newExpr(n)}
413 case "string":
414 return &basicType{newExpr(n), stringKind}
415 case "bytes":
416 return &basicType{newExpr(n), bytesKind}
417 case "bool":
418 return &basicType{newExpr(n), boolKind}
419 case "int":
420 return &basicType{newExpr(n), intKind}
421 case "float":
422 return &basicType{newExpr(n), floatKind}
423 case "number":
424 return &basicType{newExpr(n), numKind}
425 case "duration":
426 return &basicType{newExpr(n), durationKind}
427
428 case "len":
429 return lenBuiltin
Marcel van Lohuizena460fe82019-04-26 10:20:51 +0200430 case "and":
431 return andBuiltin
432 case "or":
433 return orBuiltin
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100434 }
435 if r, ok := predefinedRanges[n.Name]; ok {
436 return r
437 }
438
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200439 value = v.errf(n, "reference %q not found", n.Name)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100440 break
441 }
442
443 if a, ok := n.Node.(*ast.Alias); ok {
444 value = v.walk(a.Expr)
445 break
446 }
447
Marcel van Lohuizen7dd28f92019-06-18 13:08:46 +0200448 f := v.label(n.Name, true)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100449 if n.Scope != nil {
450 n2 := v.mapScope(n.Scope)
Marcel van Lohuizen7dd28f92019-06-18 13:08:46 +0200451 if l, ok := n2.(*lambdaExpr); ok && len(l.params.arcs) == 1 {
452 f = 0
453 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100454 value = &nodeRef{baseValue: newExpr(n), node: n2}
Marcel van Lohuizen7dd28f92019-06-18 13:08:46 +0200455 value = &selectorExpr{newExpr(n), value, f}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100456 } else {
457 n2 := v.mapScope(n.Node)
458 value = &nodeRef{baseValue: newExpr(n), node: n2}
459 }
460
461 case *ast.BottomLit:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200462 // TODO: record inline comment.
Marcel van Lohuizen8a3c35b2019-06-10 18:25:37 +0200463 value = &bottom{baseValue: newExpr(n), format: "from source"}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100464
465 case *ast.BadDecl:
466 // nothing to do
467
468 case *ast.BadExpr:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200469 value = v.errf(n, "invalid expression")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100470
471 case *ast.BasicLit:
472 value = v.litParser.parse(n)
473
474 case *ast.Interpolation:
475 if len(n.Elts) == 0 {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200476 return v.errf(n, "invalid interpolation")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100477 }
478 first, ok1 := n.Elts[0].(*ast.BasicLit)
479 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
480 if !ok1 || !ok2 {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200481 return v.errf(n, "invalid interpolation")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100482 }
483 if len(n.Elts) == 1 {
484 value = v.walk(n.Elts[0])
485 break
486 }
487 lit := &interpolation{baseValue: newExpr(n), k: stringKind}
488 value = lit
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100489 info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100490 if err != nil {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200491 return v.errf(n, "invalid interpolation: %v", err)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100492 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400493 prefix := ""
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100494 for i := 0; i < len(n.Elts); i += 2 {
495 l, ok := n.Elts[i].(*ast.BasicLit)
496 if !ok {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200497 return v.errf(n, "invalid interpolation")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100498 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400499 s := l.Value
500 if !strings.HasPrefix(s, prefix) {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200501 return v.errf(l, "invalid interpolation: unmatched ')'")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100502 }
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400503 s = l.Value[prefixLen:]
504 x := parseString(v.ctx(), l, info, s)
505 lit.parts = append(lit.parts, x)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100506 if i+1 < len(n.Elts) {
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400507 lit.parts = append(lit.parts, v.walk(n.Elts[i+1]))
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100508 }
509 prefix = ")"
Marcel van Lohuizen369e4232019-02-15 10:59:29 +0400510 prefixLen = 1
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100511 }
512
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100513 case *ast.ParenExpr:
514 value = v.walk(n.X)
515
516 case *ast.SelectorExpr:
517 v.inSelector++
518 value = &selectorExpr{
519 newExpr(n),
520 v.walk(n.X),
521 v.label(n.Sel.Name, true),
522 }
523 v.inSelector--
524
525 case *ast.IndexExpr:
526 value = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
527
528 case *ast.SliceExpr:
529 slice := &sliceExpr{baseValue: newExpr(n), x: v.walk(n.X)}
530 if n.Low != nil {
531 slice.lo = v.walk(n.Low)
532 }
533 if n.High != nil {
534 slice.hi = v.walk(n.High)
535 }
536 value = slice
537
538 case *ast.CallExpr:
539 call := &callExpr{baseValue: newExpr(n), x: v.walk(n.Fun)}
540 for _, a := range n.Args {
541 call.args = append(call.args, v.walk(a))
542 }
543 value = call
544
545 case *ast.UnaryExpr:
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100546 switch n.Op {
547 case token.NOT, token.ADD, token.SUB:
548 value = &unaryExpr{
549 newExpr(n),
550 tokenMap[n.Op],
551 v.walk(n.X),
552 }
Marcel van Lohuizen706e69c2019-02-11 18:21:14 +0100553 case token.GEQ, token.GTR, token.LSS, token.LEQ,
554 token.NEQ, token.MAT, token.NMAT:
Marcel van Lohuizen4a360992019-05-11 18:18:31 +0200555 value = newBound(
Marcel van Lohuizen6767a012019-06-26 12:15:16 +0200556 v.ctx(),
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100557 newExpr(n),
558 tokenMap[n.Op],
Marcel van Lohuizen4a360992019-05-11 18:18:31 +0200559 topKind|nonGround,
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100560 v.walk(n.X),
Marcel van Lohuizen4a360992019-05-11 18:18:31 +0200561 )
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100562
563 case token.MUL:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200564 return v.errf(n, "preference mark not allowed at this position")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100565 default:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200566 return v.errf(n, "unsupported unary operator %q", n.Op)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100567 }
568
569 case *ast.BinaryExpr:
570 switch n.Op {
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100571 case token.OR:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100572 d := &disjunction{baseValue: newExpr(n)}
573 v.addDisjunctionElem(d, n.X, false)
574 v.addDisjunctionElem(d, n.Y, false)
575 value = d
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100576
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100577 default:
Marcel van Lohuizen6767a012019-06-26 12:15:16 +0200578 value = updateBin(v.ctx(), &binaryExpr{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100579 newExpr(n),
580 tokenMap[n.Op], // op
581 v.walk(n.X), // left
582 v.walk(n.Y), // right
Marcel van Lohuizen6767a012019-06-26 12:15:16 +0200583 })
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100584 }
585
Marcel van Lohuizen5b49d762019-05-13 10:59:45 +0200586 case *ast.CommentGroup:
587 // Nothing to do for a free-floating comment group.
588
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100589 // nothing to do
590 // case *syntax.EmitDecl:
591 default:
592 // TODO: unhandled node.
593 // value = ctx.mkErr(n, "unknown node type %T", n)
594 panic(fmt.Sprintf("unimplemented %T", n))
595
596 }
597 return value
598}
599
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100600func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
601 switch x := n.(type) {
602 case *ast.BinaryExpr:
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100603 if x.Op == token.OR {
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100604 v.addDisjunctionElem(d, x.X, mark)
605 v.addDisjunctionElem(d, x.Y, mark)
606 return
607 }
608 case *ast.UnaryExpr:
609 if x.Op == token.MUL {
610 mark = true
611 n = x.X
612 }
Marcel van Lohuizen94d845d2019-05-10 00:28:03 +0200613 d.hasDefaults = true
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100614 }
615 d.values = append(d.values, dValue{v.walk(n), mark})
616}
617
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100618func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
619 for _, c := range clauses {
620 if n, ok := c.(*ast.ForClause); ok {
621 params := &params{}
622 fn := &lambdaExpr{newExpr(n.Source), params, nil}
623 v.setScope(n, fn)
624 }
625 }
626 for i := len(clauses) - 1; i >= 0; i-- {
627 switch n := clauses[i].(type) {
628 case *ast.ForClause:
629 fn := v.mapScope(n).(*lambdaExpr)
630 fn.value = y
631
632 key := "_"
633 if n.Key != nil {
634 key = n.Key.Name
635 }
636 f := v.label(key, true)
637 fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
638
639 f = v.label(n.Value.Name, true)
640 fn.add(f, &top{})
641
642 y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
643
644 case *ast.IfClause:
645 y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
646 }
647 }
648 return y
649}