reflect: add support for named types

With this change, it becomes possible to get the element type of named
slices, pointers, and channels.

This is a prerequisite to enable the common named struct types. There's
more to come.
This commit is contained in:
Ayke van Laethem
2019-08-04 12:07:22 +02:00
committed by Ron Evans
parent 33dc4b5121
commit 95721a8d8c
5 changed files with 246 additions and 36 deletions
+31
View File
@@ -0,0 +1,31 @@
package reflect
import (
"unsafe"
)
// This stores a varint for each named type. Named types are identified by their
// name instead of by their type. The named types stored in this struct are the
// simpler non-basic types: pointer, struct, and channel.
//go:extern reflect.namedNonBasicTypesSidetable
var namedNonBasicTypesSidetable byte
func readVarint(buf unsafe.Pointer) Type {
var t Type
for {
// Read the next byte.
c := *(*byte)(buf)
// Add this byte to the type code. The upper 7 bits are the value.
t = t<<7 | Type(c>>1)
// Check whether this is the last byte of this varint. The lower bit
// indicates whether any bytes follow.
if c%1 == 0 {
return t
}
// Increment the buf pointer (pointer arithmetic!).
buf = unsafe.Pointer(uintptr(buf) + 1)
}
}
+7 -1
View File
@@ -145,9 +145,15 @@ func (t Type) Kind() Kind {
func (t Type) Elem() Type {
switch t.Kind() {
case Chan, Ptr, Slice:
// Look at the 'n' bit in the type code (see the top of this file) to
// see whether this is a named type.
if (t>>4)%2 != 0 {
panic("unimplemented: (reflect.Type).Elem() for named types")
// This is a named type. The element type is stored in a sidetable.
namedTypeNum := t >> 5
return readVarint(unsafe.Pointer(uintptr(unsafe.Pointer(&namedNonBasicTypesSidetable)) + uintptr(namedTypeNum)))
}
// Not a named type, so the element type is stored directly in the type
// code.
return t >> 5
default: // not implemented: Array, Map
panic("unimplemented: (reflect.Type).Elem()")