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