pattern.go raw

   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() {}
 525