1
2
3
4
5
6
7 package ast
8
9 import (
10 "bytes"
11 "fmt"
12 "go/token"
13 )
14
15
16
17
18
19 type Scope struct {
20 Outer *Scope
21 Objects map[string]*Object
22 }
23
24
25 func NewScope(outer *Scope) *Scope {
26 const n = 4
27 return &Scope{outer, make(map[string]*Object, n)}
28 }
29
30
31
32
33
34 func (s *Scope) Lookup(name string) *Object {
35 return s.Objects[name]
36 }
37
38
39
40
41
42
43 func (s *Scope) Insert(obj *Object) (alt *Object) {
44 if alt = s.Objects[obj.Name]; alt == nil {
45 s.Objects[obj.Name] = obj
46 }
47 return
48 }
49
50
51 func (s *Scope) String() string {
52 var buf bytes.Buffer
53 fmt.Fprintf(&buf, "scope %p {", s)
54 if s != nil && len(s.Objects) > 0 {
55 fmt.Fprintln(&buf)
56 for _, obj := range s.Objects {
57 fmt.Fprintf(&buf, "\t%s %s\n", obj.Kind, obj.Name)
58 }
59 }
60 fmt.Fprintf(&buf, "}\n")
61 return buf.String()
62 }
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 type Object struct {
81 Kind ObjKind
82 Name string
83 Decl interface{}
84 Data interface{}
85 Type interface{}
86 }
87
88
89 func NewObj(kind ObjKind, name string) *Object {
90 return &Object{Kind: kind, Name: name}
91 }
92
93
94
95
96 func (obj *Object) Pos() token.Pos {
97 name := obj.Name
98 switch d := obj.Decl.(type) {
99 case *Field:
100 for _, n := range d.Names {
101 if n.Name == name {
102 return n.Pos()
103 }
104 }
105 case *ImportSpec:
106 if d.Name != nil && d.Name.Name == name {
107 return d.Name.Pos()
108 }
109 return d.Path.Pos()
110 case *ValueSpec:
111 for _, n := range d.Names {
112 if n.Name == name {
113 return n.Pos()
114 }
115 }
116 case *TypeSpec:
117 if d.Name.Name == name {
118 return d.Name.Pos()
119 }
120 case *FuncDecl:
121 if d.Name.Name == name {
122 return d.Name.Pos()
123 }
124 case *LabeledStmt:
125 if d.Label.Name == name {
126 return d.Label.Pos()
127 }
128 }
129 return token.NoPos
130 }
131
132
133 type ObjKind int
134
135
136 const (
137 Bad ObjKind = iota
138 Pkg
139 Con
140 Typ
141 Var
142 Fun
143 Lbl
144 )
145
146 var objKindStrings = [...]string{
147 Bad: "bad",
148 Pkg: "package",
149 Con: "const",
150 Typ: "type",
151 Var: "var",
152 Fun: "func",
153 Lbl: "label",
154 }
155
156 func (kind ObjKind) String() string { return objKindStrings[kind] }