...

Source file src/cuelang.org/go/internal/core/compile/compile.go

Documentation: cuelang.org/go/internal/core/compile

     1  // 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  
    15  package compile
    16  
    17  import (
    18  	"strings"
    19  
    20  	"cuelang.org/go/cue/ast"
    21  	"cuelang.org/go/cue/errors"
    22  	"cuelang.org/go/cue/literal"
    23  	"cuelang.org/go/cue/token"
    24  	"cuelang.org/go/internal"
    25  	"cuelang.org/go/internal/astinternal"
    26  	"cuelang.org/go/internal/core/adt"
    27  )
    28  
    29  // A Scope represents a nested scope of Vertices.
    30  type Scope interface {
    31  	Parent() Scope
    32  	Vertex() *adt.Vertex
    33  }
    34  
    35  // Config configures a compilation.
    36  type Config struct {
    37  	// Scope specifies a node in which to look up unresolved references. This
    38  	// is useful for evaluating expressions within an already evaluated
    39  	// configuration.
    40  	Scope Scope
    41  
    42  	// Imports allows unresolved identifiers to resolve to imports.
    43  	//
    44  	// Under normal circumstances, identifiers bind to import specifications,
    45  	// which get resolved to an ImportReference. Use this option to
    46  	// automatically resolve identifiers to imports.
    47  	Imports func(x *ast.Ident) (pkgPath string)
    48  
    49  	// pkgPath is used to qualify the scope of hidden fields. The default
    50  	// scope is "_".
    51  	pkgPath string
    52  }
    53  
    54  // Files compiles the given files as a single instance. It disregards
    55  // the package names and it is the responsibility of the user to verify that
    56  // the packages names are consistent. The pkgID must be a unique identifier
    57  // for a package in a module, for instance as obtained from build.Instance.ID.
    58  //
    59  // Files may return a completed parse even if it has errors.
    60  func Files(cfg *Config, r adt.Runtime, pkgID string, files ...*ast.File) (*adt.Vertex, errors.Error) {
    61  	c := newCompiler(cfg, pkgID, r)
    62  
    63  	v := c.compileFiles(files)
    64  
    65  	if c.errs != nil {
    66  		return v, c.errs
    67  	}
    68  	return v, nil
    69  }
    70  
    71  // Expr compiles the given expression into a conjunct. The pkgID must be a
    72  // unique identifier for a package in a module, for instance as obtained from
    73  // build.Instance.ID.
    74  func Expr(cfg *Config, r adt.Runtime, pkgPath string, x ast.Expr) (adt.Conjunct, errors.Error) {
    75  	c := newCompiler(cfg, pkgPath, r)
    76  
    77  	v := c.compileExpr(x)
    78  
    79  	if c.errs != nil {
    80  		return v, c.errs
    81  	}
    82  	return v, nil
    83  }
    84  
    85  func newCompiler(cfg *Config, pkgPath string, r adt.Runtime) *compiler {
    86  	c := &compiler{
    87  		index: r,
    88  	}
    89  	if cfg != nil {
    90  		c.Config = *cfg
    91  	}
    92  	if pkgPath == "" {
    93  		pkgPath = "_"
    94  	}
    95  	c.Config.pkgPath = pkgPath
    96  	return c
    97  }
    98  
    99  type compiler struct {
   100  	Config
   101  	upCountOffset int32 // 1 for files; 0 for expressions
   102  
   103  	index adt.StringIndexer
   104  
   105  	stack      []frame
   106  	inSelector int
   107  
   108  	// refersToForVariable tracks whether an expression refers to a key or
   109  	// value produced by a for comprehension embedded within a struct.
   110  	// An Environment associated with such a comprehension value is collapsed
   111  	// onto the destination.
   112  	// Tracking this is necessary for let fields, which should not be unified
   113  	// into the destination when referring to such values.
   114  	// See https://cuelang.org/issue/2218.
   115  	// TODO(perf): use this to compute when a field can be structure shared
   116  	// across different iterations of the same field.
   117  	refersToForVariable bool
   118  
   119  	fileScope map[adt.Feature]bool
   120  
   121  	num literal.NumInfo
   122  
   123  	errs errors.Error
   124  }
   125  
   126  func (c *compiler) reset() {
   127  	c.fileScope = nil
   128  	c.stack = c.stack[:0]
   129  	c.errs = nil
   130  }
   131  
   132  func (c *compiler) errf(n ast.Node, format string, args ...interface{}) *adt.Bottom {
   133  	err := &compilerError{
   134  		n:       n,
   135  		path:    c.path(),
   136  		Message: errors.NewMessagef(format, args...),
   137  	}
   138  	c.errs = errors.Append(c.errs, err)
   139  	return &adt.Bottom{Err: err}
   140  }
   141  
   142  func (c *compiler) path() []string {
   143  	a := []string{}
   144  	for _, f := range c.stack {
   145  		if f.label != nil {
   146  			a = append(a, f.label.labelString())
   147  		}
   148  	}
   149  	return a
   150  }
   151  
   152  type frame struct {
   153  	label labeler  // path name leading to this frame.
   154  	scope ast.Node // *ast.File or *ast.Struct
   155  	field ast.Decl
   156  	// scope   map[ast.Node]bool
   157  	upCount int32 // 1 for field, 0 for embedding.
   158  
   159  	// isComprehensionVar indicates that this scope refers to a for clause
   160  	// that is part of a comprehension embedded in a struct.
   161  	isComprehensionVar bool
   162  
   163  	aliases map[string]aliasEntry
   164  }
   165  
   166  type aliasEntry struct {
   167  	label   labeler
   168  	srcExpr ast.Expr
   169  	expr    adt.Expr
   170  	source  ast.Node
   171  	feature adt.Feature // For let declarations
   172  	used    bool
   173  }
   174  
   175  func (c *compiler) insertAlias(id *ast.Ident, a aliasEntry) *adt.Bottom {
   176  	k := len(c.stack) - 1
   177  	m := c.stack[k].aliases
   178  	if m == nil {
   179  		m = map[string]aliasEntry{}
   180  		c.stack[k].aliases = m
   181  	}
   182  
   183  	if id == nil || !ast.IsValidIdent(id.Name) {
   184  		return c.errf(a.source, "invalid identifier name")
   185  	}
   186  
   187  	if e, ok := m[id.Name]; ok {
   188  		return c.errf(a.source,
   189  			"alias %q already declared; previous declaration at %s",
   190  			id.Name, e.source.Pos())
   191  	}
   192  	if id.Name == "_" {
   193  		return c.errf(id, "cannot use _ as alias or let clause")
   194  	}
   195  
   196  	m[id.Name] = a
   197  	return nil
   198  }
   199  
   200  func (c *compiler) updateAlias(id *ast.Ident, expr adt.Expr) {
   201  	k := len(c.stack) - 1
   202  	m := c.stack[k].aliases
   203  
   204  	x := m[id.Name]
   205  	x.expr = expr
   206  	x.label = nil
   207  	x.srcExpr = nil
   208  	m[id.Name] = x
   209  }
   210  
   211  // lookupAlias looks up an alias with the given name at the k'th stack position.
   212  func (c *compiler) lookupAlias(k int, id *ast.Ident) aliasEntry {
   213  	m := c.stack[k].aliases
   214  	name := id.Name
   215  	entry, ok := m[name]
   216  
   217  	if !ok {
   218  		err := c.errf(id, "could not find LetClause associated with identifier %q", name)
   219  		return aliasEntry{expr: err}
   220  	}
   221  
   222  	switch {
   223  	case entry.label != nil:
   224  		// TODO: allow cyclic references in let expressions once these can be
   225  		// encoded as a ValueReference.
   226  		if entry.srcExpr == nil {
   227  			entry.expr = c.errf(id, "cyclic references in let clause or alias")
   228  			break
   229  		}
   230  
   231  		src := entry.srcExpr
   232  		entry.srcExpr = nil // mark to allow detecting cycles
   233  		m[name] = entry
   234  
   235  		entry.expr = c.labeledExprAt(k, nil, entry.label, src)
   236  		entry.label = nil
   237  	}
   238  
   239  	entry.used = true
   240  	m[name] = entry
   241  	return entry
   242  }
   243  
   244  func (c *compiler) pushScope(n labeler, upCount int32, id ast.Node) *frame {
   245  	c.stack = append(c.stack, frame{
   246  		label:   n,
   247  		scope:   id,
   248  		upCount: upCount,
   249  	})
   250  	return &c.stack[len(c.stack)-1]
   251  }
   252  
   253  func (c *compiler) popScope() {
   254  	k := len(c.stack) - 1
   255  	f := c.stack[k]
   256  	for k, v := range f.aliases {
   257  		if !v.used {
   258  			c.errf(v.source, "unreferenced alias or let clause %s", k)
   259  		}
   260  	}
   261  	c.stack = c.stack[:k]
   262  }
   263  
   264  func (c *compiler) compileFiles(a []*ast.File) *adt.Vertex { // Or value?
   265  	c.fileScope = map[adt.Feature]bool{}
   266  	c.upCountOffset = 1
   267  
   268  	// TODO(resolve): this is also done in the runtime package, do we need both?
   269  
   270  	// Populate file scope to handle unresolved references.
   271  	// Excluded from cross-file resolution are:
   272  	// - import specs
   273  	// - aliases
   274  	// - let declarations
   275  	// - anything in an anonymous file
   276  	//
   277  	for _, f := range a {
   278  		if p := internal.GetPackageInfo(f); p.IsAnonymous() {
   279  			continue
   280  		}
   281  		for _, d := range f.Decls {
   282  			if f, ok := d.(*ast.Field); ok {
   283  				if id, ok := f.Label.(*ast.Ident); ok {
   284  					c.fileScope[c.label(id)] = true
   285  				}
   286  			}
   287  		}
   288  	}
   289  
   290  	// TODO: set doc.
   291  	res := &adt.Vertex{}
   292  
   293  	// env := &adt.Environment{Vertex: nil} // runtime: c.runtime
   294  
   295  	env := &adt.Environment{}
   296  	top := env
   297  
   298  	for p := c.Config.Scope; p != nil; p = p.Parent() {
   299  		top.Vertex = p.Vertex()
   300  		top.Up = &adt.Environment{}
   301  		top = top.Up
   302  	}
   303  
   304  	for _, file := range a {
   305  		c.pushScope(nil, 0, file) // File scope
   306  		v := &adt.StructLit{Src: file}
   307  		c.addDecls(v, file.Decls)
   308  		res.Conjuncts = append(res.Conjuncts, adt.MakeRootConjunct(env, v))
   309  		c.popScope()
   310  	}
   311  
   312  	return res
   313  }
   314  
   315  func (c *compiler) compileExpr(x ast.Expr) adt.Conjunct {
   316  	expr := c.expr(x)
   317  
   318  	env := &adt.Environment{}
   319  	top := env
   320  
   321  	for p := c.Config.Scope; p != nil; p = p.Parent() {
   322  		top.Vertex = p.Vertex()
   323  		top.Up = &adt.Environment{}
   324  		top = top.Up
   325  	}
   326  
   327  	return adt.MakeRootConjunct(env, expr)
   328  }
   329  
   330  // resolve assumes that all existing resolutions are legal. Validation should
   331  // be done in a separate step if required.
   332  //
   333  // TODO: collect validation pass to verify that all resolutions are
   334  // legal?
   335  func (c *compiler) resolve(n *ast.Ident) adt.Expr {
   336  	// X in import "path/X"
   337  	// X in import X "path"
   338  	if imp, ok := n.Node.(*ast.ImportSpec); ok {
   339  		return &adt.ImportReference{
   340  			Src:        n,
   341  			ImportPath: c.label(imp.Path),
   342  			Label:      c.label(n),
   343  		}
   344  	}
   345  
   346  	label := c.label(n)
   347  
   348  	if label == adt.InvalidLabel { // `_`
   349  		return &adt.Top{Src: n}
   350  	}
   351  
   352  	// Unresolved field.
   353  	if n.Node == nil {
   354  		upCount := int32(0)
   355  		for _, c := range c.stack {
   356  			upCount += c.upCount
   357  		}
   358  		if c.fileScope[label] {
   359  			return &adt.FieldReference{
   360  				Src:     n,
   361  				UpCount: upCount,
   362  				Label:   label,
   363  			}
   364  		}
   365  		upCount += c.upCountOffset
   366  		for p := c.Scope; p != nil; p = p.Parent() {
   367  			for _, a := range p.Vertex().Arcs {
   368  				switch {
   369  				case a.Label.IsLet() && a.Label.IdentString(c.index) == n.Name:
   370  					label = a.Label
   371  				case a.Label == label:
   372  					return &adt.FieldReference{
   373  						Src:     n,
   374  						UpCount: upCount,
   375  						Label:   label,
   376  					}
   377  				}
   378  			}
   379  			upCount++
   380  		}
   381  
   382  		if c.Config.Imports != nil {
   383  			if pkgPath := c.Config.Imports(n); pkgPath != "" {
   384  				return &adt.ImportReference{
   385  					Src:        n,
   386  					ImportPath: adt.MakeStringLabel(c.index, pkgPath),
   387  					Label:      c.label(n),
   388  				}
   389  			}
   390  		}
   391  
   392  		if p := predeclared(n); p != nil {
   393  			return p
   394  		}
   395  
   396  		return c.errf(n, "reference %q not found", n.Name)
   397  	}
   398  
   399  	//   X in [X=x]: y  Scope: Field  Node: Expr (x)
   400  	//   X in X=[x]: y  Scope: Field  Node: Field
   401  	//   X in x: X=y    Scope: Field  Node: Alias
   402  	if f, ok := n.Scope.(*ast.Field); ok {
   403  		upCount := int32(0)
   404  
   405  		k := len(c.stack) - 1
   406  		for ; k >= 0; k-- {
   407  			if c.stack[k].field == f {
   408  				break
   409  			}
   410  			upCount += c.stack[k].upCount
   411  		}
   412  
   413  		label := &adt.LabelReference{
   414  			Src:     n,
   415  			UpCount: upCount,
   416  		}
   417  
   418  		switch f := n.Node.(type) {
   419  		case *ast.Field:
   420  			_ = c.lookupAlias(k, f.Label.(*ast.Alias).Ident) // mark as used
   421  			// The expression of field Label is always done in the same
   422  			// Environment as pointed to by the UpCount of the DynamicReference
   423  			// and the evaluation of a DynamicReference assumes this.
   424  			// We therefore set the UpCount of the LabelReference to 0.
   425  			label.UpCount = 0
   426  			return &adt.DynamicReference{
   427  				Src:     n,
   428  				UpCount: upCount,
   429  				Label:   label,
   430  			}
   431  
   432  		case *ast.Alias:
   433  			_ = c.lookupAlias(k, f.Ident) // mark as used
   434  			return &adt.ValueReference{
   435  				Src:     n,
   436  				UpCount: upCount,
   437  				Label:   c.label(f.Ident),
   438  			}
   439  		}
   440  		return label
   441  	}
   442  
   443  	upCount := int32(0)
   444  
   445  	k := len(c.stack) - 1
   446  	for ; k >= 0; k-- {
   447  		if f := c.stack[k]; f.scope == n.Scope {
   448  			if f.isComprehensionVar {
   449  				c.refersToForVariable = true
   450  			}
   451  			break
   452  		}
   453  		upCount += c.stack[k].upCount
   454  	}
   455  	if k < 0 {
   456  		// This is a programmatic error and should never happen if the users
   457  		// just builds with the cue command or if astutil.Resolve is used
   458  		// correctly.
   459  		c.errf(n, "reference %q set to unknown node in AST; "+
   460  			"this can result from incorrect API usage or a compiler bug",
   461  			n.Name)
   462  	}
   463  
   464  	if n.Scope == nil {
   465  		// Package.
   466  		// Should have been handled above.
   467  		return c.errf(n, "unresolved identifier %v", n.Name)
   468  	}
   469  
   470  	switch f := n.Node.(type) {
   471  	// Local expressions
   472  	case *ast.LetClause:
   473  		entry := c.lookupAlias(k, n)
   474  		if entry.expr == nil {
   475  			panic("unreachable")
   476  		}
   477  		label = entry.feature
   478  
   479  		// let x = y
   480  		return &adt.LetReference{
   481  			Src:     n,
   482  			UpCount: upCount,
   483  			Label:   label,
   484  			X:       entry.expr, // TODO: remove usage
   485  		}
   486  
   487  	// TODO: handle new-style aliases
   488  
   489  	case *ast.Field:
   490  		// X=x: y
   491  		// X=(x): y
   492  		// X="\(x)": y
   493  		a, ok := f.Label.(*ast.Alias)
   494  		if !ok {
   495  			return c.errf(n, "illegal reference %s", n.Name)
   496  		}
   497  		aliasInfo := c.lookupAlias(k, a.Ident) // marks alias as used.
   498  		lab, ok := a.Expr.(ast.Label)
   499  		if !ok {
   500  			return c.errf(a.Expr, "invalid label expression")
   501  		}
   502  		name, _, err := ast.LabelName(lab)
   503  		switch {
   504  		case errors.Is(err, ast.ErrIsExpression):
   505  			if aliasInfo.expr == nil {
   506  				panic("unreachable")
   507  			}
   508  			return &adt.DynamicReference{
   509  				Src:     n,
   510  				UpCount: upCount,
   511  				Label:   aliasInfo.expr,
   512  			}
   513  
   514  		case err != nil:
   515  			return c.errf(n, "invalid label: %v", err)
   516  
   517  		case name != "":
   518  			label = c.label(lab)
   519  
   520  		default:
   521  			return c.errf(n, "unsupported field alias %q", name)
   522  		}
   523  	}
   524  
   525  	return &adt.FieldReference{
   526  		Src:     n,
   527  		UpCount: upCount,
   528  		Label:   label,
   529  	}
   530  }
   531  
   532  func (c *compiler) addDecls(st *adt.StructLit, a []ast.Decl) {
   533  	for _, d := range a {
   534  		c.markAlias(d)
   535  	}
   536  	for _, d := range a {
   537  		c.addLetDecl(d)
   538  	}
   539  	for _, d := range a {
   540  		if x := c.decl(d); x != nil {
   541  			st.Decls = append(st.Decls, x)
   542  		}
   543  	}
   544  }
   545  
   546  func (c *compiler) markAlias(d ast.Decl) {
   547  	switch x := d.(type) {
   548  	case *ast.Field:
   549  		lab := x.Label
   550  		if a, ok := lab.(*ast.Alias); ok {
   551  			if _, ok = a.Expr.(ast.Label); !ok {
   552  				c.errf(a, "alias expression is not a valid label")
   553  			}
   554  
   555  			e := aliasEntry{source: a}
   556  
   557  			c.insertAlias(a.Ident, e)
   558  		}
   559  
   560  	case *ast.LetClause:
   561  		a := aliasEntry{
   562  			label:   (*letScope)(x),
   563  			srcExpr: x.Expr,
   564  			source:  x,
   565  			feature: adt.MakeLetLabel(c.index, x.Ident.Name),
   566  		}
   567  		c.insertAlias(x.Ident, a)
   568  
   569  	case *ast.Alias:
   570  		c.errf(x, "old-style alias no longer supported: use let clause; use cue fix to update.")
   571  	}
   572  }
   573  
   574  func (c *compiler) decl(d ast.Decl) adt.Decl {
   575  	switch x := d.(type) {
   576  	case *ast.BadDecl:
   577  		return c.errf(d, "")
   578  
   579  	case *ast.Field:
   580  		lab := x.Label
   581  		if a, ok := lab.(*ast.Alias); ok {
   582  			if lab, ok = a.Expr.(ast.Label); !ok {
   583  				return c.errf(a, "alias expression is not a valid label")
   584  			}
   585  		}
   586  
   587  		v := x.Value
   588  		var value adt.Expr
   589  		if a, ok := v.(*ast.Alias); ok {
   590  			c.pushScope(nil, 0, a)
   591  			c.insertAlias(a.Ident, aliasEntry{source: a})
   592  			value = c.labeledExpr(x, (*fieldLabel)(x), a.Expr)
   593  			c.popScope()
   594  		} else {
   595  			value = c.labeledExpr(x, (*fieldLabel)(x), v)
   596  		}
   597  
   598  		switch l := lab.(type) {
   599  		case *ast.Ident, *ast.BasicLit:
   600  			label := c.label(lab)
   601  
   602  			if label == adt.InvalidLabel {
   603  				return c.errf(x, "cannot use _ as label")
   604  			}
   605  
   606  			t, _ := internal.ConstraintToken(x)
   607  
   608  			return &adt.Field{
   609  				Src:     x,
   610  				Label:   label,
   611  				ArcType: adt.ConstraintFromToken(t),
   612  				Value:   value,
   613  			}
   614  
   615  		case *ast.ListLit:
   616  			if len(l.Elts) != 1 {
   617  				// error
   618  				return c.errf(x, "list label must have one element")
   619  			}
   620  			var label adt.Feature
   621  			elem := l.Elts[0]
   622  			// TODO: record alias for error handling? In principle it is okay
   623  			// to have duplicates, but we do want it to be used.
   624  			if a, ok := elem.(*ast.Alias); ok {
   625  				label = c.label(a.Ident)
   626  				elem = a.Expr
   627  			}
   628  
   629  			return &adt.BulkOptionalField{
   630  				Src:    x,
   631  				Filter: c.expr(elem),
   632  				Value:  value,
   633  				Label:  label,
   634  			}
   635  
   636  		case *ast.ParenExpr:
   637  			t, _ := internal.ConstraintToken(x)
   638  
   639  			return &adt.DynamicField{
   640  				Src:     x,
   641  				Key:     c.expr(l),
   642  				ArcType: adt.ConstraintFromToken(t),
   643  				Value:   value,
   644  			}
   645  
   646  		case *ast.Interpolation:
   647  			t, _ := internal.ConstraintToken(x)
   648  
   649  			return &adt.DynamicField{
   650  				Src:     x,
   651  				Key:     c.expr(l),
   652  				ArcType: adt.ConstraintFromToken(t),
   653  				Value:   value,
   654  			}
   655  		}
   656  
   657  	case *ast.LetClause:
   658  		m := c.stack[len(c.stack)-1].aliases
   659  		entry := m[x.Ident.Name]
   660  
   661  		// A reference to the let should, in principle, be interpreted as a
   662  		// value reference, not field reference:
   663  		// - this is syntactically consistent for the use of =
   664  		// - this is semantically the only valid interpretation
   665  		// In practice this amounts to the same thing, as let expressions cannot
   666  		// be addressed from outside their scope. But it will matter once
   667  		// expressions may refer to a let from within the let.
   668  
   669  		savedUses := c.refersToForVariable
   670  		c.refersToForVariable = false
   671  		value := c.labeledExpr(x, (*letScope)(x), x.Expr)
   672  		refsCompVar := c.refersToForVariable
   673  		c.refersToForVariable = savedUses || refsCompVar
   674  
   675  		return &adt.LetField{
   676  			Src:     x,
   677  			Label:   entry.feature,
   678  			IsMulti: refsCompVar,
   679  			Value:   value,
   680  		}
   681  
   682  	// case: *ast.Alias: // TODO(value alias)
   683  
   684  	case *ast.CommentGroup:
   685  		// Nothing to do for a free-floating comment group.
   686  
   687  	case *ast.Attribute:
   688  		// Nothing to do for now for an attribute declaration.
   689  
   690  	case *ast.Ellipsis:
   691  		return &adt.Ellipsis{
   692  			Src:   x,
   693  			Value: c.expr(x.Type),
   694  		}
   695  
   696  	case *ast.Comprehension:
   697  		return c.comprehension(x, false)
   698  
   699  	case *ast.EmbedDecl: // Deprecated
   700  		return c.expr(x.Expr)
   701  
   702  	case ast.Expr:
   703  		return c.expr(x)
   704  	}
   705  	return nil
   706  }
   707  
   708  func (c *compiler) addLetDecl(d ast.Decl) {
   709  	switch x := d.(type) {
   710  	case *ast.Field:
   711  		lab := x.Label
   712  		if a, ok := lab.(*ast.Alias); ok {
   713  			if lab, ok = a.Expr.(ast.Label); !ok {
   714  				// error reported elsewhere
   715  				return
   716  			}
   717  
   718  			switch lab.(type) {
   719  			case *ast.Ident, *ast.BasicLit, *ast.ListLit:
   720  				// Even though we won't need the alias, we still register it
   721  				// for duplicate and failed reference detection.
   722  			default:
   723  				c.updateAlias(a.Ident, c.expr(a.Expr))
   724  			}
   725  		}
   726  
   727  	case *ast.Alias:
   728  		c.errf(x, "old-style alias no longer supported: use let clause; use cue fix to update.")
   729  	}
   730  }
   731  
   732  func (c *compiler) elem(n ast.Expr) adt.Elem {
   733  	switch x := n.(type) {
   734  	case *ast.Ellipsis:
   735  		return &adt.Ellipsis{
   736  			Src:   x,
   737  			Value: c.expr(x.Type),
   738  		}
   739  
   740  	case *ast.Comprehension:
   741  		return c.comprehension(x, true)
   742  
   743  	case ast.Expr:
   744  		return c.expr(x)
   745  	}
   746  	return nil
   747  }
   748  
   749  func (c *compiler) comprehension(x *ast.Comprehension, inList bool) adt.Elem {
   750  	var a []adt.Yielder
   751  	for _, v := range x.Clauses {
   752  		switch x := v.(type) {
   753  		case *ast.ForClause:
   754  			var key adt.Feature
   755  			if x.Key != nil {
   756  				key = c.label(x.Key)
   757  			}
   758  			y := &adt.ForClause{
   759  				Syntax: x,
   760  				Key:    key,
   761  				Value:  c.label(x.Value),
   762  				Src:    c.expr(x.Source),
   763  			}
   764  			f := c.pushScope((*forScope)(x), 1, v)
   765  			defer c.popScope()
   766  			f.isComprehensionVar = !inList
   767  			a = append(a, y)
   768  
   769  		case *ast.IfClause:
   770  			y := &adt.IfClause{
   771  				Src:       x,
   772  				Condition: c.expr(x.Condition),
   773  			}
   774  			a = append(a, y)
   775  
   776  		case *ast.LetClause:
   777  			// Check if any references in the expression refer to a for
   778  			// comprehension.
   779  			savedUses := c.refersToForVariable
   780  			c.refersToForVariable = false
   781  			expr := c.expr(x.Expr)
   782  			refsCompVar := c.refersToForVariable
   783  			c.refersToForVariable = savedUses || refsCompVar
   784  
   785  			y := &adt.LetClause{
   786  				Src:   x,
   787  				Label: c.label(x.Ident),
   788  				Expr:  expr,
   789  			}
   790  			f := c.pushScope((*letScope)(x), 1, v)
   791  			defer c.popScope()
   792  			f.isComprehensionVar = !inList && refsCompVar
   793  			a = append(a, y)
   794  		}
   795  
   796  		if _, ok := a[0].(*adt.LetClause); ok {
   797  			return c.errf(x,
   798  				"first comprehension clause must be 'if' or 'for'")
   799  		}
   800  	}
   801  
   802  	// TODO: make x.Value an *ast.StructLit and this is redundant.
   803  	if y, ok := x.Value.(*ast.StructLit); !ok {
   804  		return c.errf(x.Value,
   805  			"comprehension value must be struct, found %T", y)
   806  	}
   807  
   808  	y := c.expr(x.Value)
   809  
   810  	st, ok := y.(*adt.StructLit)
   811  	if !ok {
   812  		// Error must have been generated.
   813  		return y
   814  	}
   815  
   816  	if len(a) == 0 {
   817  		return c.errf(x, "comprehension value without clauses")
   818  	}
   819  
   820  	return &adt.Comprehension{
   821  		Syntax:  x,
   822  		Clauses: a,
   823  		Value:   st,
   824  	}
   825  }
   826  
   827  func (c *compiler) labeledExpr(f ast.Decl, lab labeler, expr ast.Expr) adt.Expr {
   828  	k := len(c.stack) - 1
   829  	return c.labeledExprAt(k, f, lab, expr)
   830  }
   831  
   832  func (c *compiler) labeledExprAt(k int, f ast.Decl, lab labeler, expr ast.Expr) adt.Expr {
   833  	saved := c.stack[k]
   834  
   835  	c.stack[k].label = lab
   836  	c.stack[k].field = f
   837  
   838  	value := c.expr(expr)
   839  
   840  	c.stack[k] = saved
   841  	return value
   842  }
   843  
   844  func (c *compiler) expr(expr ast.Expr) adt.Expr {
   845  	switch n := expr.(type) {
   846  	case nil:
   847  		return nil
   848  	case *ast.Ident:
   849  		return c.resolve(n)
   850  
   851  	case *ast.Func:
   852  		// We don't yet support function types natively in
   853  		// CUE.  ast.Func exists only to support external
   854  		// interpreters. Function values (really, adt.Builtin)
   855  		// are only created by the runtime, or injected by
   856  		// external interpreters.
   857  		//
   858  		// TODO: revise this when we add function types.
   859  		return c.resolve(ast.NewIdent("_"))
   860  
   861  	case *ast.StructLit:
   862  		c.pushScope(nil, 1, n)
   863  		v := &adt.StructLit{Src: n}
   864  		c.addDecls(v, n.Elts)
   865  		c.popScope()
   866  		return v
   867  
   868  	case *ast.ListLit:
   869  		c.pushScope(nil, 1, n)
   870  		v := &adt.ListLit{Src: n}
   871  		elts, ellipsis := internal.ListEllipsis(n)
   872  		for _, d := range elts {
   873  			elem := c.elem(d)
   874  
   875  			switch x := elem.(type) {
   876  			case nil:
   877  			case adt.Elem:
   878  				v.Elems = append(v.Elems, x)
   879  			default:
   880  				c.errf(d, "type %T not allowed in ListLit", d)
   881  			}
   882  		}
   883  		if ellipsis != nil {
   884  			d := &adt.Ellipsis{
   885  				Src:   ellipsis,
   886  				Value: c.expr(ellipsis.Type),
   887  			}
   888  			v.Elems = append(v.Elems, d)
   889  		}
   890  		c.popScope()
   891  		return v
   892  
   893  	case *ast.SelectorExpr:
   894  		c.inSelector++
   895  		ret := &adt.SelectorExpr{
   896  			Src: n,
   897  			X:   c.expr(n.X),
   898  			Sel: c.label(n.Sel)}
   899  		c.inSelector--
   900  		return ret
   901  
   902  	case *ast.IndexExpr:
   903  		return &adt.IndexExpr{
   904  			Src:   n,
   905  			X:     c.expr(n.X),
   906  			Index: c.expr(n.Index),
   907  		}
   908  
   909  	case *ast.SliceExpr:
   910  		slice := &adt.SliceExpr{Src: n, X: c.expr(n.X)}
   911  		if n.Low != nil {
   912  			slice.Lo = c.expr(n.Low)
   913  		}
   914  		if n.High != nil {
   915  			slice.Hi = c.expr(n.High)
   916  		}
   917  		return slice
   918  
   919  	case *ast.BottomLit:
   920  		return &adt.Bottom{
   921  			Src:  n,
   922  			Code: adt.UserError,
   923  			Err:  errors.Newf(n.Pos(), "explicit error (_|_ literal) in source"),
   924  		}
   925  
   926  	case *ast.BadExpr:
   927  		return c.errf(n, "invalid expression")
   928  
   929  	case *ast.BasicLit:
   930  		return c.parse(n)
   931  
   932  	case *ast.Interpolation:
   933  		if len(n.Elts) == 0 {
   934  			return c.errf(n, "invalid interpolation")
   935  		}
   936  		first, ok1 := n.Elts[0].(*ast.BasicLit)
   937  		last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
   938  		if !ok1 || !ok2 {
   939  			return c.errf(n, "invalid interpolation")
   940  		}
   941  		if len(n.Elts) == 1 {
   942  			return c.expr(n.Elts[0])
   943  		}
   944  		lit := &adt.Interpolation{Src: n}
   945  		info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value)
   946  		if err != nil {
   947  			return c.errf(n, "invalid interpolation: %v", err)
   948  		}
   949  		if info.IsDouble() {
   950  			lit.K = adt.StringKind
   951  		} else {
   952  			lit.K = adt.BytesKind
   953  		}
   954  		prefix := ""
   955  		for i := 0; i < len(n.Elts); i += 2 {
   956  			l, ok := n.Elts[i].(*ast.BasicLit)
   957  			if !ok {
   958  				return c.errf(n, "invalid interpolation")
   959  			}
   960  			s := l.Value
   961  			if !strings.HasPrefix(s, prefix) {
   962  				return c.errf(l, "invalid interpolation: unmatched ')'")
   963  			}
   964  			s = l.Value[prefixLen:]
   965  			x := parseString(c, l, info, s)
   966  			lit.Parts = append(lit.Parts, x)
   967  			if i+1 < len(n.Elts) {
   968  				lit.Parts = append(lit.Parts, c.expr(n.Elts[i+1]))
   969  			}
   970  			prefix = ")"
   971  			prefixLen = 1
   972  		}
   973  		return lit
   974  
   975  	case *ast.ParenExpr:
   976  		return c.expr(n.X)
   977  
   978  	case *ast.CallExpr:
   979  		call := &adt.CallExpr{Src: n, Fun: c.expr(n.Fun)}
   980  		for _, a := range n.Args {
   981  			call.Args = append(call.Args, c.expr(a))
   982  		}
   983  		return call
   984  
   985  	case *ast.UnaryExpr:
   986  		switch n.Op {
   987  		case token.NOT, token.ADD, token.SUB:
   988  			return &adt.UnaryExpr{
   989  				Src: n,
   990  				Op:  adt.OpFromToken(n.Op),
   991  				X:   c.expr(n.X),
   992  			}
   993  		case token.GEQ, token.GTR, token.LSS, token.LEQ,
   994  			token.NEQ, token.MAT, token.NMAT:
   995  			return &adt.BoundExpr{
   996  				Src:  n,
   997  				Op:   adt.OpFromToken(n.Op),
   998  				Expr: c.expr(n.X),
   999  			}
  1000  
  1001  		case token.MUL:
  1002  			return c.errf(n, "preference mark not allowed at this position")
  1003  		default:
  1004  			return c.errf(n, "unsupported unary operator %q", n.Op)
  1005  		}
  1006  
  1007  	case *ast.BinaryExpr:
  1008  		switch n.Op {
  1009  		case token.OR:
  1010  			d := &adt.DisjunctionExpr{Src: n}
  1011  			c.addDisjunctionElem(d, n.X, false)
  1012  			c.addDisjunctionElem(d, n.Y, false)
  1013  			return d
  1014  
  1015  		default:
  1016  			op := adt.OpFromToken(n.Op)
  1017  			x := c.expr(n.X)
  1018  			y := c.expr(n.Y)
  1019  			if op != adt.AndOp {
  1020  				c.assertConcreteIsPossible(n.X, op, x)
  1021  				c.assertConcreteIsPossible(n.Y, op, y)
  1022  			}
  1023  			// return updateBin(c,
  1024  			return &adt.BinaryExpr{Src: n, Op: op, X: x, Y: y} // )
  1025  		}
  1026  
  1027  	default:
  1028  		return c.errf(n, "%s values not allowed in this position", ast.Name(n))
  1029  	}
  1030  }
  1031  
  1032  func (c *compiler) assertConcreteIsPossible(src ast.Node, op adt.Op, x adt.Expr) bool {
  1033  	if !adt.AssertConcreteIsPossible(op, x) {
  1034  		str := astinternal.DebugStr(src)
  1035  		c.errf(src, "invalid operand %s ('%s' requires concrete value)", str, op)
  1036  	}
  1037  	return false
  1038  }
  1039  
  1040  func (c *compiler) addDisjunctionElem(d *adt.DisjunctionExpr, n ast.Expr, mark bool) {
  1041  	switch x := n.(type) {
  1042  	case *ast.BinaryExpr:
  1043  		if x.Op == token.OR {
  1044  			c.addDisjunctionElem(d, x.X, mark)
  1045  			c.addDisjunctionElem(d, x.Y, mark)
  1046  			return
  1047  		}
  1048  	case *ast.UnaryExpr:
  1049  		if x.Op == token.MUL {
  1050  			d.HasDefaults = true
  1051  			c.addDisjunctionElem(d, x.X, true)
  1052  			return
  1053  		}
  1054  	}
  1055  	d.Values = append(d.Values, adt.Disjunct{Val: c.expr(n), Default: mark})
  1056  }
  1057  
  1058  // TODO(perf): validate that regexps are cached at the right time.
  1059  
  1060  func (c *compiler) parse(l *ast.BasicLit) (n adt.Expr) {
  1061  	s := l.Value
  1062  	if s == "" {
  1063  		return c.errf(l, "invalid literal %q", s)
  1064  	}
  1065  	switch l.Kind {
  1066  	case token.STRING:
  1067  		info, nStart, _, err := literal.ParseQuotes(s, s)
  1068  		if err != nil {
  1069  			return c.errf(l, err.Error())
  1070  		}
  1071  		s := s[nStart:]
  1072  		return parseString(c, l, info, s)
  1073  
  1074  	case token.FLOAT, token.INT:
  1075  		err := literal.ParseNum(s, &c.num)
  1076  		if err != nil {
  1077  			return c.errf(l, "parse error: %v", err)
  1078  		}
  1079  		kind := adt.FloatKind
  1080  		if c.num.IsInt() {
  1081  			kind = adt.IntKind
  1082  		}
  1083  		n := &adt.Num{Src: l, K: kind}
  1084  		if err = c.num.Decimal(&n.X); err != nil {
  1085  			return c.errf(l, "error converting number to decimal: %v", err)
  1086  		}
  1087  		return n
  1088  
  1089  	case token.TRUE:
  1090  		return &adt.Bool{Src: l, B: true}
  1091  
  1092  	case token.FALSE:
  1093  		return &adt.Bool{Src: l, B: false}
  1094  
  1095  	case token.NULL:
  1096  		return &adt.Null{Src: l}
  1097  
  1098  	default:
  1099  		return c.errf(l, "unknown literal type")
  1100  	}
  1101  }
  1102  
  1103  // parseString decodes a string without the starting and ending quotes.
  1104  func parseString(c *compiler, node ast.Expr, q literal.QuoteInfo, s string) (n adt.Expr) {
  1105  	str, err := q.Unquote(s)
  1106  	if err != nil {
  1107  		return c.errf(node, "invalid string: %v", err)
  1108  	}
  1109  	if q.IsDouble() {
  1110  		return &adt.String{Src: node, Str: str, RE: nil}
  1111  	}
  1112  	return &adt.Bytes{Src: node, B: []byte(str), RE: nil}
  1113  }
  1114  

View as plain text