| // Copyright 2011 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 the universe and unsafe package scopes. |
| |
| package types |
| |
| import ( |
| "go/ast" |
| "strings" |
| |
| constants "code.google.com/p/go.exp/go/types/constant" |
| ) |
| |
| var ( |
| Universe *Scope |
| Unsafe *Package |
| universeIota *Const |
| ) |
| |
| // Predeclared types, indexed by BasicKind. |
| var Typ = [...]*Basic{ |
| Invalid: {Invalid, 0, 0, "invalid type"}, |
| |
| Bool: {Bool, IsBoolean, 1, "bool"}, |
| Int: {Int, IsInteger, 0, "int"}, |
| Int8: {Int8, IsInteger, 1, "int8"}, |
| Int16: {Int16, IsInteger, 2, "int16"}, |
| Int32: {Int32, IsInteger, 4, "int32"}, |
| Int64: {Int64, IsInteger, 8, "int64"}, |
| Uint: {Uint, IsInteger | IsUnsigned, 0, "uint"}, |
| Uint8: {Uint8, IsInteger | IsUnsigned, 1, "uint8"}, |
| Uint16: {Uint16, IsInteger | IsUnsigned, 2, "uint16"}, |
| Uint32: {Uint32, IsInteger | IsUnsigned, 4, "uint32"}, |
| Uint64: {Uint64, IsInteger | IsUnsigned, 8, "uint64"}, |
| Uintptr: {Uintptr, IsInteger | IsUnsigned, 0, "uintptr"}, |
| Float32: {Float32, IsFloat, 4, "float32"}, |
| Float64: {Float64, IsFloat, 8, "float64"}, |
| Complex64: {Complex64, IsComplex, 8, "complex64"}, |
| Complex128: {Complex128, IsComplex, 16, "complex128"}, |
| String: {String, IsString, 0, "string"}, |
| UnsafePointer: {UnsafePointer, 0, 0, "Pointer"}, |
| |
| UntypedBool: {UntypedBool, IsBoolean | IsUntyped, 0, "untyped boolean"}, |
| UntypedInt: {UntypedInt, IsInteger | IsUntyped, 0, "untyped integer"}, |
| UntypedRune: {UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"}, |
| UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"}, |
| UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"}, |
| UntypedString: {UntypedString, IsString | IsUntyped, 0, "untyped string"}, |
| UntypedNil: {UntypedNil, IsUntyped, 0, "untyped nil"}, |
| } |
| |
| var aliases = [...]*Basic{ |
| {Byte, IsInteger | IsUnsigned, 1, "byte"}, |
| {Rune, IsInteger, 4, "rune"}, |
| } |
| |
| var predeclaredConstants = [...]*Const{ |
| {Name: "true", Type: Typ[UntypedBool], Val: constants.MakeBool(true)}, |
| {Name: "false", Type: Typ[UntypedBool], Val: constants.MakeBool(false)}, |
| {Name: "iota", Type: Typ[UntypedInt], Val: constants.MakeInt64(0)}, |
| {Name: "nil", Type: Typ[UntypedNil], Val: constants.MakeNil()}, |
| } |
| |
| var predeclaredFunctions = [...]*builtin{ |
| {_Append, "append", 1, true, false}, |
| {_Cap, "cap", 1, false, false}, |
| {_Close, "close", 1, false, true}, |
| {_Complex, "complex", 2, false, false}, |
| {_Copy, "copy", 2, false, true}, |
| {_Delete, "delete", 2, false, true}, |
| {_Imag, "imag", 1, false, false}, |
| {_Len, "len", 1, false, false}, |
| {_Make, "make", 1, true, false}, |
| {_New, "new", 1, false, false}, |
| {_Panic, "panic", 1, false, true}, |
| {_Print, "print", 0, true, true}, |
| {_Println, "println", 0, true, true}, |
| {_Real, "real", 1, false, false}, |
| {_Recover, "recover", 0, false, true}, |
| |
| {_Alignof, "Alignof", 1, false, false}, |
| {_Offsetof, "Offsetof", 1, false, false}, |
| {_Sizeof, "Sizeof", 1, false, false}, |
| } |
| |
| func init() { |
| Universe = new(Scope) |
| Unsafe = &Package{Name: "unsafe", Scope: new(Scope)} |
| |
| // predeclared types |
| for _, t := range Typ { |
| def(&TypeName{Name: t.Name, Type: t}) |
| } |
| for _, t := range aliases { |
| def(&TypeName{Name: t.Name, Type: t}) |
| } |
| |
| // error type |
| { |
| // Error has a nil package in its qualified name since it is in no package |
| err := &Method{QualifiedName{nil, "Error"}, &Signature{Results: []*Var{{Name: "", Type: Typ[String]}}}} |
| def(&TypeName{Name: "error", Type: &NamedType{Underlying: &Interface{Methods: []*Method{err}}}}) |
| } |
| |
| for _, c := range predeclaredConstants { |
| def(c) |
| } |
| |
| for _, f := range predeclaredFunctions { |
| def(&Func{Name: f.name, Type: f}) |
| } |
| |
| universeIota = Universe.Lookup("iota").(*Const) |
| } |
| |
| // Objects with names containing blanks are internal and not entered into |
| // a scope. Objects with exported names are inserted in the unsafe package |
| // scope; other objects are inserted in the universe scope. |
| // |
| func def(obj Object) { |
| name := obj.GetName() |
| if strings.Index(name, " ") >= 0 { |
| return // nothing to do |
| } |
| // fix Obj link for named types |
| if typ, ok := obj.GetType().(*NamedType); ok { |
| typ.Obj = obj.(*TypeName) |
| } |
| // exported identifiers go into package unsafe |
| scope := Universe |
| if ast.IsExported(name) { |
| scope = Unsafe.Scope |
| // set Pkg field |
| switch obj := obj.(type) { |
| case *TypeName: |
| obj.Pkg = Unsafe |
| case *Func: |
| obj.Pkg = Unsafe |
| default: |
| unreachable() |
| } |
| } |
| if scope.Insert(obj) != nil { |
| panic("internal error: double declaration") |
| } |
| } |