blob: 15e6212bbdb7e610dfdfadd1c6738219ed571fbe [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{
129 path: v.appendPath(nil),
130 n: n,
131 Message: errors.Message{
132 Format: format,
133 Args: args,
134 },
135 })
136 arguments := append([]interface{}{format}, args...)
137 return v.mkErr(newNode(n), arguments...)
138}
139
140func (v *astVisitor) appendPath(a []string) []string {
141 if v.parent != nil {
142 a = v.parent.appendPath(a)
143 }
144 if v.sel != "" {
145 a = append(a, v.sel)
146 }
147 return a
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100148}
149
150func (v *astVisitor) resolve(n *ast.Ident) value {
151 ctx := v.ctx()
152 label := v.label(n.Name, true)
153 if r := v.resolveRoot; r != nil {
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200154 for _, a := range r.arcs {
155 if a.feature == label {
156 return &selectorExpr{newExpr(n),
157 &nodeRef{baseValue: newExpr(n), node: r}, label}
158 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100159 }
160 if v.inSelector > 0 {
161 if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
162 return &nodeRef{baseValue: newExpr(n), node: p}
163 }
164 }
165 }
166 return nil
167}
168
169func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
170 ctx := v.ctx()
Marcel van Lohuizen6ceb6012019-02-18 18:30:38 +0100171 path, err := literal.Unquote(imp.Path.Value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100172 if err != nil {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200173 return v.errf(imp, "illformed import spec")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100174 }
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +0200175 // TODO: allow builtin *and* imported package. The result is a unified
176 // struct.
Marcel van Lohuizen8bc02e52019-04-01 13:14:07 +0200177 if p := getBuiltinPkg(ctx, path); p != nil {
178 return p
179 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100180 bimp := v.inst.LookupImport(path)
181 if bimp == nil {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200182 return v.errf(imp, "package %q not found", path)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100183 }
184 impInst := v.index.loadInstance(bimp)
185 return impInst.rootValue.evalPartial(ctx)
186}
187
188// We probably don't need to call Walk.s
189func (v *astVisitor) walk(astNode ast.Node) (value value) {
190 switch n := astNode.(type) {
191 case *ast.File:
192 obj := v.object
193 v1 := &astVisitor{
194 astState: v.astState,
195 object: obj,
196 }
197 for _, e := range n.Decls {
198 switch x := e.(type) {
199 case *ast.EmitDecl:
200 if v1.object.emit == nil {
201 v1.object.emit = v1.walk(x.Expr)
202 } else {
203 v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
204 }
205 default:
206 v1.walk(e)
207 }
208 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100209 value = obj
210
211 case *ast.ImportDecl:
212 for _, s := range n.Specs {
213 v.walk(s)
214 }
215
216 case *ast.ImportSpec:
217 val := v.loadImport(n)
218 if !isBottom(val) {
219 v.setScope(n, val.(*structLit))
220 }
221
222 case *ast.StructLit:
223 obj := v.mapScope(n).(*structLit)
224 v1 := &astVisitor{
225 astState: v.astState,
226 object: obj,
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200227 parent: v,
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100228 }
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200229 passDoc := len(n.Elts) == 1 && !n.Lbrace.IsValid() && v.doc != nil
230 if passDoc {
231 v1.doc = v.doc
232 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100233 for _, e := range n.Elts {
234 switch x := e.(type) {
235 case *ast.EmitDecl:
236 // Only allowed at top-level.
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200237 return v1.errf(x, "emitting values is only allowed at top level")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100238 case *ast.Field, *ast.Alias:
239 v1.walk(e)
240 case *ast.ComprehensionDecl:
241 v1.walk(x)
242 }
243 }
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200244 if passDoc {
245 v.doc = v1.doc // signal usage of document back to parent.
246 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100247 value = obj
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100248
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200249 case *ast.ListLit:
250 v1 := &astVisitor{
251 astState: v.astState,
252 object: v.object,
253 parent: v,
254 }
255 arcs := []arc{}
256 for i, e := range n.Elts {
257 v1.sel = strconv.Itoa(i)
258 arcs = append(arcs, arc{feature: label(i), v: v1.walk(e)})
259 }
260 s := &structLit{baseValue: newExpr(n), arcs: arcs}
261 list := &list{baseValue: newExpr(n), elem: s}
262 list.initLit()
263 if n.Ellipsis != token.NoPos || n.Type != nil {
264 list.len = newBound(list.baseValue, opGeq, intKind, list.len)
265 if n.Type != nil {
266 list.typ = v1.walk(n.Type)
267 }
268 }
269 value = list
270
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100271 case *ast.ComprehensionDecl:
272 yielder := &yield{baseValue: newExpr(n.Field.Value)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100273 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100274 baseValue: newDecl(n),
275 clauses: wrapClauses(v, yielder, n.Clauses),
276 }
277 field := n.Field
278 switch x := field.Label.(type) {
279 case *ast.Interpolation:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200280 v.sel = "?"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100281 yielder.key = v.walk(x)
282 yielder.value = v.walk(field.Value)
283
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100284 case *ast.TemplateLabel:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200285 v.sel = "*"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100286 f := v.label(x.Ident.Name, true)
287
288 sig := &params{}
289 sig.add(f, &basicType{newNode(field.Label), stringKind})
290 template := &lambdaExpr{newExpr(field.Value), sig, nil}
291
292 v.setScope(field, template)
293 template.value = v.walk(field.Value)
294 yielder.value = template
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100295 fc.isTemplate = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100296
297 case *ast.BasicLit, *ast.Ident:
298 name, ok := ast.LabelName(x)
299 if !ok {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200300 return v.errf(x, "invalid field name: %v", x)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100301 }
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200302 // TODO: is this correct? Just for info, so not very important.
303 v.sel = name
Marcel van Lohuizenf23fbff2018-12-20 12:23:16 +0100304
305 // TODO: if the clauses do not contain a guard, we know that this
306 // field will always be added and we can move the comprehension one
307 // level down. This, in turn, has the advantage that it is more
308 // likely that the cross-reference limitation for field
309 // comprehensions is not violated. To ensure compatibility between
310 // implementations, though, we should relax the spec as well.
311 // The cross-reference rule is simple and this relaxation seems a
312 // bit more complex.
313
314 // TODO: for now we can also consider making this an error if
315 // the list of clauses does not contain if and make a suggestion
316 // to rewrite it.
317
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100318 if name != "" {
319 yielder.key = &stringLit{newNode(x), name}
320 yielder.value = v.walk(field.Value)
321 }
322
323 default:
324 panic("cue: unknown label type")
325 }
326 // yielder.key = v.walk(n.Field.Label)
327 // yielder.value = v.walk(n.Field.Value)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100328 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100329
330 case *ast.Field:
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100331 opt := n.Optional != token.NoPos
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100332 switch x := n.Label.(type) {
333 case *ast.Interpolation:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200334 v.sel = "?"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100335 yielder := &yield{baseValue: newNode(x)}
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100336 fc := &fieldComprehension{
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100337 baseValue: newDecl(n),
338 clauses: yielder,
339 }
340 yielder.key = v.walk(x)
341 yielder.value = v.walk(n.Value)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100342 yielder.opt = opt
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100343 v.object.comprehensions = append(v.object.comprehensions, fc)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100344
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100345 case *ast.TemplateLabel:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200346 v.sel = "*"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100347 f := v.label(x.Ident.Name, true)
348
349 sig := &params{}
350 sig.add(f, &basicType{newNode(n.Label), stringKind})
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200351 template := &lambdaExpr{newNode(n), sig, nil}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100352
353 v.setScope(n, template)
354 template.value = v.walk(n.Value)
355
356 if v.object.template == nil {
357 v.object.template = template
358 } else {
359 v.object.template = mkBin(v.ctx(), token.NoPos, opUnify, v.object.template, template)
360 }
361
362 case *ast.BasicLit, *ast.Ident:
Marcel van Lohuizene9fd2142019-04-12 15:46:31 +0200363 if internal.DropOptional && opt {
364 break
365 }
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200366 v.sel, _ = ast.LabelName(x)
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +0100367 attrs, err := createAttrs(v.ctx(), newNode(n), n.Attrs)
368 if err != nil {
369 return err
370 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100371 f, ok := v.nodeLabel(x)
372 if !ok {
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200373 return v.errf(n.Label, "invalid field name: %v", n.Label)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100374 }
375 if f != 0 {
Marcel van Lohuizen079451a2019-05-15 14:51:11 +0200376 var leftOverDoc *docNode
377 for _, c := range n.Comments() {
378 if c.Position == 0 {
379 leftOverDoc = v.doc
380 v.doc = &docNode{n: n}
381 break
382 }
383 }
384 val := v.walk(n.Value)
385 v.object.insertValue(v.ctx(), f, opt, val, attrs, v.doc)
386 v.doc = leftOverDoc
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100387 }
388
389 default:
390 panic("cue: unknown label type")
391 }
392
393 case *ast.Alias:
394 // parsed verbatim at reference.
395
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100396 case *ast.ListComprehension:
397 yielder := &yield{baseValue: newExpr(n.Expr)}
398 lc := &listComprehension{
399 newExpr(n),
400 wrapClauses(v, yielder, n.Clauses),
401 }
402 // we don't support key for lists (yet?)
403 yielder.value = v.walk(n.Expr)
404 return lc
405
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100406 // Expressions
407 case *ast.Ident:
408 if n.Node == nil {
409 if value = v.resolve(n); value != nil {
410 break
411 }
412
413 switch n.Name {
414 case "_":
415 return &top{newExpr(n)}
416 case "string":
417 return &basicType{newExpr(n), stringKind}
418 case "bytes":
419 return &basicType{newExpr(n), bytesKind}
420 case "bool":
421 return &basicType{newExpr(n), boolKind}
422 case "int":
423 return &basicType{newExpr(n), intKind}
424 case "float":
425 return &basicType{newExpr(n), floatKind}
426 case "number":
427 return &basicType{newExpr(n), numKind}
428 case "duration":
429 return &basicType{newExpr(n), durationKind}
430
431 case "len":
432 return lenBuiltin
Marcel van Lohuizena460fe82019-04-26 10:20:51 +0200433 case "and":
434 return andBuiltin
435 case "or":
436 return orBuiltin
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100437 }
438 if r, ok := predefinedRanges[n.Name]; ok {
439 return r
440 }
441
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200442 value = v.errf(n, "reference %q not found", n.Name)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100443 break
444 }
445
446 if a, ok := n.Node.(*ast.Alias); ok {
447 value = v.walk(a.Expr)
448 break
449 }
450
451 label := v.label(n.Name, true)
452 if n.Scope != nil {
453 n2 := v.mapScope(n.Scope)
454 value = &nodeRef{baseValue: newExpr(n), node: n2}
455 value = &selectorExpr{newExpr(n), value, label}
456 } 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.
463 value = &bottom{baseValue: newExpr(n), msg: "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 Lohuizen7d0797b2019-02-07 18:35:28 +0100556 newExpr(n),
557 tokenMap[n.Op],
Marcel van Lohuizen4a360992019-05-11 18:18:31 +0200558 topKind|nonGround,
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100559 v.walk(n.X),
Marcel van Lohuizen4a360992019-05-11 18:18:31 +0200560 )
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100561
562 case token.MUL:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200563 return v.errf(n, "preference mark not allowed at this position")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100564 default:
Marcel van Lohuizen52d4dd72019-06-09 11:53:40 +0200565 return v.errf(n, "unsupported unary operator %q", n.Op)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100566 }
567
568 case *ast.BinaryExpr:
569 switch n.Op {
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100570 case token.OR:
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100571 d := &disjunction{baseValue: newExpr(n)}
572 v.addDisjunctionElem(d, n.X, false)
573 v.addDisjunctionElem(d, n.Y, false)
574 value = d
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100575
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100576 default:
577 value = &binaryExpr{
578 newExpr(n),
579 tokenMap[n.Op], // op
580 v.walk(n.X), // left
581 v.walk(n.Y), // right
582 }
583 }
584
Marcel van Lohuizen5b49d762019-05-13 10:59:45 +0200585 case *ast.CommentGroup:
586 // Nothing to do for a free-floating comment group.
587
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100588 // nothing to do
589 // case *syntax.EmitDecl:
590 default:
591 // TODO: unhandled node.
592 // value = ctx.mkErr(n, "unknown node type %T", n)
593 panic(fmt.Sprintf("unimplemented %T", n))
594
595 }
596 return value
597}
598
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100599func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
600 switch x := n.(type) {
601 case *ast.BinaryExpr:
Marcel van Lohuizenbedcf0c2019-02-22 18:00:00 +0100602 if x.Op == token.OR {
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100603 v.addDisjunctionElem(d, x.X, mark)
604 v.addDisjunctionElem(d, x.Y, mark)
605 return
606 }
607 case *ast.UnaryExpr:
608 if x.Op == token.MUL {
609 mark = true
610 n = x.X
611 }
Marcel van Lohuizen94d845d2019-05-10 00:28:03 +0200612 d.hasDefaults = true
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100613 }
614 d.values = append(d.values, dValue{v.walk(n), mark})
615}
616
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100617func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
618 for _, c := range clauses {
619 if n, ok := c.(*ast.ForClause); ok {
620 params := &params{}
621 fn := &lambdaExpr{newExpr(n.Source), params, nil}
622 v.setScope(n, fn)
623 }
624 }
625 for i := len(clauses) - 1; i >= 0; i-- {
626 switch n := clauses[i].(type) {
627 case *ast.ForClause:
628 fn := v.mapScope(n).(*lambdaExpr)
629 fn.value = y
630
631 key := "_"
632 if n.Key != nil {
633 key = n.Key.Name
634 }
635 f := v.label(key, true)
636 fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
637
638 f = v.label(n.Value.Name, true)
639 fn.add(f, &top{})
640
641 y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
642
643 case *ast.IfClause:
644 y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
645 }
646 }
647 return y
648}