github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/pattern/pattern.go (about)

     1  package pattern
     2  
     3  import (
     4  	"fmt"
     5  	"go/token"
     6  	"reflect"
     7  	"strings"
     8  )
     9  
    10  var (
    11  	_ Node = Ellipsis{}
    12  	_ Node = Binding{}
    13  	_ Node = RangeStmt{}
    14  	_ Node = AssignStmt{}
    15  	_ Node = IndexExpr{}
    16  	_ Node = IndexListExpr{}
    17  	_ Node = Ident{}
    18  	_ Node = Builtin{}
    19  	_ Node = String("")
    20  	_ Node = Any{}
    21  	_ Node = ValueSpec{}
    22  	_ Node = List{}
    23  	_ Node = GenDecl{}
    24  	_ Node = BinaryExpr{}
    25  	_ Node = ForStmt{}
    26  	_ Node = ArrayType{}
    27  	_ Node = DeferStmt{}
    28  	_ Node = MapType{}
    29  	_ Node = ReturnStmt{}
    30  	_ Node = SliceExpr{}
    31  	_ Node = StarExpr{}
    32  	_ Node = UnaryExpr{}
    33  	_ Node = SendStmt{}
    34  	_ Node = SelectStmt{}
    35  	_ Node = ImportSpec{}
    36  	_ Node = IfStmt{}
    37  	_ Node = GoStmt{}
    38  	_ Node = Field{}
    39  	_ Node = SelectorExpr{}
    40  	_ Node = StructType{}
    41  	_ Node = KeyValueExpr{}
    42  	_ Node = FuncType{}
    43  	_ Node = FuncLit{}
    44  	_ Node = FuncDecl{}
    45  	_ Node = Token(0)
    46  	_ Node = ChanType{}
    47  	_ Node = CallExpr{}
    48  	_ Node = CaseClause{}
    49  	_ Node = CommClause{}
    50  	_ Node = CompositeLit{}
    51  	_ Node = EmptyStmt{}
    52  	_ Node = SwitchStmt{}
    53  	_ Node = TypeSwitchStmt{}
    54  	_ Node = TypeAssertExpr{}
    55  	_ Node = TypeSpec{}
    56  	_ Node = InterfaceType{}
    57  	_ Node = BranchStmt{}
    58  	_ Node = IncDecStmt{}
    59  	_ Node = BasicLit{}
    60  	_ Node = Nil{}
    61  	_ Node = Object{}
    62  	_ Node = Symbol{}
    63  	_ Node = Not{}
    64  	_ Node = Or{}
    65  	_ Node = IntegerLiteral{}
    66  	_ Node = TrulyConstantExpression{}
    67  )
    68  
    69  type Symbol struct {
    70  	Name Node
    71  }
    72  
    73  type Token token.Token
    74  
    75  type Nil struct {
    76  }
    77  
    78  type Ellipsis struct {
    79  	Elt Node
    80  }
    81  
    82  type IncDecStmt struct {
    83  	X   Node
    84  	Tok Node
    85  }
    86  
    87  type BranchStmt struct {
    88  	Tok   Node
    89  	Label Node
    90  }
    91  
    92  type InterfaceType struct {
    93  	Methods Node
    94  }
    95  
    96  type TypeSpec struct {
    97  	Name Node
    98  	Type Node
    99  }
   100  
   101  type TypeAssertExpr struct {
   102  	X    Node
   103  	Type Node
   104  }
   105  
   106  type TypeSwitchStmt struct {
   107  	Init   Node
   108  	Assign Node
   109  	Body   Node
   110  }
   111  
   112  type SwitchStmt struct {
   113  	Init Node
   114  	Tag  Node
   115  	Body Node
   116  }
   117  
   118  type EmptyStmt struct {
   119  }
   120  
   121  type CompositeLit struct {
   122  	Type Node
   123  	Elts Node
   124  }
   125  
   126  type CommClause struct {
   127  	Comm Node
   128  	Body Node
   129  }
   130  
   131  type CaseClause struct {
   132  	List Node
   133  	Body Node
   134  }
   135  
   136  type CallExpr struct {
   137  	Fun  Node
   138  	Args Node
   139  	// XXX handle ellipsis
   140  }
   141  
   142  // TODO(dh): add a ChanDir node, and a way of instantiating it.
   143  
   144  type ChanType struct {
   145  	Dir   Node
   146  	Value Node
   147  }
   148  
   149  type FuncDecl struct {
   150  	Recv Node
   151  	Name Node
   152  	Type Node
   153  	Body Node
   154  }
   155  
   156  type FuncLit struct {
   157  	Type Node
   158  	Body Node
   159  }
   160  
   161  type FuncType struct {
   162  	Params  Node
   163  	Results Node
   164  }
   165  
   166  type KeyValueExpr struct {
   167  	Key   Node
   168  	Value Node
   169  }
   170  
   171  type StructType struct {
   172  	Fields Node
   173  }
   174  
   175  type SelectorExpr struct {
   176  	X   Node
   177  	Sel Node
   178  }
   179  
   180  type Field struct {
   181  	Names Node
   182  	Type  Node
   183  	Tag   Node
   184  }
   185  
   186  type GoStmt struct {
   187  	Call Node
   188  }
   189  
   190  type IfStmt struct {
   191  	Init Node
   192  	Cond Node
   193  	Body Node
   194  	Else Node
   195  }
   196  
   197  type ImportSpec struct {
   198  	Name Node
   199  	Path Node
   200  }
   201  
   202  type SelectStmt struct {
   203  	Body Node
   204  }
   205  
   206  type ArrayType struct {
   207  	Len Node
   208  	Elt Node
   209  }
   210  
   211  type DeferStmt struct {
   212  	Call Node
   213  }
   214  
   215  type MapType struct {
   216  	Key   Node
   217  	Value Node
   218  }
   219  
   220  type ReturnStmt struct {
   221  	Results Node
   222  }
   223  
   224  type SliceExpr struct {
   225  	X    Node
   226  	Low  Node
   227  	High Node
   228  	Max  Node
   229  }
   230  
   231  type StarExpr struct {
   232  	X Node
   233  }
   234  
   235  type UnaryExpr struct {
   236  	Op Node
   237  	X  Node
   238  }
   239  
   240  type SendStmt struct {
   241  	Chan  Node
   242  	Value Node
   243  }
   244  
   245  type Binding struct {
   246  	Name string
   247  	Node Node
   248  
   249  	idx int
   250  }
   251  
   252  type RangeStmt struct {
   253  	Key   Node
   254  	Value Node
   255  	Tok   Node
   256  	X     Node
   257  	Body  Node
   258  }
   259  
   260  type AssignStmt struct {
   261  	Lhs Node
   262  	Tok Node
   263  	Rhs Node
   264  }
   265  
   266  type IndexExpr struct {
   267  	X     Node
   268  	Index Node
   269  }
   270  
   271  type IndexListExpr struct {
   272  	X       Node
   273  	Indices Node
   274  }
   275  
   276  type Node interface {
   277  	String() string
   278  	isNode()
   279  }
   280  
   281  type Ident struct {
   282  	Name Node
   283  }
   284  
   285  type Object struct {
   286  	Name Node
   287  }
   288  
   289  type Builtin struct {
   290  	Name Node
   291  }
   292  
   293  type String string
   294  
   295  type Any struct{}
   296  
   297  type ValueSpec struct {
   298  	Names  Node
   299  	Type   Node
   300  	Values Node
   301  }
   302  
   303  type List struct {
   304  	Head Node
   305  	Tail Node
   306  }
   307  
   308  type GenDecl struct {
   309  	Tok   Node
   310  	Specs Node
   311  }
   312  
   313  type BasicLit struct {
   314  	Kind  Node
   315  	Value Node
   316  }
   317  
   318  // An IntegerLiteral is a constant expression made up of only integer basic literals and the "+" and "-" unary operators.
   319  // That is, 0, -4, -+42 are all integer literals, but 1 + 2 is not.
   320  type IntegerLiteral struct {
   321  	Value Node
   322  }
   323  
   324  type BinaryExpr struct {
   325  	X  Node
   326  	Op Node
   327  	Y  Node
   328  }
   329  
   330  type ForStmt struct {
   331  	Init Node
   332  	Cond Node
   333  	Post Node
   334  	Body Node
   335  }
   336  
   337  type Or struct {
   338  	Nodes []Node
   339  }
   340  
   341  type Not struct {
   342  	Node Node
   343  }
   344  
   345  // A TrulyConstantExpression is a constant expression that does not make use of any identifiers.
   346  // It is constant even under varying build tags.
   347  type TrulyConstantExpression struct {
   348  	Value Node
   349  }
   350  
   351  func stringify(n Node) string {
   352  	v := reflect.ValueOf(n)
   353  	var parts []string
   354  	parts = append(parts, v.Type().Name())
   355  	for i := 0; i < v.NumField(); i++ {
   356  		parts = append(parts, fmt.Sprintf("%s", v.Field(i)))
   357  	}
   358  	return "(" + strings.Join(parts, " ") + ")"
   359  }
   360  
   361  func (stmt AssignStmt) String() string              { return stringify(stmt) }
   362  func (expr IndexExpr) String() string               { return stringify(expr) }
   363  func (expr IndexListExpr) String() string           { return stringify(expr) }
   364  func (id Ident) String() string                     { return stringify(id) }
   365  func (spec ValueSpec) String() string               { return stringify(spec) }
   366  func (decl GenDecl) String() string                 { return stringify(decl) }
   367  func (lit BasicLit) String() string                 { return stringify(lit) }
   368  func (expr BinaryExpr) String() string              { return stringify(expr) }
   369  func (stmt ForStmt) String() string                 { return stringify(stmt) }
   370  func (stmt RangeStmt) String() string               { return stringify(stmt) }
   371  func (typ ArrayType) String() string                { return stringify(typ) }
   372  func (stmt DeferStmt) String() string               { return stringify(stmt) }
   373  func (typ MapType) String() string                  { return stringify(typ) }
   374  func (stmt ReturnStmt) String() string              { return stringify(stmt) }
   375  func (expr SliceExpr) String() string               { return stringify(expr) }
   376  func (expr StarExpr) String() string                { return stringify(expr) }
   377  func (expr UnaryExpr) String() string               { return stringify(expr) }
   378  func (stmt SendStmt) String() string                { return stringify(stmt) }
   379  func (spec ImportSpec) String() string              { return stringify(spec) }
   380  func (stmt SelectStmt) String() string              { return stringify(stmt) }
   381  func (stmt IfStmt) String() string                  { return stringify(stmt) }
   382  func (stmt IncDecStmt) String() string              { return stringify(stmt) }
   383  func (stmt GoStmt) String() string                  { return stringify(stmt) }
   384  func (field Field) String() string                  { return stringify(field) }
   385  func (expr SelectorExpr) String() string            { return stringify(expr) }
   386  func (typ StructType) String() string               { return stringify(typ) }
   387  func (expr KeyValueExpr) String() string            { return stringify(expr) }
   388  func (typ FuncType) String() string                 { return stringify(typ) }
   389  func (lit FuncLit) String() string                  { return stringify(lit) }
   390  func (decl FuncDecl) String() string                { return stringify(decl) }
   391  func (stmt BranchStmt) String() string              { return stringify(stmt) }
   392  func (expr CallExpr) String() string                { return stringify(expr) }
   393  func (clause CaseClause) String() string            { return stringify(clause) }
   394  func (typ ChanType) String() string                 { return stringify(typ) }
   395  func (clause CommClause) String() string            { return stringify(clause) }
   396  func (lit CompositeLit) String() string             { return stringify(lit) }
   397  func (stmt EmptyStmt) String() string               { return stringify(stmt) }
   398  func (typ InterfaceType) String() string            { return stringify(typ) }
   399  func (stmt SwitchStmt) String() string              { return stringify(stmt) }
   400  func (expr TypeAssertExpr) String() string          { return stringify(expr) }
   401  func (spec TypeSpec) String() string                { return stringify(spec) }
   402  func (stmt TypeSwitchStmt) String() string          { return stringify(stmt) }
   403  func (nil Nil) String() string                      { return "nil" }
   404  func (builtin Builtin) String() string              { return stringify(builtin) }
   405  func (obj Object) String() string                   { return stringify(obj) }
   406  func (fn Symbol) String() string                    { return stringify(fn) }
   407  func (el Ellipsis) String() string                  { return stringify(el) }
   408  func (not Not) String() string                      { return stringify(not) }
   409  func (lit IntegerLiteral) String() string           { return stringify(lit) }
   410  func (expr TrulyConstantExpression) String() string { return stringify(expr) }
   411  
   412  func (or Or) String() string {
   413  	s := "(Or"
   414  	for _, node := range or.Nodes {
   415  		s += " "
   416  		s += node.String()
   417  	}
   418  	s += ")"
   419  	return s
   420  }
   421  
   422  func isProperList(l List) bool {
   423  	if l.Head == nil && l.Tail == nil {
   424  		return true
   425  	}
   426  	switch tail := l.Tail.(type) {
   427  	case nil:
   428  		return false
   429  	case List:
   430  		return isProperList(tail)
   431  	default:
   432  		return false
   433  	}
   434  }
   435  
   436  func (l List) String() string {
   437  	if l.Head == nil && l.Tail == nil {
   438  		return "[]"
   439  	}
   440  
   441  	if isProperList(l) {
   442  		// pretty-print the list
   443  		var objs []string
   444  		for l.Head != nil {
   445  			objs = append(objs, l.Head.String())
   446  			l = l.Tail.(List)
   447  		}
   448  		return fmt.Sprintf("[%s]", strings.Join(objs, " "))
   449  	}
   450  
   451  	return fmt.Sprintf("%s:%s", l.Head, l.Tail)
   452  }
   453  
   454  func (bind Binding) String() string {
   455  	if bind.Node == nil {
   456  		return bind.Name
   457  	}
   458  	return fmt.Sprintf("%s@%s", bind.Name, bind.Node)
   459  }
   460  
   461  func (s String) String() string { return fmt.Sprintf("%q", string(s)) }
   462  
   463  func (tok Token) String() string {
   464  	return fmt.Sprintf("%q", strings.ToUpper(token.Token(tok).String()))
   465  }
   466  
   467  func (Any) String() string { return "_" }
   468  
   469  func (AssignStmt) isNode()              {}
   470  func (IndexExpr) isNode()               {}
   471  func (IndexListExpr) isNode()           {}
   472  func (Ident) isNode()                   {}
   473  func (ValueSpec) isNode()               {}
   474  func (GenDecl) isNode()                 {}
   475  func (BasicLit) isNode()                {}
   476  func (BinaryExpr) isNode()              {}
   477  func (ForStmt) isNode()                 {}
   478  func (RangeStmt) isNode()               {}
   479  func (ArrayType) isNode()               {}
   480  func (DeferStmt) isNode()               {}
   481  func (MapType) isNode()                 {}
   482  func (ReturnStmt) isNode()              {}
   483  func (SliceExpr) isNode()               {}
   484  func (StarExpr) isNode()                {}
   485  func (UnaryExpr) isNode()               {}
   486  func (SendStmt) isNode()                {}
   487  func (ImportSpec) isNode()              {}
   488  func (SelectStmt) isNode()              {}
   489  func (IfStmt) isNode()                  {}
   490  func (IncDecStmt) isNode()              {}
   491  func (GoStmt) isNode()                  {}
   492  func (Field) isNode()                   {}
   493  func (SelectorExpr) isNode()            {}
   494  func (StructType) isNode()              {}
   495  func (KeyValueExpr) isNode()            {}
   496  func (FuncType) isNode()                {}
   497  func (FuncLit) isNode()                 {}
   498  func (FuncDecl) isNode()                {}
   499  func (BranchStmt) isNode()              {}
   500  func (CallExpr) isNode()                {}
   501  func (CaseClause) isNode()              {}
   502  func (ChanType) isNode()                {}
   503  func (CommClause) isNode()              {}
   504  func (CompositeLit) isNode()            {}
   505  func (EmptyStmt) isNode()               {}
   506  func (InterfaceType) isNode()           {}
   507  func (SwitchStmt) isNode()              {}
   508  func (TypeAssertExpr) isNode()          {}
   509  func (TypeSpec) isNode()                {}
   510  func (TypeSwitchStmt) isNode()          {}
   511  func (Nil) isNode()                     {}
   512  func (Builtin) isNode()                 {}
   513  func (Object) isNode()                  {}
   514  func (Symbol) isNode()                  {}
   515  func (Ellipsis) isNode()                {}
   516  func (Or) isNode()                      {}
   517  func (List) isNode()                    {}
   518  func (String) isNode()                  {}
   519  func (Token) isNode()                   {}
   520  func (Any) isNode()                     {}
   521  func (Binding) isNode()                 {}
   522  func (Not) isNode()                     {}
   523  func (IntegerLiteral) isNode()          {}
   524  func (TrulyConstantExpression) isNode() {}