cuelang.org/go@v0.10.1/cue/ast/ast.go (about)

     1  // 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  
    15  // Package ast declares the types used to represent syntax trees for CUE
    16  // packages.
    17  package ast
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"cuelang.org/go/cue/literal"
    24  	"cuelang.org/go/cue/token"
    25  )
    26  
    27  // ----------------------------------------------------------------------------
    28  // Interfaces
    29  //
    30  // There are three main classes of nodes: expressions, clauses, and declaration
    31  // nodes. The node names usually match the corresponding CUE spec production
    32  // names to which they correspond. The node fields correspond to the individual
    33  // parts of the respective productions.
    34  //
    35  // All nodes contain position information marking the beginning of the
    36  // corresponding source text segment; it is accessible via the Pos accessor
    37  // method. Nodes may contain additional position info for language constructs
    38  // where comments may be found between parts of the construct (typically any
    39  // larger, parenthesized subpart). That position information is needed to
    40  // properly position comments when printing the construct.
    41  
    42  // A Node represents any node in the abstract syntax tree.
    43  type Node interface {
    44  	Pos() token.Pos // position of first character belonging to the node
    45  	End() token.Pos // position of first character immediately after the node
    46  
    47  	// pos reports the pointer to the position of first character belonging to
    48  	// the node or nil if there is no such position.
    49  	pos() *token.Pos
    50  
    51  	// Deprecated: use [Comments]
    52  	Comments() []*CommentGroup
    53  
    54  	// Deprecated: use [AddComment]
    55  	AddComment(*CommentGroup)
    56  	commentInfo() *comments
    57  }
    58  
    59  // Name describes the type of n.
    60  func Name(n Node) string {
    61  	s := fmt.Sprintf("%T", n)
    62  	return strings.ToLower(s[strings.Index(s, "ast.")+4:])
    63  }
    64  
    65  func getPos(n Node) token.Pos {
    66  	p := n.pos()
    67  	if p == nil {
    68  		return token.NoPos
    69  	}
    70  	return *p
    71  }
    72  
    73  // SetPos sets a node to the given position, if possible.
    74  func SetPos(n Node, p token.Pos) {
    75  	ptr := n.pos()
    76  	if ptr == nil {
    77  		return
    78  	}
    79  	*ptr = p
    80  }
    81  
    82  // SetRelPos sets the relative position of a node without modifying its
    83  // file position. Setting it to token.NoRelPos allows a node to adopt default
    84  // formatting.
    85  func SetRelPos(n Node, p token.RelPos) {
    86  	ptr := n.pos()
    87  	if ptr == nil {
    88  		return
    89  	}
    90  	pos := *ptr
    91  	*ptr = pos.WithRel(p)
    92  }
    93  
    94  // An Expr is implemented by all expression nodes.
    95  type Expr interface {
    96  	Node
    97  	declNode() // An expression can be used as a declaration.
    98  	exprNode()
    99  }
   100  
   101  type expr struct{ decl }
   102  
   103  func (expr) exprNode() {}
   104  
   105  // A Decl node is implemented by all declarations.
   106  type Decl interface {
   107  	Node
   108  	declNode()
   109  }
   110  
   111  type decl struct{}
   112  
   113  func (decl) declNode() {}
   114  
   115  // A Label is any production that can be used as an LHS label.
   116  type Label interface {
   117  	Node
   118  	labelNode()
   119  }
   120  
   121  type label struct{}
   122  
   123  func (l label) labelNode() {}
   124  
   125  // Clause nodes are part of comprehensions.
   126  type Clause interface {
   127  	Node
   128  	clauseNode()
   129  }
   130  
   131  type clause struct{}
   132  
   133  func (clause) clauseNode() {}
   134  
   135  // Comments
   136  
   137  type comments struct {
   138  	groups *[]*CommentGroup
   139  }
   140  
   141  func (c *comments) commentInfo() *comments { return c }
   142  
   143  func (c *comments) Comments() []*CommentGroup {
   144  	if c.groups == nil {
   145  		return []*CommentGroup{}
   146  	}
   147  	return *c.groups
   148  }
   149  
   150  // // AddComment adds the given comments to the fields.
   151  // // If line is true the comment is inserted at the preceding token.
   152  
   153  func (c *comments) AddComment(cg *CommentGroup) {
   154  	if cg == nil {
   155  		return
   156  	}
   157  	if c.groups == nil {
   158  		a := []*CommentGroup{cg}
   159  		c.groups = &a
   160  		return
   161  	}
   162  
   163  	*c.groups = append(*c.groups, cg)
   164  	a := *c.groups
   165  	for i := len(a) - 2; i >= 0 && a[i].Position > cg.Position; i-- {
   166  		a[i], a[i+1] = a[i+1], a[i]
   167  	}
   168  }
   169  
   170  func (c *comments) SetComments(cgs []*CommentGroup) {
   171  	if c.groups == nil {
   172  		a := cgs
   173  		c.groups = &a
   174  		return
   175  	}
   176  	*c.groups = cgs
   177  }
   178  
   179  // A Comment node represents a single //-style comment.
   180  type Comment struct {
   181  	Slash token.Pos // position of "/" starting the comment
   182  	Text  string    // comment text excluding '\n'
   183  }
   184  
   185  func (c *Comment) Comments() []*CommentGroup { return nil }
   186  func (c *Comment) AddComment(*CommentGroup)  {}
   187  func (c *Comment) commentInfo() *comments    { return nil }
   188  
   189  func (c *Comment) Pos() token.Pos  { return c.Slash }
   190  func (c *Comment) pos() *token.Pos { return &c.Slash }
   191  func (c *Comment) End() token.Pos  { return c.Slash.Add(len(c.Text)) }
   192  
   193  // A CommentGroup represents a sequence of comments
   194  // with no other tokens and no empty lines between.
   195  type CommentGroup struct {
   196  	// TODO: remove and use the token position of the first comment.
   197  	Doc  bool
   198  	Line bool // true if it is on the same line as the node's end pos.
   199  
   200  	// Position indicates where a comment should be attached if a node has
   201  	// multiple tokens. 0 means before the first token, 1 means before the
   202  	// second, etc. For instance, for a field, the positions are:
   203  	//    <0> Label <1> ":" <2> Expr <3> "," <4>
   204  	Position int8
   205  	List     []*Comment // len(List) > 0
   206  
   207  	decl
   208  }
   209  
   210  func (g *CommentGroup) Pos() token.Pos  { return getPos(g) }
   211  func (g *CommentGroup) pos() *token.Pos { return g.List[0].pos() }
   212  func (g *CommentGroup) End() token.Pos  { return g.List[len(g.List)-1].End() }
   213  
   214  func (g *CommentGroup) Comments() []*CommentGroup { return nil }
   215  func (g *CommentGroup) AddComment(*CommentGroup)  {}
   216  func (g *CommentGroup) commentInfo() *comments    { return nil }
   217  
   218  func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }
   219  
   220  func stripTrailingWhitespace(s string) string {
   221  	i := len(s)
   222  	for i > 0 && isWhitespace(s[i-1]) {
   223  		i--
   224  	}
   225  	return s[0:i]
   226  }
   227  
   228  // Text returns the text of the comment.
   229  // Comment markers ("//"), the first space of a line comment, and
   230  // leading and trailing empty lines are removed. Multiple empty lines are
   231  // reduced to one, and trailing space on lines is trimmed. Unless the result
   232  // is empty, it is newline-terminated.
   233  func (g *CommentGroup) Text() string {
   234  	if g == nil {
   235  		return ""
   236  	}
   237  	comments := make([]string, len(g.List))
   238  	for i, c := range g.List {
   239  		comments[i] = c.Text
   240  	}
   241  
   242  	lines := make([]string, 0, 10) // most comments are less than 10 lines
   243  	for _, c := range comments {
   244  		// Remove comment markers.
   245  		// The parser has given us exactly the comment text.
   246  		c = c[2:]
   247  		// strip first space - required for Example tests
   248  		if len(c) > 0 && c[0] == ' ' {
   249  			c = c[1:]
   250  		}
   251  
   252  		// Split on newlines.
   253  		cl := strings.Split(c, "\n")
   254  
   255  		// Walk lines, stripping trailing white space and adding to list.
   256  		for _, l := range cl {
   257  			lines = append(lines, stripTrailingWhitespace(l))
   258  		}
   259  	}
   260  
   261  	// Remove leading blank lines; convert runs of
   262  	// interior blank lines to a single blank line.
   263  	n := 0
   264  	for _, line := range lines {
   265  		if line != "" || n > 0 && lines[n-1] != "" {
   266  			lines[n] = line
   267  			n++
   268  		}
   269  	}
   270  	lines = lines[0:n]
   271  
   272  	// Add final "" entry to get trailing newline from Join.
   273  	if n > 0 && lines[n-1] != "" {
   274  		lines = append(lines, "")
   275  	}
   276  
   277  	return strings.Join(lines, "\n")
   278  }
   279  
   280  // An Attribute provides meta data about a field.
   281  type Attribute struct {
   282  	At   token.Pos
   283  	Text string // must be a valid attribute format.
   284  
   285  	comments
   286  	decl
   287  }
   288  
   289  func (a *Attribute) Pos() token.Pos  { return a.At }
   290  func (a *Attribute) pos() *token.Pos { return &a.At }
   291  func (a *Attribute) End() token.Pos  { return a.At.Add(len(a.Text)) }
   292  
   293  func (a *Attribute) Split() (key, body string) {
   294  	s := a.Text
   295  	p := strings.IndexByte(s, '(')
   296  	if p < 0 || !strings.HasPrefix(s, "@") || !strings.HasSuffix(s, ")") {
   297  		return "", ""
   298  	}
   299  	return a.Text[1:p], a.Text[p+1 : len(s)-1]
   300  }
   301  
   302  // A Field represents a field declaration in a struct.
   303  type Field struct {
   304  	Label      Label       // must have at least one element.
   305  	Optional   token.Pos   // Deprecated
   306  	Constraint token.Token // token.ILLEGAL, token.OPTION, or token.NOT
   307  
   308  	// No TokenPos: Value must be an StructLit with one field.
   309  	TokenPos token.Pos
   310  	Token    token.Token // Deprecated: always token.COLON
   311  
   312  	Value Expr // the value associated with this field.
   313  
   314  	Attrs []*Attribute
   315  
   316  	comments
   317  	decl
   318  }
   319  
   320  func (d *Field) Pos() token.Pos  { return d.Label.Pos() }
   321  func (d *Field) pos() *token.Pos { return d.Label.pos() }
   322  func (d *Field) End() token.Pos {
   323  	if len(d.Attrs) > 0 {
   324  		return d.Attrs[len(d.Attrs)-1].End()
   325  	}
   326  	return d.Value.End()
   327  }
   328  
   329  // TODO: make Alias a type of Field. This is possible now we have different
   330  // separator types.
   331  
   332  // An Alias binds another field to the alias name in the current struct.
   333  type Alias struct {
   334  	Ident *Ident    // field name, always an Ident
   335  	Equal token.Pos // position of "="
   336  	Expr  Expr      // An Ident or SelectorExpr
   337  
   338  	comments
   339  	clause
   340  	decl
   341  	expr
   342  	label
   343  }
   344  
   345  func (a *Alias) Pos() token.Pos  { return a.Ident.Pos() }
   346  func (a *Alias) pos() *token.Pos { return a.Ident.pos() }
   347  func (a *Alias) End() token.Pos  { return a.Expr.End() }
   348  
   349  // A Comprehension node represents a comprehension declaration.
   350  type Comprehension struct {
   351  	Clauses []Clause // There must be at least one clause.
   352  	Value   Expr     // Must be a struct TODO: change to Struct
   353  
   354  	comments
   355  	decl
   356  	expr // TODO: only allow Comprehension in "Embedding" productions.
   357  }
   358  
   359  func (x *Comprehension) Pos() token.Pos  { return getPos(x) }
   360  func (x *Comprehension) pos() *token.Pos { return x.Clauses[0].pos() }
   361  func (x *Comprehension) End() token.Pos {
   362  	return x.Value.End()
   363  }
   364  
   365  // ----------------------------------------------------------------------------
   366  // Expressions and types
   367  //
   368  // An expression is represented by a tree consisting of one
   369  // or more of the following concrete expression nodes.
   370  
   371  // A BadExpr node is a placeholder for expressions containing
   372  // syntax errors for which no correct expression nodes can be
   373  // created. This is different from an ErrorExpr which represents
   374  // an explicitly marked error in the source.
   375  type BadExpr struct {
   376  	From, To token.Pos // position range of bad expression
   377  
   378  	comments
   379  	expr
   380  }
   381  
   382  // A BottomLit indicates an error.
   383  type BottomLit struct {
   384  	Bottom token.Pos
   385  
   386  	comments
   387  	expr
   388  }
   389  
   390  // An Ident node represents a left-hand side identifier,
   391  // including the underscore "_" identifier to represent top.
   392  type Ident struct {
   393  	NamePos token.Pos // identifier position
   394  
   395  	// This LHS path element may be an identifier. Possible forms:
   396  	//  foo:    a normal identifier
   397  	//  "foo":  JSON compatible
   398  	Name string
   399  
   400  	Scope Node // scope in which node was found or nil if referring directly
   401  	Node  Node
   402  
   403  	comments
   404  	label
   405  	expr
   406  }
   407  
   408  // A BasicLit node represents a literal of basic type.
   409  type BasicLit struct {
   410  	ValuePos token.Pos   // literal position
   411  	Kind     token.Token // INT, FLOAT, DURATION, or STRING
   412  	Value    string      // literal string; e.g. 42, 0x7f, 3.14, 1_234_567, 1e-9, 2.4i, 'a', '\x7f', "foo", or '\m\n\o'
   413  
   414  	comments
   415  	expr
   416  	label
   417  }
   418  
   419  // TODO: introduce and use NewLabel and NewBytes and perhaps NewText (in the
   420  // later case NewString would return a string or bytes type) to distinguish from
   421  // NewString. Consider how to pass indentation information.
   422  
   423  // NewString creates a new BasicLit with a string value without position.
   424  // It quotes the given string.
   425  // Useful for ASTs generated by code other than the CUE parser.
   426  func NewString(str string) *BasicLit {
   427  	str = literal.String.Quote(str)
   428  	return &BasicLit{Kind: token.STRING, ValuePos: token.NoPos, Value: str}
   429  }
   430  
   431  // NewNull creates a new BasicLit configured to be a null value.
   432  // Useful for ASTs generated by code other than the CUE parser.
   433  func NewNull() *BasicLit {
   434  	return &BasicLit{Kind: token.NULL, Value: "null"}
   435  }
   436  
   437  // NewLit creates a new BasicLit with from a token type and string without
   438  // position.
   439  // Useful for ASTs generated by code other than the CUE parser.
   440  func NewLit(tok token.Token, s string) *BasicLit {
   441  	return &BasicLit{Kind: tok, Value: s}
   442  }
   443  
   444  // NewBool creates a new BasicLit with a bool value without position.
   445  // Useful for ASTs generated by code other than the CUE parser.
   446  func NewBool(b bool) *BasicLit {
   447  	x := &BasicLit{}
   448  	if b {
   449  		x.Kind = token.TRUE
   450  		x.Value = "true"
   451  	} else {
   452  		x.Kind = token.FALSE
   453  		x.Value = "false"
   454  	}
   455  	return x
   456  }
   457  
   458  // TODO:
   459  // - use CUE-specific quoting (hoist functionality in export)
   460  // - NewBytes
   461  
   462  // A Interpolation node represents a string or bytes interpolation.
   463  type Interpolation struct {
   464  	Elts []Expr // interleaving of strings and expressions.
   465  
   466  	comments
   467  	expr
   468  	label
   469  }
   470  
   471  // A Func node represents a function type.
   472  //
   473  // This is an experimental type and the contents will change without notice.
   474  type Func struct {
   475  	Func token.Pos // position of "func"
   476  	Args []Expr    // list of elements; or nil
   477  	Ret  Expr      // return type, must not be nil
   478  
   479  	comments
   480  	expr
   481  }
   482  
   483  // A StructLit node represents a literal struct.
   484  type StructLit struct {
   485  	Lbrace token.Pos // position of "{"
   486  	Elts   []Decl    // list of elements; or nil
   487  	Rbrace token.Pos // position of "}"
   488  
   489  	comments
   490  	expr
   491  }
   492  
   493  // NewStruct creates a struct from the given fields.
   494  //
   495  // A field is either a *Field, an *Ellipsis, *LetClause, a *CommentGroup, or a
   496  // Label, optionally followed by a token.OPTION or token.NOT to indicate the
   497  // field is optional or required, followed by an expression for the field value.
   498  //
   499  // It will panic if a values not matching these patterns are given. Useful for
   500  // ASTs generated by code other than the CUE parser.
   501  func NewStruct(fields ...interface{}) *StructLit {
   502  	s := &StructLit{
   503  		// Set default positions so that comment attachment is as expected.
   504  		Lbrace: token.NoSpace.Pos(),
   505  	}
   506  	for i := 0; i < len(fields); i++ {
   507  		var (
   508  			label      Label
   509  			optional   = token.NoPos
   510  			constraint = token.ILLEGAL
   511  			expr       Expr
   512  		)
   513  
   514  		switch x := fields[i].(type) {
   515  		case *Field:
   516  			s.Elts = append(s.Elts, x)
   517  			continue
   518  		case *CommentGroup:
   519  			s.Elts = append(s.Elts, x)
   520  			continue
   521  		case *Ellipsis:
   522  			s.Elts = append(s.Elts, x)
   523  			continue
   524  		case *LetClause:
   525  			s.Elts = append(s.Elts, x)
   526  			continue
   527  		case *embedding:
   528  			s.Elts = append(s.Elts, (*EmbedDecl)(x))
   529  			continue
   530  		case Label:
   531  			label = x
   532  		case string:
   533  			label = NewString(x)
   534  		default:
   535  			panic(fmt.Sprintf("unsupported label type %T", x))
   536  		}
   537  
   538  	inner:
   539  		for i++; i < len(fields); i++ {
   540  			switch x := (fields[i]).(type) {
   541  			case Expr:
   542  				expr = x
   543  				break inner
   544  			case token.Token:
   545  				switch x {
   546  				case token.OPTION:
   547  					constraint = x
   548  					optional = token.Blank.Pos()
   549  				case token.NOT:
   550  					constraint = x
   551  				case token.COLON, token.ILLEGAL:
   552  				default:
   553  					panic(fmt.Sprintf("invalid token %s", x))
   554  				}
   555  			default:
   556  				panic(fmt.Sprintf("unsupported expression type %T", x))
   557  			}
   558  		}
   559  		if expr == nil {
   560  			panic("label not matched with expression")
   561  		}
   562  		s.Elts = append(s.Elts, &Field{
   563  			Label:      label,
   564  			Optional:   optional,
   565  			Constraint: constraint,
   566  			Value:      expr,
   567  		})
   568  	}
   569  	return s
   570  }
   571  
   572  // Embed can be used in conjunction with NewStruct to embed values.
   573  func Embed(x Expr) *embedding {
   574  	return (*embedding)(&EmbedDecl{Expr: x})
   575  }
   576  
   577  type embedding EmbedDecl
   578  
   579  // A ListLit node represents a literal list.
   580  type ListLit struct {
   581  	Lbrack token.Pos // position of "["
   582  
   583  	// TODO: change to embedding or similar.
   584  	Elts   []Expr    // list of composite elements; or nil
   585  	Rbrack token.Pos // position of "]"
   586  
   587  	comments
   588  	expr
   589  	label
   590  }
   591  
   592  // NewList creates a list of Expressions.
   593  // Useful for ASTs generated by code other than the CUE parser.
   594  func NewList(exprs ...Expr) *ListLit {
   595  	return &ListLit{Elts: exprs}
   596  }
   597  
   598  type Ellipsis struct {
   599  	Ellipsis token.Pos // open list if set
   600  	Type     Expr      // type for the remaining elements
   601  
   602  	comments
   603  	decl
   604  	expr
   605  }
   606  
   607  // A ForClause node represents a for clause in a comprehension.
   608  type ForClause struct {
   609  	For token.Pos
   610  	Key *Ident // allow pattern matching?
   611  	// TODO: change to Comma
   612  	Colon  token.Pos
   613  	Value  *Ident // allow pattern matching?
   614  	In     token.Pos
   615  	Source Expr
   616  
   617  	comments
   618  	clause
   619  }
   620  
   621  // A IfClause node represents an if guard clause in a comprehension.
   622  type IfClause struct {
   623  	If        token.Pos
   624  	Condition Expr
   625  
   626  	comments
   627  	clause
   628  }
   629  
   630  // A LetClause node represents a let clause in a comprehension.
   631  type LetClause struct {
   632  	Let   token.Pos
   633  	Ident *Ident
   634  	Equal token.Pos
   635  	Expr  Expr
   636  
   637  	comments
   638  	clause
   639  	decl
   640  }
   641  
   642  // A ParenExpr node represents a parenthesized expression.
   643  type ParenExpr struct {
   644  	Lparen token.Pos // position of "("
   645  	X      Expr      // parenthesized expression
   646  	Rparen token.Pos // position of ")"
   647  
   648  	comments
   649  	expr
   650  	label
   651  }
   652  
   653  // A SelectorExpr node represents an expression followed by a selector.
   654  type SelectorExpr struct {
   655  	X   Expr  // expression
   656  	Sel Label // field selector
   657  
   658  	comments
   659  	expr
   660  }
   661  
   662  // NewSel creates a sequence of selectors.
   663  // Useful for ASTs generated by code other than the CUE parser.
   664  func NewSel(x Expr, sel ...string) Expr {
   665  	for _, s := range sel {
   666  		x = &SelectorExpr{X: x, Sel: NewIdent(s)}
   667  	}
   668  	return x
   669  }
   670  
   671  // An IndexExpr node represents an expression followed by an index.
   672  type IndexExpr struct {
   673  	X      Expr      // expression
   674  	Lbrack token.Pos // position of "["
   675  	Index  Expr      // index expression
   676  	Rbrack token.Pos // position of "]"
   677  
   678  	comments
   679  	expr
   680  }
   681  
   682  // An SliceExpr node represents an expression followed by slice indices.
   683  type SliceExpr struct {
   684  	X      Expr      // expression
   685  	Lbrack token.Pos // position of "["
   686  	Low    Expr      // begin of slice range; or nil
   687  	High   Expr      // end of slice range; or nil
   688  	Rbrack token.Pos // position of "]"
   689  
   690  	comments
   691  	expr
   692  }
   693  
   694  // A CallExpr node represents an expression followed by an argument list.
   695  type CallExpr struct {
   696  	Fun    Expr      // function expression
   697  	Lparen token.Pos // position of "("
   698  	Args   []Expr    // function arguments; or nil
   699  	Rparen token.Pos // position of ")"
   700  
   701  	comments
   702  	expr
   703  }
   704  
   705  // NewCall creates a new CallExpr.
   706  // Useful for ASTs generated by code other than the CUE parser.
   707  func NewCall(fun Expr, args ...Expr) *CallExpr {
   708  	return &CallExpr{Fun: fun, Args: args}
   709  }
   710  
   711  // A UnaryExpr node represents a unary expression.
   712  type UnaryExpr struct {
   713  	OpPos token.Pos   // position of Op
   714  	Op    token.Token // operator
   715  	X     Expr        // operand
   716  
   717  	comments
   718  	expr
   719  }
   720  
   721  // A BinaryExpr node represents a binary expression.
   722  type BinaryExpr struct {
   723  	X     Expr        // left operand
   724  	OpPos token.Pos   // position of Op
   725  	Op    token.Token // operator
   726  	Y     Expr        // right operand
   727  
   728  	comments
   729  	expr
   730  }
   731  
   732  // NewBinExpr creates for list of expressions of length 2 or greater a chained
   733  // binary expression of the form (((x1 op x2) op x3) ...). For lists of length
   734  // 1 it returns the expression itself. It panics for empty lists.
   735  // Useful for ASTs generated by code other than the CUE parser.
   736  func NewBinExpr(op token.Token, operands ...Expr) Expr {
   737  	if len(operands) == 0 {
   738  		return nil
   739  	}
   740  	expr := operands[0]
   741  	for _, e := range operands[1:] {
   742  		expr = &BinaryExpr{X: expr, Op: op, Y: e}
   743  	}
   744  	return expr
   745  }
   746  
   747  // token.Pos and End implementations for expression/type nodes.
   748  
   749  func (x *BadExpr) Pos() token.Pos        { return x.From }
   750  func (x *BadExpr) pos() *token.Pos       { return &x.From }
   751  func (x *Ident) Pos() token.Pos          { return x.NamePos }
   752  func (x *Ident) pos() *token.Pos         { return &x.NamePos }
   753  func (x *BasicLit) Pos() token.Pos       { return x.ValuePos }
   754  func (x *BasicLit) pos() *token.Pos      { return &x.ValuePos }
   755  func (x *Interpolation) Pos() token.Pos  { return x.Elts[0].Pos() }
   756  func (x *Interpolation) pos() *token.Pos { return x.Elts[0].pos() }
   757  func (x *Func) Pos() token.Pos           { return x.Func }
   758  func (x *Func) pos() *token.Pos          { return &x.Func }
   759  func (x *StructLit) Pos() token.Pos      { return getPos(x) }
   760  func (x *StructLit) pos() *token.Pos {
   761  	if x.Lbrace == token.NoPos && len(x.Elts) > 0 {
   762  		return x.Elts[0].pos()
   763  	}
   764  	return &x.Lbrace
   765  }
   766  
   767  func (x *ListLit) Pos() token.Pos       { return x.Lbrack }
   768  func (x *ListLit) pos() *token.Pos      { return &x.Lbrack }
   769  func (x *Ellipsis) Pos() token.Pos      { return x.Ellipsis }
   770  func (x *Ellipsis) pos() *token.Pos     { return &x.Ellipsis }
   771  func (x *LetClause) Pos() token.Pos     { return x.Let }
   772  func (x *LetClause) pos() *token.Pos    { return &x.Let }
   773  func (x *ForClause) Pos() token.Pos     { return x.For }
   774  func (x *ForClause) pos() *token.Pos    { return &x.For }
   775  func (x *IfClause) Pos() token.Pos      { return x.If }
   776  func (x *IfClause) pos() *token.Pos     { return &x.If }
   777  func (x *ParenExpr) Pos() token.Pos     { return x.Lparen }
   778  func (x *ParenExpr) pos() *token.Pos    { return &x.Lparen }
   779  func (x *SelectorExpr) Pos() token.Pos  { return x.X.Pos() }
   780  func (x *SelectorExpr) pos() *token.Pos { return x.X.pos() }
   781  func (x *IndexExpr) Pos() token.Pos     { return x.X.Pos() }
   782  func (x *IndexExpr) pos() *token.Pos    { return x.X.pos() }
   783  func (x *SliceExpr) Pos() token.Pos     { return x.X.Pos() }
   784  func (x *SliceExpr) pos() *token.Pos    { return x.X.pos() }
   785  func (x *CallExpr) Pos() token.Pos      { return x.Fun.Pos() }
   786  func (x *CallExpr) pos() *token.Pos     { return x.Fun.pos() }
   787  func (x *UnaryExpr) Pos() token.Pos     { return x.OpPos }
   788  func (x *UnaryExpr) pos() *token.Pos    { return &x.OpPos }
   789  func (x *BinaryExpr) Pos() token.Pos    { return x.X.Pos() }
   790  func (x *BinaryExpr) pos() *token.Pos   { return x.X.pos() }
   791  func (x *BottomLit) Pos() token.Pos     { return x.Bottom }
   792  func (x *BottomLit) pos() *token.Pos    { return &x.Bottom }
   793  
   794  func (x *BadExpr) End() token.Pos { return x.To }
   795  func (x *Ident) End() token.Pos {
   796  	return x.NamePos.Add(len(x.Name))
   797  }
   798  func (x *BasicLit) End() token.Pos { return x.ValuePos.Add(len(x.Value)) }
   799  
   800  func (x *Interpolation) End() token.Pos { return x.Elts[len(x.Elts)-1].Pos() }
   801  func (x *Func) End() token.Pos          { return x.Ret.End() }
   802  func (x *StructLit) End() token.Pos {
   803  	if x.Rbrace == token.NoPos && len(x.Elts) > 0 {
   804  		return x.Elts[len(x.Elts)-1].End()
   805  	}
   806  	return x.Rbrace.Add(1)
   807  }
   808  func (x *ListLit) End() token.Pos { return x.Rbrack.Add(1) }
   809  func (x *Ellipsis) End() token.Pos {
   810  	if x.Type != nil {
   811  		return x.Type.End()
   812  	}
   813  	return x.Ellipsis.Add(3) // len("...")
   814  }
   815  func (x *LetClause) End() token.Pos    { return x.Expr.End() }
   816  func (x *ForClause) End() token.Pos    { return x.Source.End() }
   817  func (x *IfClause) End() token.Pos     { return x.Condition.End() }
   818  func (x *ParenExpr) End() token.Pos    { return x.Rparen.Add(1) }
   819  func (x *SelectorExpr) End() token.Pos { return x.Sel.End() }
   820  func (x *IndexExpr) End() token.Pos    { return x.Rbrack.Add(1) }
   821  func (x *SliceExpr) End() token.Pos    { return x.Rbrack.Add(1) }
   822  func (x *CallExpr) End() token.Pos     { return x.Rparen.Add(1) }
   823  func (x *UnaryExpr) End() token.Pos    { return x.X.End() }
   824  func (x *BinaryExpr) End() token.Pos   { return x.Y.End() }
   825  func (x *BottomLit) End() token.Pos    { return x.Bottom.Add(1) }
   826  
   827  // ----------------------------------------------------------------------------
   828  // Convenience functions for Idents
   829  
   830  // NewIdent creates a new Ident without position.
   831  // Useful for ASTs generated by code other than the CUE parser.
   832  func NewIdent(name string) *Ident {
   833  	return &Ident{token.NoPos, name, nil, nil, comments{}, label{}, expr{}}
   834  }
   835  
   836  func (id *Ident) String() string {
   837  	if id != nil {
   838  		return id.Name
   839  	}
   840  	return "<nil>"
   841  }
   842  
   843  // ----------------------------------------------------------------------------
   844  // Declarations
   845  
   846  // An ImportSpec node represents a single package import.
   847  type ImportSpec struct {
   848  	Name   *Ident    // local package name (including "."); or nil
   849  	Path   *BasicLit // import path
   850  	EndPos token.Pos // end of spec (overrides Path.Pos if nonzero)
   851  
   852  	comments
   853  }
   854  
   855  func (*ImportSpec) specNode() {}
   856  
   857  func NewImport(name *Ident, importPath string) *ImportSpec {
   858  	importPath = literal.String.Quote(importPath)
   859  	path := &BasicLit{Kind: token.STRING, Value: importPath}
   860  	return &ImportSpec{Name: name, Path: path}
   861  }
   862  
   863  // Pos and End implementations for spec nodes.
   864  
   865  func (s *ImportSpec) Pos() token.Pos { return getPos(s) }
   866  func (s *ImportSpec) pos() *token.Pos {
   867  	if s.Name != nil {
   868  		return s.Name.pos()
   869  	}
   870  	return s.Path.pos()
   871  }
   872  
   873  // func (s *AliasSpec) Pos() token.Pos { return s.Name.Pos() }
   874  // func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
   875  // func (s *TypeSpec) Pos() token.Pos  { return s.Name.Pos() }
   876  
   877  func (s *ImportSpec) End() token.Pos {
   878  	if s.EndPos != token.NoPos {
   879  		return s.EndPos
   880  	}
   881  	return s.Path.End()
   882  }
   883  
   884  // A BadDecl node is a placeholder for declarations containing
   885  // syntax errors for which no correct declaration nodes can be
   886  // created.
   887  type BadDecl struct {
   888  	From, To token.Pos // position range of bad declaration
   889  
   890  	comments
   891  	decl
   892  }
   893  
   894  // A ImportDecl node represents a series of import declarations. A valid
   895  // Lparen position (Lparen.Line > 0) indicates a parenthesized declaration.
   896  type ImportDecl struct {
   897  	Import token.Pos
   898  	Lparen token.Pos // position of '(', if any
   899  	Specs  []*ImportSpec
   900  	Rparen token.Pos // position of ')', if any
   901  
   902  	comments
   903  	decl
   904  }
   905  
   906  type Spec interface {
   907  	Node
   908  	specNode()
   909  }
   910  
   911  // An EmbedDecl node represents a single expression used as a declaration.
   912  // The expressions in this declaration is what will be emitted as
   913  // configuration output.
   914  //
   915  // An EmbedDecl may only appear at the top level.
   916  type EmbedDecl struct {
   917  	Expr Expr
   918  
   919  	comments
   920  	decl
   921  }
   922  
   923  // Pos and End implementations for declaration nodes.
   924  
   925  func (d *BadDecl) Pos() token.Pos     { return d.From }
   926  func (d *BadDecl) pos() *token.Pos    { return &d.From }
   927  func (d *ImportDecl) Pos() token.Pos  { return d.Import }
   928  func (d *ImportDecl) pos() *token.Pos { return &d.Import }
   929  func (d *EmbedDecl) Pos() token.Pos   { return d.Expr.Pos() }
   930  func (d *EmbedDecl) pos() *token.Pos  { return d.Expr.pos() }
   931  
   932  func (d *BadDecl) End() token.Pos { return d.To }
   933  func (d *ImportDecl) End() token.Pos {
   934  	if d.Rparen.IsValid() {
   935  		return d.Rparen.Add(1)
   936  	}
   937  	if len(d.Specs) == 0 {
   938  		return token.NoPos
   939  	}
   940  	return d.Specs[0].End()
   941  }
   942  func (d *EmbedDecl) End() token.Pos { return d.Expr.End() }
   943  
   944  // ----------------------------------------------------------------------------
   945  // Files and packages
   946  
   947  // A File node represents a CUE source file.
   948  //
   949  // The Comments list contains all comments in the source file in order of
   950  // appearance, including the comments that are pointed to from other nodes
   951  // via Doc and Comment fields.
   952  type File struct {
   953  	Filename string
   954  	Decls    []Decl // top-level declarations; or nil
   955  
   956  	Imports    []*ImportSpec // imports in this file
   957  	Unresolved []*Ident      // unresolved identifiers in this file
   958  
   959  	comments
   960  }
   961  
   962  // Preamble returns the declarations of the preamble.
   963  func (f *File) Preamble() []Decl {
   964  	p := 0
   965  outer:
   966  	for i, d := range f.Decls {
   967  		switch d.(type) {
   968  		default:
   969  			break outer
   970  
   971  		case *Package:
   972  			p = i + 1
   973  		case *CommentGroup:
   974  		case *Attribute:
   975  		case *ImportDecl:
   976  			p = i + 1
   977  		}
   978  	}
   979  	return f.Decls[:p]
   980  }
   981  
   982  func (f *File) VisitImports(fn func(d *ImportDecl)) {
   983  	for _, d := range f.Decls {
   984  		switch x := d.(type) {
   985  		case *CommentGroup:
   986  		case *Package:
   987  		case *Attribute:
   988  		case *ImportDecl:
   989  			fn(x)
   990  		default:
   991  			return
   992  		}
   993  	}
   994  }
   995  
   996  // PackageName returns the package name associated with this file or "" if no
   997  // package is associated.
   998  func (f *File) PackageName() string {
   999  	for _, d := range f.Decls {
  1000  		switch x := d.(type) {
  1001  		case *Package:
  1002  			if x.Name.Name == "_" {
  1003  				return ""
  1004  			}
  1005  			return x.Name.Name
  1006  		case *CommentGroup, *Attribute:
  1007  		default:
  1008  			return ""
  1009  		}
  1010  	}
  1011  	return ""
  1012  }
  1013  
  1014  func (f *File) Pos() token.Pos {
  1015  	if len(f.Decls) > 0 {
  1016  		return f.Decls[0].Pos()
  1017  	}
  1018  	if f.Filename != "" {
  1019  		// TODO. Do something more principled and efficient.
  1020  		return token.NewFile(f.Filename, -1, 1).Pos(0, 0)
  1021  	}
  1022  	return token.NoPos
  1023  }
  1024  
  1025  func (f *File) pos() *token.Pos {
  1026  	if len(f.Decls) > 0 {
  1027  		return f.Decls[0].pos()
  1028  	}
  1029  	if f.Filename != "" {
  1030  		return nil
  1031  	}
  1032  	return nil
  1033  }
  1034  
  1035  func (f *File) End() token.Pos {
  1036  	if n := len(f.Decls); n > 0 {
  1037  		return f.Decls[n-1].End()
  1038  	}
  1039  	return token.NoPos
  1040  }
  1041  
  1042  // A Package represents a package clause.
  1043  type Package struct {
  1044  	PackagePos token.Pos // position of "package" pseudo-keyword
  1045  	Name       *Ident    // package name
  1046  
  1047  	comments
  1048  	decl
  1049  }
  1050  
  1051  func (p *Package) Pos() token.Pos { return getPos(p) }
  1052  func (p *Package) pos() *token.Pos {
  1053  	if p.PackagePos != token.NoPos {
  1054  		return &p.PackagePos
  1055  	}
  1056  	if p.Name != nil {
  1057  		return p.Name.pos()
  1058  	}
  1059  	return nil
  1060  }
  1061  
  1062  func (p *Package) End() token.Pos {
  1063  	if p.Name != nil {
  1064  		return p.Name.End()
  1065  	}
  1066  	return token.NoPos
  1067  }