// 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"; "runtime"; "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; getAddr() addr; } func MakeZero(typ Type) Value 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); } func (v *value) getAddr() addr { return 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); } // implemented in ../pkg/runtime/reflect.cgo func mapaccess(m, key, val *byte) bool func mapassign(m, key, val *byte) func maplen(m *byte) int32 func mapiterinit(m *byte) *byte func mapiternext(it *byte) func mapiterkey(it *byte, key *byte) bool func makemap(t *runtime.MapType) *byte // Get returns the value associated with key in the map v. // It returns nil if key is not found in the map. func (v *MapValue) Get(key Value) Value { t := v.Type().(*MapType); typesMustMatch(t.Key(), key.Type()); m := *(**byte)(v.addr); if m == nil { return nil; } newval := MakeZero(t.Elem()); if !mapaccess(m, (*byte)(key.getAddr()), (*byte)(newval.getAddr())) { return nil; } return newval; } // Put sets the value associated with key in the map v to val. // If val is nil, Put deletes the key from map. func (v *MapValue) Put(key, val Value) { t := v.Type().(*MapType); typesMustMatch(t.Key(), key.Type()); var vaddr *byte; if val != nil { typesMustMatch(t.Elem(), val.Type()); vaddr = (*byte)(val.getAddr()); } m := *(**byte)(v.addr); mapassign(m, (*byte)(key.getAddr()), vaddr); } // Len returns the number of keys in the map v. func (v *MapValue) Len() int { m := *(**byte)(v.addr); if m == nil { return 0; } return int(maplen(m)); } // Keys returns a slice containing all the keys present in the map, // in unspecified order. func (v *MapValue) Keys() []Value { tk := v.Type().(*MapType).Key(); m := *(**byte)(v.addr); it := mapiterinit(m); a := make([]Value, maplen(m)); var i int; for i = 0; i < len(a); i++ { k := MakeZero(tk); if !mapiterkey(it, (*byte)(k.getAddr())) { break; } a[i] = k; mapiternext(it); } return a[0:i]; } func MakeMap(typ *MapType) *MapValue { v := MakeZero(typ).(*MapValue); *(**byte)(v.addr) = makemap((*runtime.MapType)(unsafe.Pointer(typ))); return v; } /* * 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); } // MakeZero 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); }