interp: fix litteral map containing binary functions
The case of assigning a binary function to a funcT object was solved elsewhere. Factor the case in genDestValue to apply it at multiple places. Fixes #1100.
This commit is contained in:
@@ -6,7 +6,10 @@ func f(s string) string { return "hello " + s }
|
||||
|
||||
func g(s string) string { return "hi " + s }
|
||||
|
||||
var methods = map[string]func(string) string{"f": f}
|
||||
var methods = map[string]func(string) string{
|
||||
"f": f,
|
||||
"h": strings.ToLower,
|
||||
}
|
||||
|
||||
func main() {
|
||||
methods["i"] = strings.ToUpper
|
||||
@@ -14,9 +17,11 @@ func main() {
|
||||
println(methods["f"]("test"))
|
||||
println(methods["g"]("test"))
|
||||
println(methods["i"]("test"))
|
||||
println(methods["h"]("TEST"))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// hello test
|
||||
// hi test
|
||||
// TEST
|
||||
// test
|
||||
|
||||
@@ -570,7 +570,7 @@ func isRecursiveType(t *itype, rtype reflect.Type) bool {
|
||||
return true
|
||||
}
|
||||
switch t.cat {
|
||||
case arrayT, mapT, ptrT, sliceT:
|
||||
case aliasT, arrayT, mapT, ptrT, sliceT:
|
||||
return isRecursiveType(t.val, t.val.rtype)
|
||||
default:
|
||||
return false
|
||||
@@ -589,34 +589,10 @@ func assign(n *node) {
|
||||
|
||||
for i := 0; i < n.nleft; i++ {
|
||||
dest, src := n.child[i], n.child[sbase+i]
|
||||
switch {
|
||||
case isInterfaceSrc(dest.typ):
|
||||
if len(dest.typ.field) > 0 {
|
||||
svalue[i] = genValueInterface(src)
|
||||
break
|
||||
}
|
||||
svalue[i] = genValue(src)
|
||||
case (dest.typ.cat == valueT || dest.typ.cat == errorT) && dest.typ.rtype.Kind() == reflect.Interface:
|
||||
svalue[i] = genInterfaceWrapper(src, dest.typ.rtype)
|
||||
case isFuncSrc(src.typ) && dest.typ.cat == valueT:
|
||||
if isFuncSrc(src.typ) && isField(dest) {
|
||||
svalue[i] = genFunctionWrapper(src)
|
||||
case isFuncSrc(src.typ) && isField(dest):
|
||||
svalue[i] = genFunctionWrapper(src)
|
||||
case isFuncSrc(dest.typ) && src.typ.cat == valueT:
|
||||
svalue[i] = genValueNode(src)
|
||||
case src.kind == basicLit && src.val == nil:
|
||||
t := dest.typ.TypeOf()
|
||||
svalue[i] = func(*frame) reflect.Value { return reflect.New(t).Elem() }
|
||||
case isRecursiveType(dest.typ, dest.typ.rtype):
|
||||
svalue[i] = genValueRecursiveInterface(src, dest.typ.rtype)
|
||||
case isRecursiveType(src.typ, src.typ.rtype):
|
||||
svalue[i] = genValueRecursiveInterfacePtrValue(src)
|
||||
case src.typ.untyped && isComplex(dest.typ.TypeOf()):
|
||||
svalue[i] = genValueComplex(src)
|
||||
case src.typ.untyped && !dest.typ.untyped:
|
||||
svalue[i] = genValueAs(src, dest.typ.TypeOf())
|
||||
default:
|
||||
svalue[i] = genValue(src)
|
||||
} else {
|
||||
svalue[i] = genDestValue(dest.typ, src)
|
||||
}
|
||||
if isMapEntry(dest) {
|
||||
if isInterfaceSrc(dest.child[1].typ) { // key
|
||||
@@ -2302,25 +2278,14 @@ func arrayLit(n *node) {
|
||||
|
||||
values := make([]func(*frame) reflect.Value, len(child))
|
||||
index := make([]int, len(child))
|
||||
rtype := n.typ.val.TypeOf()
|
||||
var max, prev int
|
||||
|
||||
for i, c := range child {
|
||||
if c.kind == keyValueExpr {
|
||||
convertLiteralValue(c.child[1], rtype)
|
||||
if isInterfaceSrc(n.typ.val) && !isEmptyInterface(n.typ.val) {
|
||||
values[i] = genValueInterface(c.child[1])
|
||||
} else {
|
||||
values[i] = genValue(c.child[1])
|
||||
}
|
||||
values[i] = genDestValue(n.typ.val, c.child[1])
|
||||
index[i] = int(vInt(c.child[0].rval))
|
||||
} else {
|
||||
convertLiteralValue(c, rtype)
|
||||
if isInterfaceSrc(n.typ.val) && !isEmptyInterface(n.typ.val) {
|
||||
values[i] = genValueInterface(c)
|
||||
} else {
|
||||
values[i] = genValue(c)
|
||||
}
|
||||
values[i] = genDestValue(n.typ.val, c)
|
||||
index[i] = prev
|
||||
}
|
||||
prev = index[i] + 1
|
||||
@@ -2357,18 +2322,8 @@ func mapLit(n *node) {
|
||||
keys := make([]func(*frame) reflect.Value, len(child))
|
||||
values := make([]func(*frame) reflect.Value, len(child))
|
||||
for i, c := range child {
|
||||
convertLiteralValue(c.child[0], n.typ.key.TypeOf())
|
||||
convertLiteralValue(c.child[1], n.typ.val.TypeOf())
|
||||
if isInterfaceSrc(n.typ.key) {
|
||||
keys[i] = genValueInterface(c.child[0])
|
||||
} else {
|
||||
keys[i] = genValue(c.child[0])
|
||||
}
|
||||
if isInterfaceSrc(n.typ.val) && !isEmptyInterface(n.typ.val) {
|
||||
values[i] = genValueInterface(c.child[1])
|
||||
} else {
|
||||
values[i] = genValue(c.child[1])
|
||||
}
|
||||
keys[i] = genDestValue(n.typ.key, c.child[0])
|
||||
values[i] = genDestValue(n.typ.val, c.child[1])
|
||||
}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
@@ -3450,15 +3405,7 @@ func send(n *node) {
|
||||
next := getExec(n.tnext)
|
||||
c0, c1 := n.child[0], n.child[1]
|
||||
value0 := genValue(c0) // Send channel.
|
||||
convertLiteralValue(c1, c0.typ.val.TypeOf())
|
||||
|
||||
var value1 func(*frame) reflect.Value // Value to send.
|
||||
switch {
|
||||
case isInterfaceBin(c0.typ.val):
|
||||
value1 = genInterfaceWrapper(c1, c0.typ.val.rtype)
|
||||
default:
|
||||
value1 = genValue(c1)
|
||||
}
|
||||
value1 := genDestValue(c0.typ.val, c1)
|
||||
|
||||
if !n.interp.cancelChan {
|
||||
// Send is non-cancellable, has the least overhead.
|
||||
|
||||
@@ -1723,7 +1723,7 @@ func isInterfaceSrc(t *itype) bool {
|
||||
}
|
||||
|
||||
func isInterfaceBin(t *itype) bool {
|
||||
return t.cat == valueT && t.rtype.Kind() == reflect.Interface
|
||||
return t.cat == valueT && t.rtype.Kind() == reflect.Interface || t.cat == errorT
|
||||
}
|
||||
|
||||
func isInterface(t *itype) bool {
|
||||
|
||||
@@ -214,6 +214,31 @@ func genValue(n *node) func(*frame) reflect.Value {
|
||||
}
|
||||
}
|
||||
|
||||
func genDestValue(typ *itype, n *node) func(*frame) reflect.Value {
|
||||
convertLiteralValue(n, typ.TypeOf())
|
||||
switch {
|
||||
case isInterfaceSrc(typ) && !isEmptyInterface(typ):
|
||||
return genValueInterface(n)
|
||||
case isFuncSrc(typ) && n.typ.cat == valueT:
|
||||
return genValueNode(n)
|
||||
case typ.cat == valueT && isFuncSrc(n.typ):
|
||||
return genFunctionWrapper(n)
|
||||
case isInterfaceBin(typ):
|
||||
return genInterfaceWrapper(n, typ.rtype)
|
||||
case n.kind == basicLit && n.val == nil:
|
||||
return func(*frame) reflect.Value { return reflect.New(typ.rtype).Elem() }
|
||||
case isRecursiveType(typ, typ.rtype):
|
||||
return genValueRecursiveInterface(n, typ.rtype)
|
||||
case isRecursiveType(n.typ, n.typ.rtype):
|
||||
return genValueRecursiveInterfacePtrValue(n)
|
||||
case n.typ.untyped && isComplex(typ.TypeOf()):
|
||||
return genValueComplex(n)
|
||||
case n.typ.untyped && !typ.untyped:
|
||||
return genValueAs(n, typ.TypeOf())
|
||||
}
|
||||
return genValue(n)
|
||||
}
|
||||
|
||||
func genValueArray(n *node) func(*frame) reflect.Value {
|
||||
value := genValue(n)
|
||||
// dereference array pointer, to support array operations on array pointer
|
||||
@@ -310,7 +335,7 @@ func zeroInterfaceValue() reflect.Value {
|
||||
}
|
||||
|
||||
func wantEmptyInterface(n *node) bool {
|
||||
return n.typ.cat == interfaceT && len(n.typ.field) == 0 ||
|
||||
return isEmptyInterface(n.typ) ||
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user