Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(414)

Side by Side Diff: src/pkg/reflect/type.go

Issue 4281055: code review 4281055: reflect: new Type and Value definitions (Closed)
Patch Set: diff -r 82050f8e7881 https://go.googlecode.com/hg/ Created 13 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // The reflect package implements run-time reflection, allowing a program to 5 // The reflect package implements run-time reflection, allowing a program to
6 // manipulate objects with arbitrary types. The typical use is to take a 6 // manipulate objects with arbitrary types. The typical use is to take a
7 // value with static type interface{} and extract its dynamic type 7 // value with static type interface{} and extract its dynamic type
8 // information by calling Typeof, which returns an object with interface 8 // information by calling Typeof, which returns a Type.
9 // type Type. That contains a pointer to a struct of type *StructType,
10 // *IntType, etc. representing the details of the underlying type. A type
11 // switch or type assertion can reveal which.
12 // 9 //
13 // A call to NewValue creates a Value representing the run-time data; it 10 // A call to NewValue returns a Value representing the run-time data.
14 // contains a *StructValue, *IntValue, etc. MakeZero takes a Type and 11 // MakeZero takes a Type and returns a Value representing a zero value
15 // returns a Value representing a zero value for that type. 12 // for that type.
16 package reflect 13 package reflect
17 14
18 import ( 15 import (
19 "runtime" 16 "runtime"
20 "strconv" 17 "strconv"
21 "sync" 18 "sync"
22 "unsafe" 19 "unsafe"
23 ) 20 )
24 21
25 /* 22 /*
23 We want to be able to call methods on Type and to compare types for equality.
r 2011/04/02 18:45:33 i think this comment can go. at least it needs rep
24 Thus Type must be either an opaque type or an interface.
25 If we make it an interface then existing code changes less.
26 If we make Type an opaque type then that could allow overwriting
27 type data using copying. It also means saying *Type everywhere
28 but plain Value (not *Value), which is a bit strange. Let's use
29 the interface for better protection and to lose the *.
30
31
32 */
33
34 // Type is the representation of a Go type.
r 2011/04/02 18:45:33 might be good to have helper methods or functions
35 //
36 // Not all methods apply to all kinds of types. Restrictions,
37 // if any, are noted in the documentation for each method.
38 // Use the Kind method to find out the kind of type before
39 // calling kind-specific methods. Calling a method
40 // inappropriate to the kind of type causes a run time panic.
r 2011/04/02 18:45:33 s/run time/run-time/ (adjective)
41 type Type interface {
42 // Methods applicable to all types.
43
44 // Align returns the alignment of a value of this type
45 // when allocated in memory.
r 2011/04/02 18:45:33 what units?
46 Align() int
47
48 // FieldAlign returns the alignment of a value of this type
49 // when used as a field in a struct.
r 2011/04/02 18:45:33 what units?
50 FieldAlign() int
51
52 // Method returns the i'th method in the type's method set.
r 2011/04/02 18:45:33 what happens if i is out of range? obviously, it p
53 //
54 // For a non-interface type T or *T, the returned Method's Type and Func
55 // fields describe a function whose first argument is the receiver.
56 //
57 // For an interface type, the returned Method's Type field gives the
58 // method signature, without a receiver, and the Func field is nil.
59 Method(int) Method
60
61 // NumMethods returns the number of methods in the type's method set.
62 NumMethod() int
63
64 // Name returns the type's name within its package.
r 2011/04/02 18:45:33 really? i thought it returned pkg.NameOfType
65 // It returns an empty string for unnamed types.
66 Name() string
67
68 // PkgPath returns the type's package path.
69 // The package path is a full package import path like "container/vector ".
70 // PkgPath returns an empty string for unnamed types.
71 PkgPath() string
72
73 // Size returns the number of bytes needed to store
74 // a value of the given type; it is analogous to unsafe.Sizeof.
75 Size() uintptr
76
77 // String returns a string representation of the type.
78 // The string representation may use shortened package names
79 // (e.g., vector instead of "container/vector") and is not
80 // guaranteed to be unique among types. To test for equality,
81 // compare the Types directly.
82 String() string
83
84 // Kind returns the specific kind of this type.
85 Kind() Kind
86
87 // Methods applicable only to some types, depending on Kind.
88 // The methods allowed for each kind are:
89 //
90 // Int*, Uint*, Float*, Complex*: Bits
91 // Array: Elem, Len
92 // Chan: ChanDir, Elem
93 // Func: In, NumIn, Out, NumOut, DotDotDot.
94 // Map: Key, Elem
95 // Ptr: Elem
96 // Slice: Elem
97 // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumFi eld
98
99 // Bits returns the size of the type in bits.
100 // It panics if the type's Kind is not one of the
101 // sized or unsized Int, Uint, Float, or Complex knids.
102 Bits() int
103
104 // ChanDir returns a channel type's direction.
105 // It panics if the type's Kind is not Chan.
106 ChanDir() ChanDir
107
108 // DotDotDot returns true if a function type's final input parameter
109 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the paramet er's
110 // underlying static type []T.
111 //
112 // For concreteness, if t represents func(x int, y ... float), then
113 //
114 // t.NumIn() == 2
115 // t.In(0) is the reflect.Type for "int"
116 // t.In(1) is the reflect.Type for "[]float"
117 // t.DotDotDot() == true
118 //
119 // DotDotDot panics if the type's Kind is not Func.
120 DotDotDot() bool
r 2011/04/02 18:45:33 wrong name for a boolean method. HasDotDotDot is
121
122 // Elem returns a type's element type.
niemeyer 2011/04/04 13:52:35 s/element type/element Type/ ?
rsc 2011/04/05 16:29:45 I intentionally left type lower case in most place
123 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
124 Elem() Type
125
126 // Field returns a struct type's i'th field.
r 2011/04/02 18:45:33 what if i is out of range?
127 // It panics if the type's Kind is not Struct.
128 Field(i int) StructField
129
130 // FieldByIndex returns the nested field corresponding
131 // to the index sequence. It is equivalent to calling Field
132 // successively for each index i.
133 // It panics if the type's Kind is not Struct.
134 FieldByIndex(index []int) StructField
135
136 // FieldByName returns the struct field with the given name
137 // and a boolean indicating if the field was found.
138 FieldByName(name string) (StructField, bool)
139
140 // FieldByNameFunc returns the first struct field with a name
141 // that satisfies the match function and a boolean indicating if
142 // the field was found.
143 FieldByNameFunc(match func(string) bool) (StructField, bool)
144
145 // In returns the type of a function type's i'th input parameter.
146 // It panics if the type's Kind is not Func.
r 2011/04/02 18:45:33 here and for Out: what if i is out of range?
147 In(i int) Type
148
149 // Key returns a map type's key type.
150 // It panics if the type's Kind is not Map.
151 Key() Type
niemeyer 2011/04/04 13:52:35 Should this be called MapKey, or MapKeys be rename
rsc 2011/04/05 16:29:45 I don't think so. SliceType still uses Elem() to
152
153 // Len returns an array type's length.
154 // It panics if the type's Kind is not Array.
155 Len() int
156
157 // NumField returns a struct type's field count.
158 // It panics if the type's Kind is not Struct.
159 NumField() int
160
161 // NumIn returns a function type's input parameter count.
162 // It panics if the type's Kind is not Func.
163 NumIn() int
164
165 // NumOut returns a function type's output parameter count.
166 // It panics if the type's Kind is not Func.
167 NumOut() int
168
169 // Out returns the type of a function type's i'th output parameter.
170 // It panics if the type's Kind is not Func.
171 Out(i int) Type
172
173 uncommon() *uncommonType
174 }
175
176 // A Kind represents the specific kind of type that a Type represents.
177 // The zero Kind is not a valid kind.
178 type Kind uint8
179
180 const (
181 Invalid Kind = iota
182 Bool
183 Int
184 Int8
185 Int16
186 Int32
187 Int64
188 Uint
189 Uint8
190 Uint16
191 Uint32
192 Uint64
193 Uintptr
194 Float32
195 Float64
196 Complex64
197 Complex128
198 Array
199 Chan
200 Func
201 Interface
202 Map
203 Ptr
204 Slice
205 String
206 Struct
207 UnsafePointer
208 )
209
210 /*
26 * Copy of data structures from ../runtime/type.go. 211 * Copy of data structures from ../runtime/type.go.
27 * For comments, see the ones in that file. 212 * For comments, see the ones in that file.
28 * 213 *
29 * These data structures are known to the compiler and the runtime. 214 * These data structures are known to the compiler and the runtime.
30 * 215 *
31 * Putting these types in runtime instead of reflect means that 216 * Putting these types in runtime instead of reflect means that
32 * reflect doesn't need to be autolinked into every binary, which 217 * reflect doesn't need to be autolinked into every binary, which
33 * simplifies bootstrapping and package dependencies. 218 * simplifies bootstrapping and package dependencies.
34 * Unfortunately, it also means that reflect needs its own 219 * Unfortunately, it also means that reflect needs its own
35 * copy in order to access the private fields. 220 * copy in order to access the private fields.
(...skipping 24 matching lines...) Expand all
60 ifn unsafe.Pointer 245 ifn unsafe.Pointer
61 tfn unsafe.Pointer 246 tfn unsafe.Pointer
62 } 247 }
63 248
64 type uncommonType struct { 249 type uncommonType struct {
65 name *string 250 name *string
66 pkgPath *string 251 pkgPath *string
67 methods []method 252 methods []method
68 } 253 }
69 254
70 // BoolType represents a boolean type.
71 type BoolType struct {
72 commonType "bool"
73 }
74
75 // FloatType represents a float type.
76 type FloatType struct {
77 commonType "float"
78 }
79
80 // ComplexType represents a complex type.
81 type ComplexType struct {
82 commonType "complex"
83 }
84
85 // IntType represents a signed integer type.
86 type IntType struct {
87 commonType "int"
88 }
89
90 // UintType represents a uint type.
91 type UintType struct {
92 commonType "uint"
93 }
94
95 // StringType represents a string type.
96 type StringType struct {
97 commonType "string"
98 }
99
100 // UnsafePointerType represents an unsafe.Pointer type.
101 type UnsafePointerType struct {
102 commonType "unsafe.Pointer"
103 }
104
105 // ArrayType represents a fixed array type.
106 type ArrayType struct {
107 commonType "array"
108 elem *runtime.Type
109 len uintptr
110 }
111
112 // ChanDir represents a channel type's direction. 255 // ChanDir represents a channel type's direction.
113 type ChanDir int 256 type ChanDir int
114 257
115 const ( 258 const (
116 RecvDir ChanDir = 1 << iota 259 RecvDir ChanDir = 1 << iota
117 SendDir 260 SendDir
118 BothDir = RecvDir | SendDir 261 BothDir = RecvDir | SendDir
119 ) 262 )
120 263
121 // ChanType represents a channel type. 264
122 type ChanType struct { 265 // arrayType represents a fixed array type.
266 type arrayType struct {
267 » commonType "array"
268 » elem *runtime.Type
269 » len uintptr
270 }
271
272 // chanType represents a channel type.
273 type chanType struct {
123 commonType "chan" 274 commonType "chan"
124 elem *runtime.Type 275 elem *runtime.Type
125 dir uintptr 276 dir uintptr
126 } 277 }
127 278
128 // FuncType represents a function type. 279 // funcType represents a function type.
129 type FuncType struct { 280 type funcType struct {
130 commonType "func" 281 commonType "func"
131 dotdotdot bool 282 dotdotdot bool
132 in []*runtime.Type 283 in []*runtime.Type
133 out []*runtime.Type 284 out []*runtime.Type
134 } 285 }
135 286
136 // Method on interface type 287 // imethod represents a method on an interface type
137 type imethod struct { 288 type imethod struct {
138 name *string 289 name *string
139 pkgPath *string 290 pkgPath *string
140 typ *runtime.Type 291 typ *runtime.Type
141 } 292 }
142 293
143 // InterfaceType represents an interface type. 294 // interfaceType represents an interface type.
144 type InterfaceType struct { 295 type interfaceType struct {
145 commonType "interface" 296 commonType "interface"
146 methods []imethod 297 methods []imethod
147 } 298 }
148 299
149 // MapType represents a map type. 300 // mapType represents a map type.
150 type MapType struct { 301 type mapType struct {
151 commonType "map" 302 commonType "map"
152 key *runtime.Type 303 key *runtime.Type
153 elem *runtime.Type 304 elem *runtime.Type
154 } 305 }
155 306
156 // PtrType represents a pointer type. 307 // ptrType represents a pointer type.
157 type PtrType struct { 308 type ptrType struct {
158 commonType "ptr" 309 commonType "ptr"
159 elem *runtime.Type 310 elem *runtime.Type
160 } 311 }
161 312
162 // SliceType represents a slice type. 313 // sliceType represents a slice type.
163 type SliceType struct { 314 type sliceType struct {
164 commonType "slice" 315 commonType "slice"
165 elem *runtime.Type 316 elem *runtime.Type
166 } 317 }
167 318
168 // arrayOrSliceType is an unexported method that guarantees only
169 // arrays and slices implement ArrayOrSliceType.
170 func (*SliceType) arrayOrSliceType() {}
171
172 // Struct field 319 // Struct field
173 type structField struct { 320 type structField struct {
174 name *string 321 name *string
175 pkgPath *string 322 pkgPath *string
176 typ *runtime.Type 323 typ *runtime.Type
177 tag *string 324 tag *string
178 offset uintptr 325 offset uintptr
179 } 326 }
180 327
181 // StructType represents a struct type. 328 // structType represents a struct type.
182 type StructType struct { 329 type structType struct {
183 commonType "struct" 330 commonType "struct"
184 fields []structField 331 fields []structField
185 } 332 }
186 333
187 334
188 /* 335 /*
189 * The compiler knows the exact layout of all the data structures above. 336 * The compiler knows the exact layout of all the data structures above.
190 * The compiler does not know about the data structures and methods below. 337 * The compiler does not know about the data structures and methods below.
191 */ 338 */
192 339
193 // Method represents a single method. 340 // Method represents a single method.
194 type Method struct { 341 type Method struct {
195 PkgPath string // empty for uppercase Name 342 PkgPath string // empty for uppercase Name
196 Name string 343 Name string
197 » Type *FuncType 344 » Type Type
198 » Func *FuncValue 345 » Func Value
199 } 346 }
200 347
201 // Type is the runtime representation of a Go type.
202 // Every type implements the methods listed here.
203 // Some types implement additional interfaces;
204 // use a type switch to find out what kind of type a Type is.
205 // Each type in a program has a unique Type, so == on Types
206 // corresponds to Go's type equality.
207 type Type interface {
208 // PkgPath returns the type's package path.
209 // The package path is a full package import path like "container/vector ".
210 // PkgPath returns an empty string for unnamed types.
211 PkgPath() string
212
213 // Name returns the type's name within its package.
214 // Name returns an empty string for unnamed types.
215 Name() string
216
217 // String returns a string representation of the type.
218 // The string representation may use shortened package names
219 // (e.g., vector instead of "container/vector") and is not
220 // guaranteed to be unique among types. To test for equality,
221 // compare the Types directly.
222 String() string
223
224 // Size returns the number of bytes needed to store
225 // a value of the given type; it is analogous to unsafe.Sizeof.
226 Size() uintptr
227
228 // Bits returns the size of the type in bits.
229 // It is intended for use with numeric types and may overflow
230 // when used for composite types.
231 Bits() int
232
233 // Align returns the alignment of a value of this type
234 // when allocated in memory.
235 Align() int
236
237 // FieldAlign returns the alignment of a value of this type
238 // when used as a field in a struct.
239 FieldAlign() int
240
241 // Kind returns the specific kind of this type.
242 Kind() Kind
243
244 // Method returns the i'th method in the type's method set.
245 //
246 // For a non-interface type T or *T, the returned Method's Type and Func
247 // fields describe a function whose first argument is the receiver.
248 //
249 // For an interface type, the returned Method's Type field gives the
250 // method signature, without a receiver, and the Func field is nil.
251 Method(int) Method
252
253 // NumMethods returns the number of methods in the type's method set.
254 NumMethod() int
255
256 common() *commonType
257 uncommon() *uncommonType
258 }
259
260 // A Kind represents the specific kind of type that a Type represents.
261 // For numeric types, the Kind gives more information than the Type's
262 // dynamic type. For example, the Type of a float32 is FloatType, but
263 // the Kind is Float32.
264 //
265 // The zero Kind is not a valid kind.
266 type Kind uint8
267
268 const (
269 Bool Kind = 1 + iota
270 Int
271 Int8
272 Int16
273 Int32
274 Int64
275 Uint
276 Uint8
277 Uint16
278 Uint32
279 Uint64
280 Uintptr
281 Float32
282 Float64
283 Complex64
284 Complex128
285 Array
286 Chan
287 Func
288 Interface
289 Map
290 Ptr
291 Slice
292 String
293 Struct
294 UnsafePointer
295 )
296
297 // High bit says whether type has 348 // High bit says whether type has
298 // embedded pointers,to help garbage collector. 349 // embedded pointers,to help garbage collector.
299 const kindMask = 0x7f 350 const kindMask = 0x7f
300 351
301 func (k Kind) String() string { 352 func (k Kind) String() string {
302 if int(k) < len(kindNames) { 353 if int(k) < len(kindNames) {
303 return kindNames[k] 354 return kindNames[k]
304 } 355 }
305 return "kind" + strconv.Itoa(int(k)) 356 return "kind" + strconv.Itoa(int(k))
306 } 357 }
307 358
308 var kindNames = []string{ 359 var kindNames = []string{
360 Invalid: "invalid",
309 Bool: "bool", 361 Bool: "bool",
310 Int: "int", 362 Int: "int",
311 Int8: "int8", 363 Int8: "int8",
312 Int16: "int16", 364 Int16: "int16",
313 Int32: "int32", 365 Int32: "int32",
314 Int64: "int64", 366 Int64: "int64",
315 Uint: "uint", 367 Uint: "uint",
316 Uint8: "uint8", 368 Uint8: "uint8",
317 Uint16: "uint16", 369 Uint16: "uint16",
318 Uint32: "uint32", 370 Uint32: "uint32",
(...skipping 26 matching lines...) Expand all
345 return *t.pkgPath 397 return *t.pkgPath
346 } 398 }
347 399
348 func (t *uncommonType) Name() string { 400 func (t *uncommonType) Name() string {
349 if t == nil || t.name == nil { 401 if t == nil || t.name == nil {
350 return "" 402 return ""
351 } 403 }
352 return *t.name 404 return *t.name
353 } 405 }
354 406
407 func (t *commonType) toType() Type {
408 if t == nil {
409 return nil
410 }
411 return t
412 }
413
355 func (t *commonType) String() string { return *t.string } 414 func (t *commonType) String() string { return *t.string }
356 415
357 func (t *commonType) Size() uintptr { return t.size } 416 func (t *commonType) Size() uintptr { return t.size }
358 417
359 func (t *commonType) Bits() int { return int(t.size * 8) } 418 func (t *commonType) Bits() int {
419 » k := t.Kind()
420 » if k < Int || k > Complex128 {
421 » » panic("reflect: Bits of non-arithmetic Type")
422 » }
423 » return int(t.size) * 8
424 }
360 425
361 func (t *commonType) Align() int { return int(t.align) } 426 func (t *commonType) Align() int { return int(t.align) }
362 427
363 func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } 428 func (t *commonType) FieldAlign() int { return int(t.fieldAlign) }
364 429
365 func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) } 430 func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) }
366 431
367 func (t *commonType) common() *commonType { return t } 432 func (t *commonType) common() *commonType { return t }
368 433
369 func (t *uncommonType) Method(i int) (m Method) { 434 func (t *uncommonType) Method(i int) (m Method) {
370 if t == nil || i < 0 || i >= len(t.methods) { 435 if t == nil || i < 0 || i >= len(t.methods) {
371 return 436 return
372 } 437 }
373 p := &t.methods[i] 438 p := &t.methods[i]
374 if p.name != nil { 439 if p.name != nil {
375 m.Name = *p.name 440 m.Name = *p.name
376 } 441 }
377 if p.pkgPath != nil { 442 if p.pkgPath != nil {
378 m.PkgPath = *p.pkgPath 443 m.PkgPath = *p.pkgPath
379 } 444 }
380 » m.Type = toType(*p.typ).(*FuncType) 445 » m.Type = toType(p.typ)
381 fn := p.tfn 446 fn := p.tfn
382 » m.Func = &FuncValue{value: value{m.Type, addr(&fn), canSet}} 447 » m.Func = Value{&funcValue{value: value{m.Type, addr(&fn), canSet}}}
383 return 448 return
384 } 449 }
385 450
386 func (t *uncommonType) NumMethod() int { 451 func (t *uncommonType) NumMethod() int {
387 if t == nil { 452 if t == nil {
388 return 0 453 return 0
389 } 454 }
390 return len(t.methods) 455 return len(t.methods)
391 } 456 }
392 457
393 // TODO(rsc): 6g supplies these, but they are not 458 // TODO(rsc): 6g supplies these, but they are not
394 // as efficient as they could be: they have commonType 459 // as efficient as they could be: they have commonType
395 // as the receiver instead of *commonType. 460 // as the receiver instead of *commonType.
396 func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() } 461 func (t *commonType) NumMethod() int {
462 » if t.Kind() == Interface {
463 » » tt := (*interfaceType)(unsafe.Pointer(t))
464 » » return tt.NumMethod()
465 » }
466 » return t.uncommonType.NumMethod()
467 }
397 468
398 func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) } 469 func (t *commonType) Method(i int) (m Method) {
470 » if t.Kind() == Interface {
471 » » tt := (*interfaceType)(unsafe.Pointer(t))
472 » » return tt.Method(i)
473 » }
474 » return t.uncommonType.Method(i)
475 }
399 476
400 func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() } 477 func (t *commonType) PkgPath() string {
478 » return t.uncommonType.PkgPath()
479 }
401 480
402 func (t *commonType) Name() string { return t.uncommonType.Name() } 481 func (t *commonType) Name() string {
482 » return t.uncommonType.Name()
483 }
403 484
404 // Len returns the number of elements in the array. 485 func (t *commonType) ChanDir() ChanDir {
405 func (t *ArrayType) Len() int { return int(t.len) } 486 » if t.Kind() != Chan {
487 » » panic("reflect: ChanDir of non-chan type")
488 » }
489 » tt := (*chanType)(unsafe.Pointer(t))
490 » return ChanDir(tt.dir)
491 }
406 492
407 // Elem returns the type of the array's elements. 493 func (t *commonType) DotDotDot() bool {
408 func (t *ArrayType) Elem() Type { return toType(*t.elem) } 494 » if t.Kind() != Func {
495 » » panic("reflect: DotDotDot of non-func type")
496 » }
497 » tt := (*funcType)(unsafe.Pointer(t))
498 » return tt.dotdotdot
499 }
409 500
410 // arrayOrSliceType is an unexported method that guarantees only 501 func (t *commonType) Elem() Type {
411 // arrays and slices implement ArrayOrSliceType. 502 » switch t.Kind() {
412 func (*ArrayType) arrayOrSliceType() {} 503 » case Array:
504 » » tt := (*arrayType)(unsafe.Pointer(t))
505 » » return toType(tt.elem)
506 » case Chan:
507 » » tt := (*chanType)(unsafe.Pointer(t))
508 » » return toType(tt.elem)
509 » case Map:
510 » » tt := (*mapType)(unsafe.Pointer(t))
511 » » return toType(tt.elem)
512 » case Ptr:
513 » » tt := (*ptrType)(unsafe.Pointer(t))
514 » » return toType(tt.elem)
515 » case Slice:
516 » » tt := (*sliceType)(unsafe.Pointer(t))
517 » » return toType(tt.elem)
518 » }
519 » panic("reflect; Elem of invalid type")
520 }
413 521
414 // Dir returns the channel direction. 522 func (t *commonType) Field(i int) StructField {
415 func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) } 523 » if t.Kind() != Struct {
524 » » panic("reflect: Field of non-struct type")
niemeyer 2011/04/04 13:52:35 It would be helpful to have a TypeError analogous
rsc 2011/04/05 16:29:45 Sure, I will add that in a separate CL.
525 » }
526 » tt := (*structType)(unsafe.Pointer(t))
527 » return tt.Field(i)
528 }
416 529
417 // Elem returns the channel's element type. 530 func (t *commonType) FieldByIndex(index []int) StructField {
418 func (t *ChanType) Elem() Type { return toType(*t.elem) } 531 » if t.Kind() != Struct {
532 » » panic("reflect: FieldByIndex of non-struct type")
533 » }
534 » tt := (*structType)(unsafe.Pointer(t))
535 » return tt.FieldByIndex(index)
536 }
537
538 func (t *commonType) FieldByName(name string) (StructField, bool) {
539 » if t.Kind() != Struct {
540 » » panic("reflect: FieldByName of non-struct type")
541 » }
542 » tt := (*structType)(unsafe.Pointer(t))
543 » return tt.FieldByName(name)
544 }
545
546 func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool ) {
547 » if t.Kind() != Struct {
548 » » panic("reflect: FieldByNameFunc of non-struct type")
549 » }
550 » tt := (*structType)(unsafe.Pointer(t))
551 » return tt.FieldByNameFunc(match)
552 }
553
554 func (t *commonType) In(i int) Type {
555 » if t.Kind() != Func {
556 » » panic("reflect: In of non-func type")
557 » }
558 » tt := (*funcType)(unsafe.Pointer(t))
559 » return toType(tt.in[i])
560 }
561
562 func (t *commonType) Key() Type {
563 » if t.Kind() != Map {
564 » » panic("reflect: Key of non-map type")
565 » }
566 » tt := (*mapType)(unsafe.Pointer(t))
567 » return toType(tt.key)
568 }
569
570 func (t *commonType) Len() int {
571 » if t.Kind() != Array {
572 » » panic("reflect: Len of non-array type")
573 » }
574 » tt := (*arrayType)(unsafe.Pointer(t))
575 » return int(tt.len)
576 }
577
578 func (t *commonType) NumField() int {
579 » if t.Kind() != Struct {
580 » » panic("reflect: NumField of non-struct type")
581 » }
582 » tt := (*structType)(unsafe.Pointer(t))
583 » return len(tt.fields)
584 }
585
586 func (t *commonType) NumIn() int {
587 » if t.Kind() != Func {
588 » » panic("reflect; NumIn of non-func type")
589 » }
590 » tt := (*funcType)(unsafe.Pointer(t))
591 » return len(tt.in)
592 }
593
594 func (t *commonType) NumOut() int {
595 » if t.Kind() != Func {
596 » » panic("reflect; NumOut of non-func type")
597 » }
598 » tt := (*funcType)(unsafe.Pointer(t))
599 » return len(tt.out)
600 }
601
602 func (t *commonType) Out(i int) Type {
603 » if t.Kind() != Func {
604 » » panic("reflect: Out of non-func type")
605 » }
606 » tt := (*funcType)(unsafe.Pointer(t))
607 » return toType(tt.out[i])
608 }
419 609
420 func (d ChanDir) String() string { 610 func (d ChanDir) String() string {
421 switch d { 611 switch d {
422 case SendDir: 612 case SendDir:
423 return "chan<-" 613 return "chan<-"
424 case RecvDir: 614 case RecvDir:
425 return "<-chan" 615 return "<-chan"
426 case BothDir: 616 case BothDir:
427 return "chan" 617 return "chan"
428 } 618 }
429 return "ChanDir" + strconv.Itoa(int(d)) 619 return "ChanDir" + strconv.Itoa(int(d))
430 } 620 }
431 621
432 // In returns the type of the i'th function input parameter.
433 func (t *FuncType) In(i int) Type {
434 if i < 0 || i >= len(t.in) {
435 return nil
436 }
437 return toType(*t.in[i])
438 }
439
440 // DotDotDot returns true if the final function input parameter
441 // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the
442 // parameter's underlying static type []T.
443 //
444 // For concreteness, if t is func(x int, y ... float), then
445 //
446 // t.NumIn() == 2
447 // t.In(0) is the reflect.Type for "int"
448 // t.In(1) is the reflect.Type for "[]float"
449 // t.DotDotDot() == true
450 //
451 func (t *FuncType) DotDotDot() bool { return t.dotdotdot }
452
453 // NumIn returns the number of input parameters.
454 func (t *FuncType) NumIn() int { return len(t.in) }
455
456 // Out returns the type of the i'th function output parameter.
457 func (t *FuncType) Out(i int) Type {
458 if i < 0 || i >= len(t.out) {
459 return nil
460 }
461 return toType(*t.out[i])
462 }
463
464 // NumOut returns the number of function output parameters.
465 func (t *FuncType) NumOut() int { return len(t.out) }
466
467 // Method returns the i'th method in the type's method set. 622 // Method returns the i'th method in the type's method set.
468 func (t *InterfaceType) Method(i int) (m Method) { 623 func (t *interfaceType) Method(i int) (m Method) {
469 if i < 0 || i >= len(t.methods) { 624 if i < 0 || i >= len(t.methods) {
470 return 625 return
471 } 626 }
472 p := &t.methods[i] 627 p := &t.methods[i]
473 m.Name = *p.name 628 m.Name = *p.name
474 if p.pkgPath != nil { 629 if p.pkgPath != nil {
475 m.PkgPath = *p.pkgPath 630 m.PkgPath = *p.pkgPath
476 } 631 }
477 » m.Type = toType(*p.typ).(*FuncType) 632 » m.Type = toType(p.typ)
478 return 633 return
479 } 634 }
480 635
481 // NumMethod returns the number of interface methods in the type's method set. 636 // NumMethod returns the number of interface methods in the type's method set.
482 func (t *InterfaceType) NumMethod() int { return len(t.methods) } 637 func (t *interfaceType) NumMethod() int { return len(t.methods) }
483
484 // Key returns the map key type.
485 func (t *MapType) Key() Type { return toType(*t.key) }
486
487 // Elem returns the map element type.
488 func (t *MapType) Elem() Type { return toType(*t.elem) }
489
490 // Elem returns the pointer element type.
491 func (t *PtrType) Elem() Type { return toType(*t.elem) }
492
493 // Elem returns the type of the slice's elements.
494 func (t *SliceType) Elem() Type { return toType(*t.elem) }
495 638
496 type StructField struct { 639 type StructField struct {
497 PkgPath string // empty for uppercase Name 640 PkgPath string // empty for uppercase Name
498 Name string 641 Name string
499 Type Type 642 Type Type
500 Tag string 643 Tag string
501 Offset uintptr 644 Offset uintptr
502 Index []int 645 Index []int
503 Anonymous bool 646 Anonymous bool
504 } 647 }
505 648
506 // Field returns the i'th struct field. 649 // Field returns the i'th struct field.
507 func (t *StructType) Field(i int) (f StructField) { 650 func (t *structType) Field(i int) (f StructField) {
508 if i < 0 || i >= len(t.fields) { 651 if i < 0 || i >= len(t.fields) {
509 return 652 return
510 } 653 }
511 p := t.fields[i] 654 p := t.fields[i]
512 » f.Type = toType(*p.typ) 655 » f.Type = toType(p.typ)
513 if p.name != nil { 656 if p.name != nil {
514 f.Name = *p.name 657 f.Name = *p.name
515 } else { 658 } else {
516 t := f.Type 659 t := f.Type
517 » » if pt, ok := t.(*PtrType); ok { 660 » » if t.Kind() == Ptr {
518 » » » t = pt.Elem() 661 » » » t = t.Elem()
519 } 662 }
520 f.Name = t.Name() 663 f.Name = t.Name()
521 f.Anonymous = true 664 f.Anonymous = true
522 } 665 }
523 if p.pkgPath != nil { 666 if p.pkgPath != nil {
524 f.PkgPath = *p.pkgPath 667 f.PkgPath = *p.pkgPath
525 } 668 }
526 if p.tag != nil { 669 if p.tag != nil {
527 f.Tag = *p.tag 670 f.Tag = *p.tag
528 } 671 }
529 f.Offset = p.offset 672 f.Offset = p.offset
530 f.Index = []int{i} 673 f.Index = []int{i}
531 return 674 return
532 } 675 }
533 676
534 // TODO(gri): Should there be an error/bool indicator if the index 677 // TODO(gri): Should there be an error/bool indicator if the index
535 // is wrong for FieldByIndex? 678 // is wrong for FieldByIndex?
536 679
537 // FieldByIndex returns the nested field corresponding to index. 680 // FieldByIndex returns the nested field corresponding to index.
538 func (t *StructType) FieldByIndex(index []int) (f StructField) { 681 func (t *structType) FieldByIndex(index []int) (f StructField) {
682 » f.Type = Type(t.toType())
539 for i, x := range index { 683 for i, x := range index {
540 if i > 0 { 684 if i > 0 {
541 ft := f.Type 685 ft := f.Type
542 » » » if pt, ok := ft.(*PtrType); ok { 686 » » » if ft.Kind() == Ptr {
543 » » » » ft = pt.Elem() 687 » » » » ft = ft.Elem()
544 } 688 }
545 » » » if st, ok := ft.(*StructType); ok { 689 » » » if ft.Kind() != Struct {
546 » » » » t = st 690 » » » » return StructField{}
niemeyer 2011/04/04 13:52:35 Should we take the chance to make this panic rathe
rsc 2011/04/05 16:29:45 Done.
547 » » » } else {
548 » » » » var f0 StructField
549 » » » » f = f0
550 » » » » return
551 } 691 }
692 f.Type = ft
552 } 693 }
553 » » f = t.Field(x) 694 » » f = f.Type.Field(x)
554 } 695 }
555 return 696 return
556 } 697 }
557 698
558 const inf = 1 << 30 // infinity - no struct has that many nesting levels 699 const inf = 1 << 30 // infinity - no struct has that many nesting levels
559 700
560 func (t *StructType) fieldByNameFunc(match func(string) bool, mark map[*StructTy pe]bool, depth int) (ff StructField, fd int) { 701 func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structTy pe]bool, depth int) (ff StructField, fd int) {
561 fd = inf // field depth 702 fd = inf // field depth
562 703
563 if mark[t] { 704 if mark[t] {
564 // Struct already seen. 705 // Struct already seen.
565 return 706 return
566 } 707 }
567 mark[t] = true 708 mark[t] = true
568 709
569 var fi int // field index 710 var fi int // field index
570 n := 0 // number of matching fields at depth fd 711 n := 0 // number of matching fields at depth fd
571 L: 712 L:
572 for i := range t.fields { 713 for i := range t.fields {
573 f := t.Field(i) 714 f := t.Field(i)
574 d := inf 715 d := inf
575 switch { 716 switch {
576 case match(f.Name): 717 case match(f.Name):
577 // Matching top-level field. 718 // Matching top-level field.
578 d = depth 719 d = depth
579 case f.Anonymous: 720 case f.Anonymous:
580 ft := f.Type 721 ft := f.Type
581 » » » if pt, ok := ft.(*PtrType); ok { 722 » » » if ft.Kind() == Ptr {
582 » » » » ft = pt.Elem() 723 » » » » ft = ft.Elem()
583 } 724 }
584 switch { 725 switch {
585 case match(ft.Name()): 726 case match(ft.Name()):
586 // Matching anonymous top-level field. 727 // Matching anonymous top-level field.
587 d = depth 728 d = depth
588 case fd > depth: 729 case fd > depth:
589 // No top-level field yet; look inside nested st ructs. 730 // No top-level field yet; look inside nested st ructs.
590 » » » » if st, ok := ft.(*StructType); ok { 731 » » » » if ft.Kind() == Struct {
732 » » » » » st := (*structType)(unsafe.Pointer(ft.(* commonType)))
591 f, d = st.fieldByNameFunc(match, mark, d epth+1) 733 f, d = st.fieldByNameFunc(match, mark, d epth+1)
592 } 734 }
593 } 735 }
594 } 736 }
595 737
596 switch { 738 switch {
597 case d < fd: 739 case d < fd:
598 // Found field at shallower depth. 740 // Found field at shallower depth.
599 ff, fi, fd = f, i, d 741 ff, fi, fd = f, i, d
600 n = 1 742 n = 1
(...skipping 18 matching lines...) Expand all
619 // None or more than one matching field found. 761 // None or more than one matching field found.
620 fd = inf 762 fd = inf
621 } 763 }
622 764
623 mark[t] = false, false 765 mark[t] = false, false
624 return 766 return
625 } 767 }
626 768
627 // FieldByName returns the struct field with the given name 769 // FieldByName returns the struct field with the given name
628 // and a boolean to indicate if the field was found. 770 // and a boolean to indicate if the field was found.
629 func (t *StructType) FieldByName(name string) (f StructField, present bool) { 771 func (t *structType) FieldByName(name string) (f StructField, present bool) {
630 return t.FieldByNameFunc(func(s string) bool { return s == name }) 772 return t.FieldByNameFunc(func(s string) bool { return s == name })
631 } 773 }
632 774
633 // FieldByNameFunc returns the struct field with a name that satisfies the 775 // FieldByNameFunc returns the struct field with a name that satisfies the
634 // match function and a boolean to indicate if the field was found. 776 // match function and a boolean to indicate if the field was found.
635 func (t *StructType) FieldByNameFunc(match func(string) bool) (f StructField, pr esent bool) { 777 func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, pr esent bool) {
636 » if ff, fd := t.fieldByNameFunc(match, make(map[*StructType]bool), 0); fd < inf { 778 » if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf {
637 ff.Index = ff.Index[0 : fd+1] 779 ff.Index = ff.Index[0 : fd+1]
638 f, present = ff, true 780 f, present = ff, true
639 } 781 }
640 return 782 return
641 } 783 }
642 784
643 // NumField returns the number of struct fields.
644 func (t *StructType) NumField() int { return len(t.fields) }
645
646 // Convert runtime type to reflect type. 785 // Convert runtime type to reflect type.
647 // Same memory layouts, different method sets. 786 func toType(p *runtime.Type) Type {
648 func toType(i interface{}) Type { 787 » type hdr struct {
649 » switch v := i.(type) { 788 » » x interface{}
650 » case nil: 789 » » t commonType
651 » » return nil
652 » case *runtime.BoolType:
653 » » return (*BoolType)(unsafe.Pointer(v))
654 » case *runtime.FloatType:
655 » » return (*FloatType)(unsafe.Pointer(v))
656 » case *runtime.ComplexType:
657 » » return (*ComplexType)(unsafe.Pointer(v))
658 » case *runtime.IntType:
659 » » return (*IntType)(unsafe.Pointer(v))
660 » case *runtime.StringType:
661 » » return (*StringType)(unsafe.Pointer(v))
662 » case *runtime.UintType:
663 » » return (*UintType)(unsafe.Pointer(v))
664 » case *runtime.UnsafePointerType:
665 » » return (*UnsafePointerType)(unsafe.Pointer(v))
666 » case *runtime.ArrayType:
667 » » return (*ArrayType)(unsafe.Pointer(v))
668 » case *runtime.ChanType:
669 » » return (*ChanType)(unsafe.Pointer(v))
670 » case *runtime.FuncType:
671 » » return (*FuncType)(unsafe.Pointer(v))
672 » case *runtime.InterfaceType:
673 » » return (*InterfaceType)(unsafe.Pointer(v))
674 » case *runtime.MapType:
675 » » return (*MapType)(unsafe.Pointer(v))
676 » case *runtime.PtrType:
677 » » return (*PtrType)(unsafe.Pointer(v))
678 » case *runtime.SliceType:
679 » » return (*SliceType)(unsafe.Pointer(v))
680 » case *runtime.StructType:
681 » » return (*StructType)(unsafe.Pointer(v))
682 } 790 }
683 » println(i) 791 » t := &(*hdr)(unsafe.Pointer(p)).t
684 » panic("toType") 792 » return t.toType()
685 }
686
687 // ArrayOrSliceType is the common interface implemented
688 // by both ArrayType and SliceType.
689 type ArrayOrSliceType interface {
690 » Type
691 » Elem() Type
692 » arrayOrSliceType() // Guarantees only Array and Slice implement this int erface.
693 } 793 }
694 794
695 // Typeof returns the reflection Type of the value in the interface{}. 795 // Typeof returns the reflection Type of the value in the interface{}.
696 func Typeof(i interface{}) Type { return toType(unsafe.Typeof(i)) } 796 func Typeof(i interface{}) Type {
797 » type hdr struct {
798 » » typ *byte
799 » » val *commonType
800 » }
801 » rt := unsafe.Typeof(i)
802 » t := (*(*hdr)(unsafe.Pointer(&rt))).val
803 » return t.toType()
804 }
697 805
698 // ptrMap is the cache for PtrTo. 806 // ptrMap is the cache for PtrTo.
699 var ptrMap struct { 807 var ptrMap struct {
700 sync.RWMutex 808 sync.RWMutex
701 » m map[Type]*PtrType 809 » m map[*commonType]*ptrType
702 }
703
704 // runtimePtrType is the runtime layout for a *PtrType.
705 // The memory immediately before the *PtrType is always
706 // the canonical runtime.Type to be used for a *runtime.Type
707 // describing this PtrType.
708 type runtimePtrType struct {
709 » runtime.Type
710 » runtime.PtrType
711 } 810 }
712 811
713 // PtrTo returns the pointer type with element t. 812 // PtrTo returns the pointer type with element t.
714 // For example, if t represents type Foo, PtrTo(t) represents *Foo. 813 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
715 func PtrTo(t Type) *PtrType { 814 func PtrTo(t Type) Type {
716 // If t records its pointer-to type, use it. 815 // If t records its pointer-to type, use it.
717 » ct := t.common() 816 » ct := t.(*commonType)
718 if p := ct.ptrToThis; p != nil { 817 if p := ct.ptrToThis; p != nil {
719 » » return toType(*p).(*PtrType) 818 » » return toType(p)
720 } 819 }
721 820
722 // Otherwise, synthesize one. 821 // Otherwise, synthesize one.
723 // This only happens for pointers with no methods. 822 // This only happens for pointers with no methods.
724 // We keep the mapping in a map on the side, because 823 // We keep the mapping in a map on the side, because
725 // this operation is rare and a separate map lets us keep 824 // this operation is rare and a separate map lets us keep
726 // the type structures in read-only memory. 825 // the type structures in read-only memory.
727 ptrMap.RLock() 826 ptrMap.RLock()
728 if m := ptrMap.m; m != nil { 827 if m := ptrMap.m; m != nil {
729 » » if p := m[t]; p != nil { 828 » » if p := m[ct]; p != nil {
730 ptrMap.RUnlock() 829 ptrMap.RUnlock()
731 » » » return p 830 » » » return p.commonType.toType()
732 } 831 }
733 } 832 }
734 ptrMap.RUnlock() 833 ptrMap.RUnlock()
735 ptrMap.Lock() 834 ptrMap.Lock()
736 if ptrMap.m == nil { 835 if ptrMap.m == nil {
737 » » ptrMap.m = make(map[Type]*PtrType) 836 » » ptrMap.m = make(map[*commonType]*ptrType)
738 } 837 }
739 » p := ptrMap.m[t] 838 » p := ptrMap.m[ct]
740 if p != nil { 839 if p != nil {
741 // some other goroutine won the race and created it 840 // some other goroutine won the race and created it
742 ptrMap.Unlock() 841 ptrMap.Unlock()
743 return p 842 return p
744 } 843 }
745 844
746 » // runtime.Type value is always right before type structure. 845 » var rt struct {
747 » // 2*ptrSize is size of interface header 846 » » i runtime.Type
748 » rt := (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - uintp tr(unsafe.Sizeof(runtime.Type(nil))))) 847 » » ptrType
848 » }
849 » rt.i = (*runtime.PtrType)(unsafe.Pointer(&rt.ptrType))
749 850
750 » rp := new(runtimePtrType) 851 » // initialize p using *byte's PtrType as a prototype.
751 » rp.Type = &rp.PtrType
752
753 » // initialize rp.PtrType using *byte's PtrType as a prototype.
754 // have to do assignment as PtrType, not runtime.PtrType, 852 // have to do assignment as PtrType, not runtime.PtrType,
755 // in order to write to unexported fields. 853 // in order to write to unexported fields.
756 » p = (*PtrType)(unsafe.Pointer(&rp.PtrType)) 854 » p = &rt.ptrType
757 » bp := (*PtrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.Pt rType))) 855 » bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.Pt rType)))
758 *p = *bp 856 *p = *bp
759 857
760 s := "*" + *ct.string 858 s := "*" + *ct.string
761 p.string = &s 859 p.string = &s
762 860
763 // For the type structures linked into the binary, the 861 // For the type structures linked into the binary, the
764 // compiler provides a good hash of the string. 862 // compiler provides a good hash of the string.
765 // Create a good hash for the new string by using 863 // Create a good hash for the new string by using
766 // the FNV-1 hash's mixing function to combine the 864 // the FNV-1 hash's mixing function to combine the
767 // old hash and the new "*". 865 // old hash and the new "*".
768 p.hash = ct.hash*16777619 ^ '*' 866 p.hash = ct.hash*16777619 ^ '*'
769 867
770 p.uncommonType = nil 868 p.uncommonType = nil
771 p.ptrToThis = nil 869 p.ptrToThis = nil
772 » p.elem = rt 870 » p.elem = (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - ui ntptr(unsafe.Offsetof(rt.ptrType))))
773 871
774 » ptrMap.m[t] = (*PtrType)(unsafe.Pointer(&rp.PtrType)) 872 » ptrMap.m[ct] = p
775 ptrMap.Unlock() 873 ptrMap.Unlock()
776 » return p 874 » return p.commonType.toType()
777 } 875 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b