os.install: once.install syscall.install
path.install: strings.install
rand.install:
-reflect.install: strconv.install sync.install utf8.install
+reflect.install: runtime.install strconv.install strings.install
regexp.install: bytes.install container/vector.install io.install os.install runtime.install utf8.install
runtime.install:
sort.install:
+++ /dev/null
-// 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.
-
-package reflect
-
-import (
- "runtime";
- "strconv";
- "strings";
- "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.
- */
-
-type uncommonType struct
-
-type commonType struct {
- size uintptr;
- hash uint32;
- alg uint8;
- align uint8;
- fieldAlign uint8;
- string *string;
- *uncommonType;
-}
-
-type method struct {
- hash uint32;
- name *string;
- pkgPath *string;
- typ *runtime.Type;
- ifn unsafe.Pointer;
- tfn unsafe.Pointer;
-}
-
-type uncommonType struct {
- name *string;
- pkgPath *string;
- methods []method;
-}
-
-// BoolType represents a boolean type.
-type BoolType struct {
- commonType
-}
-
-// Float32Type represents a float32 type.
-type Float32Type struct {
- commonType
-}
-
-// Float64Type represents a float64 type.
-type Float64Type struct {
- commonType
-}
-
-// FloatType represents a float type.
-type FloatType struct {
- commonType
-}
-
-// Int16Type represents an int16 type.
-type Int16Type struct {
- commonType
-}
-
-// Int32Type represents an int32 type.
-type Int32Type struct {
- commonType
-}
-
-// Int64Type represents an int64 type.
-type Int64Type struct {
- commonType
-}
-
-// Int8Type represents an int8 type.
-type Int8Type struct {
- commonType
-}
-
-// IntType represents an int type.
-type IntType struct {
- commonType
-}
-
-// Uint16Type represents a uint16 type.
-type Uint16Type struct {
- commonType
-}
-
-// Uint32Type represents a uint32 type.
-type Uint32Type struct {
- commonType
-}
-
-// Uint64Type represents a uint64 type.
-type Uint64Type struct {
- commonType
-}
-
-// Uint8Type represents a uint8 type.
-type Uint8Type struct {
- commonType
-}
-
-// UintType represents a uint type.
-type UintType struct {
- commonType
-}
-
-// StringType represents a string type.
-type StringType struct {
- commonType
-}
-
-// UintptrType represents a uintptr type.
-type UintptrType struct {
- commonType
-}
-
-// DotDotDotType represents the ... that can
-// be used as the type of the final function parameter.
-type DotDotDotType struct {
- commonType
-}
-
-// UnsafePointerType represents an unsafe.Pointer type.
-type UnsafePointerType struct {
- commonType
-}
-
-// ArrayType represents a fixed array type.
-type ArrayType struct {
- commonType;
- 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;
- elem *runtime.Type;
- dir uintptr;
-}
-
-// FuncType represents a function type.
-type FuncType struct {
- commonType;
- in []*runtime.Type;
- out []*runtime.Type;
-}
-
-// Method on interface type
-type imethod struct {
- hash uint32;
- perm uint32;
- name *string;
- pkgPath *string;
- typ *runtime.Type;
-}
-
-// InterfaceType represents an interface type.
-type InterfaceType struct {
- commonType;
- methods []imethod;
-}
-
-// MapType represents a map type.
-type MapType struct {
- commonType;
- key *runtime.Type;
- elem *runtime.Type;
-}
-
-// PtrType represents a pointer type.
-type PtrType struct {
- commonType;
- elem *runtime.Type;
-}
-
-// SliceType represents a slice type.
-type SliceType struct {
- commonType;
- 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;
- 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.
- */
-
-type Type interface
-type addr unsafe.Pointer
-type FuncValue struct
-func newFuncValue(typ Type, addr addr) *FuncValue
-
-// 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 {
- // Name returns the type's package and name.
- // The package is a full package import path like "container/vector".
- Name() (pkgPath string, 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;
-
- // 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;
-
- // 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;
-}
-
-func toType(i interface{}) Type
-
-func (t *uncommonType) Name() (pkgPath string, name string) {
- if t == nil {
- return;
- }
- if t.pkgPath != nil {
- pkgPath = *t.pkgPath;
- }
- if t.name != nil {
- name = *t.name;
- }
- return;
-}
-
-func (t *commonType) String() string {
- return *t.string;
-}
-
-func (t *commonType) Size() uintptr {
- return t.size;
-}
-
-func (t *commonType) Align() int {
- return int(t.align);
-}
-
-func (t *commonType) FieldAlign() int {
- return int(t.fieldAlign);
-}
-
-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 = toType(*p.typ).(*FuncType);
- fn := p.tfn;
- m.Func = newFuncValue(m.Type, addr(&fn));
- 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) Name() (pkgPath string, 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 toType(*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 toType(*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 toType(*t.in[i]);
-}
-
-// 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 toType(*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 = toType(*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 toType(*t.key);
-}
-
-// Elem returns the map element type.
-func (t *MapType) Elem() Type {
- return toType(*t.elem);
-}
-
-// Elem returns the pointer element type.
-func (t *PtrType) Elem() Type {
- return toType(*t.elem);
-}
-
-// Elem returns the type of the slice's elements.
-func (t *SliceType) Elem() Type {
- return toType(*t.elem);
-}
-
-type StructField struct {
- PkgPath string; // empty for uppercase Name
- Name string;
- Type Type;
- Tag string;
- Offset uintptr;
- 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 = toType(*p.typ);
- if p.name != nil {
- f.Name = *p.name;
- } else {
- nam, pkg := f.Type.Name();
- f.Name = nam;
- f.Anonymous = true;
- }
- if p.pkgPath != nil {
- f.PkgPath = *p.pkgPath;
- }
- if p.tag != nil {
- f.Tag = *p.tag;
- }
- f.Offset = p.offset;
- return;
-}
-
-// NumField returns the number of struct fields.
-func (t *StructType) NumField() int {
- return len(t.fields);
-}
-
-// Convert runtime type to reflect type.
-// Same memory layouts, different method sets.
-func toType(i interface{}) Type {
- switch v := i.(type) {
- case *runtime.BoolType:
- return (*BoolType)(unsafe.Pointer(v));
- case *runtime.DotDotDotType:
- return (*DotDotDotType)(unsafe.Pointer(v));
- case *runtime.FloatType:
- return (*FloatType)(unsafe.Pointer(v));
- case *runtime.Float32Type:
- return (*Float32Type)(unsafe.Pointer(v));
- case *runtime.Float64Type:
- return (*Float64Type)(unsafe.Pointer(v));
- case *runtime.IntType:
- return (*IntType)(unsafe.Pointer(v));
- case *runtime.Int8Type:
- return (*Int8Type)(unsafe.Pointer(v));
- case *runtime.Int16Type:
- return (*Int16Type)(unsafe.Pointer(v));
- case *runtime.Int32Type:
- return (*Int32Type)(unsafe.Pointer(v));
- case *runtime.Int64Type:
- return (*Int64Type)(unsafe.Pointer(v));
- case *runtime.StringType:
- return (*StringType)(unsafe.Pointer(v));
- case *runtime.UintType:
- return (*UintType)(unsafe.Pointer(v));
- case *runtime.Uint8Type:
- return (*Uint8Type)(unsafe.Pointer(v));
- case *runtime.Uint16Type:
- return (*Uint16Type)(unsafe.Pointer(v));
- case *runtime.Uint32Type:
- return (*Uint32Type)(unsafe.Pointer(v));
- case *runtime.Uint64Type:
- return (*Uint64Type)(unsafe.Pointer(v));
- case *runtime.UintptrType:
- return (*UintptrType)(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));
- }
- panicln("toType", i);
-}
-
-// ArrayOrSliceType is the common interface implemented
-// by both ArrayType and SliceType.
-type ArrayOrSliceType interface {
- Type;
- Elem() Type;
-}
-
-
+++ /dev/null
-// 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.
-
-package reflect
-
-import (
- "reflect";
- "unsafe";
-)
-
-const cannotSet = "cannot set value obtained via unexported struct field"
-
-// TODO: This will have to go away when
-// the new gc goes in.
-func memmove(dst, src, n uintptr) {
- var p uintptr; // dummy for sizeof
- const ptrsize = uintptr(unsafe.Sizeof(p));
- switch {
- case src < dst && src+n > dst:
- // byte copy backward
- // careful: i is unsigned
- for i := n; i > 0; {
- i--;
- *(*byte)(addr(dst+i)) = *(*byte)(addr(src+i));
- }
- case (n|src|dst) & (ptrsize-1) != 0:
- // byte copy forward
- for i := uintptr(0); i < n; i++ {
- *(*byte)(addr(dst+i)) = *(*byte)(addr(src+i));
- }
- default:
- // word copy forward
- for i := uintptr(0); i < n; i += ptrsize {
- *(*uintptr)(addr(dst+i)) = *(*uintptr)(addr(src+i));
- }
- }
-}
-
-// Value is the common interface to reflection values.
-// The implementations of Value (e.g., ArrayValue, StructValue)
-// have additional type-specific methods.
-type Value interface {
- // Type returns the value's type.
- Type() Type;
-
- // Interface returns the value as an interface{}.
- Interface() interface{};
-
- // CanSet returns whether the value can be changed.
- // Values obtained by the use of non-exported struct fields
- // can be used in Get but not Set.
- // If CanSet() returns false, calling the type-specific Set
- // will cause a crash.
- CanSet() bool;
-
- // Addr returns a pointer to the underlying data.
- // It is for advanced clients that also
- // import the "unsafe" package.
- Addr() uintptr;
-}
-
-type value struct {
- typ Type;
- addr addr;
- canSet bool;
-}
-
-func (v *value) Type() Type {
- return v.typ
-}
-
-func (v *value) Addr() uintptr {
- return uintptr(v.addr);
-}
-
-type InterfaceValue struct
-type StructValue struct
-
-func (v *value) Interface() interface{} {
- if typ, ok := v.typ.(*InterfaceType); ok {
- // There are two different representations of interface values,
- // one if the interface type has methods and one if it doesn't.
- // These two representations require different expressions
- // to extract correctly.
- if typ.NumMethod() == 0 {
- // Extract as interface value without methods.
- return *(*interface{})(v.addr)
- }
- // Extract from v.addr as interface value with methods.
- return *(*interface{ m() })(v.addr)
- }
- return unsafe.Unreflect(v.typ, unsafe.Pointer(v.addr));
-}
-
-func (v *value) CanSet() bool {
- return v.canSet;
-}
-
-func newValue(typ Type, addr addr, canSet bool) Value
-func NewValue(i interface{}) Value
-
-/*
- * basic types
- */
-
-// BoolValue represents a bool value.
-type BoolValue struct {
- value;
-}
-
-// Get returns the underlying bool value.
-func (v *BoolValue) Get() bool {
- return *(*bool)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *BoolValue) Set(x bool) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*bool)(v.addr) = x;
-}
-
-// FloatValue represents a float value.
-type FloatValue struct {
- value;
-}
-
-// Get returns the underlying float value.
-func (v *FloatValue) Get() float {
- return *(*float)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *FloatValue) Set(x float) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*float)(v.addr) = x;
-}
-
-// Float32Value represents a float32 value.
-type Float32Value struct {
- value;
-}
-
-// Get returns the underlying float32 value.
-func (v *Float32Value) Get() float32 {
- return *(*float32)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Float32Value) Set(x float32) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*float32)(v.addr) = x;
-}
-
-// Float64Value represents a float64 value.
-type Float64Value struct {
- value;
-}
-
-// Get returns the underlying float64 value.
-func (v *Float64Value) Get() float64 {
- return *(*float64)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Float64Value) Set(x float64) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*float64)(v.addr) = x;
-}
-
-// IntValue represents an int value.
-type IntValue struct {
- value;
-}
-
-// Get returns the underlying int value.
-func (v *IntValue) Get() int {
- return *(*int)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *IntValue) Set(x int) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*int)(v.addr) = x;
-}
-
-// Int8Value represents an int8 value.
-type Int8Value struct {
- value;
-}
-
-// Get returns the underlying int8 value.
-func (v *Int8Value) Get() int8 {
- return *(*int8)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Int8Value) Set(x int8) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*int8)(v.addr) = x;
-}
-
-// Int16Value represents an int16 value.
-type Int16Value struct {
- value;
-}
-
-// Get returns the underlying int16 value.
-func (v *Int16Value) Get() int16 {
- return *(*int16)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Int16Value) Set(x int16) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*int16)(v.addr) = x;
-}
-
-// Int32Value represents an int32 value.
-type Int32Value struct {
- value;
-}
-
-// Get returns the underlying int32 value.
-func (v *Int32Value) Get() int32 {
- return *(*int32)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Int32Value) Set(x int32) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*int32)(v.addr) = x;
-}
-
-// Int64Value represents an int64 value.
-type Int64Value struct {
- value;
-}
-
-// Get returns the underlying int64 value.
-func (v *Int64Value) Get() int64 {
- return *(*int64)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Int64Value) Set(x int64) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*int64)(v.addr) = x;
-}
-
-// StringValue represents a string value.
-type StringValue struct {
- value;
-}
-
-// Get returns the underlying string value.
-func (v *StringValue) Get() string {
- return *(*string)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *StringValue) Set(x string) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*string)(v.addr) = x;
-}
-
-// UintValue represents a uint value.
-type UintValue struct {
- value;
-}
-
-// Get returns the underlying uint value.
-func (v *UintValue) Get() uint {
- return *(*uint)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *UintValue) Set(x uint) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*uint)(v.addr) = x;
-}
-
-// Uint8Value represents a uint8 value.
-type Uint8Value struct {
- value;
-}
-
-// Get returns the underlying uint8 value.
-func (v *Uint8Value) Get() uint8 {
- return *(*uint8)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Uint8Value) Set(x uint8) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*uint8)(v.addr) = x;
-}
-
-// Uint16Value represents a uint16 value.
-type Uint16Value struct {
- value;
-}
-
-// Get returns the underlying uint16 value.
-func (v *Uint16Value) Get() uint16 {
- return *(*uint16)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Uint16Value) Set(x uint16) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*uint16)(v.addr) = x;
-}
-
-// Uint32Value represents a uint32 value.
-type Uint32Value struct {
- value;
-}
-
-// Get returns the underlying uint32 value.
-func (v *Uint32Value) Get() uint32 {
- return *(*uint32)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Uint32Value) Set(x uint32) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*uint32)(v.addr) = x;
-}
-
-// Uint64Value represents a uint64 value.
-type Uint64Value struct {
- value;
-}
-
-// Get returns the underlying uint64 value.
-func (v *Uint64Value) Get() uint64 {
- return *(*uint64)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *Uint64Value) Set(x uint64) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*uint64)(v.addr) = x;
-}
-
-// UintptrValue represents a uintptr value.
-type UintptrValue struct {
- value;
-}
-
-// Get returns the underlying uintptr value.
-func (v *UintptrValue) Get() uintptr {
- return *(*uintptr)(v.addr);
-}
-
-// Set sets v to the value x.
-func (v *UintptrValue) Set(x uintptr) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*uintptr)(v.addr) = x;
-}
-
-// UnsafePointerValue represents an unsafe.Pointer value.
-type UnsafePointerValue struct {
- value;
-}
-
-// Get returns the underlying uintptr value.
-// Get returns uintptr, not unsafe.Pointer, so that
-// programs that do not import "unsafe" cannot
-// obtain a value of unsafe.Pointer type from "reflect".
-func (v *UnsafePointerValue) Get() uintptr {
- return uintptr(*(*unsafe.Pointer)(v.addr));
-}
-
-// Set sets v to the value x.
-func (v *UnsafePointerValue) Set(x unsafe.Pointer) {
- if !v.canSet {
- panic(cannotSet);
- }
- *(*unsafe.Pointer)(v.addr) = x;
-}
-
-func typesMustMatch(t1, t2 reflect.Type) {
- if t1 != t2 {
- panicln("type mismatch:", t1, "!=", t2);
- }
-}
-
-/*
- * array
- */
-
-// ArrayOrSliceValue is the common interface
-// implemented by both ArrayValue and SliceValue.
-type ArrayOrSliceValue interface {
- Value;
- Len() int;
- Cap() int;
- Elem(i int) Value;
- addr() addr;
-}
-
-// ArrayCopy copies the contents of src into dst until either
-// dst has been filled or src has been exhausted.
-// It returns the number of elements copied.
-// The arrays dst and src must have the same element type.
-func ArrayCopy(dst, src ArrayOrSliceValue) int {
- // TODO: This will have to move into the runtime
- // once the real gc goes in.
- de := dst.Type().(ArrayOrSliceType).Elem();
- se := src.Type().(ArrayOrSliceType).Elem();
- typesMustMatch(de, se);
- n := dst.Len();
- if xn := src.Len(); n > xn {
- n = xn;
- }
- memmove(uintptr(dst.addr()), uintptr(src.addr()), uintptr(n) * de.Size());
- return n;
-}
-
-// An ArrayValue represents an array.
-type ArrayValue struct {
- value
-}
-
-// Len returns the length of the array.
-func (v *ArrayValue) Len() int {
- return v.typ.(*ArrayType).Len();
-}
-
-// Cap returns the capacity of the array (equal to Len()).
-func (v *ArrayValue) Cap() int {
- return v.typ.(*ArrayType).Len();
-}
-
-// addr returns the base address of the data in the array.
-func (v *ArrayValue) addr() addr {
- return v.value.addr;
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *ArrayValue) Set(x *ArrayValue) {
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- ArrayCopy(v, x);
-}
-
-// Elem returns the i'th element of v.
-func (v *ArrayValue) Elem(i int) Value {
- typ := v.typ.(*ArrayType).Elem();
- n := v.Len();
- if i < 0 || i >= n {
- panic("index", i, "in array len", n);
- }
- p := addr(uintptr(v.addr()) + uintptr(i)*typ.Size());
- return newValue(typ, p, v.canSet);
-}
-
-/*
- * slice
- */
-
-// runtime representation of slice
-type SliceHeader struct {
- Data uintptr;
- Len uint32;
- Cap uint32;
-}
-
-// A SliceValue represents a slice.
-type SliceValue struct {
- value
-}
-
-func (v *SliceValue) slice() *SliceHeader {
- return (*SliceHeader)(v.value.addr);
-}
-
-// IsNil returns whether v is a nil slice.
-func (v *SliceValue) IsNil() bool {
- return v.slice().Data == 0;
-}
-
-// Len returns the length of the slice.
-func (v *SliceValue) Len() int {
- return int(v.slice().Len);
-}
-
-// Cap returns the capacity of the slice.
-func (v *SliceValue) Cap() int {
- return int(v.slice().Cap);
-}
-
-// addr returns the base address of the data in the slice.
-func (v *SliceValue) addr() addr {
- return addr(v.slice().Data);
-}
-
-// SetLen changes the length of v.
-// The new length n must be between 0 and the capacity, inclusive.
-func (v *SliceValue) SetLen(n int) {
- s := v.slice();
- if n < 0 || n > int(s.Cap) {
- panicln("SetLen", n, "with capacity", s.Cap);
- }
- s.Len = uint32(n);
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *SliceValue) Set(x *SliceValue) {
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- *v.slice() = *x.slice();
-}
-
-// Slice returns a sub-slice of the slice v.
-func (v *SliceValue) Slice(beg, end int) *SliceValue {
- cap := v.Cap();
- if beg < 0 || end < beg || end > cap {
- panic("slice bounds [", beg, ":", end, "] with capacity ", cap);
- }
- typ := v.typ.(*SliceType);
- s := new(SliceHeader);
- s.Data = uintptr(v.addr()) + uintptr(beg) * typ.Elem().Size();
- s.Len = uint32(end - beg);
- s.Cap = uint32(cap - beg);
- return newValue(typ, addr(s), v.canSet).(*SliceValue);
-}
-
-// Elem returns the i'th element of v.
-func (v *SliceValue) Elem(i int) Value {
- typ := v.typ.(*SliceType).Elem();
- n := v.Len();
- if i < 0 || i >= n {
- panicln("index", i, "in array of length", n);
- }
- p := addr(uintptr(v.addr()) + uintptr(i)*typ.Size());
- return newValue(typ, p, v.canSet);
-}
-
-// MakeSlice creates a new zero-initialized slice value
-// for the specified slice type, length, and capacity.
-func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
- s := new(SliceHeader);
- size := typ.Elem().Size() * uintptr(cap);
- if size == 0 {
- size = 1;
- }
- data := make([]uint8, size);
- s.Data = uintptr(addr(&data[0]));
- s.Len = uint32(len);
- s.Cap = uint32(cap);
- return newValue(typ, addr(s), true).(*SliceValue);
-}
-
-/*
- * chan
- */
-
-// A ChanValue represents a chan.
-type ChanValue struct {
- value
-}
-
-// IsNil returns whether v is a nil channel.
-func (v *ChanValue) IsNil() bool {
- return *(*uintptr)(v.addr) == 0;
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *ChanValue) Set(x *ChanValue) {
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
-}
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *ChanValue) Get() uintptr {
- return *(*uintptr)(v.addr);
-}
-
-// Send sends x on the channel v.
-func (v *ChanValue) Send(x Value) {
- panic("unimplemented: channel Send");
-}
-
-// Recv receives and returns a value from the channel v.
-func (v *ChanValue) Recv() Value {
- panic("unimplemented: channel Receive");
-}
-
-// TrySend attempts to sends x on the channel v but will not block.
-// It returns true if the value was sent, false otherwise.
-func (v *ChanValue) TrySend(x Value) bool {
- panic("unimplemented: channel TrySend");
-}
-
-// TryRecv attempts to receive a value from the channel v but will not block.
-// It returns the value if one is received, nil otherwise.
-func (v *ChanValue) TryRecv() Value {
- panic("unimplemented: channel TryRecv");
-}
-
-/*
- * func
- */
-
-// A FuncValue represents a function value.
-type FuncValue struct {
- value
-}
-
-// IsNil returns whether v is a nil function.
-func (v *FuncValue) IsNil() bool {
- return *(*uintptr)(v.addr) == 0;
-}
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *FuncValue) Get() uintptr {
- return *(*uintptr)(v.addr);
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *FuncValue) Set(x *FuncValue) {
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
-}
-
-// Call calls the function v with input parameters in.
-// It returns the function's output parameters as Values.
-func (v *FuncValue) Call(in []Value) []Value {
- panic("unimplemented: function Call");
-}
-
-
-/*
- * interface
- */
-
-// An InterfaceValue represents an interface value.
-type InterfaceValue struct {
- value
-}
-
-// No Get because v.Interface() is available.
-
-// IsNil returns whether v is a nil interface value.
-func (v *InterfaceValue) IsNil() bool {
- return v.Interface() == nil;
-}
-
-// Elem returns the concrete value stored in the interface value v.
-func (v *InterfaceValue) Elem() Value {
- return NewValue(v.Interface());
-}
-
-// Set assigns x to v.
-func (v *InterfaceValue) Set(x interface{}) {
- if !v.canSet {
- panic(cannotSet);
- }
- // Two different representations; see comment in Get.
- // Empty interface is easy.
- if v.typ.(*InterfaceType).NumMethod() == 0 {
- *(*interface{})(v.addr) = x;
- }
-
- // Non-empty interface requires a runtime check.
- panic("unimplemented: interface Set");
-// unsafe.SetInterface(v.typ, v.addr, x);
-}
-
-/*
- * map
- */
-
-// A MapValue represents a map value.
-type MapValue struct {
- value
-}
-
-// IsNil returns whether v is a nil map value.
-func (v *MapValue) IsNil() bool {
- return *(*uintptr)(v.addr) == 0;
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *MapValue) Set(x *MapValue) {
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
-}
-
-// Elem returns the value associated with key in the map v.
-// It returns nil if key is not found in the map.
-func (v *MapValue) Elem(key Value) Value {
- panic("unimplemented: map Elem");
-}
-
-// Len returns the number of keys in the map v.
-func (v *MapValue) Len() int {
- panic("unimplemented: map Len");
-}
-
-// Keys returns a slice containing all the keys present in the map,
-// in unspecified order.
-func (v *MapValue) Keys() []Value {
- panic("unimplemented: map Keys");
-}
-
-/*
- * ptr
- */
-
-// A PtrValue represents a pointer.
-type PtrValue struct {
- value
-}
-
-// IsNil returns whether v is a nil pointer.
-func (v *PtrValue) IsNil() bool {
- return *(*uintptr)(v.addr) == 0;
-}
-
-// Get returns the uintptr value of v.
-// It is mainly useful for printing.
-func (v *PtrValue) Get() uintptr {
- return *(*uintptr)(v.addr);
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *PtrValue) Set(x *PtrValue) {
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- // TODO: This will have to move into the runtime
- // once the new gc goes in
- *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
-}
-
-// PointTo changes v to point to x.
-func (v *PtrValue) PointTo(x Value) {
- if !x.CanSet() {
- panic("cannot set x; cannot point to x");
- }
- typesMustMatch(v.typ.(*PtrType).Elem(), x.Type());
- // TODO: This will have to move into the runtime
- // once the new gc goes in.
- *(*uintptr)(v.addr) = x.Addr();
-}
-
-// Elem returns the value that v points to.
-// If v is a nil pointer, Elem returns a nil Value.
-func (v *PtrValue) Elem() Value {
- if v.IsNil() {
- return nil;
- }
- return newValue(v.typ.(*PtrType).Elem(), *(*addr)(v.addr), v.canSet);
-}
-
-// Indirect returns the value that v points to.
-// If v is a nil pointer, Indirect returns a nil Value.
-// If v is not a pointer, Indirect returns v.
-func Indirect(v Value) Value {
- if pv, ok := v.(*PtrValue); ok {
- return pv.Elem();
- }
- return v;
-}
-
-/*
- * struct
- */
-
-// A StructValue represents a struct value.
-type StructValue struct {
- value
-}
-
-// Set assigns x to v.
-// The new value x must have the same type as v.
-func (v *StructValue) Set(x *StructValue) {
- // TODO: This will have to move into the runtime
- // once the gc goes in.
- if !v.canSet {
- panic(cannotSet);
- }
- typesMustMatch(v.typ, x.typ);
- memmove(uintptr(v.addr), uintptr(x.addr), v.typ.Size());
-}
-
-// Field returns the i'th field of the struct.
-func (v *StructValue) Field(i int) Value {
- t := v.typ.(*StructType);
- if i < 0 || i >= t.NumField() {
- return nil;
- }
- f := t.Field(i);
- return newValue(f.Type, addr(uintptr(v.addr)+f.Offset), v.canSet && f.PkgPath == "");
-}
-
-// NumField returns the number of fields in the struct.
-func (v *StructValue) NumField() int {
- return v.typ.(*StructType).NumField();
-}
-
-/*
- * constructors
- */
-
-// Typeof returns the reflection Type of the value in the interface{}.
-func Typeof(i interface{}) Type {
- return toType(unsafe.Typeof(i));
-}
-
-// NewValue returns a new Value initialized to the concrete value
-// stored in the interface i. NewValue(nil) returns nil.
-func NewValue(i interface{}) Value {
- if i == nil {
- return nil;
- }
- t, a := unsafe.Reflect(i);
- return newValue(toType(t), addr(a), true);
-}
-
-func newValue(typ Type, addr addr, canSet bool) Value {
- // All values have same memory layout;
- // build once and convert.
- v := &struct{value}{value{typ, addr, canSet}};
- switch t := typ.(type) { // TODO(rsc): s/t := // ?
- case *ArrayType:
- // TODO(rsc): Something must prevent
- // clients of the package from doing
- // this same kind of cast.
- // We should be allowed because
- // they're our types.
- // Something about implicit assignment
- // to struct fields.
- return (*ArrayValue)(v);
- case *BoolType:
- return (*BoolValue)(v);
- case *ChanType:
- return (*ChanValue)(v);
- case *FloatType:
- return (*FloatValue)(v);
- case *Float32Type:
- return (*Float32Value)(v);
- case *Float64Type:
- return (*Float64Value)(v);
- case *FuncType:
- return (*FuncValue)(v);
- case *IntType:
- return (*IntValue)(v);
- case *Int8Type:
- return (*Int8Value)(v);
- case *Int16Type:
- return (*Int16Value)(v);
- case *Int32Type:
- return (*Int32Value)(v);
- case *Int64Type:
- return (*Int64Value)(v);
- case *InterfaceType:
- return (*InterfaceValue)(v);
- case *MapType:
- return (*MapValue)(v);
- case *PtrType:
- return (*PtrValue)(v);
- case *SliceType:
- return (*SliceValue)(v);
- case *StringType:
- return (*StringValue)(v);
- case *StructType:
- return (*StructValue)(v);
- case *UintType:
- return (*UintValue)(v);
- case *Uint8Type:
- return (*Uint8Value)(v);
- case *Uint16Type:
- return (*Uint16Value)(v);
- case *Uint32Type:
- return (*Uint32Value)(v);
- case *Uint64Type:
- return (*Uint64Value)(v);
- case *UintptrType:
- return (*UintptrValue)(v);
- case *UnsafePointerType:
- return (*UnsafePointerValue)(v);
- }
- panicln("newValue", typ.String());
-}
-
-func newFuncValue(typ Type, addr addr) *FuncValue {
- return newValue(typ, addr, true).(*FuncValue);
-}
-
-// MakeZeroValue returns a zero Value for the specified Type.
-func MakeZero(typ Type) Value {
- // TODO: this will have to move into
- // the runtime proper in order to play nicely
- // with the garbage collector.
- size := typ.Size();
- if size == 0 {
- size = 1;
- }
- data := make([]uint8, size);
- return newValue(typ, addr(&data[0]), true);
-}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Reflection library.
-// Types and parsing of type strings.
-
-// This package implements data ``reflection''. A program can use it to analyze types
-// and values it does not know at compile time, such as the values passed in a call
-// to a function with a ... parameter. This is achieved by extracting the dynamic
-// contents of an interface value.
package reflect
import (
- "sync";
+ "runtime";
+ "strconv";
+ "strings";
"unsafe";
- "utf8";
-)
-
-type Type interface
-
-func ExpandType(name string) Type
-
-func typestrings() string // implemented in C; declared here
-
-// These constants identify what kind of thing a Type represents: an int, struct, etc.
-const (
- MissingKind = iota;
- ArrayKind;
- BoolKind;
- ChanKind;
- DotDotDotKind;
- FloatKind;
- Float32Kind;
- Float64Kind;
- FuncKind;
- IntKind;
- Int16Kind;
- Int32Kind;
- Int64Kind;
- Int8Kind;
- InterfaceKind;
- MapKind;
- PtrKind;
- StringKind;
- StructKind;
- UintKind;
- Uint16Kind;
- Uint32Kind;
- Uint64Kind;
- Uint8Kind;
- UintptrKind;
)
-// For sizes and alignments.
-
-type allTypes struct {
- xarray []byte;
- xbool bool;
- xchan chan byte;
- xfloat float;
- xfloat32 float32;
- xfloat64 float64;
- xfunc func();
- xint int;
- xint16 int16;
- xint32 int32;
- xint64 int64;
- xint8 int8;
- xinterface interface {};
- xmap map[byte]byte;
- xptr *byte;
- xslice []byte;
- xstring string;
- xuint uint;
- xuint16 uint16;
- xuint32 uint32;
- xuint64 uint64;
- xuint8 uint8;
- xuintptr uintptr;
-}
-
-var (
- x allTypes;
- minStruct struct { uint8 };
-)
-
-const (
- minStructAlignMask = unsafe.Sizeof(minStruct) - 1;
- ptrsize = unsafe.Sizeof(&x);
- interfacesize = unsafe.Sizeof(x.xinterface);
-)
-
-const missingString = "$missing$" // syntactic name for undefined type names
-const dotDotDotString = "..."
-
-// Type is the generic interface to reflection types. Once its Kind is known,
-// such as ArrayKind, the Type can be narrowed to the appropriate, more
-// specific interface, such as ArrayType. Such narrowed types still implement
-// the Type interface.
-type Type interface {
- // The kind of thing described: ArrayKind, BoolKind, etc.
- Kind() int;
- // The name declared for the type ("int", "BoolArray", etc.).
- Name() string;
- // For a named type, same as Name(); otherwise a representation of the type such as "[]int".
- String() string;
- // The number of bytes needed to store a value; analogous to unsafe.Sizeof().
- Size() int;
- // The alignment of a value of this type when used as a field in a struct.
- FieldAlign() int;
-}
+/*
+ * 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.
+ */
+
+type uncommonType struct
-// Fields and methods common to all types
type commonType struct {
- kind int;
- str string;
- name string;
- size int;
+ size uintptr;
+ hash uint32;
+ alg uint8;
+ align uint8;
+ fieldAlign uint8;
+ string *string;
+ *uncommonType;
}
-func (c *commonType) Kind() int {
- return c.kind
+type method struct {
+ hash uint32;
+ name *string;
+ pkgPath *string;
+ typ *runtime.Type;
+ ifn unsafe.Pointer;
+ tfn unsafe.Pointer;
}
-func (c *commonType) Name() string {
- return c.name
+type uncommonType struct {
+ name *string;
+ pkgPath *string;
+ methods []method;
}
-func (c *commonType) String() string {
- // If there is a name, show that instead of its expansion.
- // This is important for reflection: a named type
- // might have methods that the unnamed type does not.
- if c.name != "" {
- return c.name
- }
- return c.str
+// BoolType represents a boolean type.
+type BoolType struct {
+ commonType
}
-func (c *commonType) Size() int {
- return c.size
+// Float32Type represents a float32 type.
+type Float32Type struct {
+ commonType
}
-// -- Basic
-
-type basicType struct {
- commonType;
- fieldAlign int;
+// Float64Type represents a float64 type.
+type Float64Type struct {
+ commonType
}
-func newBasicType(name string, kind int, size int, fieldAlign int) Type {
- return &basicType{ commonType{kind, name, name, size}, fieldAlign }
+// FloatType represents a float type.
+type FloatType struct {
+ commonType
}
-func (t *basicType) FieldAlign() int {
- return t.fieldAlign
+// Int16Type represents an int16 type.
+type Int16Type struct {
+ commonType
}
-// Prebuilt basic Type objects representing the predeclared basic types.
-// Most are self-evident except:
-// Missing represents types whose representation cannot be discovered; usually an error.
-// DotDotDot represents the pseudo-type of a ... parameter.
-var (
- Missing = newBasicType(missingString, MissingKind, 1, 1);
- DotDotDot = newBasicType(dotDotDotString, DotDotDotKind, unsafe.Sizeof(x.xinterface), unsafe.Alignof(x.xinterface));
- Bool = newBasicType("bool", BoolKind, unsafe.Sizeof(x.xbool), unsafe.Alignof(x.xbool));
- Int = newBasicType("int", IntKind, unsafe.Sizeof(x.xint), unsafe.Alignof(x.xint));
- Int8 = newBasicType("int8", Int8Kind, unsafe.Sizeof(x.xint8), unsafe.Alignof(x.xint8));
- Int16 = newBasicType("int16", Int16Kind, unsafe.Sizeof(x.xint16), unsafe.Alignof(x.xint16));
- Int32 = newBasicType("int32", Int32Kind, unsafe.Sizeof(x.xint32), unsafe.Alignof(x.xint32));
- Int64 = newBasicType("int64", Int64Kind, unsafe.Sizeof(x.xint64), unsafe.Alignof(x.xint64));
- Uint = newBasicType("uint", UintKind, unsafe.Sizeof(x.xuint), unsafe.Alignof(x.xuint));
- Uint8 = newBasicType("uint8", Uint8Kind, unsafe.Sizeof(x.xuint8), unsafe.Alignof(x.xuint8));
- Uint16 = newBasicType("uint16", Uint16Kind, unsafe.Sizeof(x.xuint16), unsafe.Alignof(x.xuint16));
- Uint32 = newBasicType("uint32", Uint32Kind, unsafe.Sizeof(x.xuint32), unsafe.Alignof(x.xuint32));
- Uint64 = newBasicType("uint64", Uint64Kind, unsafe.Sizeof(x.xuint64), unsafe.Alignof(x.xuint64));
- Uintptr = newBasicType("uintptr", UintptrKind, unsafe.Sizeof(x.xuintptr), unsafe.Alignof(x.xuintptr));
- Float = newBasicType("float", FloatKind, unsafe.Sizeof(x.xfloat), unsafe.Alignof(x.xfloat));
- Float32 = newBasicType("float32", Float32Kind, unsafe.Sizeof(x.xfloat32), unsafe.Alignof(x.xfloat32));
- Float64 = newBasicType("float64", Float64Kind, unsafe.Sizeof(x.xfloat64), unsafe.Alignof(x.xfloat64));
- String = newBasicType("string", StringKind, unsafe.Sizeof(x.xstring), unsafe.Alignof(x.xstring));
-)
-
-// Stub types allow us to defer evaluating type names until needed.
-// If the name is empty, the type must be non-nil.
-
-type stubType struct {
- name string;
- typ Type;
+// Int32Type represents an int32 type.
+type Int32Type struct {
+ commonType
}
-func newStubType(name string, typ Type) *stubType {
- return &stubType{name, typ}
+// Int64Type represents an int64 type.
+type Int64Type struct {
+ commonType
}
-func (t *stubType) Get() Type {
- if t.typ == nil {
- t.typ = ExpandType(t.name)
- }
- return t.typ
+// Int8Type represents an int8 type.
+type Int8Type struct {
+ commonType
}
-// -- Pointer
-
-// PtrType represents a pointer.
-type PtrType interface {
- Type;
- Sub() Type // The type of the pointed-to item; for "*int", it will be "int".
+// IntType represents an int type.
+type IntType struct {
+ commonType
}
-type ptrTypeStruct struct {
- commonType;
- sub *stubType;
+// Uint16Type represents a uint16 type.
+type Uint16Type struct {
+ commonType
}
-func newPtrTypeStruct(name, typestring string, sub *stubType) *ptrTypeStruct {
- return &ptrTypeStruct{ commonType{PtrKind, typestring, name, ptrsize}, sub}
+// Uint32Type represents a uint32 type.
+type Uint32Type struct {
+ commonType
}
-func (t *ptrTypeStruct) FieldAlign() int {
- return unsafe.Alignof(x.xptr);
+// Uint64Type represents a uint64 type.
+type Uint64Type struct {
+ commonType
}
-func (t *ptrTypeStruct) Sub() Type {
- return t.sub.Get()
+// Uint8Type represents a uint8 type.
+type Uint8Type struct {
+ commonType
}
-// -- Array
-
-// ArrayType represents an array or slice type.
-type ArrayType interface {
- Type;
- IsSlice() bool; // True for slices, false for arrays.
- Len() int; // 0 for slices, the length for array types.
- Elem() Type; // The type of the elements.
+// UintType represents a uint type.
+type UintType struct {
+ commonType
}
-type arrayTypeStruct struct {
- commonType;
- elem *stubType;
- isslice bool; // otherwise fixed array
- len int;
+// StringType represents a string type.
+type StringType struct {
+ commonType
}
-func newArrayTypeStruct(name, typestring string, open bool, len int, elem *stubType) *arrayTypeStruct {
- return &arrayTypeStruct{ commonType{ArrayKind, typestring, name, 0 }, elem, open, len}
+// UintptrType represents a uintptr type.
+type UintptrType struct {
+ commonType
}
-func (t *arrayTypeStruct) Size() int {
- if t.isslice {
- return unsafe.Sizeof(x.xslice);
- }
- return t.len * t.elem.Get().Size();
-}
-
-func (t *arrayTypeStruct) FieldAlign() int {
- if t.isslice {
- return unsafe.Alignof(x.xslice);
- }
- return t.elem.Get().FieldAlign();
+// DotDotDotType represents the ... that can
+// be used as the type of the final function parameter.
+type DotDotDotType struct {
+ commonType
}
-func (t *arrayTypeStruct) IsSlice() bool {
- return t.isslice
+// UnsafePointerType represents an unsafe.Pointer type.
+type UnsafePointerType struct {
+ commonType
}
-func (t *arrayTypeStruct) Len() int {
- if t.isslice {
- return 0
- }
- return t.len
-}
-
-func (t *arrayTypeStruct) Elem() Type {
- return t.elem.Get()
+// ArrayType represents a fixed array type.
+type ArrayType struct {
+ commonType;
+ elem *runtime.Type;
+ len uintptr;
}
-// -- Map
-
-// MapType represents a map type.
-type MapType interface {
- Type;
- Key() Type; // The type of the keys.
- Elem() Type; // The type of the elements/values.
-}
+// ChanDir represents a channel type's direction.
+type ChanDir int
+const (
+ RecvDir ChanDir = 1<<iota;
+ SendDir;
+ BothDir = RecvDir | SendDir;
+)
-type mapTypeStruct struct {
+// ChanType represents a channel type.
+type ChanType struct {
commonType;
- key *stubType;
- elem *stubType;
+ elem *runtime.Type;
+ dir uintptr;
}
-func newMapTypeStruct(name, typestring string, key, elem *stubType) *mapTypeStruct {
- return &mapTypeStruct{ commonType{MapKind, typestring, name, ptrsize}, key, elem}
+// FuncType represents a function type.
+type FuncType struct {
+ commonType;
+ in []*runtime.Type;
+ out []*runtime.Type;
}
-func (t *mapTypeStruct) FieldAlign() int {
- return unsafe.Alignof(x.xmap);
+// Method on interface type
+type imethod struct {
+ hash uint32;
+ perm uint32;
+ name *string;
+ pkgPath *string;
+ typ *runtime.Type;
}
-func (t *mapTypeStruct) Key() Type {
- return t.key.Get()
+// InterfaceType represents an interface type.
+type InterfaceType struct {
+ commonType;
+ methods []imethod;
}
-func (t *mapTypeStruct) Elem() Type {
- return t.elem.Get()
+// MapType represents a map type.
+type MapType struct {
+ commonType;
+ key *runtime.Type;
+ elem *runtime.Type;
}
-// -- Chan
-
-// ChanType represents a chan type.
-type ChanType interface {
- Type;
- Dir() int; // The direction of the channel.
- Elem() Type; // The type of the elements.
+// PtrType represents a pointer type.
+type PtrType struct {
+ commonType;
+ elem *runtime.Type;
}
-// Channel direction.
-const (
- SendDir = 1 << iota;
- RecvDir;
- BothDir = SendDir | RecvDir;
-)
-
-type chanTypeStruct struct {
+// SliceType represents a slice type.
+type SliceType struct {
commonType;
- elem *stubType;
- dir int;
+ elem *runtime.Type;
}
-func newChanTypeStruct(name, typestring string, dir int, elem *stubType) *chanTypeStruct {
- return &chanTypeStruct{ commonType{ChanKind, typestring, name, ptrsize}, elem, dir}
+// Struct field
+type structField struct {
+ name *string;
+ pkgPath *string;
+ typ *runtime.Type;
+ tag *string;
+ offset uintptr;
}
-func (t *chanTypeStruct) FieldAlign() int {
- return unsafe.Alignof(x.xchan);
+// StructType represents a struct type.
+type StructType struct {
+ commonType;
+ fields []structField;
}
-func (t *chanTypeStruct) Dir() int {
- return t.dir
-}
-func (t *chanTypeStruct) Elem() Type {
- return t.elem.Get()
-}
+/*
+ * The compiler knows the exact layout of all the data structures above.
+ * The compiler does not know about the data structures and methods below.
+ */
-// -- Struct
+type Type interface
+type addr unsafe.Pointer
+type FuncValue struct
+func newFuncValue(typ Type, addr addr) *FuncValue
+
+// 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 {
+ // Name returns the type's package and name.
+ // The package is a full package import path like "container/vector".
+ Name() (pkgPath string, 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;
-// StructType represents a struct type.
-type StructType interface {
- Type;
- // Field returns, for field i, its name, Type, tag information, and byte offset.
- // The indices are in declaration order starting at 0.
- Field(i int) (name string, typ Type, tag string, offset int);
- // Len is the number of fields.
- Len() int;
-}
+ // Size returns the number of bytes needed to store
+ // a value of the given type; it is analogous to unsafe.Sizeof.
+ Size() uintptr;
-type structField struct {
- name string;
- typ *stubType;
- tag string;
- offset int;
-}
+ // Align returns the alignment of a value of this type
+ // when allocated in memory.
+ Align() int;
-type structTypeStruct struct {
- commonType;
- field []structField;
- fieldAlign int;
-}
+ // FieldAlign returns the alignment of a value of this type
+ // when used as a field in a struct.
+ FieldAlign() int;
-func newStructTypeStruct(name, typestring string, field []structField) *structTypeStruct {
- return &structTypeStruct{ commonType{StructKind, typestring, name, 0}, field, 0}
+ // 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;
}
-func (t *structTypeStruct) FieldAlign() int {
- t.Size(); // Compute size and alignment.
- return t.fieldAlign
-}
+func toType(i interface{}) Type
-func (t *structTypeStruct) Size() int {
- if t.size > 0 {
- return t.size
+func (t *uncommonType) Name() (pkgPath string, name string) {
+ if t == nil {
+ return;
}
- size := 0;
- structAlignMask := 0;
- for i := 0; i < len(t.field); i++ {
- typ := t.field[i].typ.Get();
- elemsize := typ.Size();
- alignMask := typ.FieldAlign() - 1;
- if alignMask > structAlignMask {
- structAlignMask = alignMask
- }
- if alignMask > 0 {
- size = (size + alignMask) &^ alignMask;
- }
- t.field[i].offset = size;
- size += elemsize;
+ if t.pkgPath != nil {
+ pkgPath = *t.pkgPath;
}
- if structAlignMask > 0 {
- // 6g etc. always aligns structs to a minimum size, typically int64
- if structAlignMask < minStructAlignMask {
- structAlignMask = minStructAlignMask
- }
- // TODO: In the PPC64 ELF ABI, floating point fields
- // in a struct are aligned to a 4-byte boundary, but
- // if the first field in the struct is a 64-bit float,
- // the whole struct is aligned to an 8-byte boundary.
- size = (size + structAlignMask) &^ structAlignMask;
- t.fieldAlign = structAlignMask + 1;
+ if t.name != nil {
+ name = *t.name;
}
- t.size = size;
- return size;
+ return;
}
-func (t *structTypeStruct) Field(i int) (name string, typ Type, tag string, offset int) {
- if t.field[i].offset == 0 {
- t.Size(); // will compute offsets
- }
- return t.field[i].name, t.field[i].typ.Get(), t.field[i].tag, t.field[i].offset
+func (t *commonType) String() string {
+ return *t.string;
}
-func (t *structTypeStruct) Len() int {
- return len(t.field)
+func (t *commonType) Size() uintptr {
+ return t.size;
}
-// -- Interface
-
-// InterfaceType represents an interface type.
-// It behaves much like a StructType, treating the methods as fields.
-type InterfaceType interface {
- Type;
- // Field returns, for method i, its name, Type, the empty string, and 0.
- // The indices are in declaration order starting at 0. TODO: is this true?
- Field(int) (name string, typ Type, tag string, offset int);
- Len() int;
+func (t *commonType) Align() int {
+ return int(t.align);
}
-type interfaceTypeStruct struct {
- commonType;
- field []structField;
+func (t *commonType) FieldAlign() int {
+ return int(t.fieldAlign);
}
-func newInterfaceTypeStruct(name, typestring string, field []structField) *interfaceTypeStruct {
- return &interfaceTypeStruct{ commonType{InterfaceKind, typestring, name, interfacesize}, field }
+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 = toType(*p.typ).(*FuncType);
+ fn := p.tfn;
+ m.Func = newFuncValue(m.Type, addr(&fn));
+ return;
}
-func (t *interfaceTypeStruct) FieldAlign() int {
- return unsafe.Alignof(x.xinterface);
+func (t *uncommonType) NumMethod() int {
+ if t == nil {
+ return 0;
+ }
+ return len(t.methods);
}
-func (t *interfaceTypeStruct) Field(i int) (name string, typ Type, tag string, offset int) {
- return t.field[i].name, t.field[i].typ.Get(), "", 0
+// 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 *interfaceTypeStruct) Len() int {
- return len(t.field)
+func (t *commonType) Method(i int) (m Method) {
+ return t.uncommonType.Method(i);
}
-var nilInterface = newInterfaceTypeStruct("nil", "", make([]structField, 0));
-
-// -- Func
-
-// FuncType represents a function type.
-type FuncType interface {
- Type;
- In() StructType; // The parameters in the form of a StructType.
- Out() StructType; // The results in the form of a StructType.
+func (t *commonType) Name() (pkgPath string, name string) {
+ return t.uncommonType.Name();
}
-type funcTypeStruct struct {
- commonType;
- in *structTypeStruct;
- out *structTypeStruct;
+// Len returns the number of elements in the array.
+func (t *ArrayType) Len() int {
+ return int(t.len);
}
-func newFuncTypeStruct(name, typestring string, in, out *structTypeStruct) *funcTypeStruct {
- return &funcTypeStruct{ commonType{FuncKind, typestring, name, ptrsize}, in, out }
+// Elem returns the type of the array's elements.
+func (t *ArrayType) Elem() Type {
+ return toType(*t.elem);
}
-func (t *funcTypeStruct) FieldAlign() int {
- return unsafe.Alignof(x.xfunc);
+// Dir returns the channel direction.
+func (t *ChanType) Dir() ChanDir {
+ return ChanDir(t.dir);
}
-func (t *funcTypeStruct) In() StructType {
- return t.in
+// Elem returns the channel's element type.
+func (t *ChanType) Elem() Type {
+ return toType(*t.elem);
}
-func (t *funcTypeStruct) Out() StructType {
- if t.out == nil { // nil.(StructType) != nil so make sure caller sees real nil
- return nil
+func (d ChanDir) String() string {
+ switch d {
+ case SendDir:
+ return "chan<-";
+ case RecvDir:
+ return "<-chan";
+ case BothDir:
+ return "chan";
}
- return t.out
+ return "ChanDir" + strconv.Itoa(int(d));
}
-// Cache of expanded types keyed by type name.
-var types map[string] Type
-
-// List of typename, typestring pairs
-var typestring map[string] string
-var initialized bool = false
-
-// Map of basic types to prebuilt stubTypes
-var basicstub map[string] *stubType
-
-var missingStub *stubType;
-var dotDotDotStub *stubType;
-
-// The database stored in the maps is global; use locking to guarantee safety.
-var typestringlock sync.Mutex
-
-func lock() {
- typestringlock.Lock()
-}
-
-func unlock() {
- typestringlock.Unlock()
-}
-
-func init() {
- lock(); // not necessary because of init ordering but be safe.
-
- types = make(map[string] Type);
- typestring = make(map[string] string);
- basicstub = make(map[string] *stubType);
-
- // Basics go into types table
- types[missingString] = Missing;
- types[dotDotDotString] = DotDotDot;
- types["int"] = Int;
- types["int8"] = Int8;
- types["int16"] = Int16;
- types["int32"] = Int32;
- types["int64"] = Int64;
- types["uint"] = Uint;
- types["uint8"] = Uint8;
- types["uint16"] = Uint16;
- types["uint32"] = Uint32;
- types["uint64"] = Uint64;
- types["uintptr"] = Uintptr;
- types["float"] = Float;
- types["float32"] = Float32;
- types["float64"] = Float64;
- types["string"] = String;
- types["bool"] = Bool;
-
- // Basics get prebuilt stubs
- missingStub = newStubType(missingString, Missing);
- dotDotDotStub = newStubType(dotDotDotString, DotDotDot);
- basicstub[missingString] = missingStub;
- basicstub[dotDotDotString] = dotDotDotStub;
- basicstub["int"] = newStubType("int", Int);
- basicstub["int8"] = newStubType("int8", Int8);
- basicstub["int16"] = newStubType("int16", Int16);
- basicstub["int32"] = newStubType("int32", Int32);
- basicstub["int64"] = newStubType("int64", Int64);
- basicstub["uint"] = newStubType("uint", Uint);
- basicstub["uint8"] = newStubType("uint8", Uint8);
- basicstub["uint16"] = newStubType("uint16", Uint16);
- basicstub["uint32"] = newStubType("uint32", Uint32);
- basicstub["uint64"] = newStubType("uint64", Uint64);
- basicstub["uintptr"] = newStubType("uintptr", Uintptr);
- basicstub["float"] = newStubType("float", Float);
- basicstub["float32"] = newStubType("float32", Float32);
- basicstub["float64"] = newStubType("float64", Float64);
- basicstub["string"] = newStubType("string", String);
- basicstub["bool"] = newStubType("bool", Bool);
-
- unlock();
-}
-
-/*
- Parsing of type strings. These strings are how the run-time recovers type
- information dynamically.
-
- Grammar
-
- stubtype = - represent as StubType when possible
- type
- identifier =
- name
- '?'
- type =
- basictypename - int8, string, etc.
- typename
- arraytype
- structtype
- interfacetype
- chantype
- maptype
- pointertype
- functiontype
- typename =
- name '.' name
- doublequotedstring =
- string in " "; escapes are \x00 (NUL) \n \t \" \\
- fieldlist =
- [ field { [ ',' | ';' ] field } ]
- field =
- identifier stubtype [ doublequotedstring ]
- arraytype =
- '[' [ number ] ']' stubtype
- structtype =
- 'struct' '{' fieldlist '}'
- interfacetype =
- 'interface' '{' fieldlist '}'
- chantype =
- '<-' 'chan' stubtype
- 'chan' '<-' stubtype
- 'chan' stubtype
- maptype =
- 'map' '[' stubtype ']' stubtype
- pointertype =
- '*' stubtype
- functiontype =
- [ 'func' ] '(' fieldlist ')' [ '(' fieldlist ')' | stubtype ]
-
- In functiontype 'func' is optional because it is omitted in
- the reflection string for interface types.
-
-*/
-
-// Helper functions for token scanning
-func isdigit(c uint8) bool {
- return '0' <= c && c <= '9'
-}
-
-func special(c uint8) bool {
- s := "*[](){}<;,"; // Note: '.' is not in this list. "P.T" is an identifer, as is "?".
- for i := 0; i < len(s); i++ {
- if c == s[i] {
- return true
- }
+// 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 false;
+ return toType(*t.in[i]);
}
-func hex00(s string, i int) bool {
- return i + 2 < len(s) && s[i] == '0' && s[i+1] == '0'
+// NumIn returns the number of input parameters.
+func (t *FuncType) NumIn() int {
+ return len(t.in);
}
-// Process backslashes. String known to be well-formed.
-// Initial double-quote is left in, as an indication this token is a string.
-func unescape(s string, backslash bool) string {
- if !backslash {
- return s
- }
- out := "\"";
- for i := 1; i < len(s); i++ {
- c := s[i];
- if c == '\\' {
- i++;
- c = s[i];
- switch c {
- case 'n':
- c = '\n';
- case 't':
- c = '\t';
- case 'x':
- if hex00(s, i+1) {
- i += 2;
- c = 0;
- break;
- }
- // otherwise just put an 'x'; erroneous but safe.
- // default is correct already; \\ is \; \" is "
- }
- }
- out += string(c);
+// 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 out;
-}
-
-// Simple parser for type strings
-type typeParser struct {
- str string; // string being parsed
- token string; // the token being parsed now
- tokstart int; // starting position of token
- prevend int; // (one after) ending position of previous token
- index int; // next character position in str
+ return toType(*t.out[i]);
}
-// Return typestring starting at position i. It will finish at the
-// end of the previous token (before trailing white space).
-func (p *typeParser) TypeString(i int) string {
- return p.str[i:p.prevend];
+// NumOut returns the number of function output parameters.
+func (t *FuncType) NumOut() int {
+ return len(t.out);
}
-// Load next token into p.token
-func (p *typeParser) Next() {
- p.prevend = p.index;
- token := "";
- for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ {
- }
- p.tokstart = p.index;
- if p.index >= len(p.str) {
- p.token = "";
- return;
- }
- start := p.index;
- c, w := utf8.DecodeRuneInString(p.str[p.index:len(p.str)]);
- p.index += w;
- switch {
- case c == '<':
- if p.index < len(p.str) && p.str[p.index] == '-' {
- p.index++;
- p.token = "<-";
- return;
- }
- fallthrough; // shouldn't happen but let the parser figure it out
- case c == '.':
- if p.index < len(p.str)+2 && p.str[p.index-1:p.index+2] == dotDotDotString {
- p.index += 2;
- p.token = dotDotDotString;
- return;
- }
- fallthrough; // shouldn't happen but let the parser figure it out
- case special(uint8(c)):
- p.token = string(c);
- return;
- case isdigit(uint8(c)):
- for p.index < len(p.str) && isdigit(p.str[p.index]) {
- p.index++
- }
- p.token = p.str[start : p.index];
- return;
- case c == '"': // double-quoted string for struct field annotation
- backslash := false;
- for p.index < len(p.str) && p.str[p.index] != '"' {
- if p.str[p.index] == '\\' {
- if p.index+1 == len(p.str) { // bad final backslash
- break;
- }
- p.index++; // skip (and accept) backslash
- backslash = true;
- }
- p.index++
- }
- p.token = unescape(p.str[start : p.index], backslash);
- if p.index < len(p.str) { // properly terminated string
- p.index++; // skip the terminating double-quote
- }
+// Method returns the i'th interface method.
+func (t *InterfaceType) Method(i int) (m Method) {
+ if i < 0 || i >= len(t.methods) {
return;
}
- for p.index < len(p.str) && p.str[p.index] != ' ' && !special(p.str[p.index]) {
- p.index++
+ p := t.methods[i];
+ m.Name = *p.name;
+ if p.pkgPath != nil {
+ m.PkgPath = *p.pkgPath;
}
- p.token = p.str[start : p.index];
+ m.Type = toType(*p.typ).(*FuncType);
+ return;
}
-func (p *typeParser) Type(name string) *stubType
-
-func (p *typeParser) Array(name string, tokstart int) *stubType {
- size := 0;
- open := true;
- if p.token != "]" {
- if len(p.token) == 0 || !isdigit(p.token[0]) {
- return missingStub
- }
- // write our own (trivial and simpleminded) atoi to avoid dependency
- size = 0;
- for i := 0; i < len(p.token); i++ {
- size = size * 10 + int(p.token[i]) - '0'
- }
- p.Next();
- open = false;
- }
- if p.token != "]" {
- return missingStub
- }
- p.Next();
- elemtype := p.Type("");
- return newStubType(name, newArrayTypeStruct(name, p.TypeString(tokstart), open, size, elemtype));
+// NumMethod returns the number of interface methods.
+func (t *InterfaceType) NumMethod() int {
+ return len(t.methods);
}
-func (p *typeParser) Map(name string, tokstart int) *stubType {
- if p.token != "[" {
- return missingStub
- }
- p.Next();
- keytype := p.Type("");
- if p.token != "]" {
- return missingStub
- }
- p.Next();
- elemtype := p.Type("");
- return newStubType(name, newMapTypeStruct(name, p.TypeString(tokstart), keytype, elemtype));
+// Key returns the map key type.
+func (t *MapType) Key() Type {
+ return toType(*t.key);
}
-func (p *typeParser) Chan(name string, tokstart, dir int) *stubType {
- if p.token == "<-" {
- if dir != BothDir {
- return missingStub
- }
- p.Next();
- dir = SendDir;
- }
- elemtype := p.Type("");
- return newStubType(name, newChanTypeStruct(name, p.TypeString(tokstart), dir, elemtype));
+// Elem returns the map element type.
+func (t *MapType) Elem() Type {
+ return toType(*t.elem);
}
-// Parse array of fields for struct, interface, and func arguments
-func (p *typeParser) Fields(sep, term string) []structField {
- a := make([]structField, 10);
- nf := 0;
- for p.token != "" && p.token != term {
- if nf == len(a) {
- a1 := make([]structField, 2*nf);
- for i := 0; i < nf; i++ {
- a1[i] = a[i];
- }
- a = a1;
- }
- name := p.token;
- if name == "?" { // used to represent a missing name
- name = ""
- }
- a[nf].name = name;
- p.Next();
- a[nf].typ = p.Type("");
- if p.token != "" && p.token[0] == '"' {
- a[nf].tag = p.token[1:len(p.token)];
- p.Next();
- }
- nf++;
- if p.token != sep {
- break;
- }
- p.Next(); // skip separator
- }
- return a[0:nf];
+// Elem returns the pointer element type.
+func (t *PtrType) Elem() Type {
+ return toType(*t.elem);
}
-// A single type packaged as a field for a function return
-func (p *typeParser) OneField() []structField {
- a := make([]structField, 1);
- a[0].name = "";
- a[0].typ = p.Type("");
- return a;
+// Elem returns the type of the slice's elements.
+func (t *SliceType) Elem() Type {
+ return toType(*t.elem);
}
-func (p *typeParser) Struct(name string, tokstart int) *stubType {
- f := p.Fields(";", "}");
- if p.token != "}" {
- return missingStub;
- }
- p.Next();
- return newStubType(name, newStructTypeStruct(name, p.TypeString(tokstart), f));
-}
-
-func (p *typeParser) Interface(name string, tokstart int) *stubType {
- f := p.Fields(";", "}");
- if p.token != "}" {
- return missingStub;
- }
- p.Next();
- return newStubType(name, newInterfaceTypeStruct(name, p.TypeString(tokstart), f));
+type StructField struct {
+ PkgPath string; // empty for uppercase Name
+ Name string;
+ Type Type;
+ Tag string;
+ Offset uintptr;
+ Anonymous bool;
}
-func (p *typeParser) Func(name string, tokstart int) *stubType {
- // may be 1 or 2 parenthesized lists
- f1 := newStructTypeStruct("", "", p.Fields(",", ")"));
- if p.token != ")" {
- return missingStub;
+// Field returns the i'th struct field.
+func (t *StructType) Field(i int) (f StructField) {
+ if i < 0 || i >= len(t.fields) {
+ return;
}
- p.Next();
- if p.token != "(" {
- // 1 list: the in parameters are a list. Is there a single out parameter?
- switch p.token {
- case "", "}", ")", ",", ";":
- return newStubType(name, newFuncTypeStruct(name, p.TypeString(tokstart), f1, nil));
- }
- // A single out parameter.
- f2 := newStructTypeStruct("", "", p.OneField());
- return newStubType(name, newFuncTypeStruct(name, p.TypeString(tokstart), f1, f2));
+ p := t.fields[i];
+ f.Type = toType(*p.typ);
+ if p.name != nil {
+ f.Name = *p.name;
} else {
- p.Next();
- }
- f2 := newStructTypeStruct("", "", p.Fields(",", ")"));
- if p.token != ")" {
- return missingStub;
- }
- p.Next();
- // 2 lists: the in and out parameters are present
- return newStubType(name, newFuncTypeStruct(name, p.TypeString(tokstart), f1, f2));
-}
-
-func (p *typeParser) Type(name string) *stubType {
- dir := BothDir;
- tokstart := p.tokstart;
- switch {
- case p.token == "":
- return nil;
- case p.token == "*":
- p.Next();
- sub := p.Type("");
- return newStubType(name, newPtrTypeStruct(name, p.TypeString(tokstart), sub));
- case p.token == "[":
- p.Next();
- return p.Array(name, tokstart);
- case p.token == "map":
- p.Next();
- return p.Map(name, tokstart);
- case p.token == "<-":
- p.Next();
- dir = RecvDir;
- if p.token != "chan" {
- return missingStub;
- }
- fallthrough;
- case p.token == "chan":
- p.Next();
- return p.Chan(name, tokstart, dir);
- case p.token == "struct":
- p.Next();
- if p.token != "{" {
- return missingStub
- }
- p.Next();
- return p.Struct(name, tokstart);
- case p.token == "interface":
- p.Next();
- if p.token != "{" {
- return missingStub
- }
- p.Next();
- return p.Interface(name, tokstart);
- case p.token == "func":
- p.Next();
- if p.token != "(" {
- return missingStub
- }
- p.Next();
- return p.Func(name, tokstart);
- case p.token == "(":
- p.Next();
- return p.Func(name, tokstart);
- case isdigit(p.token[0]):
- p.Next();
- return missingStub;
- case special(p.token[0]):
- p.Next();
- return missingStub;
- }
- // must be an identifier. is it basic? if so, we have a stub
- if s, ok := basicstub[p.token]; ok {
- p.Next();
- if name != "" {
- // Need to make a copy because we are renaming a basic type
- b := s.Get();
- s = newStubType(name, newBasicType(name, b.Kind(), b.Size(), b.FieldAlign()));
- }
- return s
- }
- // not a basic - must be of the form "P.T"
- ndot := 0;
- for i := 0; i < len(p.token); i++ {
- if p.token[i] == '.' {
- ndot++
- }
- }
- if ndot != 1 {
- p.Next();
- return missingStub;
- }
- s := newStubType(p.token, nil);
- p.Next();
- return s;
-}
-
-// ParseTypeString takes a type name and type string (such as "[]int") and
-// returns the Type structure representing a type name specifying the corresponding
-// type. An empty typestring represents (the type of) a nil interface value.
-func ParseTypeString(name, typestring string) Type {
- if typestring == "" {
- // If the typestring is empty, it represents (the type of) a nil interface value
- return nilInterface
- }
- p := new(typeParser);
- p.str = typestring;
- p.Next();
- return p.Type(name).Get();
+ nam, pkg := f.Type.Name();
+ f.Name = nam;
+ f.Anonymous = true;
+ }
+ if p.pkgPath != nil {
+ f.PkgPath = *p.pkgPath;
+ }
+ if p.tag != nil {
+ f.Tag = *p.tag;
+ }
+ f.Offset = p.offset;
+ return;
+}
+
+// NumField returns the number of struct fields.
+func (t *StructType) NumField() int {
+ return len(t.fields);
+}
+
+// Convert runtime type to reflect type.
+// Same memory layouts, different method sets.
+func toType(i interface{}) Type {
+ switch v := i.(type) {
+ case *runtime.BoolType:
+ return (*BoolType)(unsafe.Pointer(v));
+ case *runtime.DotDotDotType:
+ return (*DotDotDotType)(unsafe.Pointer(v));
+ case *runtime.FloatType:
+ return (*FloatType)(unsafe.Pointer(v));
+ case *runtime.Float32Type:
+ return (*Float32Type)(unsafe.Pointer(v));
+ case *runtime.Float64Type:
+ return (*Float64Type)(unsafe.Pointer(v));
+ case *runtime.IntType:
+ return (*IntType)(unsafe.Pointer(v));
+ case *runtime.Int8Type:
+ return (*Int8Type)(unsafe.Pointer(v));
+ case *runtime.Int16Type:
+ return (*Int16Type)(unsafe.Pointer(v));
+ case *runtime.Int32Type:
+ return (*Int32Type)(unsafe.Pointer(v));
+ case *runtime.Int64Type:
+ return (*Int64Type)(unsafe.Pointer(v));
+ case *runtime.StringType:
+ return (*StringType)(unsafe.Pointer(v));
+ case *runtime.UintType:
+ return (*UintType)(unsafe.Pointer(v));
+ case *runtime.Uint8Type:
+ return (*Uint8Type)(unsafe.Pointer(v));
+ case *runtime.Uint16Type:
+ return (*Uint16Type)(unsafe.Pointer(v));
+ case *runtime.Uint32Type:
+ return (*Uint32Type)(unsafe.Pointer(v));
+ case *runtime.Uint64Type:
+ return (*Uint64Type)(unsafe.Pointer(v));
+ case *runtime.UintptrType:
+ return (*UintptrType)(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));
+ }
+ panicln("toType", i);
+}
+
+// ArrayOrSliceType is the common interface implemented
+// by both ArrayType and SliceType.
+type ArrayOrSliceType interface {
+ Type;
+ Elem() Type;
}
-// Create typestring map from reflect.typestrings() data. Lock is held.
-func initializeTypeStrings() {
- if initialized {
- return
- }
- initialized = true;
- s := typestrings();
- slen := len(s);
- for i := 0; i < slen; {
- // "reflect.PtrType interface { Sub () (? reflect.Type) }\n"
- // find the identifier
- idstart := i;
- for ; i < slen && s[i] != ' '; i++ {
- }
- if i == slen {
- print("reflect.InitializeTypeStrings: bad identifier\n");
- return;
- }
- idend := i;
- i++;
- // find the end of the line, terminating the type
- typestart := i;
- for ; i < slen && s[i] != '\n'; i++ {
- }
- if i == slen {
- print("reflect.InitializeTypeStrings: bad type string\n");
- return;
- }
- typeend := i;
- i++; //skip newline
- typestring[s[idstart:idend]] = s[typestart:typeend];
- }
-}
-// Look up type string associated with name. Lock is held.
-func typeNameToTypeString(name string) string {
- s, ok := typestring[name];
- if !ok {
- initializeTypeStrings();
- s, ok = typestring[name];
- if !ok {
- s = missingString;
- typestring[name] = s;
- }
- }
- return s
-}
-
-// ExpandType takes the name of a type and returns its Type structure,
-// unpacking the associated type string if necessary.
-func ExpandType(name string) Type {
- lock();
- t, ok := types[name];
- if ok {
- unlock();
- return t
- }
- types[name] = Missing; // prevent recursion; will overwrite
- t1 := ParseTypeString(name, typeNameToTypeString(name));
- types[name] = t1;
- unlock();
- return t1;
-}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Reflection library.
-// Handling values.
-
package reflect
import (
"unsafe";
)
-// Addr is shorthand for unsafe.Pointer and is used to represent the address of Values.
-type Addr unsafe.Pointer
+const cannotSet = "cannot set value obtained via unexported struct field"
-func equalType(a, b Type) bool {
- return a.Kind() == b.Kind() && a.String() == b.String()
+// TODO: This will have to go away when
+// the new gc goes in.
+func memmove(dst, src, n uintptr) {
+ var p uintptr; // dummy for sizeof
+ const ptrsize = uintptr(unsafe.Sizeof(p));
+ switch {
+ case src < dst && src+n > dst:
+ // byte copy backward
+ // careful: i is unsigned
+ for i := n; i > 0; {
+ i--;
+ *(*byte)(addr(dst+i)) = *(*byte)(addr(src+i));
+ }
+ case (n|src|dst) & (ptrsize-1) != 0:
+ // byte copy forward
+ for i := uintptr(0); i < n; i++ {
+ *(*byte)(addr(dst+i)) = *(*byte)(addr(src+i));
+ }
+ default:
+ // word copy forward
+ for i := uintptr(0); i < n; i += ptrsize {
+ *(*uintptr)(addr(dst+i)) = *(*uintptr)(addr(src+i));
+ }
+ }
}
-// Value is the generic interface to reflection values. Once its Kind is known,
-// such as BoolKind, the Value can be narrowed to the appropriate, more
-// specific interface, such as BoolValue. Such narrowed values still implement
-// the Value interface.
+// Value is the common interface to reflection values.
+// The implementations of Value (e.g., ArrayValue, StructValue)
+// have additional type-specific methods.
type Value interface {
- // The kind of thing described: ArrayKind, BoolKind, etc.
- Kind() int;
- // The reflection Type of the value.
+ // Type returns the value's type.
Type() Type;
- // The address of the value.
- Addr() Addr;
- // The value itself is the dynamic value of an empty interface.
- Interface() interface {};
-}
-func NewValue(e interface{}) Value;
+ // Interface returns the value as an interface{}.
+ Interface() interface{};
-// commonValue fields and functionality for all values
+ // CanSet returns whether the value can be changed.
+ // Values obtained by the use of non-exported struct fields
+ // can be used in Get but not Set.
+ // If CanSet() returns false, calling the type-specific Set
+ // will cause a crash.
+ CanSet() bool;
-type commonValue struct {
- kind int;
- typ Type;
- addr Addr;
+ // Addr returns a pointer to the underlying data.
+ // It is for advanced clients that also
+ // import the "unsafe" package.
+ Addr() uintptr;
}
-func (c *commonValue) Kind() int {
- return c.kind
+type value struct {
+ typ Type;
+ addr addr;
+ canSet bool;
}
-func (c *commonValue) Type() Type {
- return c.typ
+func (v *value) Type() Type {
+ return v.typ
}
-func (c *commonValue) Addr() Addr {
- return c.addr
+func (v *value) Addr() uintptr {
+ return uintptr(v.addr);
}
-func (c *commonValue) Interface() interface {} {
- var i interface {};
- switch {
- case c.typ.Kind() == InterfaceKind:
- panic("not reached"); // InterfaceValue overrides this method
- case c.typ.Size() > unsafe.Sizeof(uintptr(0)):
- i = unsafe.Unreflect(uint64(uintptr(c.addr)), c.typ.String(), true);
- default:
- if uintptr(c.addr) == 0 {
- panicln("reflect: address 0 for", c.typ.String());
+type InterfaceValue struct
+type StructValue struct
+
+func (v *value) Interface() interface{} {
+ if typ, ok := v.typ.(*InterfaceType); ok {
+ // There are two different representations of interface values,
+ // one if the interface type has methods and one if it doesn't.
+ // These two representations require different expressions
+ // to extract correctly.
+ if typ.NumMethod() == 0 {
+ // Extract as interface value without methods.
+ return *(*interface{})(v.addr)
}
- i = unsafe.Unreflect(uint64(uintptr(*(*Addr)(c.addr))), c.typ.String(), false);
+ // Extract from v.addr as interface value with methods.
+ return *(*interface{ m() })(v.addr)
}
- return i;
+ return unsafe.Unreflect(v.typ, unsafe.Pointer(v.addr));
}
-func newValueAddr(typ Type, addr Addr) Value
-
-type creatorFn func(typ Type, addr Addr) Value
+func (v *value) CanSet() bool {
+ return v.canSet;
+}
+func newValue(typ Type, addr addr, canSet bool) Value
+func NewValue(i interface{}) Value
-// -- Missing
+/*
+ * basic types
+ */
-// MissingValue represents a value whose type is not known. It usually
-// indicates an error.
-type MissingValue interface {
- Value;
+// BoolValue represents a bool value.
+type BoolValue struct {
+ value;
}
-type missingValueStruct struct {
- commonValue
+// Get returns the underlying bool value.
+func (v *BoolValue) Get() bool {
+ return *(*bool)(v.addr);
}
-func missingCreator(typ Type, addr Addr) Value {
- return &missingValueStruct{ commonValue{MissingKind, typ, addr} }
+// Set sets v to the value x.
+func (v *BoolValue) Set(x bool) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*bool)(v.addr) = x;
}
-// -- Int
-
-// IntValue represents an int value.
-type IntValue interface {
- Value;
- Get() int; // Get the underlying int.
- Set(int); // Set the underlying int.
+// FloatValue represents a float value.
+type FloatValue struct {
+ value;
}
-type intValueStruct struct {
- commonValue
+// Get returns the underlying float value.
+func (v *FloatValue) Get() float {
+ return *(*float)(v.addr);
}
-func intCreator(typ Type, addr Addr) Value {
- return &intValueStruct{ commonValue{IntKind, typ, addr} }
+// Set sets v to the value x.
+func (v *FloatValue) Set(x float) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*float)(v.addr) = x;
}
-func (v *intValueStruct) Get() int {
- return *(*int)(v.addr)
+// Float32Value represents a float32 value.
+type Float32Value struct {
+ value;
}
-func (v *intValueStruct) Set(i int) {
- *(*int)(v.addr) = i
+// Get returns the underlying float32 value.
+func (v *Float32Value) Get() float32 {
+ return *(*float32)(v.addr);
}
-// -- Int8
-
-// Int8Value represents an int8 value.
-type Int8Value interface {
- Value;
- Get() int8; // Get the underlying int8.
- Set(int8); // Set the underlying int8.
+// Set sets v to the value x.
+func (v *Float32Value) Set(x float32) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*float32)(v.addr) = x;
}
-type int8ValueStruct struct {
- commonValue
+// Float64Value represents a float64 value.
+type Float64Value struct {
+ value;
}
-func int8Creator(typ Type, addr Addr) Value {
- return &int8ValueStruct{ commonValue{Int8Kind, typ, addr} }
+// Get returns the underlying float64 value.
+func (v *Float64Value) Get() float64 {
+ return *(*float64)(v.addr);
}
-func (v *int8ValueStruct) Get() int8 {
- return *(*int8)(v.addr)
+// Set sets v to the value x.
+func (v *Float64Value) Set(x float64) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*float64)(v.addr) = x;
}
-func (v *int8ValueStruct) Set(i int8) {
- *(*int8)(v.addr) = i
+// IntValue represents an int value.
+type IntValue struct {
+ value;
}
-// -- Int16
-
-// Int16Value represents an int16 value.
-type Int16Value interface {
- Value;
- Get() int16; // Get the underlying int16.
- Set(int16); // Set the underlying int16.
+// Get returns the underlying int value.
+func (v *IntValue) Get() int {
+ return *(*int)(v.addr);
}
-type int16ValueStruct struct {
- commonValue
+// Set sets v to the value x.
+func (v *IntValue) Set(x int) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*int)(v.addr) = x;
}
-func int16Creator(typ Type, addr Addr) Value {
- return &int16ValueStruct{ commonValue{Int16Kind, typ, addr} }
+// Int8Value represents an int8 value.
+type Int8Value struct {
+ value;
}
-func (v *int16ValueStruct) Get() int16 {
- return *(*int16)(v.addr)
+// Get returns the underlying int8 value.
+func (v *Int8Value) Get() int8 {
+ return *(*int8)(v.addr);
}
-func (v *int16ValueStruct) Set(i int16) {
- *(*int16)(v.addr) = i
+// Set sets v to the value x.
+func (v *Int8Value) Set(x int8) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*int8)(v.addr) = x;
}
-// -- Int32
-
-// Int32Value represents an int32 value.
-type Int32Value interface {
- Value;
- Get() int32; // Get the underlying int32.
- Set(int32); // Set the underlying int32.
+// Int16Value represents an int16 value.
+type Int16Value struct {
+ value;
}
-type int32ValueStruct struct {
- commonValue
+// Get returns the underlying int16 value.
+func (v *Int16Value) Get() int16 {
+ return *(*int16)(v.addr);
}
-func int32Creator(typ Type, addr Addr) Value {
- return &int32ValueStruct{ commonValue{Int32Kind, typ, addr} }
+// Set sets v to the value x.
+func (v *Int16Value) Set(x int16) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*int16)(v.addr) = x;
}
-func (v *int32ValueStruct) Get() int32 {
- return *(*int32)(v.addr)
+// Int32Value represents an int32 value.
+type Int32Value struct {
+ value;
}
-func (v *int32ValueStruct) Set(i int32) {
- *(*int32)(v.addr) = i
+// Get returns the underlying int32 value.
+func (v *Int32Value) Get() int32 {
+ return *(*int32)(v.addr);
}
-// -- Int64
-
-// Int64Value represents an int64 value.
-type Int64Value interface {
- Value;
- Get() int64; // Get the underlying int64.
- Set(int64); // Set the underlying int64.
+// Set sets v to the value x.
+func (v *Int32Value) Set(x int32) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*int32)(v.addr) = x;
}
-type int64ValueStruct struct {
- commonValue
+// Int64Value represents an int64 value.
+type Int64Value struct {
+ value;
}
-func int64Creator(typ Type, addr Addr) Value {
- return &int64ValueStruct{ commonValue{Int64Kind, typ, addr} }
+// Get returns the underlying int64 value.
+func (v *Int64Value) Get() int64 {
+ return *(*int64)(v.addr);
}
-func (v *int64ValueStruct) Get() int64 {
- return *(*int64)(v.addr)
+// Set sets v to the value x.
+func (v *Int64Value) Set(x int64) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*int64)(v.addr) = x;
}
-func (v *int64ValueStruct) Set(i int64) {
- *(*int64)(v.addr) = i
+// StringValue represents a string value.
+type StringValue struct {
+ value;
}
-// -- Uint
-
-// UintValue represents a uint value.
-type UintValue interface {
- Value;
- Get() uint; // Get the underlying uint.
- Set(uint); // Set the underlying uint.
+// Get returns the underlying string value.
+func (v *StringValue) Get() string {
+ return *(*string)(v.addr);
}
-type uintValueStruct struct {
- commonValue
+// Set sets v to the value x.
+func (v *StringValue) Set(x string) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*string)(v.addr) = x;
}
-func uintCreator(typ Type, addr Addr) Value {
- return &uintValueStruct{ commonValue{UintKind, typ, addr} }
+// UintValue represents a uint value.
+type UintValue struct {
+ value;
}
-func (v *uintValueStruct) Get() uint {
- return *(*uint)(v.addr)
+// Get returns the underlying uint value.
+func (v *UintValue) Get() uint {
+ return *(*uint)(v.addr);
}
-func (v *uintValueStruct) Set(i uint) {
- *(*uint)(v.addr) = i
+// Set sets v to the value x.
+func (v *UintValue) Set(x uint) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*uint)(v.addr) = x;
}
-// -- Uint8
-
// Uint8Value represents a uint8 value.
-type Uint8Value interface {
- Value;
- Get() uint8; // Get the underlying uint8.
- Set(uint8); // Set the underlying uint8.
-}
-
-type uint8ValueStruct struct {
- commonValue
+type Uint8Value struct {
+ value;
}
-func uint8Creator(typ Type, addr Addr) Value {
- return &uint8ValueStruct{ commonValue{Uint8Kind, typ, addr} }
+// Get returns the underlying uint8 value.
+func (v *Uint8Value) Get() uint8 {
+ return *(*uint8)(v.addr);
}
-func (v *uint8ValueStruct) Get() uint8 {
- return *(*uint8)(v.addr)
-}
-
-func (v *uint8ValueStruct) Set(i uint8) {
- *(*uint8)(v.addr) = i
+// Set sets v to the value x.
+func (v *Uint8Value) Set(x uint8) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*uint8)(v.addr) = x;
}
-// -- Uint16
-
// Uint16Value represents a uint16 value.
-type Uint16Value interface {
- Value;
- Get() uint16; // Get the underlying uint16.
- Set(uint16); // Set the underlying uint16.
-}
-
-type uint16ValueStruct struct {
- commonValue
+type Uint16Value struct {
+ value;
}
-func uint16Creator(typ Type, addr Addr) Value {
- return &uint16ValueStruct{ commonValue{Uint16Kind, typ, addr} }
+// Get returns the underlying uint16 value.
+func (v *Uint16Value) Get() uint16 {
+ return *(*uint16)(v.addr);
}
-func (v *uint16ValueStruct) Get() uint16 {
- return *(*uint16)(v.addr)
-}
-
-func (v *uint16ValueStruct) Set(i uint16) {
- *(*uint16)(v.addr) = i
+// Set sets v to the value x.
+func (v *Uint16Value) Set(x uint16) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*uint16)(v.addr) = x;
}
-// -- Uint32
-
// Uint32Value represents a uint32 value.
-type Uint32Value interface {
- Value;
- Get() uint32; // Get the underlying uint32.
- Set(uint32); // Set the underlying uint32.
-}
-
-type uint32ValueStruct struct {
- commonValue
+type Uint32Value struct {
+ value;
}
-func uint32Creator(typ Type, addr Addr) Value {
- return &uint32ValueStruct{ commonValue{Uint32Kind, typ, addr} }
+// Get returns the underlying uint32 value.
+func (v *Uint32Value) Get() uint32 {
+ return *(*uint32)(v.addr);
}
-func (v *uint32ValueStruct) Get() uint32 {
- return *(*uint32)(v.addr)
-}
-
-func (v *uint32ValueStruct) Set(i uint32) {
- *(*uint32)(v.addr) = i
+// Set sets v to the value x.
+func (v *Uint32Value) Set(x uint32) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*uint32)(v.addr) = x;
}
-// -- Uint64
-
// Uint64Value represents a uint64 value.
-type Uint64Value interface {
- Value;
- Get() uint64; // Get the underlying uint64.
- Set(uint64); // Set the underlying uint64.
-}
-
-type uint64ValueStruct struct {
- commonValue
+type Uint64Value struct {
+ value;
}
-func uint64Creator(typ Type, addr Addr) Value {
- return &uint64ValueStruct{ commonValue{Uint64Kind, typ, addr} }
+// Get returns the underlying uint64 value.
+func (v *Uint64Value) Get() uint64 {
+ return *(*uint64)(v.addr);
}
-func (v *uint64ValueStruct) Get() uint64 {
- return *(*uint64)(v.addr)
-}
-
-func (v *uint64ValueStruct) Set(i uint64) {
- *(*uint64)(v.addr) = i
+// Set sets v to the value x.
+func (v *Uint64Value) Set(x uint64) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*uint64)(v.addr) = x;
}
-// -- Uintptr
-
// UintptrValue represents a uintptr value.
-type UintptrValue interface {
- Value;
- Get() uintptr; // Get the underlying uintptr.
- Set(uintptr); // Set the underlying uintptr.
-}
-
-type uintptrValueStruct struct {
- commonValue
-}
-
-func uintptrCreator(typ Type, addr Addr) Value {
- return &uintptrValueStruct{ commonValue{UintptrKind, typ, addr} }
-}
-
-func (v *uintptrValueStruct) Get() uintptr {
- return *(*uintptr)(v.addr)
+type UintptrValue struct {
+ value;
}
-func (v *uintptrValueStruct) Set(i uintptr) {
- *(*uintptr)(v.addr) = i
+// Get returns the underlying uintptr value.
+func (v *UintptrValue) Get() uintptr {
+ return *(*uintptr)(v.addr);
}
-// -- Float
-
-// FloatValue represents a float value.
-type FloatValue interface {
- Value;
- Get() float; // Get the underlying float.
- Set(float); // Get the underlying float.
+// Set sets v to the value x.
+func (v *UintptrValue) Set(x uintptr) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*uintptr)(v.addr) = x;
}
-type floatValueStruct struct {
- commonValue
+// UnsafePointerValue represents an unsafe.Pointer value.
+type UnsafePointerValue struct {
+ value;
}
-func floatCreator(typ Type, addr Addr) Value {
- return &floatValueStruct{ commonValue{FloatKind, typ, addr} }
+// Get returns the underlying uintptr value.
+// Get returns uintptr, not unsafe.Pointer, so that
+// programs that do not import "unsafe" cannot
+// obtain a value of unsafe.Pointer type from "reflect".
+func (v *UnsafePointerValue) Get() uintptr {
+ return uintptr(*(*unsafe.Pointer)(v.addr));
}
-func (v *floatValueStruct) Get() float {
- return *(*float)(v.addr)
+// Set sets v to the value x.
+func (v *UnsafePointerValue) Set(x unsafe.Pointer) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ *(*unsafe.Pointer)(v.addr) = x;
}
-func (v *floatValueStruct) Set(f float) {
- *(*float)(v.addr) = f
+func typesMustMatch(t1, t2 reflect.Type) {
+ if t1 != t2 {
+ panicln("type mismatch:", t1, "!=", t2);
+ }
}
-// -- Float32
+/*
+ * array
+ */
-// Float32Value represents a float32 value.
-type Float32Value interface {
+// ArrayOrSliceValue is the common interface
+// implemented by both ArrayValue and SliceValue.
+type ArrayOrSliceValue interface {
Value;
- Get() float32; // Get the underlying float32.
- Set(float32); // Get the underlying float32.
-}
-
-type float32ValueStruct struct {
- commonValue
-}
-
-func float32Creator(typ Type, addr Addr) Value {
- return &float32ValueStruct{ commonValue{Float32Kind, typ, addr} }
-}
-
-func (v *float32ValueStruct) Get() float32 {
- return *(*float32)(v.addr)
+ Len() int;
+ Cap() int;
+ Elem(i int) Value;
+ addr() addr;
+}
+
+// ArrayCopy copies the contents of src into dst until either
+// dst has been filled or src has been exhausted.
+// It returns the number of elements copied.
+// The arrays dst and src must have the same element type.
+func ArrayCopy(dst, src ArrayOrSliceValue) int {
+ // TODO: This will have to move into the runtime
+ // once the real gc goes in.
+ de := dst.Type().(ArrayOrSliceType).Elem();
+ se := src.Type().(ArrayOrSliceType).Elem();
+ typesMustMatch(de, se);
+ n := dst.Len();
+ if xn := src.Len(); n > xn {
+ n = xn;
+ }
+ memmove(uintptr(dst.addr()), uintptr(src.addr()), uintptr(n) * de.Size());
+ return n;
}
-func (v *float32ValueStruct) Set(f float32) {
- *(*float32)(v.addr) = f
+// An ArrayValue represents an array.
+type ArrayValue struct {
+ value
}
-// -- Float64
-
-// Float64Value represents a float64 value.
-type Float64Value interface {
- Value;
- Get() float64; // Get the underlying float64.
- Set(float64); // Get the underlying float64.
+// Len returns the length of the array.
+func (v *ArrayValue) Len() int {
+ return v.typ.(*ArrayType).Len();
}
-type float64ValueStruct struct {
- commonValue
+// Cap returns the capacity of the array (equal to Len()).
+func (v *ArrayValue) Cap() int {
+ return v.typ.(*ArrayType).Len();
}
-func float64Creator(typ Type, addr Addr) Value {
- return &float64ValueStruct{ commonValue{Float64Kind, typ, addr} }
+// addr returns the base address of the data in the array.
+func (v *ArrayValue) addr() addr {
+ return v.value.addr;
}
-func (v *float64ValueStruct) Get() float64 {
- return *(*float64)(v.addr)
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *ArrayValue) Set(x *ArrayValue) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ typesMustMatch(v.typ, x.typ);
+ ArrayCopy(v, x);
}
-func (v *float64ValueStruct) Set(f float64) {
- *(*float64)(v.addr) = f
+// Elem returns the i'th element of v.
+func (v *ArrayValue) Elem(i int) Value {
+ typ := v.typ.(*ArrayType).Elem();
+ n := v.Len();
+ if i < 0 || i >= n {
+ panic("index", i, "in array len", n);
+ }
+ p := addr(uintptr(v.addr()) + uintptr(i)*typ.Size());
+ return newValue(typ, p, v.canSet);
}
-// -- String
+/*
+ * slice
+ */
-// StringValue represents a string value.
-type StringValue interface {
- Value;
- Get() string; // Get the underlying string value.
- Set(string); // Set the underlying string value.
+// runtime representation of slice
+type SliceHeader struct {
+ Data uintptr;
+ Len uint32;
+ Cap uint32;
}
-type stringValueStruct struct {
- commonValue
+// A SliceValue represents a slice.
+type SliceValue struct {
+ value
}
-func stringCreator(typ Type, addr Addr) Value {
- return &stringValueStruct{ commonValue{StringKind, typ, addr} }
+func (v *SliceValue) slice() *SliceHeader {
+ return (*SliceHeader)(v.value.addr);
}
-func (v *stringValueStruct) Get() string {
- return *(*string)(v.addr)
+// IsNil returns whether v is a nil slice.
+func (v *SliceValue) IsNil() bool {
+ return v.slice().Data == 0;
}
-func (v *stringValueStruct) Set(s string) {
- *(*string)(v.addr) = s
+// Len returns the length of the slice.
+func (v *SliceValue) Len() int {
+ return int(v.slice().Len);
}
-// -- Bool
-
-// BoolValue represents a bool value.
-type BoolValue interface {
- Value;
- Get() bool; // Get the underlying bool value.
- Set(bool); // Set the underlying bool value.
+// Cap returns the capacity of the slice.
+func (v *SliceValue) Cap() int {
+ return int(v.slice().Cap);
}
-type boolValueStruct struct {
- commonValue
+// addr returns the base address of the data in the slice.
+func (v *SliceValue) addr() addr {
+ return addr(v.slice().Data);
}
-func boolCreator(typ Type, addr Addr) Value {
- return &boolValueStruct{ commonValue{BoolKind, typ, addr} }
+// SetLen changes the length of v.
+// The new length n must be between 0 and the capacity, inclusive.
+func (v *SliceValue) SetLen(n int) {
+ s := v.slice();
+ if n < 0 || n > int(s.Cap) {
+ panicln("SetLen", n, "with capacity", s.Cap);
+ }
+ s.Len = uint32(n);
}
-func (v *boolValueStruct) Get() bool {
- return *(*bool)(v.addr)
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *SliceValue) Set(x *SliceValue) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ typesMustMatch(v.typ, x.typ);
+ *v.slice() = *x.slice();
}
-func (v *boolValueStruct) Set(b bool) {
- *(*bool)(v.addr) = b
+// Slice returns a sub-slice of the slice v.
+func (v *SliceValue) Slice(beg, end int) *SliceValue {
+ cap := v.Cap();
+ if beg < 0 || end < beg || end > cap {
+ panic("slice bounds [", beg, ":", end, "] with capacity ", cap);
+ }
+ typ := v.typ.(*SliceType);
+ s := new(SliceHeader);
+ s.Data = uintptr(v.addr()) + uintptr(beg) * typ.Elem().Size();
+ s.Len = uint32(end - beg);
+ s.Cap = uint32(cap - beg);
+ return newValue(typ, addr(s), v.canSet).(*SliceValue);
+}
+
+// Elem returns the i'th element of v.
+func (v *SliceValue) Elem(i int) Value {
+ typ := v.typ.(*SliceType).Elem();
+ n := v.Len();
+ if i < 0 || i >= n {
+ panicln("index", i, "in array of length", n);
+ }
+ p := addr(uintptr(v.addr()) + uintptr(i)*typ.Size());
+ return newValue(typ, p, v.canSet);
}
-// -- Pointer
-
-// PtrValue represents a pointer value.
-type PtrValue interface {
- Value;
- Sub() Value; // The Value pointed to.
- Get() Addr; // Get the address stored in the pointer.
- SetSub(Value); // Set the the pointed-to Value.
- IsNil() bool;
+// MakeSlice creates a new zero-initialized slice value
+// for the specified slice type, length, and capacity.
+func MakeSlice(typ *SliceType, len, cap int) *SliceValue {
+ s := new(SliceHeader);
+ size := typ.Elem().Size() * uintptr(cap);
+ if size == 0 {
+ size = 1;
+ }
+ data := make([]uint8, size);
+ s.Data = uintptr(addr(&data[0]));
+ s.Len = uint32(len);
+ s.Cap = uint32(cap);
+ return newValue(typ, addr(s), true).(*SliceValue);
}
-type ptrValueStruct struct {
- commonValue
-}
+/*
+ * chan
+ */
-func (v *ptrValueStruct) Get() Addr {
- return *(*Addr)(v.addr)
+// A ChanValue represents a chan.
+type ChanValue struct {
+ value
}
-func (v *ptrValueStruct) IsNil() bool {
- return uintptr(*(*Addr)(v.addr)) == 0
+// IsNil returns whether v is a nil channel.
+func (v *ChanValue) IsNil() bool {
+ return *(*uintptr)(v.addr) == 0;
}
-func (v *ptrValueStruct) Sub() Value {
- if v.IsNil() {
- return nil
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *ChanValue) Set(x *ChanValue) {
+ if !v.canSet {
+ panic(cannotSet);
}
- return newValueAddr(v.typ.(PtrType).Sub(), v.Get());
+ typesMustMatch(v.typ, x.typ);
+ *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
}
-func (v *ptrValueStruct) SetSub(subv Value) {
- a := v.typ.(PtrType).Sub();
- b := subv.Type();
- if !equalType(a, b) {
- panicln("reflect: incompatible types in PtrValue.SetSub:",
- a.String(), b.String());
- }
- *(*Addr)(v.addr) = subv.Addr();
+// Get returns the uintptr value of v.
+// It is mainly useful for printing.
+func (v *ChanValue) Get() uintptr {
+ return *(*uintptr)(v.addr);
}
-func ptrCreator(typ Type, addr Addr) Value {
- return &ptrValueStruct{ commonValue{PtrKind, typ, addr} };
+// Send sends x on the channel v.
+func (v *ChanValue) Send(x Value) {
+ panic("unimplemented: channel Send");
}
-// -- Array
-// Slices and arrays are represented by the same interface.
-
-// ArrayValue represents an array or slice value.
-type ArrayValue interface {
- Value;
- IsSlice() bool; // Is this a slice (true) or array (false)?
- Len() int; // The length of the array/slice.
- Cap() int; // The capacity of the array/slice (==Len() for arrays).
- Elem(i int) Value; // The Value of the i'th element.
- SetLen(len int); // Set the length; slice only.
- Set(src ArrayValue); // Set the underlying Value; slice only for src and dest both.
- CopyFrom(src ArrayValue, n int); // Copy the elements from src; lengths must match.
- IsNil() bool;
+// Recv receives and returns a value from the channel v.
+func (v *ChanValue) Recv() Value {
+ panic("unimplemented: channel Receive");
}
-func copyArray(dst ArrayValue, src ArrayValue, n int);
-
-/*
- Run-time representation of slices looks like this:
- struct Slice {
- byte* array; // actual data
- uint32 nel; // number of elements
- uint32 cap;
- };
-*/
-
-// A published version of the Slice header so that clients don't have a separate copy of the definition.
-// SliceHeader is not useful to clients unless they use unsafe.Pointer.
-type SliceHeader struct {
- Data uintptr;
- Len uint32;
- Cap uint32;
+// TrySend attempts to sends x on the channel v but will not block.
+// It returns true if the value was sent, false otherwise.
+func (v *ChanValue) TrySend(x Value) bool {
+ panic("unimplemented: channel TrySend");
}
-type sliceValueStruct struct {
- commonValue;
- elemtype Type;
- elemsize int;
- slice *SliceHeader;
+// TryRecv attempts to receive a value from the channel v but will not block.
+// It returns the value if one is received, nil otherwise.
+func (v *ChanValue) TryRecv() Value {
+ panic("unimplemented: channel TryRecv");
}
-func (v *sliceValueStruct) IsSlice() bool {
- return true
-}
+/*
+ * func
+ */
-func (v *sliceValueStruct) Len() int {
- return int(v.slice.Len);
+// A FuncValue represents a function value.
+type FuncValue struct {
+ value
}
-func (v *sliceValueStruct) Cap() int {
- return int(v.slice.Cap);
+// IsNil returns whether v is a nil function.
+func (v *FuncValue) IsNil() bool {
+ return *(*uintptr)(v.addr) == 0;
}
-func (v *sliceValueStruct) SetLen(len int) {
- if len > v.Cap() {
- panicln("reflect: sliceValueStruct.SetLen", len, v.Cap());
- }
- v.slice.Len = uint32(len);
+// Get returns the uintptr value of v.
+// It is mainly useful for printing.
+func (v *FuncValue) Get() uintptr {
+ return *(*uintptr)(v.addr);
}
-func (v *sliceValueStruct) Set(src ArrayValue) {
- if !src.IsSlice() {
- panic("can't set slice from array");
- }
- s := src.(*sliceValueStruct);
- if !equalType(v.typ, s.typ) {
- panicln("incompatible types in ArrayValue.Set()");
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *FuncValue) Set(x *FuncValue) {
+ if !v.canSet {
+ panic(cannotSet);
}
- *v.slice = *s.slice;
+ typesMustMatch(v.typ, x.typ);
+ *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
}
-func (v *sliceValueStruct) Elem(i int) Value {
- data_uint := v.slice.Data + uintptr(i * v.elemsize);
- return newValueAddr(v.elemtype, Addr(data_uint));
+// Call calls the function v with input parameters in.
+// It returns the function's output parameters as Values.
+func (v *FuncValue) Call(in []Value) []Value {
+ panic("unimplemented: function Call");
}
-func (v *sliceValueStruct) CopyFrom(src ArrayValue, n int) {
- copyArray(v, src, n);
-}
-func (v *sliceValueStruct) IsNil() bool {
- return v.slice.Data == 0
-}
+/*
+ * interface
+ */
-type arrayValueStruct struct {
- commonValue;
- elemtype Type;
- elemsize int;
- len int;
+// An InterfaceValue represents an interface value.
+type InterfaceValue struct {
+ value
}
-func (v *arrayValueStruct) IsSlice() bool {
- return false
-}
+// No Get because v.Interface() is available.
-func (v *arrayValueStruct) Len() int {
- return v.len
+// IsNil returns whether v is a nil interface value.
+func (v *InterfaceValue) IsNil() bool {
+ return v.Interface() == nil;
}
-func (v *arrayValueStruct) Cap() int {
- return v.len
+// Elem returns the concrete value stored in the interface value v.
+func (v *InterfaceValue) Elem() Value {
+ return NewValue(v.Interface());
}
-func (v *arrayValueStruct) SetLen(len int) {
- panicln("can't set len of array");
-}
+// Set assigns x to v.
+func (v *InterfaceValue) Set(x interface{}) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ // Two different representations; see comment in Get.
+ // Empty interface is easy.
+ if v.typ.(*InterfaceType).NumMethod() == 0 {
+ *(*interface{})(v.addr) = x;
+ }
-func (v *arrayValueStruct) Set(src ArrayValue) {
- panicln("can't set array");
+ // Non-empty interface requires a runtime check.
+ panic("unimplemented: interface Set");
+// unsafe.SetInterface(v.typ, v.addr, x);
}
-func (v *arrayValueStruct) Elem(i int) Value {
- data_uint := uintptr(v.addr) + uintptr(i * v.elemsize);
- return newValueAddr(v.elemtype, Addr(data_uint));
-}
+/*
+ * map
+ */
-func (v *arrayValueStruct) CopyFrom(src ArrayValue, n int) {
- copyArray(v, src, n);
+// A MapValue represents a map value.
+type MapValue struct {
+ value
}
-func (v *arrayValueStruct) IsNil() bool {
- return false
+// IsNil returns whether v is a nil map value.
+func (v *MapValue) IsNil() bool {
+ return *(*uintptr)(v.addr) == 0;
}
-func arrayCreator(typ Type, addr Addr) Value {
- arraytype := typ.(ArrayType);
- if arraytype.IsSlice() {
- v := new(sliceValueStruct);
- v.kind = ArrayKind;
- v.addr = addr;
- v.typ = typ;
- v.elemtype = arraytype.Elem();
- v.elemsize = v.elemtype.Size();
- v.slice = (*SliceHeader)(addr);
- return v;
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *MapValue) Set(x *MapValue) {
+ if !v.canSet {
+ panic(cannotSet);
}
- v := new(arrayValueStruct);
- v.kind = ArrayKind;
- v.addr = addr;
- v.typ = typ;
- v.elemtype = arraytype.Elem();
- v.elemsize = v.elemtype.Size();
- v.len = arraytype.Len();
- return v;
-}
-
-// -- Map TODO: finish and test
-
-// MapValue represents a map value.
-// Its implementation is incomplete.
-type MapValue interface {
- Value;
- Len() int; // The number of elements; currently always returns 0.
- Elem(key Value) Value; // The value indexed by key; unimplemented.
- IsNil() bool;
-}
-
-type mapValueStruct struct {
- commonValue
-}
-
-func mapCreator(typ Type, addr Addr) Value {
- return &mapValueStruct{ commonValue{MapKind, typ, addr} }
-}
-
-func (v *mapValueStruct) Len() int {
- return 0 // TODO: probably want this to be dynamic
+ typesMustMatch(v.typ, x.typ);
+ *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
}
-func (v *mapValueStruct) IsNil() bool {
- return false // TODO: implement this properly
+// Elem returns the value associated with key in the map v.
+// It returns nil if key is not found in the map.
+func (v *MapValue) Elem(key Value) Value {
+ panic("unimplemented: map Elem");
}
-func (v *mapValueStruct) Elem(key Value) Value {
- panic("map value element");
- return nil
+// Len returns the number of keys in the map v.
+func (v *MapValue) Len() int {
+ panic("unimplemented: map Len");
}
-// -- Chan
-
-// ChanValue represents a chan value.
-// Its implementation is incomplete.
-type ChanValue interface {
- Value;
- IsNil() bool;
+// Keys returns a slice containing all the keys present in the map,
+// in unspecified order.
+func (v *MapValue) Keys() []Value {
+ panic("unimplemented: map Keys");
}
-type chanValueStruct struct {
- commonValue
-}
+/*
+ * ptr
+ */
-func (v *chanValueStruct) IsNil() bool {
- return false // TODO: implement this properly
+// A PtrValue represents a pointer.
+type PtrValue struct {
+ value
}
-func chanCreator(typ Type, addr Addr) Value {
- return &chanValueStruct{ commonValue{ChanKind, typ, addr} }
+// IsNil returns whether v is a nil pointer.
+func (v *PtrValue) IsNil() bool {
+ return *(*uintptr)(v.addr) == 0;
}
-// -- Struct
-
-// StructValue represents a struct value.
-type StructValue interface {
- Value;
- Len() int; // The number of fields.
- Field(i int) Value; // The Value of field i.
+// Get returns the uintptr value of v.
+// It is mainly useful for printing.
+func (v *PtrValue) Get() uintptr {
+ return *(*uintptr)(v.addr);
}
-type structValueStruct struct {
- commonValue;
- field []Value;
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *PtrValue) Set(x *PtrValue) {
+ if !v.canSet {
+ panic(cannotSet);
+ }
+ typesMustMatch(v.typ, x.typ);
+ // TODO: This will have to move into the runtime
+ // once the new gc goes in
+ *(*uintptr)(v.addr) = *(*uintptr)(x.addr);
}
-func (v *structValueStruct) Len() int {
- return len(v.field)
+// PointTo changes v to point to x.
+func (v *PtrValue) PointTo(x Value) {
+ if !x.CanSet() {
+ panic("cannot set x; cannot point to x");
+ }
+ typesMustMatch(v.typ.(*PtrType).Elem(), x.Type());
+ // TODO: This will have to move into the runtime
+ // once the new gc goes in.
+ *(*uintptr)(v.addr) = x.Addr();
}
-func (v *structValueStruct) Field(i int) Value {
- return v.field[i]
+// Elem returns the value that v points to.
+// If v is a nil pointer, Elem returns a nil Value.
+func (v *PtrValue) Elem() Value {
+ if v.IsNil() {
+ return nil;
+ }
+ return newValue(v.typ.(*PtrType).Elem(), *(*addr)(v.addr), v.canSet);
}
-func structCreator(typ Type, addr Addr) Value {
- t := typ.(StructType);
- nfield := t.Len();
- v := &structValueStruct{ commonValue{StructKind, typ, addr}, make([]Value, nfield) };
- for i := 0; i < nfield; i++ {
- name, ftype, str, offset := t.Field(i);
- addr_uint := uintptr(addr) + uintptr(offset);
- v.field[i] = newValueAddr(ftype, Addr(addr_uint));
+// Indirect returns the value that v points to.
+// If v is a nil pointer, Indirect returns a nil Value.
+// If v is not a pointer, Indirect returns v.
+func Indirect(v Value) Value {
+ if pv, ok := v.(*PtrValue); ok {
+ return pv.Elem();
}
- v.typ = typ;
return v;
}
-// -- Interface
-
-// InterfaceValue represents an interface value.
-type InterfaceValue interface {
- Value;
- Get() interface {}; // Get the underlying interface{} value.
- Value() Value;
- IsNil() bool;
-}
+/*
+ * struct
+ */
-type interfaceValueStruct struct {
- commonValue
+// A StructValue represents a struct value.
+type StructValue struct {
+ value
}
-func (v *interfaceValueStruct) Get() interface{} {
- // There are two different representations of interface values,
- // one if the interface type has methods and one if it doesn't.
- // These two representations require different expressions
- // to extract correctly.
- if v.Type().(InterfaceType).Len() == 0 {
- // Extract as interface value without methods.
- return *(*interface{})(v.addr)
+// Set assigns x to v.
+// The new value x must have the same type as v.
+func (v *StructValue) Set(x *StructValue) {
+ // TODO: This will have to move into the runtime
+ // once the gc goes in.
+ if !v.canSet {
+ panic(cannotSet);
}
- // Extract from v.addr as interface value with methods.
- return *(*interface{ m() })(v.addr)
+ typesMustMatch(v.typ, x.typ);
+ memmove(uintptr(v.addr), uintptr(x.addr), v.typ.Size());
}
-func (v *interfaceValueStruct) Interface() interface{} {
- return v.Get();
-}
-
-func (v *interfaceValueStruct) Value() Value {
- i := v.Get();
- if i == nil {
+// Field returns the i'th field of the struct.
+func (v *StructValue) Field(i int) Value {
+ t := v.typ.(*StructType);
+ if i < 0 || i >= t.NumField() {
return nil;
}
- return NewValue(i);
-}
-
-func (v *interfaceValueStruct) IsNil() bool {
- return *(*interface{})(v.addr) == nil
-}
-
-func interfaceCreator(typ Type, addr Addr) Value {
- return &interfaceValueStruct{ commonValue{InterfaceKind, typ, addr} }
-}
-
-// -- Func
-
-
-// FuncValue represents a func value.
-// Its implementation is incomplete.
-type FuncValue interface {
- Value;
- Get() Addr; // The address of the function.
- IsNil() bool;
-}
-
-type funcValueStruct struct {
- commonValue
+ f := t.Field(i);
+ return newValue(f.Type, addr(uintptr(v.addr)+f.Offset), v.canSet && f.PkgPath == "");
}
-func (v *funcValueStruct) Get() Addr {
- return *(*Addr)(v.addr)
+// NumField returns the number of fields in the struct.
+func (v *StructValue) NumField() int {
+ return v.typ.(*StructType).NumField();
}
-func (v *funcValueStruct) IsNil() bool {
- return *(*Addr)(v.addr) == nil
-}
-
-func funcCreator(typ Type, addr Addr) Value {
- return &funcValueStruct{ commonValue{FuncKind, typ, addr} }
-}
+/*
+ * constructors
+ */
-var creator = map[int] creatorFn {
- MissingKind : missingCreator,
- IntKind : intCreator,
- Int8Kind : int8Creator,
- Int16Kind : int16Creator,
- Int32Kind : int32Creator,
- Int64Kind : int64Creator,
- UintKind : uintCreator,
- Uint8Kind : uint8Creator,
- Uint16Kind : uint16Creator,
- Uint32Kind : uint32Creator,
- Uint64Kind : uint64Creator,
- UintptrKind : uintptrCreator,
- FloatKind : floatCreator,
- Float32Kind : float32Creator,
- Float64Kind : float64Creator,
- StringKind : stringCreator,
- BoolKind : boolCreator,
- PtrKind : ptrCreator,
- ArrayKind : arrayCreator,
- MapKind : mapCreator,
- ChanKind : chanCreator,
- StructKind : structCreator,
- InterfaceKind : interfaceCreator,
- FuncKind : funcCreator,
+// Typeof returns the reflection Type of the value in the interface{}.
+func Typeof(i interface{}) Type {
+ return toType(unsafe.Typeof(i));
}
-var typecache = make(map[string] Type);
-
-func newValueAddr(typ Type, addr Addr) Value {
- c, ok := creator[typ.Kind()];
- if !ok {
- panicln("no creator for type" , typ.String());
+// NewValue returns a new Value initialized to the concrete value
+// stored in the interface i. NewValue(nil) returns nil.
+func NewValue(i interface{}) Value {
+ if i == nil {
+ return nil;
}
- return c(typ, addr);
-}
-
-// NewZeroValue creates a new, zero-initialized Value for the specified Type.
-func NewZeroValue(typ Type) Value {
- size := typ.Size();
- if size == 0 {
- size = 1;
+ t, a := unsafe.Reflect(i);
+ return newValue(toType(t), addr(a), true);
+}
+
+func newValue(typ Type, addr addr, canSet bool) Value {
+ // All values have same memory layout;
+ // build once and convert.
+ v := &struct{value}{value{typ, addr, canSet}};
+ switch t := typ.(type) { // TODO(rsc): s/t := // ?
+ case *ArrayType:
+ // TODO(rsc): Something must prevent
+ // clients of the package from doing
+ // this same kind of cast.
+ // We should be allowed because
+ // they're our types.
+ // Something about implicit assignment
+ // to struct fields.
+ return (*ArrayValue)(v);
+ case *BoolType:
+ return (*BoolValue)(v);
+ case *ChanType:
+ return (*ChanValue)(v);
+ case *FloatType:
+ return (*FloatValue)(v);
+ case *Float32Type:
+ return (*Float32Value)(v);
+ case *Float64Type:
+ return (*Float64Value)(v);
+ case *FuncType:
+ return (*FuncValue)(v);
+ case *IntType:
+ return (*IntValue)(v);
+ case *Int8Type:
+ return (*Int8Value)(v);
+ case *Int16Type:
+ return (*Int16Value)(v);
+ case *Int32Type:
+ return (*Int32Value)(v);
+ case *Int64Type:
+ return (*Int64Value)(v);
+ case *InterfaceType:
+ return (*InterfaceValue)(v);
+ case *MapType:
+ return (*MapValue)(v);
+ case *PtrType:
+ return (*PtrValue)(v);
+ case *SliceType:
+ return (*SliceValue)(v);
+ case *StringType:
+ return (*StringValue)(v);
+ case *StructType:
+ return (*StructValue)(v);
+ case *UintType:
+ return (*UintValue)(v);
+ case *Uint8Type:
+ return (*Uint8Value)(v);
+ case *Uint16Type:
+ return (*Uint16Value)(v);
+ case *Uint32Type:
+ return (*Uint32Value)(v);
+ case *Uint64Type:
+ return (*Uint64Value)(v);
+ case *UintptrType:
+ return (*UintptrValue)(v);
+ case *UnsafePointerType:
+ return (*UnsafePointerValue)(v);
}
- data := make([]uint8, size);
- return newValueAddr(typ, Addr(&data[0]));
+ panicln("newValue", typ.String());
}
-// NewSliceValue creates a new, zero-initialized slice value (ArrayValue) for the specified
-// slice type (ArrayType), length, and capacity.
-func NewSliceValue(typ ArrayType, len, cap int) ArrayValue {
- if !typ.IsSlice() {
- return nil
- }
+func newFuncValue(typ Type, addr addr) *FuncValue {
+ return newValue(typ, addr, true).(*FuncValue);
+}
- array := new(SliceHeader);
- size := typ.Elem().Size() * cap;
+// MakeZeroValue returns a zero Value for the specified Type.
+func MakeZero(typ Type) Value {
+ // TODO: this will have to move into
+ // the runtime proper in order to play nicely
+ // with the garbage collector.
+ size := typ.Size();
if size == 0 {
size = 1;
}
data := make([]uint8, size);
- array.Data = uintptr(Addr(&data[0]));
- array.Len = uint32(len);
- array.Cap = uint32(cap);
-
- return newValueAddr(typ, Addr(array)).(ArrayValue);
-}
-
-// Works on both slices and arrays
-func copyArray(dst ArrayValue, src ArrayValue, n int) {
- if n == 0 {
- return
- }
- dt := dst.Type().(ArrayType).Elem();
- st := src.Type().(ArrayType).Elem();
- if !equalType(dt, st) {
- panicln("reflect: incompatible types in CopyArray:",
- dt.String(), st.String());
- }
- if n < 0 || n > dst.Len() || n > src.Len() {
- panicln("reflect: CopyArray: invalid count", n);
- }
- dstp := uintptr(dst.Elem(0).Addr());
- srcp := uintptr(src.Elem(0).Addr());
- end := uintptr(n)*uintptr(dt.Size());
- if end % 8 == 0 {
- for i := uintptr(0); i < end; i += 8{
- di := Addr(dstp + i);
- si := Addr(srcp + i);
- *(*uint64)(di) = *(*uint64)(si);
- }
- } else {
- for i := uintptr(0); i < end; i++ {
- di := Addr(dstp + i);
- si := Addr(srcp + i);
- *(*byte)(di) = *(*byte)(si);
- }
- }
-}
-
-func typeof(typestring string) Type {
- typ, ok := typecache[typestring];
- if !ok {
- typ = ParseTypeString("", typestring);
- if typ.Kind() == MissingKind {
- // This can not happen: unsafe.Reflect should only
- // ever tell us the names of types that exist.
- // Of course it does happen, and when it does
- // it is more helpful to catch it in action here than
- // to see $missing$ in a later print.
- panicln("missing type for", typestring);
- }
- typecache[typestring] = typ;
- }
- return typ;
-}
-
-// NewValue creates a new Value from the interface{} object provided.
-func NewValue(e interface {}) Value {
- value, typestring, indir := unsafe.Reflect(e);
- typ := typeof(typestring);
- var ap Addr;
- if indir {
- // Content of interface is large and didn't
- // fit, so it's a pointer to the actual content.
- // We have an address, but we need to
- // make a copy to avoid letting the caller
- // edit the content inside the interface.
- n := uintptr(typ.Size());
- data := make([]byte, n);
- p1 := uintptr(Addr(&data[0]));
- p2 := uintptr(value);
- for i := uintptr(0); i < n; i++ {
- *(*byte)(Addr(p1+i)) = *(*byte)(Addr(p2+i));
- }
- ap = Addr(&data[0]);
- } else {
- // Content of interface is small and stored
- // inside the interface. Make a copy so we
- // can take its address.
- x := new(uint64);
- *x = value;
- ap = Addr(x);
- }
- return newValueAddr(typ, ap);
-}
-
-// Typeof returns the type of the value in the interface{} object provided.
-func Typeof(e interface{}) Type {
- value, typestring, indir := unsafe.Reflect(e);
- return typeof(typestring);
-}
-
-// Indirect indirects one level through a value, if it is a pointer.
-// If not a pointer, the value is returned unchanged.
-// Useful when walking arbitrary data structures.
-func Indirect(v Value) Value {
- if v.Kind() == PtrKind {
- p := v.(PtrValue);
- if p.Get() == nil {
- return nil
- }
- v = p.Sub()
- }
- return v
+ return newValue(typ, addr(&data[0]), true);
}