Source file src/cmd/compile/internal/types2/universe.go

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

View as plain text