Files
moxa/interp/value.go
mpl 2e17cfab4f interp: do not wrap empty interface
The empty interface (interface{}), and its variants (such as []interface{} and map[string]interface{}), are commonly used in Go to (json) Unmarshal arbitrary data. Within Yaegi, all interface types are wrapped in a valueInterface struct in order to retain all the information needed for a consistent internal state (as reflect is not enough to achieve that). However, this wrapping ends up being problematic when it comes to the type assertions related to the aforementioned Unmarshaling.

Therefore, this PR is an attempt to consider the empty interface (and its variants) as an exception within Yaegi, that should never be wrapped within a valueInterface, and to treat it similarly to the other basic Go types. The assumption is that the wrapping should not be needed, as there is no information about implemented methods to maintain.

Fixes #984 
Fixes #829 
Fixes #1015
2021-02-04 12:08:04 +01:00

588 lines
16 KiB
Go

package interp
import (
"go/constant"
"reflect"
)
const (
notInFrame = -1 // value of node.findex for literal values (not in frame)
globalFrame = -1 // value of node.level for global symbols
)
func valueGenerator(n *node, i int) func(*frame) reflect.Value {
switch n.level {
case globalFrame:
return func(f *frame) reflect.Value { return valueOf(f.root.data, i) }
case 0:
return func(f *frame) reflect.Value { return valueOf(f.data, i) }
case 1:
return func(f *frame) reflect.Value { return valueOf(f.anc.data, i) }
case 2:
return func(f *frame) reflect.Value { return valueOf(f.anc.anc.data, i) }
default:
return func(f *frame) reflect.Value {
for level := n.level; level > 0; level-- {
f = f.anc
}
return valueOf(f.data, i)
}
}
}
// valueOf safely recovers the ith element of data. This is necessary
// because a cancellation prior to any evaluation result may leave
// the frame's data empty.
func valueOf(data []reflect.Value, i int) reflect.Value {
if i < len(data) {
return data[i]
}
return reflect.Value{}
}
func genValueBinMethodOnInterface(n *node, defaultGen func(*frame) reflect.Value) func(*frame) reflect.Value {
if n == nil || n.child == nil || n.child[0] == nil ||
n.child[0].child == nil || n.child[0].child[0] == nil {
return defaultGen
}
if n.child[0].child[1] == nil || n.child[0].child[1].ident == "" {
return defaultGen
}
value0 := genValue(n.child[0].child[0])
return func(f *frame) reflect.Value {
val, ok := value0(f).Interface().(valueInterface)
if !ok {
return defaultGen(f)
}
typ := val.node.typ
if typ.node != nil || typ.cat != valueT {
return defaultGen(f)
}
meth, _ := typ.rtype.MethodByName(n.child[0].child[1].ident)
return meth.Func
}
}
func genValueRecvIndirect(n *node) func(*frame) reflect.Value {
v := genValueRecv(n)
return func(f *frame) reflect.Value { return v(f).Elem() }
}
func genValueRecv(n *node) func(*frame) reflect.Value {
v := genValue(n.recv.node)
fi := n.recv.index
if len(fi) == 0 {
return v
}
return func(f *frame) reflect.Value {
r := v(f)
if r.Kind() == reflect.Ptr {
r = r.Elem()
}
return r.FieldByIndex(fi)
}
}
func genValueBinRecv(n *node, recv *receiver) func(*frame) reflect.Value {
value := genValue(n)
binValue := genValue(recv.node)
v := func(f *frame) reflect.Value {
if def, ok := value(f).Interface().(*node); ok {
if def != nil && def.recv != nil && def.recv.val.IsValid() {
return def.recv.val
}
}
ival, _ := binValue(f).Interface().(valueInterface)
return ival.value
}
fi := recv.index
if len(fi) == 0 {
return v
}
return func(f *frame) reflect.Value {
r := v(f)
if r.Kind() == reflect.Ptr {
r = r.Elem()
}
return r.FieldByIndex(fi)
}
}
func genValueRecvInterfacePtr(n *node) func(*frame) reflect.Value {
v := genValue(n.recv.node)
fi := n.recv.index
return func(f *frame) reflect.Value {
r := v(f)
r = r.Elem().Elem()
if len(fi) == 0 {
return r
}
if r.Kind() == reflect.Ptr {
r = r.Elem()
}
return r.FieldByIndex(fi)
}
}
func genValueAsFunctionWrapper(n *node) func(*frame) reflect.Value {
value := genValue(n)
typ := n.typ.TypeOf()
return func(f *frame) reflect.Value {
v := value(f)
if v.IsNil() {
return reflect.New(typ).Elem()
}
return genFunctionWrapper(v.Interface().(*node))(f)
}
}
func genValueAs(n *node, t reflect.Type) func(*frame) reflect.Value {
v := genValue(n)
return func(f *frame) reflect.Value {
return v(f).Convert(t)
}
}
func genValue(n *node) func(*frame) reflect.Value {
switch n.kind {
case basicLit:
convertConstantValue(n)
v := n.rval
if !v.IsValid() {
v = reflect.New(interf).Elem()
}
return func(f *frame) reflect.Value { return v }
case funcDecl:
var v reflect.Value
if w, ok := n.val.(reflect.Value); ok {
v = w
} else {
v = reflect.ValueOf(n.val)
}
return func(f *frame) reflect.Value { return v }
default:
if n.rval.IsValid() {
convertConstantValue(n)
v := n.rval
return func(f *frame) reflect.Value { return v }
}
if n.sym != nil {
i := n.sym.index
if i < 0 {
return genValue(n.sym.node)
}
if n.sym.global {
return func(f *frame) reflect.Value { return f.root.data[i] }
}
return valueGenerator(n, i)
}
if n.findex == notInFrame {
var v reflect.Value
if w, ok := n.val.(reflect.Value); ok {
v = w
} else {
v = reflect.ValueOf(n.val)
}
return func(f *frame) reflect.Value { return v }
}
return valueGenerator(n, n.findex)
}
}
func genValueArray(n *node) func(*frame) reflect.Value {
value := genValue(n)
// dereference array pointer, to support array operations on array pointer
if n.typ.TypeOf().Kind() == reflect.Ptr {
return func(f *frame) reflect.Value {
return value(f).Elem()
}
}
return value
}
func genValueRangeArray(n *node) func(*frame) reflect.Value {
value := genValue(n)
switch {
case n.typ.TypeOf().Kind() == reflect.Ptr:
// dereference array pointer, to support array operations on array pointer
return func(f *frame) reflect.Value {
return value(f).Elem()
}
case n.typ.val != nil && n.typ.val.cat == interfaceT:
if len(n.typ.val.field) > 0 {
return func(f *frame) reflect.Value {
val := value(f)
v := []valueInterface{}
for i := 0; i < val.Len(); i++ {
switch av := val.Index(i).Interface().(type) {
case []valueInterface:
v = append(v, av...)
case valueInterface:
v = append(v, av)
default:
panic(n.cfgErrorf("invalid type %v", val.Index(i).Type()))
}
}
return reflect.ValueOf(v)
}
}
// empty interface, do not wrap.
fallthrough
default:
return func(f *frame) reflect.Value {
// This is necessary to prevent changes in the returned
// reflect.Value being reflected back to the value used
// for the range expression.
return reflect.ValueOf(value(f).Interface())
}
}
}
func genValueInterfaceArray(n *node) func(*frame) reflect.Value {
value := genValue(n)
return func(f *frame) reflect.Value {
vi := value(f).Interface().([]valueInterface)
v := reflect.MakeSlice(reflect.TypeOf([]interface{}{}), len(vi), len(vi))
for i, vv := range vi {
v.Index(i).Set(vv.value)
}
return v
}
}
func genValueInterface(n *node) func(*frame) reflect.Value {
value := genValue(n)
return func(f *frame) reflect.Value {
v := value(f)
nod := n
for v.IsValid() {
// traverse interface indirections to find out concrete type
vi, ok := v.Interface().(valueInterface)
if !ok {
break
}
v = vi.value
nod = vi.node
}
// empty interface, do not wrap.
if nod.typ.cat == interfaceT && len(nod.typ.field) == 0 {
return v
}
return reflect.ValueOf(valueInterface{nod, v})
}
}
func zeroInterfaceValue() reflect.Value {
n := &node{kind: basicLit, typ: &itype{cat: nilT, untyped: true}}
v := reflect.New(interf).Elem()
return reflect.ValueOf(valueInterface{n, v})
}
func wantEmptyInterface(n *node) bool {
return n.typ.cat == interfaceT && len(n.typ.field) == 0 ||
n.anc.action == aAssign && n.anc.typ.cat == interfaceT && len(n.anc.typ.field) == 0 ||
n.anc.kind == returnStmt && n.anc.val.(*node).typ.ret[0].cat == interfaceT && len(n.anc.val.(*node).typ.ret[0].field) == 0
}
func genValueOutput(n *node, t reflect.Type) func(*frame) reflect.Value {
value := genValue(n)
switch {
case n.anc.action == aAssign && n.anc.typ.cat == interfaceT:
if len(n.anc.typ.field) == 0 {
// empty interface, do not wrap
return value
}
fallthrough
case n.anc.kind == returnStmt && n.anc.val.(*node).typ.ret[0].cat == interfaceT:
if len(n.anc.val.(*node).typ.ret[0].field) == 0 {
// empty interface, do not wrap
return value
}
// The result of the builtin has to be returned as an interface type.
// Wrap it in a valueInterface and return the dereferenced value.
return func(f *frame) reflect.Value {
d := value(f)
v := reflect.New(t).Elem()
d.Set(reflect.ValueOf(valueInterface{n, v}))
return v
}
}
return value
}
func valueInterfaceValue(v reflect.Value) reflect.Value {
for {
vv, ok := v.Interface().(valueInterface)
if !ok {
break
}
v = vv.value
}
return v
}
func genValueInterfaceValue(n *node) func(*frame) reflect.Value {
value := genValue(n)
return func(f *frame) reflect.Value {
v := value(f)
if v.Interface().(valueInterface).node == nil {
// Uninitialized interface value, set it to a correct zero value.
v.Set(zeroInterfaceValue())
v = value(f)
}
return valueInterfaceValue(v)
}
}
func genValueNode(n *node) func(*frame) reflect.Value {
value := genValue(n)
return func(f *frame) reflect.Value {
return reflect.ValueOf(&node{rval: value(f)})
}
}
func genValueRecursiveInterface(n *node, t reflect.Type) func(*frame) reflect.Value {
value := genValue(n)
return func(f *frame) reflect.Value {
vv := value(f)
v := reflect.New(t).Elem()
toRecursive(v, vv)
return v
}
}
func toRecursive(dest, src reflect.Value) {
if !src.IsValid() {
return
}
switch dest.Kind() {
case reflect.Map:
v := reflect.MakeMapWithSize(dest.Type(), src.Len())
for _, kv := range src.MapKeys() {
vv := reflect.New(dest.Type().Elem()).Elem()
toRecursive(vv, src.MapIndex(kv))
vv.SetMapIndex(kv, vv)
}
dest.Set(v)
case reflect.Slice:
l := src.Len()
v := reflect.MakeSlice(dest.Type(), l, l)
for i := 0; i < l; i++ {
toRecursive(v.Index(i), src.Index(i))
}
dest.Set(v)
case reflect.Ptr:
v := reflect.New(dest.Type().Elem()).Elem()
s := src
if s.Elem().Kind() != reflect.Struct { // In the case of *interface{}, we want *struct{}
s = s.Elem()
}
toRecursive(v, s)
dest.Set(v.Addr())
default:
dest.Set(src)
}
}
func genValueRecursiveInterfacePtrValue(n *node) func(*frame) reflect.Value {
value := genValue(n)
return func(f *frame) reflect.Value {
v := value(f)
if v.IsZero() {
return v
}
return v.Elem().Elem()
}
}
func vInt(v reflect.Value) (i int64) {
if c := vConstantValue(v); c != nil {
i, _ = constant.Int64Val(constant.ToInt(c))
return i
}
switch v.Type().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i = v.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
i = int64(v.Uint())
case reflect.Float32, reflect.Float64:
i = int64(v.Float())
case reflect.Complex64, reflect.Complex128:
i = int64(real(v.Complex()))
}
return
}
func vUint(v reflect.Value) (i uint64) {
if c := vConstantValue(v); c != nil {
i, _ = constant.Uint64Val(constant.ToInt(c))
return i
}
switch v.Type().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i = uint64(v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
i = v.Uint()
case reflect.Float32, reflect.Float64:
i = uint64(v.Float())
case reflect.Complex64, reflect.Complex128:
i = uint64(real(v.Complex()))
}
return
}
func vComplex(v reflect.Value) (c complex128) {
if c := vConstantValue(v); c != nil {
c = constant.ToComplex(c)
rel, _ := constant.Float64Val(constant.Real(c))
img, _ := constant.Float64Val(constant.Imag(c))
return complex(rel, img)
}
switch v.Type().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
c = complex(float64(v.Int()), 0)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
c = complex(float64(v.Uint()), 0)
case reflect.Float32, reflect.Float64:
c = complex(v.Float(), 0)
case reflect.Complex64, reflect.Complex128:
c = v.Complex()
}
return
}
func vFloat(v reflect.Value) (i float64) {
if c := vConstantValue(v); c != nil {
i, _ = constant.Float64Val(constant.ToFloat(c))
return i
}
switch v.Type().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i = float64(v.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
i = float64(v.Uint())
case reflect.Float32, reflect.Float64:
i = v.Float()
case reflect.Complex64, reflect.Complex128:
i = real(v.Complex())
}
return
}
func vString(v reflect.Value) (s string) {
if c := vConstantValue(v); c != nil {
s = constant.StringVal(c)
return s
}
return v.String()
}
func vConstantValue(v reflect.Value) (c constant.Value) {
if v.Type().Implements(constVal) {
c = v.Interface().(constant.Value)
}
return
}
func genValueInt(n *node) func(*frame) (reflect.Value, int64) {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *frame) (reflect.Value, int64) { v := value(f); return v, v.Int() }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return func(f *frame) (reflect.Value, int64) { v := value(f); return v, int64(v.Uint()) }
case reflect.Float32, reflect.Float64:
return func(f *frame) (reflect.Value, int64) { v := value(f); return v, int64(v.Float()) }
case reflect.Complex64, reflect.Complex128:
if n.typ.untyped && n.rval.IsValid() && imag(n.rval.Complex()) == 0 {
return func(f *frame) (reflect.Value, int64) { v := value(f); return v, int64(real(v.Complex())) }
}
}
return nil
}
func genValueUint(n *node) func(*frame) (reflect.Value, uint64) {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *frame) (reflect.Value, uint64) { v := value(f); return v, uint64(v.Int()) }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return func(f *frame) (reflect.Value, uint64) { v := value(f); return v, v.Uint() }
case reflect.Float32, reflect.Float64:
return func(f *frame) (reflect.Value, uint64) { v := value(f); return v, uint64(v.Float()) }
case reflect.Complex64, reflect.Complex128:
if n.typ.untyped && n.rval.IsValid() && imag(n.rval.Complex()) == 0 {
return func(f *frame) (reflect.Value, uint64) { v := value(f); return v, uint64(real(v.Complex())) }
}
}
return nil
}
func genValueFloat(n *node) func(*frame) (reflect.Value, float64) {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *frame) (reflect.Value, float64) { v := value(f); return v, float64(v.Int()) }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return func(f *frame) (reflect.Value, float64) { v := value(f); return v, float64(v.Uint()) }
case reflect.Float32, reflect.Float64:
return func(f *frame) (reflect.Value, float64) { v := value(f); return v, v.Float() }
case reflect.Complex64, reflect.Complex128:
if n.typ.untyped && n.rval.IsValid() && imag(n.rval.Complex()) == 0 {
return func(f *frame) (reflect.Value, float64) { v := value(f); return v, real(v.Complex()) }
}
}
return nil
}
func genValueComplex(n *node) func(*frame) reflect.Value {
vc := genComplex(n)
return func(f *frame) reflect.Value { return reflect.ValueOf(vc(f)) }
}
func genComplex(n *node) func(*frame) complex128 {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *frame) complex128 { return complex(float64(value(f).Int()), 0) }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return func(f *frame) complex128 { return complex(float64(value(f).Uint()), 0) }
case reflect.Float32, reflect.Float64:
return func(f *frame) complex128 { return complex(value(f).Float(), 0) }
case reflect.Complex64, reflect.Complex128:
return func(f *frame) complex128 { return value(f).Complex() }
}
return nil
}
func genValueString(n *node) func(*frame) (reflect.Value, string) {
value := genValue(n)
return func(f *frame) (reflect.Value, string) { v := value(f); return v, v.String() }
}