Links

4.4.1 数据结构 - 作用域

作用域是编程语言的一个重要课题,go 语言采用的是静态作用域,即词法作用域。在编译器内部,根据作用域范围从大到小将其划分为:
  1. 1.
    全局作用域,该作用域内的对象在任何地方都可以访问,编译器中叫 Universe
  2. 2.
    包作用域
  3. 3.
    文件作用域,该作用域只在编译器内部使用,语言层面没有体现
  4. 4.
    块作用域,简单说即 {} 包围起来的代码片段,例如函数体、控制语句块(例如 if, for 等内部)
编译器采用树形结构来管理作用域,对应的数据结构定义在文件 $GCROOT/compile/internal/types2/scope.go 中:
type Scope struct {
parent *Scope // 当前作用域的父作用域
children []*Scope // 当前作用域的子作用域
elems map[string]Object // 当前作用域所包含的符号对象,key 是符号名称
pos, end syntax.Pos // 作用域位置信息
comment string // for debugging only
isFunc bool // set if this is a function scope (internal use only)
}
Scope 定义了插入与查找符号的方法:
func (s *Scope) Lookup(name string) Object { /* 忽略函数体 */ }
func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) { /* 忽略函数体 */ }
func (s *Scope) Insert(obj Object) Object { /* 忽略函数体 */ }
Lookup 仅在本作用域内查找符号, LookupParent 则从当前作用域开始,顺着父作用域一直查找,这两个方法是进行符号解析的 API。 elems 用来存放当前作用域内名字到符号对象的映射,符号对象是实现了 Object 接口的结构,在后续会专门介绍。