src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

pattern.go (12692B)


      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 And struct {
    342 	Nodes []Node
    343 }
    344 
    345 type Not struct {
    346 	Node Node
    347 }
    348 
    349 // A TrulyConstantExpression is a constant expression that does not make use of any identifiers.
    350 // It is constant even under varying build tags.
    351 type TrulyConstantExpression struct {
    352 	Value Node
    353 }
    354 
    355 type IndexSymbol struct {
    356 	Path  string
    357 	Type  string
    358 	Ident string
    359 }
    360 
    361 func stringify(n Node) string {
    362 	v := reflect.ValueOf(n)
    363 	var parts []string
    364 	parts = append(parts, v.Type().Name())
    365 	for i := 0; i < v.NumField(); i++ {
    366 		parts = append(parts, fmt.Sprintf("%s", v.Field(i)))
    367 	}
    368 	return "(" + strings.Join(parts, " ") + ")"
    369 }
    370 
    371 func (stmt AssignStmt) String() string              { return stringify(stmt) }
    372 func (expr IndexExpr) String() string               { return stringify(expr) }
    373 func (expr IndexListExpr) String() string           { return stringify(expr) }
    374 func (id Ident) String() string                     { return stringify(id) }
    375 func (spec ValueSpec) String() string               { return stringify(spec) }
    376 func (decl GenDecl) String() string                 { return stringify(decl) }
    377 func (lit BasicLit) String() string                 { return stringify(lit) }
    378 func (expr BinaryExpr) String() string              { return stringify(expr) }
    379 func (stmt ForStmt) String() string                 { return stringify(stmt) }
    380 func (stmt RangeStmt) String() string               { return stringify(stmt) }
    381 func (typ ArrayType) String() string                { return stringify(typ) }
    382 func (stmt DeferStmt) String() string               { return stringify(stmt) }
    383 func (typ MapType) String() string                  { return stringify(typ) }
    384 func (stmt ReturnStmt) String() string              { return stringify(stmt) }
    385 func (expr SliceExpr) String() string               { return stringify(expr) }
    386 func (expr StarExpr) String() string                { return stringify(expr) }
    387 func (expr UnaryExpr) String() string               { return stringify(expr) }
    388 func (stmt SendStmt) String() string                { return stringify(stmt) }
    389 func (spec ImportSpec) String() string              { return stringify(spec) }
    390 func (stmt SelectStmt) String() string              { return stringify(stmt) }
    391 func (stmt IfStmt) String() string                  { return stringify(stmt) }
    392 func (stmt IncDecStmt) String() string              { return stringify(stmt) }
    393 func (stmt GoStmt) String() string                  { return stringify(stmt) }
    394 func (field Field) String() string                  { return stringify(field) }
    395 func (expr SelectorExpr) String() string            { return stringify(expr) }
    396 func (typ StructType) String() string               { return stringify(typ) }
    397 func (expr KeyValueExpr) String() string            { return stringify(expr) }
    398 func (typ FuncType) String() string                 { return stringify(typ) }
    399 func (lit FuncLit) String() string                  { return stringify(lit) }
    400 func (decl FuncDecl) String() string                { return stringify(decl) }
    401 func (stmt BranchStmt) String() string              { return stringify(stmt) }
    402 func (expr CallExpr) String() string                { return stringify(expr) }
    403 func (clause CaseClause) String() string            { return stringify(clause) }
    404 func (typ ChanType) String() string                 { return stringify(typ) }
    405 func (clause CommClause) String() string            { return stringify(clause) }
    406 func (lit CompositeLit) String() string             { return stringify(lit) }
    407 func (stmt EmptyStmt) String() string               { return stringify(stmt) }
    408 func (typ InterfaceType) String() string            { return stringify(typ) }
    409 func (stmt SwitchStmt) String() string              { return stringify(stmt) }
    410 func (expr TypeAssertExpr) String() string          { return stringify(expr) }
    411 func (spec TypeSpec) String() string                { return stringify(spec) }
    412 func (stmt TypeSwitchStmt) String() string          { return stringify(stmt) }
    413 func (nil Nil) String() string                      { return "nil" }
    414 func (builtin Builtin) String() string              { return stringify(builtin) }
    415 func (obj Object) String() string                   { return stringify(obj) }
    416 func (fn Symbol) String() string                    { return stringify(fn) }
    417 func (el Ellipsis) String() string                  { return stringify(el) }
    418 func (not Not) String() string                      { return stringify(not) }
    419 func (lit IntegerLiteral) String() string           { return stringify(lit) }
    420 func (expr TrulyConstantExpression) String() string { return stringify(expr) }
    421 func (sym IndexSymbol) String() string {
    422 	return fmt.Sprintf("(IndexSymbol %q %q %q)", sym.Path, sym.Type, sym.Ident)
    423 }
    424 
    425 func (or Or) String() string {
    426 	var s strings.Builder
    427 	s.WriteString("(Or")
    428 	for _, node := range or.Nodes {
    429 		s.WriteString(" ")
    430 		s.WriteString(node.String())
    431 	}
    432 	s.WriteString(")")
    433 	return s.String()
    434 }
    435 
    436 func (and And) String() string {
    437 	var s strings.Builder
    438 	s.WriteString("(And")
    439 	for _, node := range and.Nodes {
    440 		s.WriteString(" ")
    441 		s.WriteString(node.String())
    442 	}
    443 	s.WriteString(")")
    444 	return s.String()
    445 }
    446 
    447 func isProperList(l List) bool {
    448 	if l.Head == nil && l.Tail == nil {
    449 		return true
    450 	}
    451 	switch tail := l.Tail.(type) {
    452 	case nil:
    453 		return false
    454 	case List:
    455 		return isProperList(tail)
    456 	default:
    457 		return false
    458 	}
    459 }
    460 
    461 func (l List) String() string {
    462 	if l.Head == nil && l.Tail == nil {
    463 		return "[]"
    464 	}
    465 
    466 	if isProperList(l) {
    467 		// pretty-print the list
    468 		var objs []string
    469 		for l.Head != nil {
    470 			objs = append(objs, l.Head.String())
    471 			l = l.Tail.(List)
    472 		}
    473 		return fmt.Sprintf("[%s]", strings.Join(objs, " "))
    474 	}
    475 
    476 	return fmt.Sprintf("%s:%s", l.Head, l.Tail)
    477 }
    478 
    479 func (bind Binding) String() string {
    480 	if bind.Node == nil {
    481 		return bind.Name
    482 	}
    483 	return fmt.Sprintf("%s@%s", bind.Name, bind.Node)
    484 }
    485 
    486 func (s String) String() string { return fmt.Sprintf("%q", string(s)) }
    487 
    488 func (tok Token) String() string {
    489 	return fmt.Sprintf("%q", strings.ToUpper(token.Token(tok).String()))
    490 }
    491 
    492 func (Any) String() string { return "_" }
    493 
    494 func (AssignStmt) isNode()              {}
    495 func (IndexExpr) isNode()               {}
    496 func (IndexListExpr) isNode()           {}
    497 func (Ident) isNode()                   {}
    498 func (ValueSpec) isNode()               {}
    499 func (GenDecl) isNode()                 {}
    500 func (BasicLit) isNode()                {}
    501 func (BinaryExpr) isNode()              {}
    502 func (ForStmt) isNode()                 {}
    503 func (RangeStmt) isNode()               {}
    504 func (ArrayType) isNode()               {}
    505 func (DeferStmt) isNode()               {}
    506 func (MapType) isNode()                 {}
    507 func (ReturnStmt) isNode()              {}
    508 func (SliceExpr) isNode()               {}
    509 func (StarExpr) isNode()                {}
    510 func (UnaryExpr) isNode()               {}
    511 func (SendStmt) isNode()                {}
    512 func (ImportSpec) isNode()              {}
    513 func (SelectStmt) isNode()              {}
    514 func (IfStmt) isNode()                  {}
    515 func (IncDecStmt) isNode()              {}
    516 func (GoStmt) isNode()                  {}
    517 func (Field) isNode()                   {}
    518 func (SelectorExpr) isNode()            {}
    519 func (StructType) isNode()              {}
    520 func (KeyValueExpr) isNode()            {}
    521 func (FuncType) isNode()                {}
    522 func (FuncLit) isNode()                 {}
    523 func (FuncDecl) isNode()                {}
    524 func (BranchStmt) isNode()              {}
    525 func (CallExpr) isNode()                {}
    526 func (CaseClause) isNode()              {}
    527 func (ChanType) isNode()                {}
    528 func (CommClause) isNode()              {}
    529 func (CompositeLit) isNode()            {}
    530 func (EmptyStmt) isNode()               {}
    531 func (InterfaceType) isNode()           {}
    532 func (SwitchStmt) isNode()              {}
    533 func (TypeAssertExpr) isNode()          {}
    534 func (TypeSpec) isNode()                {}
    535 func (TypeSwitchStmt) isNode()          {}
    536 func (Nil) isNode()                     {}
    537 func (Builtin) isNode()                 {}
    538 func (Object) isNode()                  {}
    539 func (Symbol) isNode()                  {}
    540 func (Ellipsis) isNode()                {}
    541 func (Or) isNode()                      {}
    542 func (And) isNode()                     {}
    543 func (List) isNode()                    {}
    544 func (String) isNode()                  {}
    545 func (Token) isNode()                   {}
    546 func (Any) isNode()                     {}
    547 func (Binding) isNode()                 {}
    548 func (Not) isNode()                     {}
    549 func (IntegerLiteral) isNode()          {}
    550 func (TrulyConstantExpression) isNode() {}
    551 func (IndexSymbol) isNode()             {}