interp: support more type assertion cases

Fixes #955
This commit is contained in:
mpl
2020-11-30 18:00:04 +01:00
committed by GitHub
parent 662d2a6afe
commit 1e0f6ece6e
3 changed files with 213 additions and 13 deletions

View File

@@ -33,6 +33,30 @@ func valueOf(data []reflect.Value, i int) reflect.Value {
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() }
@@ -55,6 +79,35 @@ func genValueRecv(n *node) func(*frame) reflect.Value {
}
}
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