@@ -126,16 +126,16 @@ func (f *File) ParseGo(name string, src []byte) {
126
126
if f .Ref == nil {
127
127
f .Ref = make ([]* Ref , 0 , 8 )
128
128
}
129
- f .walk (ast2 , "prog" , (* File ).saveExprs )
129
+ f .walk (ast2 , ctxProg , (* File ).saveExprs )
130
130
131
131
// Accumulate exported functions.
132
132
// The comments are only on ast1 but we need to
133
133
// save the function bodies from ast2.
134
134
// The first walk fills in ExpFunc, and the
135
135
// second walk changes the entries to
136
136
// refer to ast2 instead.
137
- f .walk (ast1 , "prog" , (* File ).saveExport )
138
- f .walk (ast2 , "prog" , (* File ).saveExport2 )
137
+ f .walk (ast1 , ctxProg , (* File ).saveExport )
138
+ f .walk (ast2 , ctxProg , (* File ).saveExport2 )
139
139
140
140
f .Comments = ast1 .Comments
141
141
f .AST = ast2
@@ -166,7 +166,7 @@ func commentText(g *ast.CommentGroup) string {
166
166
}
167
167
168
168
// Save various references we are going to need later.
169
- func (f * File ) saveExprs (x interface {}, context string ) {
169
+ func (f * File ) saveExprs (x interface {}, context astContext ) {
170
170
switch x := x .(type ) {
171
171
case * ast.Expr :
172
172
switch (* x ).(type ) {
@@ -179,7 +179,7 @@ func (f *File) saveExprs(x interface{}, context string) {
179
179
}
180
180
181
181
// Save references to C.xxx for later processing.
182
- func (f * File ) saveRef (n * ast.Expr , context string ) {
182
+ func (f * File ) saveRef (n * ast.Expr , context astContext ) {
183
183
sel := (* n ).(* ast.SelectorExpr )
184
184
// For now, assume that the only instance of capital C is when
185
185
// used as the imported package identifier.
@@ -189,10 +189,10 @@ func (f *File) saveRef(n *ast.Expr, context string) {
189
189
if l , ok := sel .X .(* ast.Ident ); ! ok || l .Name != "C" {
190
190
return
191
191
}
192
- if context == "as2" {
193
- context = "expr"
192
+ if context == ctxAssign2 {
193
+ context = ctxExpr
194
194
}
195
- if context == "embed-type" {
195
+ if context == ctxEmbedType {
196
196
error_ (sel .Pos (), "cannot embed C type" )
197
197
}
198
198
goname := sel .Sel .Name
@@ -223,20 +223,20 @@ func (f *File) saveRef(n *ast.Expr, context string) {
223
223
}
224
224
225
225
// Save calls to C.xxx for later processing.
226
- func (f * File ) saveCall (call * ast.CallExpr , context string ) {
226
+ func (f * File ) saveCall (call * ast.CallExpr , context astContext ) {
227
227
sel , ok := call .Fun .(* ast.SelectorExpr )
228
228
if ! ok {
229
229
return
230
230
}
231
231
if l , ok := sel .X .(* ast.Ident ); ! ok || l .Name != "C" {
232
232
return
233
233
}
234
- c := & Call {Call : call , Deferred : context == "defer" }
234
+ c := & Call {Call : call , Deferred : context == ctxDefer }
235
235
f .Calls = append (f .Calls , c )
236
236
}
237
237
238
238
// If a function should be exported add it to ExpFunc.
239
- func (f * File ) saveExport (x interface {}, context string ) {
239
+ func (f * File ) saveExport (x interface {}, context astContext ) {
240
240
n , ok := x .(* ast.FuncDecl )
241
241
if ! ok {
242
242
return
@@ -276,7 +276,7 @@ func (f *File) saveExport(x interface{}, context string) {
276
276
}
277
277
278
278
// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
279
- func (f * File ) saveExport2 (x interface {}, context string ) {
279
+ func (f * File ) saveExport2 (x interface {}, context astContext ) {
280
280
n , ok := x .(* ast.FuncDecl )
281
281
if ! ok {
282
282
return
@@ -290,8 +290,30 @@ func (f *File) saveExport2(x interface{}, context string) {
290
290
}
291
291
}
292
292
293
+ type astContext int
294
+
295
+ const (
296
+ ctxProg astContext = iota
297
+ ctxEmbedType
298
+ ctxType
299
+ ctxStmt
300
+ ctxExpr
301
+ ctxField
302
+ ctxParam
303
+ ctxAssign2 // assignment of a single expression to two variables
304
+ ctxSwitch
305
+ ctxTypeSwitch
306
+ ctxFile
307
+ ctxDecl
308
+ ctxSpec
309
+ ctxDefer
310
+ ctxCall // any function call other than ctxCall2
311
+ ctxCall2 // function call whose result is assigned to two variables
312
+ ctxSelector
313
+ )
314
+
293
315
// walk walks the AST x, calling visit(f, x, context) for each node.
294
- func (f * File ) walk (x interface {}, context string , visit func (* File , interface {}, string )) {
316
+ func (f * File ) walk (x interface {}, context astContext , visit func (* File , interface {}, astContext )) {
295
317
visit (f , x , context )
296
318
switch n := x .(type ) {
297
319
case * ast.Expr :
@@ -306,10 +328,10 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
306
328
307
329
// These are ordered and grouped to match ../../go/ast/ast.go
308
330
case * ast.Field :
309
- if len (n .Names ) == 0 && context == "field" {
310
- f .walk (& n .Type , "embed-type" , visit )
331
+ if len (n .Names ) == 0 && context == ctxField {
332
+ f .walk (& n .Type , ctxEmbedType , visit )
311
333
} else {
312
- f .walk (& n .Type , "type" , visit )
334
+ f .walk (& n .Type , ctxType , visit )
313
335
}
314
336
case * ast.FieldList :
315
337
for _ , field := range n .List {
@@ -320,163 +342,163 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
320
342
case * ast.Ellipsis :
321
343
case * ast.BasicLit :
322
344
case * ast.FuncLit :
323
- f .walk (n .Type , "type" , visit )
324
- f .walk (n .Body , "stmt" , visit )
345
+ f .walk (n .Type , ctxType , visit )
346
+ f .walk (n .Body , ctxStmt , visit )
325
347
case * ast.CompositeLit :
326
- f .walk (& n .Type , "type" , visit )
327
- f .walk (n .Elts , "expr" , visit )
348
+ f .walk (& n .Type , ctxType , visit )
349
+ f .walk (n .Elts , ctxExpr , visit )
328
350
case * ast.ParenExpr :
329
351
f .walk (& n .X , context , visit )
330
352
case * ast.SelectorExpr :
331
- f .walk (& n .X , "selector" , visit )
353
+ f .walk (& n .X , ctxSelector , visit )
332
354
case * ast.IndexExpr :
333
- f .walk (& n .X , "expr" , visit )
334
- f .walk (& n .Index , "expr" , visit )
355
+ f .walk (& n .X , ctxExpr , visit )
356
+ f .walk (& n .Index , ctxExpr , visit )
335
357
case * ast.SliceExpr :
336
- f .walk (& n .X , "expr" , visit )
358
+ f .walk (& n .X , ctxExpr , visit )
337
359
if n .Low != nil {
338
- f .walk (& n .Low , "expr" , visit )
360
+ f .walk (& n .Low , ctxExpr , visit )
339
361
}
340
362
if n .High != nil {
341
- f .walk (& n .High , "expr" , visit )
363
+ f .walk (& n .High , ctxExpr , visit )
342
364
}
343
365
if n .Max != nil {
344
- f .walk (& n .Max , "expr" , visit )
366
+ f .walk (& n .Max , ctxExpr , visit )
345
367
}
346
368
case * ast.TypeAssertExpr :
347
- f .walk (& n .X , "expr" , visit )
348
- f .walk (& n .Type , "type" , visit )
369
+ f .walk (& n .X , ctxExpr , visit )
370
+ f .walk (& n .Type , ctxType , visit )
349
371
case * ast.CallExpr :
350
- if context == "as2" {
351
- f .walk (& n .Fun , "call2" , visit )
372
+ if context == ctxAssign2 {
373
+ f .walk (& n .Fun , ctxCall2 , visit )
352
374
} else {
353
- f .walk (& n .Fun , "call" , visit )
375
+ f .walk (& n .Fun , ctxCall , visit )
354
376
}
355
- f .walk (n .Args , "expr" , visit )
377
+ f .walk (n .Args , ctxExpr , visit )
356
378
case * ast.StarExpr :
357
379
f .walk (& n .X , context , visit )
358
380
case * ast.UnaryExpr :
359
- f .walk (& n .X , "expr" , visit )
381
+ f .walk (& n .X , ctxExpr , visit )
360
382
case * ast.BinaryExpr :
361
- f .walk (& n .X , "expr" , visit )
362
- f .walk (& n .Y , "expr" , visit )
383
+ f .walk (& n .X , ctxExpr , visit )
384
+ f .walk (& n .Y , ctxExpr , visit )
363
385
case * ast.KeyValueExpr :
364
- f .walk (& n .Key , "expr" , visit )
365
- f .walk (& n .Value , "expr" , visit )
386
+ f .walk (& n .Key , ctxExpr , visit )
387
+ f .walk (& n .Value , ctxExpr , visit )
366
388
367
389
case * ast.ArrayType :
368
- f .walk (& n .Len , "expr" , visit )
369
- f .walk (& n .Elt , "type" , visit )
390
+ f .walk (& n .Len , ctxExpr , visit )
391
+ f .walk (& n .Elt , ctxType , visit )
370
392
case * ast.StructType :
371
- f .walk (n .Fields , "field" , visit )
393
+ f .walk (n .Fields , ctxField , visit )
372
394
case * ast.FuncType :
373
- f .walk (n .Params , "param" , visit )
395
+ f .walk (n .Params , ctxParam , visit )
374
396
if n .Results != nil {
375
- f .walk (n .Results , "param" , visit )
397
+ f .walk (n .Results , ctxParam , visit )
376
398
}
377
399
case * ast.InterfaceType :
378
- f .walk (n .Methods , "field" , visit )
400
+ f .walk (n .Methods , ctxField , visit )
379
401
case * ast.MapType :
380
- f .walk (& n .Key , "type" , visit )
381
- f .walk (& n .Value , "type" , visit )
402
+ f .walk (& n .Key , ctxType , visit )
403
+ f .walk (& n .Value , ctxType , visit )
382
404
case * ast.ChanType :
383
- f .walk (& n .Value , "type" , visit )
405
+ f .walk (& n .Value , ctxType , visit )
384
406
385
407
case * ast.BadStmt :
386
408
case * ast.DeclStmt :
387
- f .walk (n .Decl , "decl" , visit )
409
+ f .walk (n .Decl , ctxDecl , visit )
388
410
case * ast.EmptyStmt :
389
411
case * ast.LabeledStmt :
390
- f .walk (n .Stmt , "stmt" , visit )
412
+ f .walk (n .Stmt , ctxStmt , visit )
391
413
case * ast.ExprStmt :
392
- f .walk (& n .X , "expr" , visit )
414
+ f .walk (& n .X , ctxExpr , visit )
393
415
case * ast.SendStmt :
394
- f .walk (& n .Chan , "expr" , visit )
395
- f .walk (& n .Value , "expr" , visit )
416
+ f .walk (& n .Chan , ctxExpr , visit )
417
+ f .walk (& n .Value , ctxExpr , visit )
396
418
case * ast.IncDecStmt :
397
- f .walk (& n .X , "expr" , visit )
419
+ f .walk (& n .X , ctxExpr , visit )
398
420
case * ast.AssignStmt :
399
- f .walk (n .Lhs , "expr" , visit )
421
+ f .walk (n .Lhs , ctxExpr , visit )
400
422
if len (n .Lhs ) == 2 && len (n .Rhs ) == 1 {
401
- f .walk (n .Rhs , "as2" , visit )
423
+ f .walk (n .Rhs , ctxAssign2 , visit )
402
424
} else {
403
- f .walk (n .Rhs , "expr" , visit )
425
+ f .walk (n .Rhs , ctxExpr , visit )
404
426
}
405
427
case * ast.GoStmt :
406
- f .walk (n .Call , "expr" , visit )
428
+ f .walk (n .Call , ctxExpr , visit )
407
429
case * ast.DeferStmt :
408
- f .walk (n .Call , "defer" , visit )
430
+ f .walk (n .Call , ctxDefer , visit )
409
431
case * ast.ReturnStmt :
410
- f .walk (n .Results , "expr" , visit )
432
+ f .walk (n .Results , ctxExpr , visit )
411
433
case * ast.BranchStmt :
412
434
case * ast.BlockStmt :
413
435
f .walk (n .List , context , visit )
414
436
case * ast.IfStmt :
415
- f .walk (n .Init , "stmt" , visit )
416
- f .walk (& n .Cond , "expr" , visit )
417
- f .walk (n .Body , "stmt" , visit )
418
- f .walk (n .Else , "stmt" , visit )
437
+ f .walk (n .Init , ctxStmt , visit )
438
+ f .walk (& n .Cond , ctxExpr , visit )
439
+ f .walk (n .Body , ctxStmt , visit )
440
+ f .walk (n .Else , ctxStmt , visit )
419
441
case * ast.CaseClause :
420
- if context == "typeswitch" {
421
- context = "type"
442
+ if context == ctxTypeSwitch {
443
+ context = ctxType
422
444
} else {
423
- context = "expr"
445
+ context = ctxExpr
424
446
}
425
447
f .walk (n .List , context , visit )
426
- f .walk (n .Body , "stmt" , visit )
448
+ f .walk (n .Body , ctxStmt , visit )
427
449
case * ast.SwitchStmt :
428
- f .walk (n .Init , "stmt" , visit )
429
- f .walk (& n .Tag , "expr" , visit )
430
- f .walk (n .Body , "switch" , visit )
450
+ f .walk (n .Init , ctxStmt , visit )
451
+ f .walk (& n .Tag , ctxExpr , visit )
452
+ f .walk (n .Body , ctxSwitch , visit )
431
453
case * ast.TypeSwitchStmt :
432
- f .walk (n .Init , "stmt" , visit )
433
- f .walk (n .Assign , "stmt" , visit )
434
- f .walk (n .Body , "typeswitch" , visit )
454
+ f .walk (n .Init , ctxStmt , visit )
455
+ f .walk (n .Assign , ctxStmt , visit )
456
+ f .walk (n .Body , ctxTypeSwitch , visit )
435
457
case * ast.CommClause :
436
- f .walk (n .Comm , "stmt" , visit )
437
- f .walk (n .Body , "stmt" , visit )
458
+ f .walk (n .Comm , ctxStmt , visit )
459
+ f .walk (n .Body , ctxStmt , visit )
438
460
case * ast.SelectStmt :
439
- f .walk (n .Body , "stmt" , visit )
461
+ f .walk (n .Body , ctxStmt , visit )
440
462
case * ast.ForStmt :
441
- f .walk (n .Init , "stmt" , visit )
442
- f .walk (& n .Cond , "expr" , visit )
443
- f .walk (n .Post , "stmt" , visit )
444
- f .walk (n .Body , "stmt" , visit )
463
+ f .walk (n .Init , ctxStmt , visit )
464
+ f .walk (& n .Cond , ctxExpr , visit )
465
+ f .walk (n .Post , ctxStmt , visit )
466
+ f .walk (n .Body , ctxStmt , visit )
445
467
case * ast.RangeStmt :
446
- f .walk (& n .Key , "expr" , visit )
447
- f .walk (& n .Value , "expr" , visit )
448
- f .walk (& n .X , "expr" , visit )
449
- f .walk (n .Body , "stmt" , visit )
468
+ f .walk (& n .Key , ctxExpr , visit )
469
+ f .walk (& n .Value , ctxExpr , visit )
470
+ f .walk (& n .X , ctxExpr , visit )
471
+ f .walk (n .Body , ctxStmt , visit )
450
472
451
473
case * ast.ImportSpec :
452
474
case * ast.ValueSpec :
453
- f .walk (& n .Type , "type" , visit )
475
+ f .walk (& n .Type , ctxType , visit )
454
476
if len (n .Names ) == 2 && len (n .Values ) == 1 {
455
- f .walk (& n .Values [0 ], "as2" , visit )
477
+ f .walk (& n .Values [0 ], ctxAssign2 , visit )
456
478
} else {
457
- f .walk (n .Values , "expr" , visit )
479
+ f .walk (n .Values , ctxExpr , visit )
458
480
}
459
481
case * ast.TypeSpec :
460
- f .walk (& n .Type , "type" , visit )
482
+ f .walk (& n .Type , ctxType , visit )
461
483
462
484
case * ast.BadDecl :
463
485
case * ast.GenDecl :
464
- f .walk (n .Specs , "spec" , visit )
486
+ f .walk (n .Specs , ctxSpec , visit )
465
487
case * ast.FuncDecl :
466
488
if n .Recv != nil {
467
- f .walk (n .Recv , "param" , visit )
489
+ f .walk (n .Recv , ctxParam , visit )
468
490
}
469
- f .walk (n .Type , "type" , visit )
491
+ f .walk (n .Type , ctxType , visit )
470
492
if n .Body != nil {
471
- f .walk (n .Body , "stmt" , visit )
493
+ f .walk (n .Body , ctxStmt , visit )
472
494
}
473
495
474
496
case * ast.File :
475
- f .walk (n .Decls , "decl" , visit )
497
+ f .walk (n .Decls , ctxDecl , visit )
476
498
477
499
case * ast.Package :
478
500
for _ , file := range n .Files {
479
- f .walk (file , "file" , visit )
501
+ f .walk (file , ctxFile , visit )
480
502
}
481
503
482
504
case []ast.Decl :
0 commit comments