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