Source file
src/go/parser/resolver.go
1
2
3
4
5 package parser
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/token"
11 "strings"
12 )
13
14 const debugResolve = false
15
16
17
18
19
20
21 func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) {
22 pkgScope := ast.NewScope(nil)
23 r := &resolver{
24 handle: handle,
25 declErr: declErr,
26 topScope: pkgScope,
27 pkgScope: pkgScope,
28 depth: 1,
29 }
30
31 for _, decl := range file.Decls {
32 ast.Walk(r, decl)
33 }
34
35 r.closeScope()
36 assert(r.topScope == nil, "unbalanced scopes")
37 assert(r.labelScope == nil, "unbalanced label scopes")
38
39
40 i := 0
41 for _, ident := range r.unresolved {
42
43 assert(ident.Obj == unresolved, "object already resolved")
44 ident.Obj = r.pkgScope.Lookup(ident.Name)
45 if ident.Obj == nil {
46 r.unresolved[i] = ident
47 i++
48 } else if debugResolve {
49 pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()
50 r.trace("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
51 }
52 }
53 file.Scope = r.pkgScope
54 file.Unresolved = r.unresolved[0:i]
55 }
56
57 type resolver struct {
58 handle *token.File
59 declErr func(token.Pos, string)
60
61
62 pkgScope *ast.Scope
63 topScope *ast.Scope
64 unresolved []*ast.Ident
65 depth int
66
67
68
69 labelScope *ast.Scope
70 targetStack [][]*ast.Ident
71 }
72
73 func (r *resolver) trace(format string, args ...any) {
74 fmt.Println(strings.Repeat(". ", r.depth) + r.sprintf(format, args...))
75 }
76
77 func (r *resolver) sprintf(format string, args ...any) string {
78 for i, arg := range args {
79 switch arg := arg.(type) {
80 case token.Pos:
81 args[i] = r.handle.Position(arg)
82 }
83 }
84 return fmt.Sprintf(format, args...)
85 }
86
87 func (r *resolver) openScope(pos token.Pos) {
88 if debugResolve {
89 r.trace("opening scope @%v", pos)
90 r.depth++
91 }
92 r.topScope = ast.NewScope(r.topScope)
93 }
94
95 func (r *resolver) closeScope() {
96 if debugResolve {
97 r.depth--
98 r.trace("closing scope")
99 }
100 r.topScope = r.topScope.Outer
101 }
102
103 func (r *resolver) openLabelScope() {
104 r.labelScope = ast.NewScope(r.labelScope)
105 r.targetStack = append(r.targetStack, nil)
106 }
107
108 func (r *resolver) closeLabelScope() {
109
110 n := len(r.targetStack) - 1
111 scope := r.labelScope
112 for _, ident := range r.targetStack[n] {
113 ident.Obj = scope.Lookup(ident.Name)
114 if ident.Obj == nil && r.declErr != nil {
115 r.declErr(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
116 }
117 }
118
119 r.targetStack = r.targetStack[0:n]
120 r.labelScope = r.labelScope.Outer
121 }
122
123 func (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
124 for _, ident := range idents {
125 if ident.Obj != nil {
126 panic(fmt.Sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
127 }
128 obj := ast.NewObj(kind, ident.Name)
129
130
131 obj.Decl = decl
132 obj.Data = data
133
134
135 if _, ok := decl.(*ast.Ident); !ok {
136 ident.Obj = obj
137 }
138 if ident.Name != "_" {
139 if debugResolve {
140 r.trace("declaring %s@%v", ident.Name, ident.Pos())
141 }
142 if alt := scope.Insert(obj); alt != nil && r.declErr != nil {
143 prevDecl := ""
144 if pos := alt.Pos(); pos.IsValid() {
145 prevDecl = r.sprintf("\n\tprevious declaration at %v", pos)
146 }
147 r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
148 }
149 }
150 }
151 }
152
153 func (r *resolver) shortVarDecl(decl *ast.AssignStmt) {
154
155
156
157 n := 0
158 for _, x := range decl.Lhs {
159 if ident, isIdent := x.(*ast.Ident); isIdent {
160 assert(ident.Obj == nil, "identifier already declared or resolved")
161 obj := ast.NewObj(ast.Var, ident.Name)
162
163 obj.Decl = decl
164 ident.Obj = obj
165 if ident.Name != "_" {
166 if debugResolve {
167 r.trace("declaring %s@%v", ident.Name, ident.Pos())
168 }
169 if alt := r.topScope.Insert(obj); alt != nil {
170 ident.Obj = alt
171 } else {
172 n++
173 }
174 }
175 }
176 }
177 if n == 0 && r.declErr != nil {
178 r.declErr(decl.Lhs[0].Pos(), "no new variables on left side of :=")
179 }
180 }
181
182
183
184
185 var unresolved = new(ast.Object)
186
187
188
189
190
191
192 func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {
193 if ident.Obj != nil {
194 panic(r.sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
195 }
196
197
198 if ident.Name == "_" {
199 return
200 }
201 for s := r.topScope; s != nil; s = s.Outer {
202 if obj := s.Lookup(ident.Name); obj != nil {
203 if debugResolve {
204 r.trace("resolved %v:%s to %v", ident.Pos(), ident.Name, obj)
205 }
206 assert(obj.Name != "", "obj with no name")
207
208
209 if _, ok := obj.Decl.(*ast.Ident); !ok {
210 ident.Obj = obj
211 }
212 return
213 }
214 }
215
216
217
218
219 if collectUnresolved {
220 ident.Obj = unresolved
221 r.unresolved = append(r.unresolved, ident)
222 }
223 }
224
225 func (r *resolver) walkExprs(list []ast.Expr) {
226 for _, node := range list {
227 ast.Walk(r, node)
228 }
229 }
230
231 func (r *resolver) walkLHS(list []ast.Expr) {
232 for _, expr := range list {
233 expr := unparen(expr)
234 if _, ok := expr.(*ast.Ident); !ok && expr != nil {
235 ast.Walk(r, expr)
236 }
237 }
238 }
239
240 func (r *resolver) walkStmts(list []ast.Stmt) {
241 for _, stmt := range list {
242 ast.Walk(r, stmt)
243 }
244 }
245
246 func (r *resolver) Visit(node ast.Node) ast.Visitor {
247 if debugResolve && node != nil {
248 r.trace("node %T@%v", node, node.Pos())
249 }
250
251 switch n := node.(type) {
252
253
254 case *ast.Ident:
255 r.resolve(n, true)
256
257 case *ast.FuncLit:
258 r.openScope(n.Pos())
259 defer r.closeScope()
260 r.walkFuncType(n.Type)
261 r.walkBody(n.Body)
262
263 case *ast.SelectorExpr:
264 ast.Walk(r, n.X)
265
266
267
268 case *ast.StructType:
269 r.openScope(n.Pos())
270 defer r.closeScope()
271 r.walkFieldList(n.Fields, ast.Var)
272
273 case *ast.FuncType:
274 r.openScope(n.Pos())
275 defer r.closeScope()
276 r.walkFuncType(n)
277
278 case *ast.CompositeLit:
279 if n.Type != nil {
280 ast.Walk(r, n.Type)
281 }
282 for _, e := range n.Elts {
283 if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
284
285
286
287 if ident, _ := kv.Key.(*ast.Ident); ident != nil {
288 r.resolve(ident, false)
289 } else {
290 ast.Walk(r, kv.Key)
291 }
292 ast.Walk(r, kv.Value)
293 } else {
294 ast.Walk(r, e)
295 }
296 }
297
298 case *ast.InterfaceType:
299 r.openScope(n.Pos())
300 defer r.closeScope()
301 r.walkFieldList(n.Methods, ast.Fun)
302
303
304 case *ast.LabeledStmt:
305 r.declare(n, nil, r.labelScope, ast.Lbl, n.Label)
306 ast.Walk(r, n.Stmt)
307
308 case *ast.AssignStmt:
309 r.walkExprs(n.Rhs)
310 if n.Tok == token.DEFINE {
311 r.shortVarDecl(n)
312 } else {
313 r.walkExprs(n.Lhs)
314 }
315
316 case *ast.BranchStmt:
317
318 if n.Tok != token.FALLTHROUGH && n.Label != nil {
319 depth := len(r.targetStack) - 1
320 r.targetStack[depth] = append(r.targetStack[depth], n.Label)
321 }
322
323 case *ast.BlockStmt:
324 r.openScope(n.Pos())
325 defer r.closeScope()
326 r.walkStmts(n.List)
327
328 case *ast.IfStmt:
329 r.openScope(n.Pos())
330 defer r.closeScope()
331 if n.Init != nil {
332 ast.Walk(r, n.Init)
333 }
334 ast.Walk(r, n.Cond)
335 ast.Walk(r, n.Body)
336 if n.Else != nil {
337 ast.Walk(r, n.Else)
338 }
339
340 case *ast.CaseClause:
341 r.walkExprs(n.List)
342 r.openScope(n.Pos())
343 defer r.closeScope()
344 r.walkStmts(n.Body)
345
346 case *ast.SwitchStmt:
347 r.openScope(n.Pos())
348 defer r.closeScope()
349 if n.Init != nil {
350 ast.Walk(r, n.Init)
351 }
352 if n.Tag != nil {
353
354
355
356
357 if n.Init != nil {
358 r.openScope(n.Tag.Pos())
359 defer r.closeScope()
360 }
361 ast.Walk(r, n.Tag)
362 }
363 if n.Body != nil {
364 r.walkStmts(n.Body.List)
365 }
366
367 case *ast.TypeSwitchStmt:
368 if n.Init != nil {
369 r.openScope(n.Pos())
370 defer r.closeScope()
371 ast.Walk(r, n.Init)
372 }
373 r.openScope(n.Assign.Pos())
374 defer r.closeScope()
375 ast.Walk(r, n.Assign)
376
377
378 if n.Body != nil {
379 r.walkStmts(n.Body.List)
380 }
381
382 case *ast.CommClause:
383 r.openScope(n.Pos())
384 defer r.closeScope()
385 if n.Comm != nil {
386 ast.Walk(r, n.Comm)
387 }
388 r.walkStmts(n.Body)
389
390 case *ast.SelectStmt:
391
392
393 if n.Body != nil {
394 r.walkStmts(n.Body.List)
395 }
396
397 case *ast.ForStmt:
398 r.openScope(n.Pos())
399 defer r.closeScope()
400 if n.Init != nil {
401 ast.Walk(r, n.Init)
402 }
403 if n.Cond != nil {
404 ast.Walk(r, n.Cond)
405 }
406 if n.Post != nil {
407 ast.Walk(r, n.Post)
408 }
409 ast.Walk(r, n.Body)
410
411 case *ast.RangeStmt:
412 r.openScope(n.Pos())
413 defer r.closeScope()
414 ast.Walk(r, n.X)
415 var lhs []ast.Expr
416 if n.Key != nil {
417 lhs = append(lhs, n.Key)
418 }
419 if n.Value != nil {
420 lhs = append(lhs, n.Value)
421 }
422 if len(lhs) > 0 {
423 if n.Tok == token.DEFINE {
424
425
426
427
428 as := &ast.AssignStmt{
429 Lhs: lhs,
430 Tok: token.DEFINE,
431 TokPos: n.TokPos,
432 Rhs: []ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}},
433 }
434
435
436
437 r.walkLHS(lhs)
438 r.shortVarDecl(as)
439 } else {
440 r.walkExprs(lhs)
441 }
442 }
443 ast.Walk(r, n.Body)
444
445
446 case *ast.GenDecl:
447 switch n.Tok {
448 case token.CONST, token.VAR:
449 for i, spec := range n.Specs {
450 spec := spec.(*ast.ValueSpec)
451 kind := ast.Con
452 if n.Tok == token.VAR {
453 kind = ast.Var
454 }
455 r.walkExprs(spec.Values)
456 if spec.Type != nil {
457 ast.Walk(r, spec.Type)
458 }
459 r.declare(spec, i, r.topScope, kind, spec.Names...)
460 }
461 case token.TYPE:
462 for _, spec := range n.Specs {
463 spec := spec.(*ast.TypeSpec)
464
465
466
467 r.declare(spec, nil, r.topScope, ast.Typ, spec.Name)
468 if spec.TypeParams != nil {
469 r.openScope(spec.Pos())
470 defer r.closeScope()
471 r.walkTParams(spec.TypeParams)
472 }
473 ast.Walk(r, spec.Type)
474 }
475 }
476
477 case *ast.FuncDecl:
478
479 r.openScope(n.Pos())
480 defer r.closeScope()
481
482 r.walkRecv(n.Recv)
483
484
485
486 if n.Type.TypeParams != nil {
487 r.walkTParams(n.Type.TypeParams)
488
489 }
490
491
492
493 r.resolveList(n.Type.Params)
494 r.resolveList(n.Type.Results)
495 r.declareList(n.Recv, ast.Var)
496 r.declareList(n.Type.Params, ast.Var)
497 r.declareList(n.Type.Results, ast.Var)
498
499 r.walkBody(n.Body)
500 if n.Recv == nil && n.Name.Name != "init" {
501 r.declare(n, nil, r.pkgScope, ast.Fun, n.Name)
502 }
503
504 default:
505 return r
506 }
507
508 return nil
509 }
510
511 func (r *resolver) walkFuncType(typ *ast.FuncType) {
512
513 r.resolveList(typ.Params)
514 r.resolveList(typ.Results)
515 r.declareList(typ.Params, ast.Var)
516 r.declareList(typ.Results, ast.Var)
517 }
518
519 func (r *resolver) resolveList(list *ast.FieldList) {
520 if list == nil {
521 return
522 }
523 for _, f := range list.List {
524 if f.Type != nil {
525 ast.Walk(r, f.Type)
526 }
527 }
528 }
529
530 func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) {
531 if list == nil {
532 return
533 }
534 for _, f := range list.List {
535 r.declare(f, nil, r.topScope, kind, f.Names...)
536 }
537 }
538
539 func (r *resolver) walkRecv(recv *ast.FieldList) {
540
541
542
543 if recv == nil || len(recv.List) == 0 {
544 return
545 }
546 typ := recv.List[0].Type
547 if ptr, ok := typ.(*ast.StarExpr); ok {
548 typ = ptr.X
549 }
550
551 var declareExprs []ast.Expr
552 var resolveExprs []ast.Expr
553 switch typ := typ.(type) {
554 case *ast.IndexExpr:
555 declareExprs = []ast.Expr{typ.Index}
556 resolveExprs = append(resolveExprs, typ.X)
557 case *ast.IndexListExpr:
558 declareExprs = typ.Indices
559 resolveExprs = append(resolveExprs, typ.X)
560 default:
561 resolveExprs = append(resolveExprs, typ)
562 }
563 for _, expr := range declareExprs {
564 if id, _ := expr.(*ast.Ident); id != nil {
565 r.declare(expr, nil, r.topScope, ast.Typ, id)
566 } else {
567
568
569 resolveExprs = append(resolveExprs, expr)
570 }
571 }
572 for _, expr := range resolveExprs {
573 if expr != nil {
574 ast.Walk(r, expr)
575 }
576 }
577
578 for _, f := range recv.List[1:] {
579 if f.Type != nil {
580 ast.Walk(r, f.Type)
581 }
582 }
583 }
584
585 func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {
586 if list == nil {
587 return
588 }
589 r.resolveList(list)
590 r.declareList(list, kind)
591 }
592
593
594
595
596 func (r *resolver) walkTParams(list *ast.FieldList) {
597 r.declareList(list, ast.Typ)
598 r.resolveList(list)
599 }
600
601 func (r *resolver) walkBody(body *ast.BlockStmt) {
602 if body == nil {
603 return
604 }
605 r.openLabelScope()
606 defer r.closeLabelScope()
607 r.walkStmts(body.List)
608 }
609
View as plain text