func (n *Field) String() string {
	s := ""
	for i, ident := range n.Idents {
		s += ident.String()
		if i != len(n.Idents)-1 {
			s += ","
		}
		s += " "
	}
	s += n.Type.String()
	if n.Tag != "" {
		s += " `" + n.Tag + "`"
	}
	return s
}
String returns the string representation of n.
package ast
import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)
var expandedPrint = false
type OperatorType int
const (
	OperatorEqual          OperatorType = iota  
	OperatorNotEqual                            
	OperatorLess                                
	OperatorLessEqual                           
	OperatorGreater                             
	OperatorGreaterEqual                        
	OperatorNot                                 
	OperatorBitAnd                              
	OperatorBitOr                               
	OperatorAnd                                 
	OperatorOr                                  
	OperatorAddition                            
	OperatorSubtraction                         
	OperatorMultiplication                      
	OperatorDivision                            
	OperatorModulo                              
	OperatorXor                                 
	OperatorAndNot                              
	OperatorLeftShift                           
	OperatorRightShift                          
	OperatorContains                            
	OperatorNotContains                         
	OperatorReceive                             
	OperatorAddress                             
	OperatorPointer                             
	OperatorExtendedAnd                         
	OperatorExtendedOr                          
	OperatorExtendedNot                         
)
func (op OperatorType) String() string {
	return []string{"==", "!=", "<", "<=", ">", ">=", "!", "&", "|", "&&", "||",
		"+", "-", "*", "/", "%", "^", "&^", "<<", ">>", "contains", "not contains",
		"<-", "&", "*", "and", "or", "not", "", ""}[op]
}
type AssignmentType int
const (
	AssignmentSimple         AssignmentType = iota  
	AssignmentDeclaration                           
	AssignmentAddition                              
	AssignmentSubtraction                           
	AssignmentMultiplication                        
	AssignmentDivision                              
	AssignmentModulo                                
	AssignmentAnd                                   
	AssignmentOr                                    
	AssignmentXor                                   
	AssignmentAndNot                                
	AssignmentLeftShift                             
	AssignmentRightShift                            
	AssignmentIncrement                             
	AssignmentDecrement                             
)
type Format int
const (
	FormatText Format = iota
	FormatHTML
	FormatCSS
	FormatJS
	FormatJSON
	FormatMarkdown
)
func (format Format) String() string {
	switch format {
	case FormatText:
		return "text"
	case FormatHTML:
		return "HTML"
	case FormatCSS:
		return "CSS"
	case FormatJS:
		return "JavaScript"
	case FormatJSON:
		return "JSON"
	case FormatMarkdown:
		return "Markdown"
	}
	panic("invalid format")
}
type Context int
const (
	ContextText Context = iota
	ContextHTML
	ContextCSS
	ContextJS
	ContextJSON
	ContextMarkdown
	ContextTag
	ContextQuotedAttr
	ContextUnquotedAttr
	ContextCSSString
	ContextJSString
	ContextJSONString
	ContextTabCodeBlock
	ContextSpacesCodeBlock
)
func (ctx Context) String() string {
	switch ctx {
	case ContextText:
		return "text"
	case ContextHTML:
		return "HTML"
	case ContextCSS:
		return "CSS"
	case ContextJS:
		return "JavaScript"
	case ContextJSON:
		return "JSON"
	case ContextMarkdown:
		return "Markdown"
	case ContextTag:
		return "tag"
	case ContextQuotedAttr:
		return "quoted attribute"
	case ContextUnquotedAttr:
		return "unquoted attribute"
	case ContextCSSString:
		return "CSS string"
	case ContextJSString:
		return "JavaScript string"
	case ContextJSONString:
		return "JSON string"
	case ContextTabCodeBlock:
		return "tab code block"
	case ContextSpacesCodeBlock:
		return "spaces code block"
	}
	panic("invalid context")
}
type LiteralType int
const (
	StringLiteral LiteralType = iota
	RuneLiteral
	IntLiteral
	FloatLiteral
	ImaginaryLiteral
)
type ChanDirection int
const (
	NoDirection ChanDirection = iota
	ReceiveDirection
	SendDirection
)
var directionString = [3]string{"no direction", "receive", "send"}
func (dir ChanDirection) String() string { return directionString[dir] }
type Node interface {
	Pos() *Position  
}
type Position struct {
	Line   int  
	Column int  
	Start  int  
	End    int  
}
func (p *Position) Pos() *Position {
	return p
}
func (p Position) String() string {
	return strconv.Itoa(p.Line) + ":" + strconv.Itoa(p.Column)
}
func (p *Position) WithEnd(end int) *Position {
	pp := *p
	pp.End = end
	return &pp
}
type Operator interface {
	Expression
	Operator() OperatorType
	Precedence() int
}
type Upvar struct {
	NativePkg string
	NativeName string
	NativeValue *reflect.Value
	NativeValueType reflect.Type
	Declaration Node
}
type Expression interface {
	Parenthesis() int
	SetParenthesis(int)
	Node
	String() string
}
type expression struct {
	parenthesis int
}
func (e *expression) Parenthesis() int {
	return e.parenthesis
}
func (e *expression) SetParenthesis(n int) {
	e.parenthesis = n
}
type Cut struct {
	Left  int
	Right int
}
type ArrayType struct {
	*expression
	*Position               
	Len         Expression  
	ElementType Expression  
}
func NewArrayType(pos *Position, len Expression, elementType Expression) *ArrayType {
	return &ArrayType{&expression{}, pos, len, elementType}
}
func (n *ArrayType) String() string {
	s := "["
	if n.Len == nil {
		s += "..."
	} else {
		s += n.Len.String()
	}
	s += "]" + n.ElementType.String()
	return s
}
type Assignment struct {
	*Position                 
	Lhs       []Expression    
	Type      AssignmentType  
	Rhs       []Expression    
}
func NewAssignment(pos *Position, lhs []Expression, typ AssignmentType, rhs []Expression) *Assignment {
	return &Assignment{pos, lhs, typ, rhs}
}
func (n *Assignment) String() string {
	var s string
	for i, v := range n.Lhs {
		if i > 0 {
			s += ", "
		}
		s += v.String()
	}
	switch n.Type {
	case AssignmentSimple:
		s += " = "
	case AssignmentDeclaration:
		s += " := "
	case AssignmentAddition:
		s += " += "
	case AssignmentSubtraction:
		s += " -= "
	case AssignmentMultiplication:
		s += " *= "
	case AssignmentDivision:
		s += " /= "
	case AssignmentModulo:
		s += " %= "
	case AssignmentIncrement:
		s += "++"
	case AssignmentDecrement:
		s += "--"
	}
	if n.Rhs != nil {
		for i, value := range n.Rhs {
			if i > 0 {
				s += ", "
			}
			s += value.String()
		}
	}
	return s
}
type BasicLiteral struct {
	expression
	*Position              
	Type      LiteralType  
	Value     string       
}
func NewBasicLiteral(pos *Position, typ LiteralType, value string) *BasicLiteral {
	return &BasicLiteral{expression{}, pos, typ, value}
}
func (n *BasicLiteral) String() string {
	return n.Value
}
type BinaryOperator struct {
	*expression
	*Position               
	Op        OperatorType  
	Expr1     Expression    
	Expr2     Expression    
}
func NewBinaryOperator(pos *Position, op OperatorType, expr1, expr2 Expression) *BinaryOperator {
	return &BinaryOperator{&expression{}, pos, op, expr1, expr2}
}
func (n *BinaryOperator) String() string {
	var s string
	if e, ok := n.Expr1.(Operator); ok && e.Precedence() <= n.Precedence() {
		s += "(" + n.Expr1.String() + ")"
	} else {
		s += n.Expr1.String()
	}
	s += " " + n.Op.String() + " "
	if e, ok := n.Expr2.(Operator); ok && e.Precedence() <= n.Precedence() {
		s += "(" + n.Expr2.String() + ")"
	} else {
		s += n.Expr2.String()
	}
	return s
}
func (n *BinaryOperator) Operator() OperatorType {
	return n.Op
}
func (n *BinaryOperator) Precedence() int {
	switch n.Op {
	case OperatorMultiplication, OperatorDivision, OperatorModulo,
		OperatorLeftShift, OperatorRightShift, OperatorBitAnd, OperatorAndNot:
		return 5
	case OperatorAddition, OperatorSubtraction, OperatorBitOr, OperatorXor:
		return 4
	case OperatorEqual, OperatorNotEqual, OperatorLess, OperatorLessEqual,
		OperatorGreater, OperatorGreaterEqual, OperatorContains, OperatorNotContains:
		return 3
	case OperatorAnd, OperatorExtendedAnd:
		return 2
	case OperatorOr, OperatorExtendedOr:
		return 1
	}
	panic("invalid operator type")
}
type Block struct {
	*Position
	Nodes []Node
}
func NewBlock(pos *Position, nodes []Node) *Block {
	return &Block{pos, nodes}
}
type Break struct {
	*Position              
	Label     *Identifier  
}
func NewBreak(pos *Position, label *Identifier) *Break {
	return &Break{pos, label}
}
type Call struct {
	*expression
	*Position                
	Func       Expression    
	Args       []Expression  
	IsVariadic bool          
	IR struct {
		AppendArg1 *Call
	}
}
func NewCall(pos *Position, fun Expression, args []Expression, isVariadic bool) *Call {
	return &Call{expression: &expression{}, Position: pos, Func: fun, Args: args, IsVariadic: isVariadic}
}
func (n *Call) String() string {
	s := n.Func.String()
	switch fn := n.Func.(type) {
	case *UnaryOperator:
		if fn.Op == OperatorPointer || fn.Op == OperatorReceive {
			s = "(" + s + ")"
		}
	case *FuncType:
		if len(fn.Result) == 0 {
			s = "(" + s + ")"
		}
	case *ChanType:
		s = "(" + s + ")"
	}
	s += "("
	for i, arg := range n.Args {
		if i > 0 {
			s += ", "
		}
		s += arg.String()
	}
	if n.IsVariadic {
		s += "..."
	}
	s += ")"
	return s
}
type Case struct {
	*Position
	Expressions []Expression
	Body        []Node
}
func NewCase(pos *Position, expressions []Expression, body []Node) *Case {
	return &Case{pos, expressions, body}
}
type ChanType struct {
	*expression
	*Position                  
	Direction   ChanDirection  
	ElementType Expression     
}
func NewChanType(pos *Position, direction ChanDirection, elementType Expression) *ChanType {
	return &ChanType{&expression{}, pos, direction, elementType}
}
func (n *ChanType) String() string {
	var s string
	if n.Direction == ReceiveDirection {
		s = "<-"
	}
	s += "chan"
	if n.Direction == SendDirection {
		s += "<-"
	}
	return s + " " + n.ElementType.String()
}
type Comment struct {
	*Position         
	Text      string  
}
func NewComment(pos *Position, text string) *Comment {
	return &Comment{pos, text}
}
type CompositeLiteral struct {
	*expression
	*Position             
	Type      Expression  
	KeyValues []KeyValue  
}
func NewCompositeLiteral(pos *Position, typ Expression, keyValues []KeyValue) *CompositeLiteral {
	return &CompositeLiteral{&expression{}, pos, typ, keyValues}
}
func (n *CompositeLiteral) String() string {
	s := n.Type.String()
	if expandedPrint {
		s += "{"
		for i, kv := range n.KeyValues {
			if i > 0 {
				s += ", "
			}
			s += kv.String()
		}
		s += "}"
		return s
	}
	if len(n.KeyValues) > 0 {
		return s + "{...}"
	}
	return s + "{}"
}
type Const struct {
	*Position                
	Lhs       []*Identifier  
	Type      Expression     
	Rhs       []Expression   
	Index     int            
}
func NewConst(pos *Position, lhs []*Identifier, typ Expression, rhs []Expression, index int) *Const {
	return &Const{pos, lhs, typ, rhs, index}
}
type Continue struct {
	*Position              
	Label     *Identifier  
}
func NewContinue(pos *Position, label *Identifier) *Continue {
	return &Continue{pos, label}
}
type Default struct {
	expression
	*Position             
	Expr1     Expression  
	Expr2     Expression  
}
func NewDefault(pos *Position, expr1, expr2 Expression) *Default {
	return &Default{Position: pos, Expr1: expr1, Expr2: expr2}
}
func (n *Default) String() string {
	return n.Expr1.String() + " default " + n.Expr2.String()
}
type Defer struct {
	*Position             
	Call      Expression  
}
func NewDefer(pos *Position, call Expression) *Defer {
	return &Defer{pos, call}
}
func (n *Defer) String() string {
	return "defer " + n.Call.String()
}
type DollarIdentifier struct {
	*expression
	*Position              
	Ident     *Identifier  
	IR struct {
		Ident Expression
	}
}
func NewDollarIdentifier(pos *Position, ident *Identifier) *DollarIdentifier {
	return &DollarIdentifier{&expression{}, pos, ident, struct{ Ident Expression }{}}
}
func (n *DollarIdentifier) String() string {
	return "$" + n.Ident.String()
}
type Extends struct {
	*Position         
	Path      string  
	Format    Format  
	Tree      *Tree   
}
func NewExtends(pos *Position, path string, format Format) *Extends {
	return &Extends{Position: pos, Path: path, Format: format}
}
func (n *Extends) String() string {
	return fmt.Sprintf("extends %v", strconv.Quote(n.Path))
}
type Fallthrough struct {
	*Position
}
func NewFallthrough(pos *Position) *Fallthrough {
	return &Fallthrough{pos}
}
type Field struct {
	Idents []*Identifier  
	Type   Expression
	Tag    string
}
func NewField(idents []*Identifier, typ Expression, tag string) *Field {
	return &Field{idents, typ, tag}
}