blob: 2e7d406285e723664cdfd83abf44f9c789edb202 [file] [log] [blame]
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +02001// Copyright 2020 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 compile
16
17import (
18 "fmt"
19 "strings"
20
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/errors"
23 "cuelang.org/go/cue/literal"
24 "cuelang.org/go/cue/token"
25 "cuelang.org/go/internal"
26 "cuelang.org/go/internal/core/adt"
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +020027 "golang.org/x/xerrors"
28)
29
30// Config configures a compilation.
31type Config struct {
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +020032 // Scope specifies a node in which to look up unresolved references. This
33 // is useful for evaluating expressions within an already evaluated
34 // configuration.
35 //
36 // TODO
37 Scope *adt.Vertex
Marcel van Lohuizencf944692020-07-15 15:28:47 +020038
39 // Imports allows unresolved identifiers to resolve to imports.
40 //
41 // Under normal circumstances, identifiers bind to import specifications,
42 // which get resolved to an ImportReference. Use this option to automaically
43 // resolve identifiers to imports.
44 Imports func(x *ast.Ident) (pkgPath string)
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +020045}
46
47// Files compiles the given files as a single instance. It disregards
48// the package names and it is the responsibility of the user to verify that
49// the packages names are consistent.
50//
51// Files may return a completed parse even if it has errors.
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +020052func Files(cfg *Config, r adt.Runtime, files ...*ast.File) (*adt.Vertex, errors.Error) {
Marcel van Lohuizen0cfe4112020-06-27 15:01:34 +020053 c := newCompiler(cfg, r)
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +020054
55 v := c.compileFiles(files)
56
57 if c.errs != nil {
58 return v, c.errs
59 }
60 return v, nil
61}
62
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +020063func Expr(cfg *Config, r adt.Runtime, x ast.Expr) (adt.Conjunct, errors.Error) {
64 if cfg == nil {
65 cfg = &Config{}
66 }
67 c := &compiler{
68 Config: *cfg,
69 index: r,
70 }
71
72 v := c.compileExpr(x)
73
74 if c.errs != nil {
75 return v, c.errs
76 }
77 return v, nil
78}
79
Marcel van Lohuizen0cfe4112020-06-27 15:01:34 +020080func newCompiler(cfg *Config, r adt.Runtime) *compiler {
81 c := &compiler{
82 index: r,
83 }
84 if cfg != nil {
85 c.Config = *cfg
86 }
87 return c
88}
89
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +020090type compiler struct {
Marcel van Lohuizen0cfe4112020-06-27 15:01:34 +020091 Config
92
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +020093 index adt.StringIndexer
94
95 stack []frame
96 inSelector int
97
98 fileScope map[adt.Feature]bool
99
100 num literal.NumInfo
101
102 errs errors.Error
103}
104
105func (c *compiler) reset() {
106 c.fileScope = nil
107 c.stack = c.stack[:0]
108 c.errs = nil
109}
110
111func (c *compiler) errf(n ast.Node, format string, args ...interface{}) *adt.Bottom {
112 err := &compilerError{
113 n: n,
114 path: c.path(),
115 Message: errors.NewMessage(format, args),
116 }
117 c.errs = errors.Append(c.errs, err)
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +0200118 return &adt.Bottom{Err: err}
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200119}
120
121func (c *compiler) path() []string {
122 a := []string{}
123 for _, f := range c.stack {
124 if f.label != nil {
125 a = append(a, f.label.labelString())
126 }
127 }
128 return a
129}
130
131type frame struct {
132 label labeler // path name leading to this frame.
133 scope ast.Node // *ast.File or *ast.Struct
134 field *ast.Field
135 // scope map[ast.Node]bool
136 upCount int32 // 1 for field, 0 for embedding.
137
138 aliases map[string]aliasEntry
139}
140
141type aliasEntry struct {
142 expr adt.Expr
143 source ast.Node
144 used bool
145}
146
147func (c *compiler) insertAlias(id *ast.Ident, a aliasEntry) *adt.Bottom {
148 k := len(c.stack) - 1
149 m := c.stack[k].aliases
150 if m == nil {
151 m = map[string]aliasEntry{}
152 c.stack[k].aliases = m
153 }
154
155 if id == nil || !ast.IsValidIdent(id.Name) {
156 return c.errf(a.source, "invalid identifier name")
157 }
158
159 if e, ok := m[id.Name]; ok {
160 return c.errf(a.source,
161 "alias %q already declared; previous declaration at %s",
162 id.Name, e.source.Pos())
163 }
164
165 m[id.Name] = a
166 return nil
167}
168
169// lookupAlias looks up an alias with the given name at the k'th stack position.
170func (c compiler) lookupAlias(k int, id *ast.Ident) aliasEntry {
171 m := c.stack[k].aliases
172 name := id.Name
173 entry, ok := m[name]
174
175 if !ok {
176 err := c.errf(id, "could not find LetClause associated with identifier %q", name)
177 return aliasEntry{expr: err}
178 }
179
180 entry.used = true
181 m[name] = entry
182 return entry
183}
184
185func (c *compiler) pushScope(n labeler, upCount int32, id ast.Node) *frame {
186 c.stack = append(c.stack, frame{
187 label: n,
188 scope: id,
189 upCount: upCount,
190 })
191 return &c.stack[len(c.stack)-1]
192}
193
194func (c *compiler) popScope() {
195 k := len(c.stack) - 1
196 f := c.stack[k]
197 for k, v := range f.aliases {
198 if !v.used {
199 c.errf(v.source, "unreferenced alias or let clause %s", k)
200 }
201 }
202 c.stack = c.stack[:k]
203}
204
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200205func (c *compiler) compileFiles(a []*ast.File) *adt.Vertex { // Or value?
206 c.fileScope = map[adt.Feature]bool{}
207
208 // Populate file scope to handle unresolved references. Note that we do
209 // not allow aliases to be resolved across file boundaries.
210 for _, f := range a {
211 for _, d := range f.Decls {
212 if f, ok := d.(*ast.Field); ok {
213 if id, ok := f.Label.(*ast.Ident); ok {
214 c.fileScope[c.label(id)] = true
215 }
216 }
217 }
218 }
219
Marcel van Lohuizencf944692020-07-15 15:28:47 +0200220 // TODO: Assume that the other context is unified with the newly compiled
221 // files. This is not the same behavior as the old functionality, but we
222 // wanted to nix this anyway. For instance by allowing pkg_tool to be
223 // treated differently.
224 if v := c.Config.Scope; v != nil {
225 for _, arc := range v.Arcs {
226 if _, ok := c.fileScope[arc.Label]; !ok {
227 c.fileScope[arc.Label] = true
228 }
229 }
230
231 c.pushScope(nil, 0, v.Source()) // File scope
232 defer c.popScope()
233 }
234
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200235 // TODO: set doc.
236 res := &adt.Vertex{}
237
238 // env := &adt.Environment{Vertex: nil} // runtime: c.runtime
239
240 for _, file := range a {
241 c.pushScope(nil, 0, file) // File scope
242 v := &adt.StructLit{Src: file}
243 c.addDecls(v, file.Decls)
Marcel van Lohuizen3d863fc2020-09-03 19:58:22 +0200244 res.Conjuncts = append(res.Conjuncts, adt.MakeRootConjunct(nil, v))
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200245 c.popScope()
246 }
247
248 return res
249}
250
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +0200251func (c *compiler) compileExpr(x ast.Expr) adt.Conjunct {
Marcel van Lohuizencf944692020-07-15 15:28:47 +0200252 c.fileScope = map[adt.Feature]bool{}
253
254 if v := c.Config.Scope; v != nil {
255 for _, arc := range v.Arcs {
256 c.fileScope[arc.Label] = true
257 }
258
259 c.pushScope(nil, 0, v.Source()) // File scope
260 defer c.popScope()
261 }
262
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +0200263 expr := c.expr(x)
264
265 env := &adt.Environment{}
Marcel van Lohuizencf944692020-07-15 15:28:47 +0200266 top := env
267
268 for p := c.Config.Scope; p != nil; p = p.Parent {
269 top.Vertex = p
270 top.Up = &adt.Environment{}
271 top = top.Up
272
273 // TODO: do something like this to allow multi-layered scopes.
274 // e := &adt.Environment{Vertex: p}
275 // if env != nil {
276 // env.Up = e
277 // }
278 // env = e
279 }
280
Marcel van Lohuizen3d863fc2020-09-03 19:58:22 +0200281 return adt.MakeRootConjunct(env, expr)
Marcel van Lohuizen0cfe4112020-06-27 15:01:34 +0200282}
283
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200284// resolve assumes that all existing resolutions are legal. Validation should
285// be done in a separate step if required.
286//
287// TODO: collect validation pass to verify that all resolutions are
288// legal?
289func (c *compiler) resolve(n *ast.Ident) adt.Expr {
290 // X in import "path/X"
291 // X in import X "path"
292 if imp, ok := n.Node.(*ast.ImportSpec); ok {
293 return &adt.ImportReference{
294 Src: n,
295 ImportPath: c.label(imp.Path),
296 Label: c.label(n),
297 }
298 }
299
300 label := c.label(n)
301
302 // Unresolved field.
303 if n.Node == nil {
304 upCount := int32(0)
305 for _, c := range c.stack {
306 upCount += c.upCount
307 }
308 if c.fileScope[label] {
309 return &adt.FieldReference{
310 Src: n,
311 UpCount: upCount,
312 Label: label,
313 }
314 }
315
Marcel van Lohuizencf944692020-07-15 15:28:47 +0200316 if c.Config.Imports != nil {
317 if pkgPath := c.Config.Imports(n); pkgPath != "" {
318 return &adt.ImportReference{
319 Src: n,
320 ImportPath: adt.MakeStringLabel(c.index, pkgPath),
321 Label: c.label(n),
322 }
323 }
324 }
325
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200326 if p := predeclared(n); p != nil {
327 return p
328 }
329
330 return c.errf(n, "reference %q not found", n.Name)
331 }
332
333 // X in [X=x]: y Scope: Field Node: Expr (x)
334 // X in X=[x]: y Scope: Field Node: Field
335 if f, ok := n.Scope.(*ast.Field); ok {
336 upCount := int32(0)
337
338 k := len(c.stack) - 1
339 for ; k >= 0; k-- {
340 if c.stack[k].field == f {
341 break
342 }
343 upCount += c.stack[k].upCount
344 }
345
346 label := &adt.LabelReference{
347 Src: n,
348 UpCount: upCount,
349 }
350
351 if f, ok := n.Node.(*ast.Field); ok {
352 _ = c.lookupAlias(k, f.Label.(*ast.Alias).Ident) // mark as used
353 return &adt.DynamicReference{
354 Src: n,
355 UpCount: upCount,
356 Label: label,
357 }
358 }
359 return label
360 }
361
362 upCount := int32(0)
363
364 k := len(c.stack) - 1
365 for ; k >= 0; k-- {
366 if c.stack[k].scope == n.Scope {
367 break
368 }
369 upCount += c.stack[k].upCount
370 }
371 if k < 0 {
372 // This is a programmatic error and should never happen if the users
373 // just builds with the cue command or if astutil.Resolve is used
374 // correctly.
375 c.errf(n, "reference %q set to unknown node in AST; "+
376 "this can result from incorrect API usage or a compiler bug",
377 n.Name)
378 }
379
380 switch n.Node.(type) {
381 // Local expressions
382 case *ast.LetClause, *ast.Alias:
383 entry := c.lookupAlias(k, n)
384
385 return &adt.LetReference{
386 Src: n,
387 UpCount: upCount,
388 Label: label,
389 X: entry.expr,
390 }
391 }
392
393 if n.Scope == nil {
394 // Package.
395 // Should have been handled above.
396 panic("unreachable") // Or direct ancestor node?
397 }
398
399 // X=x: y
400 // X=(x): y
401 // X="\(x)": y
402 if f, ok := n.Node.(*ast.Field); ok {
403 a, ok := f.Label.(*ast.Alias)
404 if !ok {
405 return c.errf(n, "illegal reference %s", n.Name)
406 }
407 aliasInfo := c.lookupAlias(k, a.Ident) // marks alias as used.
408 lab, ok := a.Expr.(ast.Label)
409 if !ok {
410 return c.errf(a.Expr, "invalid label expression")
411 }
412 name, _, err := ast.LabelName(lab)
413 switch {
414 case xerrors.Is(err, ast.ErrIsExpression):
415 if aliasInfo.expr == nil {
416 panic("unreachable")
417 }
418 return &adt.DynamicReference{
419 Src: n,
420 UpCount: upCount,
421 Label: aliasInfo.expr,
422 }
423
424 case err != nil:
425 return c.errf(n, "invalid label: %v", err)
426
427 case name != "":
428 label = c.label(lab)
429
430 default:
431 return c.errf(n, "unsupported field alias %q", name)
432 }
433 }
434
435 return &adt.FieldReference{
436 Src: n,
437 UpCount: upCount,
438 Label: label,
439 }
440}
441
442func (c *compiler) addDecls(st *adt.StructLit, a []ast.Decl) {
443 for _, d := range a {
Marcel van Lohuizene986a8f2020-07-17 08:50:49 +0200444 c.addLetDecl(d)
445 }
446 for _, d := range a {
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200447 if x := c.decl(d); x != nil {
448 st.Decls = append(st.Decls, x)
449 }
450 }
451}
452
453func (c *compiler) decl(d ast.Decl) adt.Decl {
454 switch x := d.(type) {
455 case *ast.BadDecl:
456 return c.errf(d, "")
457
458 case *ast.Field:
459 lab := x.Label
460 if a, ok := lab.(*ast.Alias); ok {
461 if lab, ok = a.Expr.(ast.Label); !ok {
462 return c.errf(a, "alias expression is not a valid label")
463 }
464
465 e := aliasEntry{source: a}
466
467 switch lab.(type) {
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +0200468 case *ast.Ident, *ast.BasicLit, *ast.ListLit:
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200469 // Even though we won't need the alias, we still register it
470 // for duplicate and failed reference detection.
471 default:
472 e.expr = c.expr(a.Expr)
473 }
474
475 if err := c.insertAlias(a.Ident, e); err != nil {
476 return err
477 }
478 }
479
480 value := c.labeledExpr(x, (*fieldLabel)(x), x.Value)
481
482 switch l := lab.(type) {
483 case *ast.Ident, *ast.BasicLit:
484 label := c.label(lab)
485
486 // TODO(legacy): remove: old-school definitions
487 if x.Token == token.ISA && !label.IsDef() {
488 name, isIdent, err := ast.LabelName(lab)
489 if err == nil && isIdent {
490 idx := c.index.StringToIndex(name)
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +0200491 label, _ = adt.MakeLabel(x, idx, adt.DefinitionLabel)
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200492 }
493 }
494
495 if x.Optional == token.NoPos {
496 return &adt.Field{
497 Src: x,
498 Label: label,
499 Value: value,
500 }
501 } else {
502 return &adt.OptionalField{
503 Src: x,
504 Label: label,
505 Value: value,
506 }
507 }
508
509 case *ast.ListLit:
510 if len(l.Elts) != 1 {
511 // error
512 return c.errf(x, "list label must have one element")
513 }
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +0200514 var label adt.Feature
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200515 elem := l.Elts[0]
516 // TODO: record alias for error handling? In principle it is okay
517 // to have duplicates, but we do want it to be used.
518 if a, ok := elem.(*ast.Alias); ok {
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +0200519 label = c.label(a.Ident)
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200520 elem = a.Expr
521 }
522
523 return &adt.BulkOptionalField{
524 Src: x,
525 Filter: c.expr(elem),
526 Value: value,
Marcel van Lohuizen08a9fdb2020-06-10 11:07:13 +0200527 Label: label,
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200528 }
529
530 case *ast.Interpolation: // *ast.ParenExpr,
531 if x.Token == token.ISA {
532 c.errf(x, "definitions not supported for interpolations")
533 }
534 return &adt.DynamicField{
535 Src: x,
536 Key: c.expr(l),
537 Value: value,
538 }
539 }
540
Marcel van Lohuizene986a8f2020-07-17 08:50:49 +0200541 // Handled in addLetDecl.
542 case *ast.LetClause, *ast.Alias:
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200543
544 case *ast.CommentGroup:
545 // Nothing to do for a free-floating comment group.
546
547 case *ast.Attribute:
548 // Nothing to do for now for an attribute declaration.
549
550 case *ast.Ellipsis:
551 return &adt.Ellipsis{
552 Src: x,
553 Value: c.expr(x.Type),
554 }
555
556 case *ast.Comprehension:
557 return c.comprehension(x)
558
559 case *ast.EmbedDecl: // Deprecated
560 return c.embed(x.Expr)
561
562 case ast.Expr:
563 return c.embed(x)
564 }
565 return nil
566}
567
Marcel van Lohuizene986a8f2020-07-17 08:50:49 +0200568func (c *compiler) addLetDecl(d ast.Decl) {
569 switch x := d.(type) {
570 // An alias reference will have an expression that is looked up in the
571 // environment cash.
572 case *ast.LetClause:
573 // Cache the parsed expression. Creating a unique expression for each
574 // reference allows the computation to be shared given that we don't
575 // have fields for expressions. This, in turn, prevents exponential
576 // blowup in x2: x1+x1, x3: x2+x2, ... patterns.
577
578 expr := c.labeledExpr(nil, (*letScope)(x), x.Expr)
579
580 a := aliasEntry{source: x, expr: expr}
581
582 c.insertAlias(x.Ident, a)
583
584 case *ast.Alias:
585
586 expr := c.labeledExpr(nil, (*deprecatedAliasScope)(x), x.Expr)
587
588 // TODO(legacy): deprecated, remove this use of Alias
589 a := aliasEntry{source: x, expr: expr}
590
591 c.insertAlias(x.Ident, a)
592 }
593}
594
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200595func (c *compiler) elem(n ast.Expr) adt.Elem {
596 switch x := n.(type) {
597 case *ast.Ellipsis:
598 return &adt.Ellipsis{
599 Src: x,
600 Value: c.expr(x.Type),
601 }
602
603 case *ast.Comprehension:
604 return c.comprehension(x)
605
606 case ast.Expr:
607 return c.expr(x)
608 }
609 return nil
610}
611
612func (c *compiler) comprehension(x *ast.Comprehension) adt.Elem {
613 var cur adt.Yielder
614 var first adt.Elem
615 var prev, next *adt.Yielder
616 for _, v := range x.Clauses {
617 switch x := v.(type) {
618 case *ast.ForClause:
619 var key adt.Feature
620 if x.Key != nil {
621 key = c.label(x.Key)
622 }
623 y := &adt.ForClause{
624 Syntax: x,
625 Key: key,
626 Value: c.label(x.Value),
627 Src: c.expr(x.Source),
628 }
629 cur = y
630 c.pushScope((*forScope)(x), 1, v)
631 defer c.popScope()
632 next = &y.Dst
633
634 case *ast.IfClause:
635 y := &adt.IfClause{
636 Src: x,
637 Condition: c.expr(x.Condition),
638 }
639 cur = y
640 next = &y.Dst
641
642 case *ast.LetClause:
643 y := &adt.LetClause{
644 Src: x,
645 Label: c.label(x.Ident),
646 Expr: c.expr(x.Expr),
647 }
648 cur = y
649 c.pushScope((*letScope)(x), 1, v)
650 defer c.popScope()
651 next = &y.Dst
652 }
653
654 if prev != nil {
655 *prev = cur
656 } else {
657 var ok bool
658 if first, ok = cur.(adt.Elem); !ok {
659 return c.errf(x,
660 "first comprehension clause must be 'if' or 'for'")
661 }
662 }
663 prev = next
664 }
665
Marcel van Lohuizenc6ade672020-08-21 17:39:06 +0200666 // TODO: make x.Value an *ast.StructLit and this is redundant.
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200667 if y, ok := x.Value.(*ast.StructLit); !ok {
668 return c.errf(x.Value,
669 "comprehension value must be struct, found %T", y)
670 }
671
672 y := c.expr(x.Value)
673
674 st, ok := y.(*adt.StructLit)
675 if !ok {
676 // Error must have been generated.
677 return y
678 }
679
680 if prev != nil {
681 *prev = &adt.ValueClause{StructLit: st}
682 } else {
683 return c.errf(x, "comprehension value without clauses")
684 }
685
686 return first
687}
688
689func (c *compiler) embed(expr ast.Expr) adt.Expr {
690 switch n := expr.(type) {
691 case *ast.StructLit:
692 c.pushScope(nil, 1, n)
693 v := &adt.StructLit{Src: n}
694 c.addDecls(v, n.Elts)
695 c.popScope()
696 return v
697 }
698 return c.expr(expr)
699}
700
701func (c *compiler) labeledExpr(f *ast.Field, lab labeler, expr ast.Expr) adt.Expr {
702 k := len(c.stack) - 1
703 if c.stack[k].field != nil {
704 panic("expected nil field")
705 }
706 c.stack[k].label = lab
707 c.stack[k].field = f
708 value := c.expr(expr)
709 c.stack[k].label = nil
710 c.stack[k].field = nil
711 return value
712}
713
714func (c *compiler) expr(expr ast.Expr) adt.Expr {
715 switch n := expr.(type) {
716 case nil:
717 return nil
718 case *ast.Ident:
719 return c.resolve(n)
720
721 case *ast.StructLit:
722 c.pushScope(nil, 1, n)
723 v := &adt.StructLit{Src: n}
724 c.addDecls(v, n.Elts)
725 c.popScope()
726 return v
727
728 case *ast.ListLit:
729 v := &adt.ListLit{Src: n}
730 elts, ellipsis := internal.ListEllipsis(n)
731 for _, d := range elts {
732 elem := c.elem(d)
733
734 switch x := elem.(type) {
735 case nil:
736 case adt.Elem:
737 v.Elems = append(v.Elems, x)
738 default:
739 c.errf(d, "type %T not allowed in ListLit", d)
740 }
741 }
742 if ellipsis != nil {
743 d := &adt.Ellipsis{
744 Src: ellipsis,
745 Value: c.expr(ellipsis.Type),
746 }
747 v.Elems = append(v.Elems, d)
748 }
749 return v
750
751 case *ast.SelectorExpr:
752 c.inSelector++
753 ret := &adt.SelectorExpr{
754 Src: n,
755 X: c.expr(n.X),
756 Sel: c.label(n.Sel)}
757 c.inSelector--
758 return ret
759
760 case *ast.IndexExpr:
761 return &adt.IndexExpr{
762 Src: n,
763 X: c.expr(n.X),
764 Index: c.expr(n.Index),
765 }
766
767 case *ast.SliceExpr:
768 slice := &adt.SliceExpr{Src: n, X: c.expr(n.X)}
769 if n.Low != nil {
770 slice.Lo = c.expr(n.Low)
771 }
772 if n.High != nil {
773 slice.Hi = c.expr(n.High)
774 }
775 return slice
776
777 case *ast.BottomLit:
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +0200778 return &adt.Bottom{
779 Src: n,
780 Code: adt.UserError,
Marcel van Lohuizendf010422020-09-12 19:56:21 +0200781 Err: errors.Newf(n.Pos(), "explicit error (_|_ literal) in source"),
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +0200782 }
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200783
784 case *ast.BadExpr:
785 return c.errf(n, "invalid expression")
786
787 case *ast.BasicLit:
788 return c.parse(n)
789
790 case *ast.Interpolation:
791 if len(n.Elts) == 0 {
792 return c.errf(n, "invalid interpolation")
793 }
794 first, ok1 := n.Elts[0].(*ast.BasicLit)
795 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
796 if !ok1 || !ok2 {
797 return c.errf(n, "invalid interpolation")
798 }
799 if len(n.Elts) == 1 {
800 return c.expr(n.Elts[0])
801 }
Marcel van Lohuizen30ca0622020-08-22 14:07:59 +0200802 lit := &adt.Interpolation{Src: n}
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200803 info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value)
804 if err != nil {
805 return c.errf(n, "invalid interpolation: %v", err)
806 }
Marcel van Lohuizen30ca0622020-08-22 14:07:59 +0200807 if info.IsDouble() {
808 lit.K = adt.StringKind
809 } else {
810 lit.K = adt.BytesKind
811 }
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200812 prefix := ""
813 for i := 0; i < len(n.Elts); i += 2 {
814 l, ok := n.Elts[i].(*ast.BasicLit)
815 if !ok {
816 return c.errf(n, "invalid interpolation")
817 }
818 s := l.Value
819 if !strings.HasPrefix(s, prefix) {
820 return c.errf(l, "invalid interpolation: unmatched ')'")
821 }
822 s = l.Value[prefixLen:]
823 x := parseString(c, l, info, s)
824 lit.Parts = append(lit.Parts, x)
825 if i+1 < len(n.Elts) {
826 lit.Parts = append(lit.Parts, c.expr(n.Elts[i+1]))
827 }
828 prefix = ")"
829 prefixLen = 1
830 }
831 return lit
832
833 case *ast.ParenExpr:
834 return c.expr(n.X)
835
836 case *ast.CallExpr:
837 call := &adt.CallExpr{Src: n, Fun: c.expr(n.Fun)}
838 for _, a := range n.Args {
839 call.Args = append(call.Args, c.expr(a))
840 }
841 return call
842
843 case *ast.UnaryExpr:
844 switch n.Op {
845 case token.NOT, token.ADD, token.SUB:
846 return &adt.UnaryExpr{
847 Src: n,
848 Op: adt.OpFromToken(n.Op),
849 X: c.expr(n.X),
850 }
851 case token.GEQ, token.GTR, token.LSS, token.LEQ,
852 token.NEQ, token.MAT, token.NMAT:
853 return &adt.BoundExpr{
854 Src: n,
855 Op: adt.OpFromToken(n.Op),
856 Expr: c.expr(n.X),
857 }
858
859 case token.MUL:
860 return c.errf(n, "preference mark not allowed at this position")
861 default:
862 return c.errf(n, "unsupported unary operator %q", n.Op)
863 }
864
865 case *ast.BinaryExpr:
866 switch n.Op {
867 case token.OR:
868 d := &adt.DisjunctionExpr{Src: n}
869 c.addDisjunctionElem(d, n.X, false)
870 c.addDisjunctionElem(d, n.Y, false)
871 return d
872
873 default:
874 // return updateBin(c,
875 return &adt.BinaryExpr{
876 Src: n,
877 Op: adt.OpFromToken(n.Op), // op
878 X: c.expr(n.X), // left
879 Y: c.expr(n.Y), // right
880 } // )
881 }
882
883 default:
884 panic(fmt.Sprintf("unknown expression type %T", n))
885 // return c.errf(n, "unknown expression type %T", n)
886 }
887}
888
889func (c *compiler) addDisjunctionElem(d *adt.DisjunctionExpr, n ast.Expr, mark bool) {
890 switch x := n.(type) {
891 case *ast.BinaryExpr:
892 if x.Op == token.OR {
893 c.addDisjunctionElem(d, x.X, mark)
894 c.addDisjunctionElem(d, x.Y, mark)
895 return
896 }
897 case *ast.UnaryExpr:
898 if x.Op == token.MUL {
899 d.HasDefaults = true
900 c.addDisjunctionElem(d, x.X, true)
901 return
902 }
903 }
904 d.Values = append(d.Values, adt.Disjunct{Val: c.expr(n), Default: mark})
905}
906
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +0200907// TODO(perf): validate that regexps are cached at the right time.
908
Marcel van Lohuizen1f42c812020-05-01 16:00:06 +0200909func (c *compiler) parse(l *ast.BasicLit) (n adt.Expr) {
910 s := l.Value
911 if s == "" {
912 return c.errf(l, "invalid literal %q", s)
913 }
914 switch l.Kind {
915 case token.STRING:
916 info, nStart, _, err := literal.ParseQuotes(s, s)
917 if err != nil {
918 return c.errf(l, err.Error())
919 }
920 s := s[nStart:]
921 return parseString(c, l, info, s)
922
923 case token.FLOAT, token.INT:
924 err := literal.ParseNum(s, &c.num)
925 if err != nil {
926 return c.errf(l, "parse error: %v", err)
927 }
928 kind := adt.FloatKind
929 if c.num.IsInt() {
930 kind = adt.IntKind
931 }
932 n := &adt.Num{Src: l, K: kind}
933 if err = c.num.Decimal(&n.X); err != nil {
934 return c.errf(l, "error converting number to decimal: %v", err)
935 }
936 return n
937
938 case token.TRUE:
939 return &adt.Bool{Src: l, B: true}
940
941 case token.FALSE:
942 return &adt.Bool{Src: l, B: false}
943
944 case token.NULL:
945 return &adt.Null{Src: l}
946
947 default:
948 return c.errf(l, "unknown literal type")
949 }
950}
951
952// parseString decodes a string without the starting and ending quotes.
953func parseString(c *compiler, node ast.Expr, q literal.QuoteInfo, s string) (n adt.Expr) {
954 str, err := q.Unquote(s)
955 if err != nil {
956 return c.errf(node, "invalid string: %v", err)
957 }
958 if q.IsDouble() {
959 return &adt.String{Src: node, Str: str, RE: nil}
960 }
961 return &adt.Bytes{Src: node, B: []byte(str), RE: nil}
962}