Black Lives Matter. Support the Equal Justice Initiative.

Source file src/go/types/universe.go

Documentation: go/types

     1  // Copyright 2011 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 sets up the universe scope and the unsafe package.
     6  
     7  package types
     8  
     9  import (
    10  	"go/constant"
    11  	"go/internal/typeparams"
    12  	"go/token"
    13  	"strings"
    14  )
    15  
    16  // The Universe scope contains all predeclared objects of Go.
    17  // It is the outermost scope of any chain of nested scopes.
    18  var Universe *Scope
    19  
    20  // The Unsafe package is the package returned by an importer
    21  // for the import path "unsafe".
    22  var Unsafe *Package
    23  
    24  var (
    25  	universeIota  *Const
    26  	universeByte  *Basic // uint8 alias, but has name "byte"
    27  	universeRune  *Basic // int32 alias, but has name "rune"
    28  	universeAny   *Interface
    29  	universeError *Named
    30  )
    31  
    32  // Typ contains the predeclared *Basic types indexed by their
    33  // corresponding BasicKind.
    34  //
    35  // The *Basic type for Typ[Byte] will have the name "uint8".
    36  // Use Universe.Lookup("byte").Type() to obtain the specific
    37  // alias basic type named "byte" (and analogous for "rune").
    38  var Typ = []*Basic{
    39  	Invalid: {Invalid, 0, "invalid type"},
    40  
    41  	Bool:          {Bool, IsBoolean, "bool"},
    42  	Int:           {Int, IsInteger, "int"},
    43  	Int8:          {Int8, IsInteger, "int8"},
    44  	Int16:         {Int16, IsInteger, "int16"},
    45  	Int32:         {Int32, IsInteger, "int32"},
    46  	Int64:         {Int64, IsInteger, "int64"},
    47  	Uint:          {Uint, IsInteger | IsUnsigned, "uint"},
    48  	Uint8:         {Uint8, IsInteger | IsUnsigned, "uint8"},
    49  	Uint16:        {Uint16, IsInteger | IsUnsigned, "uint16"},
    50  	Uint32:        {Uint32, IsInteger | IsUnsigned, "uint32"},
    51  	Uint64:        {Uint64, IsInteger | IsUnsigned, "uint64"},
    52  	Uintptr:       {Uintptr, IsInteger | IsUnsigned, "uintptr"},
    53  	Float32:       {Float32, IsFloat, "float32"},
    54  	Float64:       {Float64, IsFloat, "float64"},
    55  	Complex64:     {Complex64, IsComplex, "complex64"},
    56  	Complex128:    {Complex128, IsComplex, "complex128"},
    57  	String:        {String, IsString, "string"},
    58  	UnsafePointer: {UnsafePointer, 0, "Pointer"},
    59  
    60  	UntypedBool:    {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
    61  	UntypedInt:     {UntypedInt, IsInteger | IsUntyped, "untyped int"},
    62  	UntypedRune:    {UntypedRune, IsInteger | IsUntyped, "untyped rune"},
    63  	UntypedFloat:   {UntypedFloat, IsFloat | IsUntyped, "untyped float"},
    64  	UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"},
    65  	UntypedString:  {UntypedString, IsString | IsUntyped, "untyped string"},
    66  	UntypedNil:     {UntypedNil, IsUntyped, "untyped nil"},
    67  }
    68  
    69  var aliases = [...]*Basic{
    70  	{Byte, IsInteger | IsUnsigned, "byte"},
    71  	{Rune, IsInteger, "rune"},
    72  }
    73  
    74  func defPredeclaredTypes() {
    75  	for _, t := range Typ {
    76  		def(NewTypeName(token.NoPos, nil, t.name, t))
    77  	}
    78  	for _, t := range aliases {
    79  		def(NewTypeName(token.NoPos, nil, t.name, t))
    80  	}
    81  
    82  	// any
    83  	// (Predeclared and entered into universe scope so we do all the
    84  	// usual checks; but removed again from scope later since it's
    85  	// only visible as constraint in a type parameter list.)
    86  	def(NewTypeName(token.NoPos, nil, "any", &emptyInterface))
    87  
    88  	// Error has a nil package in its qualified name since it is in no package
    89  	{
    90  		res := NewVar(token.NoPos, nil, "", Typ[String])
    91  		sig := &Signature{results: NewTuple(res)}
    92  		err := NewFunc(token.NoPos, nil, "Error", sig)
    93  		typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()}
    94  		sig.recv = NewVar(token.NoPos, nil, "", typ)
    95  		def(NewTypeName(token.NoPos, nil, "error", typ))
    96  	}
    97  }
    98  
    99  var predeclaredConsts = [...]struct {
   100  	name string
   101  	kind BasicKind
   102  	val  constant.Value
   103  }{
   104  	{"true", UntypedBool, constant.MakeBool(true)},
   105  	{"false", UntypedBool, constant.MakeBool(false)},
   106  	{"iota", UntypedInt, constant.MakeInt64(0)},
   107  }
   108  
   109  func defPredeclaredConsts() {
   110  	for _, c := range predeclaredConsts {
   111  		def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val))
   112  	}
   113  }
   114  
   115  func defPredeclaredNil() {
   116  	def(&Nil{object{name: "nil", typ: Typ[UntypedNil], color_: black}})
   117  }
   118  
   119  // A builtinId is the id of a builtin function.
   120  type builtinId int
   121  
   122  const (
   123  	// universe scope
   124  	_Append builtinId = iota
   125  	_Cap
   126  	_Close
   127  	_Complex
   128  	_Copy
   129  	_Delete
   130  	_Imag
   131  	_Len
   132  	_Make
   133  	_New
   134  	_Panic
   135  	_Print
   136  	_Println
   137  	_Real
   138  	_Recover
   139  
   140  	// package unsafe
   141  	_Add
   142  	_Alignof
   143  	_Offsetof
   144  	_Sizeof
   145  	_Slice
   146  
   147  	// testing support
   148  	_Assert
   149  	_Trace
   150  )
   151  
   152  var predeclaredFuncs = [...]struct {
   153  	name     string
   154  	nargs    int
   155  	variadic bool
   156  	kind     exprKind
   157  }{
   158  	_Append:  {"append", 1, true, expression},
   159  	_Cap:     {"cap", 1, false, expression},
   160  	_Close:   {"close", 1, false, statement},
   161  	_Complex: {"complex", 2, false, expression},
   162  	_Copy:    {"copy", 2, false, statement},
   163  	_Delete:  {"delete", 2, false, statement},
   164  	_Imag:    {"imag", 1, false, expression},
   165  	_Len:     {"len", 1, false, expression},
   166  	_Make:    {"make", 1, true, expression},
   167  	_New:     {"new", 1, false, expression},
   168  	_Panic:   {"panic", 1, false, statement},
   169  	_Print:   {"print", 0, true, statement},
   170  	_Println: {"println", 0, true, statement},
   171  	_Real:    {"real", 1, false, expression},
   172  	_Recover: {"recover", 0, false, statement},
   173  
   174  	_Add:      {"Add", 2, false, expression},
   175  	_Alignof:  {"Alignof", 1, false, expression},
   176  	_Offsetof: {"Offsetof", 1, false, expression},
   177  	_Sizeof:   {"Sizeof", 1, false, expression},
   178  	_Slice:    {"Slice", 2, false, expression},
   179  
   180  	_Assert: {"assert", 1, false, statement},
   181  	_Trace:  {"trace", 0, true, statement},
   182  }
   183  
   184  func defPredeclaredFuncs() {
   185  	for i := range predeclaredFuncs {
   186  		id := builtinId(i)
   187  		if id == _Assert || id == _Trace {
   188  			continue // only define these in testing environment
   189  		}
   190  		def(newBuiltin(id))
   191  	}
   192  }
   193  
   194  // DefPredeclaredTestFuncs defines the assert and trace built-ins.
   195  // These built-ins are intended for debugging and testing of this
   196  // package only.
   197  func DefPredeclaredTestFuncs() {
   198  	if Universe.Lookup("assert") != nil {
   199  		return // already defined
   200  	}
   201  	def(newBuiltin(_Assert))
   202  	def(newBuiltin(_Trace))
   203  }
   204  
   205  func defPredeclaredComparable() {
   206  	// The "comparable" interface can be imagined as defined like
   207  	//
   208  	// type comparable interface {
   209  	//         == () untyped bool
   210  	//         != () untyped bool
   211  	// }
   212  	//
   213  	// == and != cannot be user-declared but we can declare
   214  	// a magic method == and check for its presence when needed.
   215  
   216  	// Define interface { == () }. We don't care about the signature
   217  	// for == so leave it empty except for the receiver, which is
   218  	// set up later to match the usual interface method assumptions.
   219  	sig := new(Signature)
   220  	eql := NewFunc(token.NoPos, nil, "==", sig)
   221  	iface := NewInterfaceType([]*Func{eql}, nil).Complete()
   222  
   223  	// set up the defined type for the interface
   224  	obj := NewTypeName(token.NoPos, nil, "comparable", nil)
   225  	named := NewNamed(obj, iface, nil)
   226  	obj.color_ = black
   227  	sig.recv = NewVar(token.NoPos, nil, "", named) // complete == signature
   228  
   229  	def(obj)
   230  }
   231  
   232  func init() {
   233  	Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
   234  	Unsafe = NewPackage("unsafe", "unsafe")
   235  	Unsafe.complete = true
   236  
   237  	defPredeclaredTypes()
   238  	defPredeclaredConsts()
   239  	defPredeclaredNil()
   240  	defPredeclaredFuncs()
   241  	if typeparams.Enabled {
   242  		defPredeclaredComparable()
   243  	}
   244  
   245  	universeIota = Universe.Lookup("iota").(*Const)
   246  	universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
   247  	universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
   248  	universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
   249  	universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)
   250  
   251  	// "any" is only visible as constraint in a type parameter list
   252  	delete(Universe.elems, "any")
   253  }
   254  
   255  // Objects with names containing blanks are internal and not entered into
   256  // a scope. Objects with exported names are inserted in the unsafe package
   257  // scope; other objects are inserted in the universe scope.
   258  //
   259  func def(obj Object) {
   260  	assert(obj.color() == black)
   261  	name := obj.Name()
   262  	if strings.Contains(name, " ") {
   263  		return // nothing to do
   264  	}
   265  	// fix Obj link for named types
   266  	if typ := asNamed(obj.Type()); typ != nil {
   267  		typ.obj = obj.(*TypeName)
   268  	}
   269  	// exported identifiers go into package unsafe
   270  	scope := Universe
   271  	if obj.Exported() {
   272  		scope = Unsafe.scope
   273  		// set Pkg field
   274  		switch obj := obj.(type) {
   275  		case *TypeName:
   276  			obj.pkg = Unsafe
   277  		case *Builtin:
   278  			obj.pkg = Unsafe
   279  		default:
   280  			unreachable()
   281  		}
   282  	}
   283  	if scope.Insert(obj) != nil {
   284  		panic("internal error: double declaration")
   285  	}
   286  }
   287  

View as plain text