From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libgo/go/reflect/type.go | 743 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 743 insertions(+) create mode 100644 libgo/go/reflect/type.go (limited to 'libgo/go/reflect/type.go') diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go new file mode 100644 index 000000000..4ad4c5f2b --- /dev/null +++ b/libgo/go/reflect/type.go @@ -0,0 +1,743 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The reflect package implements run-time reflection, allowing a program to +// manipulate objects with arbitrary types. The typical use is to take a +// value with static type interface{} and extract its dynamic type +// information by calling Typeof, which returns an object with interface +// type Type. That contains a pointer to a struct of type *StructType, +// *IntType, etc. representing the details of the underlying type. A type +// switch or type assertion can reveal which. +// +// A call to NewValue creates a Value representing the run-time data; it +// contains a *StructValue, *IntValue, etc. MakeZero takes a Type and +// returns a Value representing a zero value for that type. +package reflect + +import ( + "runtime" + "strconv" + "sync" + "unsafe" +) + +/* + * Copy of data structures from ../runtime/type.go. + * For comments, see the ones in that file. + * + * These data structures are known to the compiler and the runtime. + * + * Putting these types in runtime instead of reflect means that + * reflect doesn't need to be autolinked into every binary, which + * simplifies bootstrapping and package dependencies. + * Unfortunately, it also means that reflect needs its own + * copy in order to access the private fields. + */ + +// commonType is the common implementation of most values. +// It is embedded in other, public struct types, but always +// with a unique tag like "uint" or "float" so that the client cannot +// convert from, say, *UintType to *FloatType. + +type commonType struct { + kind uint8 + align int8 + fieldAlign uint8 + size uintptr + hash uint32 + hashfn func(unsafe.Pointer, uintptr) + equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) + string *string + *uncommonType +} + +type method struct { + name *string + pkgPath *string + mtyp *runtime.Type + typ *runtime.Type + tfn unsafe.Pointer +} + +type uncommonType struct { + name *string + pkgPath *string + methods []method +} + +// BoolType represents a boolean type. +type BoolType struct { + commonType "bool" +} + +// FloatType represents a float type. +type FloatType struct { + commonType "float" +} + +// ComplexType represents a complex type. +type ComplexType struct { + commonType "complex" +} + +// IntType represents a signed integer type. +type IntType struct { + commonType "int" +} + +// UintType represents a uint type. +type UintType struct { + commonType "uint" +} + +// StringType represents a string type. +type StringType struct { + commonType "string" +} + +// UnsafePointerType represents an unsafe.Pointer type. +type UnsafePointerType struct { + commonType "unsafe.Pointer" +} + +// ArrayType represents a fixed array type. +type ArrayType struct { + commonType "array" + elem *runtime.Type + len uintptr +} + +// ChanDir represents a channel type's direction. +type ChanDir int + +const ( + RecvDir ChanDir = 1 << iota + SendDir + BothDir = RecvDir | SendDir +) + +// ChanType represents a channel type. +type ChanType struct { + commonType "chan" + elem *runtime.Type + dir uintptr +} + +// FuncType represents a function type. +type FuncType struct { + commonType "func" + dotdotdot bool + in []*runtime.Type + out []*runtime.Type +} + +// Method on interface type +type imethod struct { + name *string + pkgPath *string + typ *runtime.Type +} + +// InterfaceType represents an interface type. +type InterfaceType struct { + commonType "interface" + methods []imethod +} + +// MapType represents a map type. +type MapType struct { + commonType "map" + key *runtime.Type + elem *runtime.Type +} + +// PtrType represents a pointer type. +type PtrType struct { + commonType "ptr" + elem *runtime.Type +} + +// SliceType represents a slice type. +type SliceType struct { + commonType "slice" + elem *runtime.Type +} + +// Struct field +type structField struct { + name *string + pkgPath *string + typ *runtime.Type + tag *string + offset uintptr +} + +// StructType represents a struct type. +type StructType struct { + commonType "struct" + fields []structField +} + + +/* + * The compiler knows the exact layout of all the data structures above. + * The compiler does not know about the data structures and methods below. + */ + +// Method represents a single method. +type Method struct { + PkgPath string // empty for uppercase Name + Name string + Type *FuncType + Func *FuncValue +} + +// Type is the runtime representation of a Go type. +// Every type implements the methods listed here. +// Some types implement additional interfaces; +// use a type switch to find out what kind of type a Type is. +// Each type in a program has a unique Type, so == on Types +// corresponds to Go's type equality. +type Type interface { + // PkgPath returns the type's package path. + // The package path is a full package import path like "container/vector". + // PkgPath returns an empty string for unnamed types. + PkgPath() string + + // Name returns the type's name within its package. + // Name returns an empty string for unnamed types. + Name() string + + // String returns a string representation of the type. + // The string representation may use shortened package names + // (e.g., vector instead of "container/vector") and is not + // guaranteed to be unique among types. To test for equality, + // compare the Types directly. + String() string + + // Size returns the number of bytes needed to store + // a value of the given type; it is analogous to unsafe.Sizeof. + Size() uintptr + + // Bits returns the size of the type in bits. + // It is intended for use with numeric types and may overflow + // when used for composite types. + Bits() int + + // Align returns the alignment of a value of this type + // when allocated in memory. + Align() int + + // FieldAlign returns the alignment of a value of this type + // when used as a field in a struct. + FieldAlign() int + + // Kind returns the specific kind of this type. + Kind() Kind + + // For non-interface types, Method returns the i'th method with receiver T. + // For interface types, Method returns the i'th method in the interface. + // NumMethod returns the number of such methods. + Method(int) Method + NumMethod() int + uncommon() *uncommonType +} + +// A Kind represents the specific kind of type that a Type represents. +// For numeric types, the Kind gives more information than the Type's +// dynamic type. For example, the Type of a float32 is FloatType, but +// the Kind is Float32. +// +// The zero Kind is not a valid kind. +type Kind uint8 + +const ( + Bool Kind = 1 + iota + Int + Int8 + Int16 + Int32 + Int64 + Uint + Uint8 + Uint16 + Uint32 + Uint64 + Uintptr + Float32 + Float64 + Complex64 + Complex128 + Array + Chan + Func + Interface + Map + Ptr + Slice + String + Struct + UnsafePointer +) + +// High bit says whether type has +// embedded pointers,to help garbage collector. +const kindMask = 0x7f + +func (k Kind) String() string { + if int(k) < len(kindNames) { + return kindNames[k] + } + return "kind" + strconv.Itoa(int(k)) +} + +var kindNames = []string{ + Bool: "bool", + Int: "int", + Int8: "int8", + Int16: "int16", + Int32: "int32", + Int64: "int64", + Uint: "uint", + Uint8: "uint8", + Uint16: "uint16", + Uint32: "uint32", + Uint64: "uint64", + Uintptr: "uintptr", + Float32: "float32", + Float64: "float64", + Complex64: "complex64", + Complex128: "complex128", + Array: "array", + Chan: "chan", + Func: "func", + Interface: "interface", + Map: "map", + Ptr: "ptr", + Slice: "slice", + String: "string", + Struct: "struct", + UnsafePointer: "unsafe.Pointer", +} + +func (t *uncommonType) uncommon() *uncommonType { + return t +} + +func (t *uncommonType) PkgPath() string { + if t == nil || t.pkgPath == nil { + return "" + } + return *t.pkgPath +} + +func (t *uncommonType) Name() string { + if t == nil || t.name == nil { + return "" + } + return *t.name +} + +func (t *commonType) String() string { return *t.string } + +func (t *commonType) Size() uintptr { return t.size } + +func (t *commonType) Bits() int { return int(t.size * 8) } + +func (t *commonType) Align() int { return int(t.align) } + +func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } + +func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) } + +func (t *uncommonType) Method(i int) (m Method) { + if t == nil || i < 0 || i >= len(t.methods) { + return + } + p := &t.methods[i] + if p.name != nil { + m.Name = *p.name + } + if p.pkgPath != nil { + m.PkgPath = *p.pkgPath + } + m.Type = runtimeToType(p.typ).(*FuncType) + fn := p.tfn + m.Func = &FuncValue{value: value{m.Type, addr(&fn), true}} + return +} + +func (t *uncommonType) NumMethod() int { + if t == nil { + return 0 + } + return len(t.methods) +} + +// TODO(rsc): 6g supplies these, but they are not +// as efficient as they could be: they have commonType +// as the receiver instead of *commonType. +func (t *commonType) NumMethod() int { return t.uncommonType.NumMethod() } + +func (t *commonType) Method(i int) (m Method) { return t.uncommonType.Method(i) } + +func (t *commonType) PkgPath() string { return t.uncommonType.PkgPath() } + +func (t *commonType) Name() string { return t.uncommonType.Name() } + +// Len returns the number of elements in the array. +func (t *ArrayType) Len() int { return int(t.len) } + +// Elem returns the type of the array's elements. +func (t *ArrayType) Elem() Type { return runtimeToType(t.elem) } + +// Dir returns the channel direction. +func (t *ChanType) Dir() ChanDir { return ChanDir(t.dir) } + +// Elem returns the channel's element type. +func (t *ChanType) Elem() Type { return runtimeToType(t.elem) } + +func (d ChanDir) String() string { + switch d { + case SendDir: + return "chan<-" + case RecvDir: + return "<-chan" + case BothDir: + return "chan" + } + return "ChanDir" + strconv.Itoa(int(d)) +} + +// In returns the type of the i'th function input parameter. +func (t *FuncType) In(i int) Type { + if i < 0 || i >= len(t.in) { + return nil + } + return runtimeToType(t.in[i]) +} + +// DotDotDot returns true if the final function input parameter +// is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the +// parameter's underlying static type []T. +// +// For concreteness, if t is func(x int, y ... float), then +// +// t.NumIn() == 2 +// t.In(0) is the reflect.Type for "int" +// t.In(1) is the reflect.Type for "[]float" +// t.DotDotDot() == true +// +func (t *FuncType) DotDotDot() bool { return t.dotdotdot } + +// NumIn returns the number of input parameters. +func (t *FuncType) NumIn() int { return len(t.in) } + +// Out returns the type of the i'th function output parameter. +func (t *FuncType) Out(i int) Type { + if i < 0 || i >= len(t.out) { + return nil + } + return runtimeToType(t.out[i]) +} + +// NumOut returns the number of function output parameters. +func (t *FuncType) NumOut() int { return len(t.out) } + +// Method returns the i'th interface method. +func (t *InterfaceType) Method(i int) (m Method) { + if i < 0 || i >= len(t.methods) { + return + } + p := &t.methods[i] + m.Name = *p.name + if p.pkgPath != nil { + m.PkgPath = *p.pkgPath + } + m.Type = runtimeToType(p.typ).(*FuncType) + return +} + +// NumMethod returns the number of interface methods. +func (t *InterfaceType) NumMethod() int { return len(t.methods) } + +// Key returns the map key type. +func (t *MapType) Key() Type { return runtimeToType(t.key) } + +// Elem returns the map element type. +func (t *MapType) Elem() Type { return runtimeToType(t.elem) } + +// Elem returns the pointer element type. +func (t *PtrType) Elem() Type { return runtimeToType(t.elem) } + +// Elem returns the type of the slice's elements. +func (t *SliceType) Elem() Type { return runtimeToType(t.elem) } + +type StructField struct { + PkgPath string // empty for uppercase Name + Name string + Type Type + Tag string + Offset uintptr + Index []int + Anonymous bool +} + +// Field returns the i'th struct field. +func (t *StructType) Field(i int) (f StructField) { + if i < 0 || i >= len(t.fields) { + return + } + p := t.fields[i] + f.Type = runtimeToType(p.typ) + if p.name != nil { + f.Name = *p.name + } else { + t := f.Type + if pt, ok := t.(*PtrType); ok { + t = pt.Elem() + } + f.Name = t.Name() + f.Anonymous = true + } + if p.pkgPath != nil { + f.PkgPath = *p.pkgPath + } + if p.tag != nil { + f.Tag = *p.tag + } + f.Offset = p.offset + f.Index = []int{i} + return +} + +// TODO(gri): Should there be an error/bool indicator if the index +// is wrong for FieldByIndex? + +// FieldByIndex returns the nested field corresponding to index. +func (t *StructType) FieldByIndex(index []int) (f StructField) { + for i, x := range index { + if i > 0 { + ft := f.Type + if pt, ok := ft.(*PtrType); ok { + ft = pt.Elem() + } + if st, ok := ft.(*StructType); ok { + t = st + } else { + var f0 StructField + f = f0 + return + } + } + f = t.Field(x) + } + return +} + +const inf = 1 << 30 // infinity - no struct has that many nesting levels + +func (t *StructType) fieldByNameFunc(match func(string) bool, mark map[*StructType]bool, depth int) (ff StructField, fd int) { + fd = inf // field depth + + if mark[t] { + // Struct already seen. + return + } + mark[t] = true + + var fi int // field index + n := 0 // number of matching fields at depth fd +L: + for i := range t.fields { + f := t.Field(i) + d := inf + switch { + case match(f.Name): + // Matching top-level field. + d = depth + case f.Anonymous: + ft := f.Type + if pt, ok := ft.(*PtrType); ok { + ft = pt.Elem() + } + switch { + case match(ft.Name()): + // Matching anonymous top-level field. + d = depth + case fd > depth: + // No top-level field yet; look inside nested structs. + if st, ok := ft.(*StructType); ok { + f, d = st.fieldByNameFunc(match, mark, depth+1) + } + } + } + + switch { + case d < fd: + // Found field at shallower depth. + ff, fi, fd = f, i, d + n = 1 + case d == fd: + // More than one matching field at the same depth (or d, fd == inf). + // Same as no field found at this depth. + n++ + if d == depth { + // Impossible to find a field at lower depth. + break L + } + } + } + + if n == 1 { + // Found matching field. + if len(ff.Index) <= depth { + ff.Index = make([]int, depth+1) + } + ff.Index[depth] = fi + } else { + // None or more than one matching field found. + fd = inf + } + + mark[t] = false, false + return +} + +// FieldByName returns the struct field with the given name +// and a boolean to indicate if the field was found. +func (t *StructType) FieldByName(name string) (f StructField, present bool) { + return t.FieldByNameFunc(func(s string) bool { return s == name }) +} + +// FieldByNameFunc returns the struct field with a name that satisfies the +// match function and a boolean to indicate if the field was found. +func (t *StructType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) { + if ff, fd := t.fieldByNameFunc(match, make(map[*StructType]bool), 0); fd < inf { + ff.Index = ff.Index[0 : fd+1] + f, present = ff, true + } + return +} + +// NumField returns the number of struct fields. +func (t *StructType) NumField() int { return len(t.fields) } + +// Canonicalize a Type. +var canonicalType = make(map[string]Type) + +var canonicalTypeLock sync.Mutex + +func canonicalize(t Type) Type { + if t == nil { + return nil + } + u := t.uncommon() + var s string + if u == nil || u.PkgPath() == "" { + s = t.String() + } else { + s = u.PkgPath() + "." + u.Name() + } + canonicalTypeLock.Lock() + if r, ok := canonicalType[s]; ok { + canonicalTypeLock.Unlock() + return r + } + canonicalType[s] = t + canonicalTypeLock.Unlock() + return t +} + +// Convert runtime type to reflect type. +// Same memory layouts, different method sets. +func toType(i interface{}) Type { + switch v := i.(type) { + case nil: + return nil + case *runtime.BoolType: + return (*BoolType)(unsafe.Pointer(v)) + case *runtime.FloatType: + return (*FloatType)(unsafe.Pointer(v)) + case *runtime.ComplexType: + return (*ComplexType)(unsafe.Pointer(v)) + case *runtime.IntType: + return (*IntType)(unsafe.Pointer(v)) + case *runtime.StringType: + return (*StringType)(unsafe.Pointer(v)) + case *runtime.UintType: + return (*UintType)(unsafe.Pointer(v)) + case *runtime.UnsafePointerType: + return (*UnsafePointerType)(unsafe.Pointer(v)) + case *runtime.ArrayType: + return (*ArrayType)(unsafe.Pointer(v)) + case *runtime.ChanType: + return (*ChanType)(unsafe.Pointer(v)) + case *runtime.FuncType: + return (*FuncType)(unsafe.Pointer(v)) + case *runtime.InterfaceType: + return (*InterfaceType)(unsafe.Pointer(v)) + case *runtime.MapType: + return (*MapType)(unsafe.Pointer(v)) + case *runtime.PtrType: + return (*PtrType)(unsafe.Pointer(v)) + case *runtime.SliceType: + return (*SliceType)(unsafe.Pointer(v)) + case *runtime.StructType: + return (*StructType)(unsafe.Pointer(v)) + } + println(i) + panic("toType") +} + +// Convert pointer to runtime Type structure to our Type structure. +func runtimeToType(v *runtime.Type) Type { + var r Type + switch Kind(v.Kind) { + case Bool: + r = (*BoolType)(unsafe.Pointer(v)) + case Int, Int8, Int16, Int32, Int64: + r = (*IntType)(unsafe.Pointer(v)) + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + r = (*UintType)(unsafe.Pointer(v)) + case Float32, Float64: + r = (*FloatType)(unsafe.Pointer(v)) + case Complex64, Complex128: + r = (*ComplexType)(unsafe.Pointer(v)) + case Array: + r = (*ArrayType)(unsafe.Pointer(v)) + case Chan: + r = (*ChanType)(unsafe.Pointer(v)) + case Func: + r = (*FuncType)(unsafe.Pointer(v)) + case Interface: + r = (*InterfaceType)(unsafe.Pointer(v)) + case Map: + r = (*MapType)(unsafe.Pointer(v)) + case Ptr: + r = (*PtrType)(unsafe.Pointer(v)) + case Slice: + r = (*SliceType)(unsafe.Pointer(v)) + case String: + r = (*StringType)(unsafe.Pointer(v)) + case Struct: + r = (*StructType)(unsafe.Pointer(v)) + case UnsafePointer: + r = (*UnsafePointerType)(unsafe.Pointer(v)) + default: + panic("runtimeToType") + } + return canonicalize(r) + panic("runtimeToType") +} + +// ArrayOrSliceType is the common interface implemented +// by both ArrayType and SliceType. +type ArrayOrSliceType interface { + Type + Elem() Type +} + +// Typeof returns the reflection Type of the value in the interface{}. +func Typeof(i interface{}) Type { return canonicalize(toType(unsafe.Typeof(i))) } -- cgit v1.2.3