diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libgo/go/reflect/value.go | |
download | cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2 cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libgo/go/reflect/value.go')
-rw-r--r-- | libgo/go/reflect/value.go | 1242 |
1 files changed, 1242 insertions, 0 deletions
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go new file mode 100644 index 000000000..8ef402bbc --- /dev/null +++ b/libgo/go/reflect/value.go @@ -0,0 +1,1242 @@ +// 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 ( + "math" + "runtime" + "unsafe" +) + +const ptrSize = uintptr(unsafe.Sizeof((*byte)(nil))) +const cannotSet = "cannot set value obtained via unexported struct field" + +type addr unsafe.Pointer + +// TODO: This will have to go away when +// the new gc goes in. +func memmove(adst, asrc addr, n uintptr) { + dst := uintptr(adst) + src := uintptr(asrc) + 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 + + // SetValue assigns v to the value; v must have the same type as the value. + SetValue(v Value) + + // Addr returns a pointer to the underlying data. + // It is for advanced clients that also + // import the "unsafe" package. + Addr() uintptr + + // Method returns a FuncValue corresponding to the value's i'th method. + // The arguments to a Call on the returned FuncValue + // should not include a receiver; the FuncValue will use + // the value as the receiver. + Method(i int) *FuncValue + + getAddr() addr +} + +// value is the common implementation of most values. +// It is embedded in other, public struct types, but always +// with a unique tag like "uint" or "float" so that the client cannot +// convert from, say, *UintValue to *FloatValue. +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 } + +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 } + +/* + * basic types + */ + +// BoolValue represents a bool value. +type BoolValue struct { + value "bool" +} + +// 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 +} + +// Set sets v to the value x. +func (v *BoolValue) SetValue(x Value) { v.Set(x.(*BoolValue).Get()) } + +// FloatValue represents a float value. +type FloatValue struct { + value "float" +} + +// Get returns the underlying int value. +func (v *FloatValue) Get() float64 { + switch v.typ.Kind() { + case Float32: + return float64(*(*float32)(v.addr)) + case Float64: + return *(*float64)(v.addr) + } + panic("reflect: invalid float kind") +} + +// Set sets v to the value x. +func (v *FloatValue) Set(x float64) { + if !v.canSet { + panic(cannotSet) + } + switch v.typ.Kind() { + default: + panic("reflect: invalid float kind") + case Float32: + *(*float32)(v.addr) = float32(x) + case Float64: + *(*float64)(v.addr) = x + } +} + +// Overflow returns true if x cannot be represented by the type of v. +func (v *FloatValue) Overflow(x float64) bool { + if v.typ.Size() == 8 { + return false + } + if x < 0 { + x = -x + } + return math.MaxFloat32 < x && x <= math.MaxFloat64 +} + +// Set sets v to the value x. +func (v *FloatValue) SetValue(x Value) { v.Set(x.(*FloatValue).Get()) } + +// ComplexValue represents a complex value. +type ComplexValue struct { + value "complex" +} + +// Get returns the underlying complex value. +func (v *ComplexValue) Get() complex128 { + switch v.typ.Kind() { + case Complex64: + return complex128(*(*complex64)(v.addr)) + case Complex128: + return *(*complex128)(v.addr) + } + panic("reflect: invalid complex kind") +} + +// Set sets v to the value x. +func (v *ComplexValue) Set(x complex128) { + if !v.canSet { + panic(cannotSet) + } + switch v.typ.Kind() { + default: + panic("reflect: invalid complex kind") + case Complex64: + *(*complex64)(v.addr) = complex64(x) + case Complex128: + *(*complex128)(v.addr) = x + } +} + +// Set sets v to the value x. +func (v *ComplexValue) SetValue(x Value) { v.Set(x.(*ComplexValue).Get()) } + +// IntValue represents an int value. +type IntValue struct { + value "int" +} + +// Get returns the underlying int value. +func (v *IntValue) Get() int64 { + switch v.typ.Kind() { + case Int: + return int64(*(*int)(v.addr)) + case Int8: + return int64(*(*int8)(v.addr)) + case Int16: + return int64(*(*int16)(v.addr)) + case Int32: + return int64(*(*int32)(v.addr)) + case Int64: + return *(*int64)(v.addr) + } + panic("reflect: invalid int kind") +} + +// Set sets v to the value x. +func (v *IntValue) Set(x int64) { + if !v.canSet { + panic(cannotSet) + } + switch v.typ.Kind() { + default: + panic("reflect: invalid int kind") + case Int: + *(*int)(v.addr) = int(x) + case Int8: + *(*int8)(v.addr) = int8(x) + case Int16: + *(*int16)(v.addr) = int16(x) + case Int32: + *(*int32)(v.addr) = int32(x) + case Int64: + *(*int64)(v.addr) = x + } +} + +// Set sets v to the value x. +func (v *IntValue) SetValue(x Value) { v.Set(x.(*IntValue).Get()) } + +// Overflow returns true if x cannot be represented by the type of v. +func (v *IntValue) Overflow(x int64) bool { + bitSize := uint(v.typ.Bits()) + trunc := (x << (64 - bitSize)) >> (64 - bitSize) + return x != trunc +} + +// StringHeader is the runtime representation of a string. +type StringHeader struct { + Data uintptr + Len int +} + +// StringValue represents a string value. +type StringValue struct { + value "string" +} + +// 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 +} + +// Set sets v to the value x. +func (v *StringValue) SetValue(x Value) { v.Set(x.(*StringValue).Get()) } + +// UintValue represents a uint value. +type UintValue struct { + value "uint" +} + +// Get returns the underlying uuint value. +func (v *UintValue) Get() uint64 { + switch v.typ.Kind() { + case Uint: + return uint64(*(*uint)(v.addr)) + case Uint8: + return uint64(*(*uint8)(v.addr)) + case Uint16: + return uint64(*(*uint16)(v.addr)) + case Uint32: + return uint64(*(*uint32)(v.addr)) + case Uint64: + return *(*uint64)(v.addr) + case Uintptr: + return uint64(*(*uintptr)(v.addr)) + } + panic("reflect: invalid uint kind") +} + +// Set sets v to the value x. +func (v *UintValue) Set(x uint64) { + if !v.canSet { + panic(cannotSet) + } + switch v.typ.Kind() { + default: + panic("reflect: invalid uint kind") + case Uint: + *(*uint)(v.addr) = uint(x) + case Uint8: + *(*uint8)(v.addr) = uint8(x) + case Uint16: + *(*uint16)(v.addr) = uint16(x) + case Uint32: + *(*uint32)(v.addr) = uint32(x) + case Uint64: + *(*uint64)(v.addr) = x + case Uintptr: + *(*uintptr)(v.addr) = uintptr(x) + } +} + +// Overflow returns true if x cannot be represented by the type of v. +func (v *UintValue) Overflow(x uint64) bool { + bitSize := uint(v.typ.Bits()) + trunc := (x << (64 - bitSize)) >> (64 - bitSize) + return x != trunc +} + +// Set sets v to the value x. +func (v *UintValue) SetValue(x Value) { v.Set(x.(*UintValue).Get()) } + +// UnsafePointerValue represents an unsafe.Pointer value. +type UnsafePointerValue struct { + value "unsafe.Pointer" +} + +// 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 +} + +// Set sets v to the value x. +func (v *UnsafePointerValue) SetValue(x Value) { + v.Set(unsafe.Pointer(x.(*UnsafePointerValue).Get())) +} + +func typesMustMatch(t1, t2 Type) { + if t1 != t2 { + panic("type mismatch: " + t1.String() + " != " + t2.String()) + } +} + +/* + * 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 +} + +// grow grows the slice s so that it can hold extra more values, allocating +// more capacity if needed. It also returns the old and new slice lengths. +func grow(s *SliceValue, extra int) (*SliceValue, int, int) { + i0 := s.Len() + i1 := i0 + extra + if i1 < i0 { + panic("append: slice overflow") + } + m := s.Cap() + if i1 <= m { + return s.Slice(0, i1), i0, i1 + } + if m == 0 { + m = extra + } else { + for m < i1 { + if i0 < 1024 { + m += m + } else { + m += m / 4 + } + } + } + t := MakeSlice(s.Type().(*SliceType), i1, m) + Copy(t, s) + return t, i0, i1 +} + +// Append appends the values x to a slice s and returns the resulting slice. +// Each x must have the same type as s' element type. +func Append(s *SliceValue, x ...Value) *SliceValue { + s, i0, i1 := grow(s, len(x)) + for i, j := i0, 0; i < i1; i, j = i+1, j+1 { + s.Elem(i).SetValue(x[j]) + } + return s +} + +// AppendSlice appends a slice t to a slice s and returns the resulting slice. +// The slices s and t must have the same element type. +func AppendSlice(s, t *SliceValue) *SliceValue { + s, i0, i1 := grow(s, t.Len()) + Copy(s.Slice(i0, i1), t) + return s +} + +// Copy 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 Copy(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(dst.addr(), src.addr(), uintptr(n)*de.Size()) + return n +} + +// An ArrayValue represents an array. +type ArrayValue struct { + value "array" +} + +// 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) + Copy(v, x) +} + +// Set sets v to the value x. +func (v *ArrayValue) SetValue(x Value) { v.Set(x.(*ArrayValue)) } + +// 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("array index out of bounds") + } + 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 int + Cap int +} + +// A SliceValue represents a slice. +type SliceValue struct { + value "slice" +} + +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) { + panic("reflect: slice length out of range in SetLen") + } + s.Len = 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() +} + +// Set sets v to the value x. +func (v *SliceValue) SetValue(x Value) { v.Set(x.(*SliceValue)) } + +// Get returns the uintptr address of the v.Cap()'th element. This gives +// the same result for all slices of the same array. +// It is mainly useful for printing. +func (v *SliceValue) Get() uintptr { + typ := v.typ.(*SliceType) + return uintptr(v.addr()) + uintptr(v.Cap())*typ.Elem().Size() +} + +// 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 index out of bounds") + } + typ := v.typ.(*SliceType) + s := new(SliceHeader) + s.Data = uintptr(v.addr()) + uintptr(beg)*typ.Elem().Size() + s.Len = end - beg + s.Cap = 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 { + panic("reflect: slice index out of range") + } + 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 := &SliceHeader{ + Data: uintptr(unsafe.NewArray(typ.Elem(), cap)), + Len: len, + Cap: cap, + } + return newValue(typ, addr(s), true).(*SliceValue) +} + +/* + * chan + */ + +// A ChanValue represents a chan. +type ChanValue struct { + value "chan" +} + +// 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) +} + +// Set sets v to the value x. +func (v *ChanValue) SetValue(x Value) { v.Set(x.(*ChanValue)) } + +// Get returns the uintptr value of v. +// It is mainly useful for printing. +func (v *ChanValue) Get() uintptr { return *(*uintptr)(v.addr) } + +// implemented in ../pkg/runtime/reflect.cgo +func makechan(typ *runtime.ChanType, size uint32) (ch *byte) +func chansend(ch, val *byte, pres *bool) +func chanrecv(ch, val *byte, pres *bool) +func chanclosed(ch *byte) bool +func chanclose(ch *byte) +func chanlen(ch *byte) int32 +func chancap(ch *byte) int32 + +// Closed returns the result of closed(c) on the underlying channel. +func (v *ChanValue) Closed() bool { + ch := *(**byte)(v.addr) + return chanclosed(ch) +} + +// Close closes the channel. +func (v *ChanValue) Close() { + ch := *(**byte)(v.addr) + chanclose(ch) +} + +func (v *ChanValue) Len() int { + ch := *(**byte)(v.addr) + return int(chanlen(ch)) +} + +func (v *ChanValue) Cap() int { + ch := *(**byte)(v.addr) + return int(chancap(ch)) +} + +// internal send; non-blocking if b != nil +func (v *ChanValue) send(x Value, b *bool) { + t := v.Type().(*ChanType) + if t.Dir()&SendDir == 0 { + panic("send on recv-only channel") + } + typesMustMatch(t.Elem(), x.Type()) + ch := *(**byte)(v.addr) + chansend(ch, (*byte)(x.getAddr()), b) +} + +// internal recv; non-blocking if b != nil +func (v *ChanValue) recv(b *bool) Value { + t := v.Type().(*ChanType) + if t.Dir()&RecvDir == 0 { + panic("recv on send-only channel") + } + ch := *(**byte)(v.addr) + x := MakeZero(t.Elem()) + chanrecv(ch, (*byte)(x.getAddr()), b) + return x +} + +// Send sends x on the channel v. +func (v *ChanValue) Send(x Value) { v.send(x, nil) } + +// Recv receives and returns a value from the channel v. +func (v *ChanValue) Recv() Value { return v.recv(nil) } + +// 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 { + var ok bool + v.send(x, &ok) + return ok +} + +// 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 { + var ok bool + x := v.recv(&ok) + if !ok { + return nil + } + return x +} + +// MakeChan creates a new channel with the specified type and buffer size. +func MakeChan(typ *ChanType, buffer int) *ChanValue { + if buffer < 0 { + panic("MakeChan: negative buffer size") + } + if typ.Dir() != BothDir { + panic("MakeChan: unidirectional channel type") + } + v := MakeZero(typ).(*ChanValue) + *(**byte)(v.addr) = makechan((*runtime.ChanType)(unsafe.Pointer(typ)), uint32(buffer)) + return v +} + +/* + * func + */ + +// A FuncValue represents a function value. +type FuncValue struct { + value "func" + first *value + isInterface bool +} + +// 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) +} + +// Set sets v to the value x. +func (v *FuncValue) SetValue(x Value) { v.Set(x.(*FuncValue)) } + +// Method returns a FuncValue corresponding to v's i'th method. +// The arguments to a Call on the returned FuncValue +// should not include a receiver; the FuncValue will use v +// as the receiver. +func (v *value) Method(i int) *FuncValue { + t := v.Type().uncommon() + if t == nil || i < 0 || i >= len(t.methods) { + return nil + } + p := &t.methods[i] + fn := p.tfn + fv := &FuncValue{value: value{runtimeToType(p.typ), addr(&fn), true}, first: v, isInterface: false} + return fv +} + +// implemented in ../pkg/runtime/*/asm.s +func call(typ *FuncType, fnaddr *byte, isInterface bool, params *addr, results *addr) + +// Call calls the function fv with input parameters in. +// It returns the function's output parameters as Values. +func (fv *FuncValue) Call(in []Value) []Value { + t := fv.Type().(*FuncType) + nin := len(in) + if fv.first != nil && !fv.isInterface { + nin++ + } + if nin != t.NumIn() { + panic("FuncValue: wrong argument count") + } + if fv.first != nil && fv.isInterface { + nin++ + } + nout := t.NumOut() + + params := make([]addr, nin) + delta := 0 + off := 0 + if v := fv.first; v != nil { + // Hard-wired first argument. + if fv.isInterface { + // v is a single uninterpreted word + params[0] = v.getAddr() + } else { + // v is a real value + tv := v.Type() + + // This is a method, so we need to always pass + // a pointer. + vAddr := v.getAddr() + if ptv, ok := tv.(*PtrType); ok { + typesMustMatch(t.In(0), tv) + } else { + p := addr(new(addr)) + *(*addr)(p) = vAddr + vAddr = p + typesMustMatch(t.In(0).(*PtrType).Elem(), tv) + } + + params[0] = vAddr + delta = 1 + } + off = 1 + } + for i, v := range in { + tv := v.Type() + tf := t.In(i + delta) + + // If this is really a method, and we are explicitly + // passing the object, then we need to pass the address + // of the object instead. Unfortunately, we don't + // have any way to know that this is a method, so we just + // check the type. FIXME: This is ugly. + vAddr := v.getAddr() + if i == 0 && tf != tv { + if ptf, ok := tf.(*PtrType); ok { + p := addr(new(addr)) + *(*addr)(p) = vAddr + vAddr = p + tf = ptf.Elem() + } + } + + typesMustMatch(tf, tv) + params[i+off] = vAddr + } + + ret := make([]Value, nout) + results := make([]addr, nout) + for i := 0; i < nout; i++ { + tv := t.Out(i) + v := MakeZero(tv) + results[i] = v.getAddr() + ret[i] = v + } + + call(t, *(**byte)(fv.addr), fv.isInterface, ¶ms[0], &results[0]) + + return ret +} + +/* + * interface + */ + +// An InterfaceValue represents an interface value. +type InterfaceValue struct { + value "interface" +} + +// IsNil returns whether v is a nil interface value. +func (v *InterfaceValue) IsNil() bool { return v.Interface() == nil } + +// No single uinptr Get because v.Interface() is available. + +// Get returns the two words that represent an interface in the runtime. +// Those words are useful only when playing unsafe games. +func (v *InterfaceValue) Get() [2]uintptr { + return *(*[2]uintptr)(v.addr) +} + +// Elem returns the concrete value stored in the interface value v. +func (v *InterfaceValue) Elem() Value { return NewValue(v.Interface()) } + +// ../runtime/reflect.cgo +func setiface(typ *InterfaceType, x *interface{}, addr addr) + +// Set assigns x to v. +func (v *InterfaceValue) Set(x Value) { + var i interface{} + if x != nil { + i = x.Interface() + } + if !v.canSet { + panic(cannotSet) + } + // Two different representations; see comment in Get. + // Empty interface is easy. + t := v.typ.(*InterfaceType) + if t.NumMethod() == 0 { + *(*interface{})(v.addr) = i + return + } + + // Non-empty interface requires a runtime check. + setiface(t, &i, v.addr) +} + +// Set sets v to the value x. +func (v *InterfaceValue) SetValue(x Value) { v.Set(x) } + +// Method returns a FuncValue corresponding to v's i'th method. +// The arguments to a Call on the returned FuncValue +// should not include a receiver; the FuncValue will use v +// as the receiver. +func (v *InterfaceValue) Method(i int) *FuncValue { + t := v.Type().(*InterfaceType) + if t == nil || i < 0 || i >= len(t.methods) { + return nil + } + p := &t.methods[i] + + // Interface is two words: itable, data. + tab := *(**[10000]addr)(v.addr) + data := &value{Typeof((*byte)(nil)), addr(uintptr(v.addr) + ptrSize), true} + + fn := tab[i+1] + fv := &FuncValue{value: value{runtimeToType(p.typ), addr(&fn), true}, first: data, isInterface: true} + return fv +} + +/* + * map + */ + +// A MapValue represents a map value. +type MapValue struct { + value "map" +} + +// 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) + } + if x == nil { + *(**uintptr)(v.addr) = nil + return + } + typesMustMatch(v.typ, x.typ) + *(*uintptr)(v.addr) = *(*uintptr)(x.addr) +} + +// Set sets v to the value x. +func (v *MapValue) SetValue(x Value) { + if x == nil { + v.Set(nil) + return + } + v.Set(x.(*MapValue)) +} + +// Get returns the uintptr value of v. +// It is mainly useful for printing. +func (v *MapValue) Get() uintptr { return *(*uintptr)(v.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 + +// 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 { + 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 +} + +// SetElem 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) SetElem(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) + mlen := int32(0) + if m != nil { + mlen = maplen(m) + } + it := mapiterinit(m) + a := make([]Value, mlen) + 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] +} + +// MakeMap creates a new map of the specified type. +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 "ptr" +} + +// 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 x == nil { + *(**uintptr)(v.addr) = nil + return + } + 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) +} + +// Set sets v to the value x. +func (v *PtrValue) SetValue(x Value) { + if x == nil { + v.Set(nil) + return + } + v.Set(x.(*PtrValue)) +} + +// PointTo changes v to point to x. +// If x is a nil Value, PointTo sets v to nil. +func (v *PtrValue) PointTo(x Value) { + if x == nil { + *(**uintptr)(v.addr) = nil + return + } + 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 "struct" +} + +// 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(v.addr, x.addr, v.typ.Size()) +} + +// Set sets v to the value x. +func (v *StructValue) SetValue(x Value) { v.Set(x.(*StructValue)) } + +// 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 == "") +} + +// FieldByIndex returns the nested field corresponding to index. +func (t *StructValue) FieldByIndex(index []int) (v Value) { + v = t + for i, x := range index { + if i > 0 { + if p, ok := v.(*PtrValue); ok { + v = p.Elem() + } + if s, ok := v.(*StructValue); ok { + t = s + } else { + v = nil + return + } + } + v = t.Field(x) + } + return +} + +// FieldByName returns the struct field with the given name. +// The result is nil if no field was found. +func (t *StructValue) FieldByName(name string) Value { + if f, ok := t.Type().(*StructType).FieldByName(name); ok { + return t.FieldByIndex(f.Index) + } + return nil +} + +// FieldByNameFunc returns the struct field with a name that satisfies the +// match function. +// The result is nil if no field was found. +func (t *StructValue) FieldByNameFunc(match func(string) bool) Value { + if f, ok := t.Type().(*StructType).FieldByNameFunc(match); ok { + return t.FieldByIndex(f.Index) + } + return nil +} + +// NumField returns the number of fields in the struct. +func (v *StructValue) NumField() int { return v.typ.(*StructType).NumField() } + +/* + * constructors + */ + +// 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(canonicalize(toType(t)), addr(a), true) +} + +func newValue(typ Type, addr addr, canSet bool) Value { + v := value{typ, addr, canSet} + switch typ.(type) { + case *ArrayType: + return &ArrayValue{v} + case *BoolType: + return &BoolValue{v} + case *ChanType: + return &ChanValue{v} + case *FloatType: + return &FloatValue{v} + case *FuncType: + return &FuncValue{value: v} + case *ComplexType: + return &ComplexValue{v} + case *IntType: + return &IntValue{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 *UnsafePointerType: + return &UnsafePointerValue{v} + } + panic("newValue" + typ.String()) +} + +// MakeZero returns a zero Value for the specified Type. +func MakeZero(typ Type) Value { + if typ == nil { + return nil + } + return newValue(typ, addr(unsafe.New(typ)), true) +} |