| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // This file implements scopes, the objects they contain, |
| // and object types. |
| |
| package ast |
| |
| // A Scope maintains the set of named language entities declared |
| // in the scope and a link to the immediately surrounding (outer) |
| // scope. |
| // |
| type Scope struct { |
| Outer *Scope |
| Objects []*Object // in declaration order |
| // Implementation note: In some cases (struct fields, |
| // function parameters) we need the source order of |
| // variables. Thus for now, we store scope entries |
| // in a linear list. If scopes become very large |
| // (say, for packages), we may need to change this |
| // to avoid slow lookups. |
| } |
| |
| |
| // NewScope creates a new scope nested in the outer scope. |
| func NewScope(outer *Scope) *Scope { |
| const n = 4 // initial scope capacity, must be > 0 |
| return &Scope{outer, make([]*Object, 0, n)} |
| } |
| |
| |
| // Lookup returns the object with the given name if it is |
| // found in scope s, otherwise it returns nil. Outer scopes |
| // are ignored. |
| // |
| // Lookup always returns nil if name is "_", even if the scope |
| // contains objects with that name. |
| // |
| func (s *Scope) Lookup(name string) *Object { |
| if name != "_" { |
| for _, obj := range s.Objects { |
| if obj.Name == name { |
| return obj |
| } |
| } |
| } |
| return nil |
| } |
| |
| |
| // Insert attempts to insert a named object into the scope s. |
| // If the scope does not contain an object with that name yet |
| // or if the object is named "_", Insert inserts the object |
| // and returns it. Otherwise, Insert leaves the scope unchanged |
| // and returns the object found in the scope instead. |
| // |
| func (s *Scope) Insert(obj *Object) *Object { |
| alt := s.Lookup(obj.Name) |
| if alt == nil { |
| s.append(obj) |
| alt = obj |
| } |
| return alt |
| } |
| |
| |
| func (s *Scope) append(obj *Object) { |
| n := len(s.Objects) |
| if n >= cap(s.Objects) { |
| new := make([]*Object, 2*n) |
| copy(new, s.Objects) |
| s.Objects = new |
| } |
| s.Objects = s.Objects[0 : n+1] |
| s.Objects[n] = obj |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Objects |
| |
| // An Object describes a language entity such as a package, |
| // constant, type, variable, or function (incl. methods). |
| // |
| type Object struct { |
| Kind Kind |
| Name string // declared name |
| Type *Type |
| Decl interface{} // corresponding Field, XxxSpec or FuncDecl |
| N int // value of iota for this declaration |
| } |
| |
| |
| // NewObj creates a new object of a given kind and name. |
| func NewObj(kind Kind, name string) *Object { |
| return &Object{Kind: kind, Name: name} |
| } |
| |
| |
| // Kind describes what an object represents. |
| type Kind int |
| |
| // The list of possible Object kinds. |
| const ( |
| Bad Kind = iota // for error handling |
| Pkg // package |
| Con // constant |
| Typ // type |
| Var // variable |
| Fun // function or method |
| ) |
| |
| |
| var objKindStrings = [...]string{ |
| Bad: "bad", |
| Pkg: "package", |
| Con: "const", |
| Typ: "type", |
| Var: "var", |
| Fun: "func", |
| } |
| |
| |
| func (kind Kind) String() string { return objKindStrings[kind] } |
| |
| |
| // IsExported returns whether obj is exported. |
| func (obj *Object) IsExported() bool { return IsExported(obj.Name) } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Types |
| |
| // A Type represents a Go type. |
| type Type struct { |
| Form Form |
| Obj *Object // corresponding type name, or nil |
| Scope *Scope // fields and methods, always present |
| N uint // basic type id, array length, number of function results, or channel direction |
| Key, Elt *Type // map key and array, pointer, slice, map or channel element |
| Params *Scope // function (receiver, input and result) parameters, tuple expressions (results of function calls), or nil |
| Expr Expr // corresponding AST expression |
| } |
| |
| |
| // NewType creates a new type of a given form. |
| func NewType(form Form) *Type { |
| return &Type{Form: form, Scope: NewScope(nil)} |
| } |
| |
| |
| // Form describes the form of a type. |
| type Form int |
| |
| // The list of possible type forms. |
| const ( |
| BadType Form = iota // for error handling |
| Unresolved // type not fully setup |
| Basic |
| Array |
| Struct |
| Pointer |
| Function |
| Method |
| Interface |
| Slice |
| Map |
| Channel |
| Tuple |
| ) |
| |
| |
| var formStrings = [...]string{ |
| BadType: "badType", |
| Unresolved: "unresolved", |
| Basic: "basic", |
| Array: "array", |
| Struct: "struct", |
| Pointer: "pointer", |
| Function: "function", |
| Method: "method", |
| Interface: "interface", |
| Slice: "slice", |
| Map: "map", |
| Channel: "channel", |
| Tuple: "tuple", |
| } |
| |
| |
| func (form Form) String() string { return formStrings[form] } |
| |
| |
| // The list of basic type id's. |
| const ( |
| Bool = iota |
| Byte |
| Uint |
| Int |
| Float |
| Complex |
| Uintptr |
| String |
| |
| Uint8 |
| Uint16 |
| Uint32 |
| Uint64 |
| |
| Int8 |
| Int16 |
| Int32 |
| Int64 |
| |
| Float32 |
| Float64 |
| |
| Complex64 |
| Complex128 |
| |
| // TODO(gri) ideal types are missing |
| ) |
| |
| |
| var BasicTypes = map[uint]string{ |
| Bool: "bool", |
| Byte: "byte", |
| Uint: "uint", |
| Int: "int", |
| Float: "float", |
| Complex: "complex", |
| Uintptr: "uintptr", |
| String: "string", |
| |
| Uint8: "uint8", |
| Uint16: "uint16", |
| Uint32: "uint32", |
| Uint64: "uint64", |
| |
| Int8: "int8", |
| Int16: "int16", |
| Int32: "int32", |
| Int64: "int64", |
| |
| Float32: "float32", |
| Float64: "float64", |
| |
| Complex64: "complex64", |
| Complex128: "complex128", |
| } |