~ubuntu-branches/ubuntu/utopic/gccgo-go/utopic

« back to all changes in this revision

Viewing changes to src/pkg/go/ast/scope.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-27 09:18:55 UTC
  • Revision ID: package-import@ubuntu.com-20140127091855-zxfshmykfsyyw4b2
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2009 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
// This file implements scopes and the objects they contain.
 
6
 
 
7
package ast
 
8
 
 
9
import (
 
10
        "bytes"
 
11
        "fmt"
 
12
        "go/token"
 
13
)
 
14
 
 
15
// A Scope maintains the set of named language entities declared
 
16
// in the scope and a link to the immediately surrounding (outer)
 
17
// scope.
 
18
//
 
19
type Scope struct {
 
20
        Outer   *Scope
 
21
        Objects map[string]*Object
 
22
}
 
23
 
 
24
// NewScope creates a new scope nested in the outer scope.
 
25
func NewScope(outer *Scope) *Scope {
 
26
        const n = 4 // initial scope capacity
 
27
        return &Scope{outer, make(map[string]*Object, n)}
 
28
}
 
29
 
 
30
// Lookup returns the object with the given name if it is
 
31
// found in scope s, otherwise it returns nil. Outer scopes
 
32
// are ignored.
 
33
//
 
34
func (s *Scope) Lookup(name string) *Object {
 
35
        return s.Objects[name]
 
36
}
 
37
 
 
38
// Insert attempts to insert a named object obj into the scope s.
 
39
// If the scope already contains an object alt with the same name,
 
40
// Insert leaves the scope unchanged and returns alt. Otherwise
 
41
// it inserts obj and returns nil."
 
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
// Debugging support
 
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
// Objects
 
66
 
 
67
// An Object describes a named language entity such as a package,
 
68
// constant, type, variable, function (incl. methods), or label.
 
69
//
 
70
// The Data fields contains object-specific data:
 
71
//
 
72
//      Kind    Data type         Data value
 
73
//      Pkg     *types.Package    package scope
 
74
//      Con     int               iota for the respective declaration
 
75
//      Con     != nil            constant value
 
76
//      Typ     *Scope            (used as method scope during type checking - transient)
 
77
//
 
78
type Object struct {
 
79
        Kind ObjKind
 
80
        Name string      // declared name
 
81
        Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil
 
82
        Data interface{} // object-specific data; or nil
 
83
        Type interface{} // place holder for type information; may be nil
 
84
}
 
85
 
 
86
// NewObj creates a new object of a given kind and name.
 
87
func NewObj(kind ObjKind, name string) *Object {
 
88
        return &Object{Kind: kind, Name: name}
 
89
}
 
90
 
 
91
// Pos computes the source position of the declaration of an object name.
 
92
// The result may be an invalid position if it cannot be computed
 
93
// (obj.Decl may be nil or not correct).
 
94
func (obj *Object) Pos() token.Pos {
 
95
        name := obj.Name
 
96
        switch d := obj.Decl.(type) {
 
97
        case *Field:
 
98
                for _, n := range d.Names {
 
99
                        if n.Name == name {
 
100
                                return n.Pos()
 
101
                        }
 
102
                }
 
103
        case *ImportSpec:
 
104
                if d.Name != nil && d.Name.Name == name {
 
105
                        return d.Name.Pos()
 
106
                }
 
107
                return d.Path.Pos()
 
108
        case *ValueSpec:
 
109
                for _, n := range d.Names {
 
110
                        if n.Name == name {
 
111
                                return n.Pos()
 
112
                        }
 
113
                }
 
114
        case *TypeSpec:
 
115
                if d.Name.Name == name {
 
116
                        return d.Name.Pos()
 
117
                }
 
118
        case *FuncDecl:
 
119
                if d.Name.Name == name {
 
120
                        return d.Name.Pos()
 
121
                }
 
122
        case *LabeledStmt:
 
123
                if d.Label.Name == name {
 
124
                        return d.Label.Pos()
 
125
                }
 
126
        case *AssignStmt:
 
127
                for _, x := range d.Lhs {
 
128
                        if ident, isIdent := x.(*Ident); isIdent && ident.Name == name {
 
129
                                return ident.Pos()
 
130
                        }
 
131
                }
 
132
        case *Scope:
 
133
                // predeclared object - nothing to do for now
 
134
        }
 
135
        return token.NoPos
 
136
}
 
137
 
 
138
// ObjKind describes what an object represents.
 
139
type ObjKind int
 
140
 
 
141
// The list of possible Object kinds.
 
142
const (
 
143
        Bad ObjKind = iota // for error handling
 
144
        Pkg                // package
 
145
        Con                // constant
 
146
        Typ                // type
 
147
        Var                // variable
 
148
        Fun                // function or method
 
149
        Lbl                // label
 
150
)
 
151
 
 
152
var objKindStrings = [...]string{
 
153
        Bad: "bad",
 
154
        Pkg: "package",
 
155
        Con: "const",
 
156
        Typ: "type",
 
157
        Var: "var",
 
158
        Fun: "func",
 
159
        Lbl: "label",
 
160
}
 
161
 
 
162
func (kind ObjKind) String() string { return objKindStrings[kind] }