Home | History | Annotate | Download | only in 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/token"
     12 	"strings"
     13 )
     14 
     15 var (
     16 	Universe     *Scope
     17 	Unsafe       *Package
     18 	universeIota *Const
     19 	universeByte *Basic // uint8 alias, but has name "byte"
     20 	universeRune *Basic // int32 alias, but has name "rune"
     21 )
     22 
     23 // Typ contains the predeclared *Basic types indexed by their
     24 // corresponding BasicKind.
     25 //
     26 // The *Basic type for Typ[Byte] will have the name "uint8".
     27 // Use Universe.Lookup("byte").Type() to obtain the specific
     28 // alias basic type named "byte" (and analogous for "rune").
     29 var Typ = []*Basic{
     30 	Invalid: {Invalid, 0, "invalid type"},
     31 
     32 	Bool:          {Bool, IsBoolean, "bool"},
     33 	Int:           {Int, IsInteger, "int"},
     34 	Int8:          {Int8, IsInteger, "int8"},
     35 	Int16:         {Int16, IsInteger, "int16"},
     36 	Int32:         {Int32, IsInteger, "int32"},
     37 	Int64:         {Int64, IsInteger, "int64"},
     38 	Uint:          {Uint, IsInteger | IsUnsigned, "uint"},
     39 	Uint8:         {Uint8, IsInteger | IsUnsigned, "uint8"},
     40 	Uint16:        {Uint16, IsInteger | IsUnsigned, "uint16"},
     41 	Uint32:        {Uint32, IsInteger | IsUnsigned, "uint32"},
     42 	Uint64:        {Uint64, IsInteger | IsUnsigned, "uint64"},
     43 	Uintptr:       {Uintptr, IsInteger | IsUnsigned, "uintptr"},
     44 	Float32:       {Float32, IsFloat, "float32"},
     45 	Float64:       {Float64, IsFloat, "float64"},
     46 	Complex64:     {Complex64, IsComplex, "complex64"},
     47 	Complex128:    {Complex128, IsComplex, "complex128"},
     48 	String:        {String, IsString, "string"},
     49 	UnsafePointer: {UnsafePointer, 0, "Pointer"},
     50 
     51 	UntypedBool:    {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
     52 	UntypedInt:     {UntypedInt, IsInteger | IsUntyped, "untyped int"},
     53 	UntypedRune:    {UntypedRune, IsInteger | IsUntyped, "untyped rune"},
     54 	UntypedFloat:   {UntypedFloat, IsFloat | IsUntyped, "untyped float"},
     55 	UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"},
     56 	UntypedString:  {UntypedString, IsString | IsUntyped, "untyped string"},
     57 	UntypedNil:     {UntypedNil, IsUntyped, "untyped nil"},
     58 }
     59 
     60 var aliases = [...]*Basic{
     61 	{Byte, IsInteger | IsUnsigned, "byte"},
     62 	{Rune, IsInteger, "rune"},
     63 }
     64 
     65 func defPredeclaredTypes() {
     66 	for _, t := range Typ {
     67 		def(NewTypeName(token.NoPos, nil, t.name, t))
     68 	}
     69 	for _, t := range aliases {
     70 		def(NewTypeName(token.NoPos, nil, t.name, t))
     71 	}
     72 
     73 	// Error has a nil package in its qualified name since it is in no package
     74 	res := NewVar(token.NoPos, nil, "", Typ[String])
     75 	sig := &Signature{results: NewTuple(res)}
     76 	err := NewFunc(token.NoPos, nil, "Error", sig)
     77 	typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()}
     78 	sig.recv = NewVar(token.NoPos, nil, "", typ)
     79 	def(NewTypeName(token.NoPos, nil, "error", typ))
     80 }
     81 
     82 var predeclaredConsts = [...]struct {
     83 	name string
     84 	kind BasicKind
     85 	val  constant.Value
     86 }{
     87 	{"true", UntypedBool, constant.MakeBool(true)},
     88 	{"false", UntypedBool, constant.MakeBool(false)},
     89 	{"iota", UntypedInt, constant.MakeInt64(0)},
     90 }
     91 
     92 func defPredeclaredConsts() {
     93 	for _, c := range predeclaredConsts {
     94 		def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val))
     95 	}
     96 }
     97 
     98 func defPredeclaredNil() {
     99 	def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}})
    100 }
    101 
    102 // A builtinId is the id of a builtin function.
    103 type builtinId int
    104 
    105 const (
    106 	// universe scope
    107 	_Append builtinId = iota
    108 	_Cap
    109 	_Close
    110 	_Complex
    111 	_Copy
    112 	_Delete
    113 	_Imag
    114 	_Len
    115 	_Make
    116 	_New
    117 	_Panic
    118 	_Print
    119 	_Println
    120 	_Real
    121 	_Recover
    122 
    123 	// package unsafe
    124 	_Alignof
    125 	_Offsetof
    126 	_Sizeof
    127 
    128 	// testing support
    129 	_Assert
    130 	_Trace
    131 )
    132 
    133 var predeclaredFuncs = [...]struct {
    134 	name     string
    135 	nargs    int
    136 	variadic bool
    137 	kind     exprKind
    138 }{
    139 	_Append:  {"append", 1, true, expression},
    140 	_Cap:     {"cap", 1, false, expression},
    141 	_Close:   {"close", 1, false, statement},
    142 	_Complex: {"complex", 2, false, expression},
    143 	_Copy:    {"copy", 2, false, statement},
    144 	_Delete:  {"delete", 2, false, statement},
    145 	_Imag:    {"imag", 1, false, expression},
    146 	_Len:     {"len", 1, false, expression},
    147 	_Make:    {"make", 1, true, expression},
    148 	_New:     {"new", 1, false, expression},
    149 	_Panic:   {"panic", 1, false, statement},
    150 	_Print:   {"print", 0, true, statement},
    151 	_Println: {"println", 0, true, statement},
    152 	_Real:    {"real", 1, false, expression},
    153 	_Recover: {"recover", 0, false, statement},
    154 
    155 	_Alignof:  {"Alignof", 1, false, expression},
    156 	_Offsetof: {"Offsetof", 1, false, expression},
    157 	_Sizeof:   {"Sizeof", 1, false, expression},
    158 
    159 	_Assert: {"assert", 1, false, statement},
    160 	_Trace:  {"trace", 0, true, statement},
    161 }
    162 
    163 func defPredeclaredFuncs() {
    164 	for i := range predeclaredFuncs {
    165 		id := builtinId(i)
    166 		if id == _Assert || id == _Trace {
    167 			continue // only define these in testing environment
    168 		}
    169 		def(newBuiltin(id))
    170 	}
    171 }
    172 
    173 // DefPredeclaredTestFuncs defines the assert and trace built-ins.
    174 // These built-ins are intended for debugging and testing of this
    175 // package only.
    176 func DefPredeclaredTestFuncs() {
    177 	if Universe.Lookup("assert") != nil {
    178 		return // already defined
    179 	}
    180 	def(newBuiltin(_Assert))
    181 	def(newBuiltin(_Trace))
    182 }
    183 
    184 func init() {
    185 	Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
    186 	Unsafe = NewPackage("unsafe", "unsafe")
    187 	Unsafe.complete = true
    188 
    189 	defPredeclaredTypes()
    190 	defPredeclaredConsts()
    191 	defPredeclaredNil()
    192 	defPredeclaredFuncs()
    193 
    194 	universeIota = Universe.Lookup("iota").(*Const)
    195 	universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
    196 	universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
    197 }
    198 
    199 // Objects with names containing blanks are internal and not entered into
    200 // a scope. Objects with exported names are inserted in the unsafe package
    201 // scope; other objects are inserted in the universe scope.
    202 //
    203 func def(obj Object) {
    204 	name := obj.Name()
    205 	if strings.Contains(name, " ") {
    206 		return // nothing to do
    207 	}
    208 	// fix Obj link for named types
    209 	if typ, ok := obj.Type().(*Named); ok {
    210 		typ.obj = obj.(*TypeName)
    211 	}
    212 	// exported identifiers go into package unsafe
    213 	scope := Universe
    214 	if obj.Exported() {
    215 		scope = Unsafe.scope
    216 		// set Pkg field
    217 		switch obj := obj.(type) {
    218 		case *TypeName:
    219 			obj.pkg = Unsafe
    220 		case *Builtin:
    221 			obj.pkg = Unsafe
    222 		default:
    223 			unreachable()
    224 		}
    225 	}
    226 	if scope.Insert(obj) != nil {
    227 		panic("internal error: double declaration")
    228 	}
    229 }
    230