interp: fix setting interface objects from operators
This is a follow-up of #1017, generalizing the use of reflect.Set method to set, and possibly overwrite, the concrete value of interface objects all accross the implementation of operators. Previous optimized implementation for non-interface objects is preserved.
This commit is contained in:
13
_test/interface50.go
Normal file
13
_test/interface50.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
a := true
|
||||
var b interface{} = 5
|
||||
println(b.(int))
|
||||
b = a == true
|
||||
println(b.(bool))
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 5
|
||||
// true
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
func {{$name}}(n *node) {
|
||||
next := getExec(n.tnext)
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
dest := genValueOutput(n, typ)
|
||||
c0, c1 := n.child[0], n.child[1]
|
||||
|
||||
@@ -31,6 +32,13 @@ func {{$name}}(n *node) {
|
||||
{{- if $op.Str}}
|
||||
case reflect.String:
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValue(c0)
|
||||
v1 := genValue(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(v0(f).String() {{$op.Name}} v1(f).String()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
s0 := vString(c0.rval)
|
||||
v1 := genValue(c1)
|
||||
@@ -56,6 +64,19 @@ func {{$name}}(n *node) {
|
||||
{{- end}}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueInt(c0)
|
||||
{{- if $op.Shift}}
|
||||
v1 := genValueUint(c1)
|
||||
{{else}}
|
||||
v1 := genValueInt(c1)
|
||||
{{end -}}
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, i := v0(f)
|
||||
_, j := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(i {{$op.Name}} j).Convert(typ))
|
||||
return next
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
i := vInt(c0.rval)
|
||||
{{- if $op.Shift}}
|
||||
@@ -63,38 +84,11 @@ func {{$name}}(n *node) {
|
||||
{{else}}
|
||||
v1 := genValueInt(c1)
|
||||
{{end -}}
|
||||
{{- if (eq $name "add")}}
|
||||
if n.typ.cat != interfaceT || len(n.typ.field) > 0 {
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, j := v1(f)
|
||||
dest(f).SetInt(i + j)
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
var valf func(sum int64) reflect.Value
|
||||
// TODO: cover other int types, and actually other numbers, and even all
|
||||
// relevant operations, not just add.
|
||||
switch typ.Kind() {
|
||||
case reflect.Int:
|
||||
valf = func(sum int64) reflect.Value { return reflect.ValueOf(int(sum)) }
|
||||
case reflect.Int32:
|
||||
valf = func(sum int64) reflect.Value { return reflect.ValueOf(int32(sum)) }
|
||||
default: // int64
|
||||
valf = func(sum int64) reflect.Value { return reflect.ValueOf(sum) }
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, j := v1(f)
|
||||
dest(f).Set(valf(i + j))
|
||||
return next
|
||||
}
|
||||
{{else -}}
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, j := v1(f)
|
||||
dest(f).SetInt(i {{$op.Name}} j)
|
||||
return next
|
||||
}
|
||||
{{end -}}
|
||||
case c1.rval.IsValid():
|
||||
v0 := genValueInt(c0)
|
||||
{{- if $op.Shift}}
|
||||
@@ -102,38 +96,11 @@ func {{$name}}(n *node) {
|
||||
{{else}}
|
||||
j := vInt(c1.rval)
|
||||
{{end -}}
|
||||
{{- if (eq $name "add")}}
|
||||
var valf func(sum int64) reflect.Value
|
||||
// TODO: cover other int types, and actually other numbers, and even all
|
||||
// relevant operations, not just add.
|
||||
switch typ.Kind() {
|
||||
case reflect.Int:
|
||||
valf = func(sum int64) reflect.Value { return reflect.ValueOf(int(sum)) }
|
||||
case reflect.Int32:
|
||||
valf = func(sum int64) reflect.Value { return reflect.ValueOf(int32(sum)) }
|
||||
default: // int64
|
||||
valf = func(sum int64) reflect.Value { return reflect.ValueOf(sum) }
|
||||
}
|
||||
if wantEmptyInterface(n) {
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, i := v0(f)
|
||||
dest(f).Set(valf(i + j))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, i := v0(f)
|
||||
dest(f).SetInt(i + j)
|
||||
return next
|
||||
}
|
||||
{{else -}}
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, i := v0(f)
|
||||
dest(f).SetInt(i {{$op.Name}} j)
|
||||
return next
|
||||
}
|
||||
{{end -}}
|
||||
default:
|
||||
v0 := genValueInt(c0)
|
||||
{{- if $op.Shift}}
|
||||
@@ -150,6 +117,15 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueUint(c0)
|
||||
v1 := genValueUint(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, i := v0(f)
|
||||
_, j := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(i {{$op.Name}} j).Convert(typ))
|
||||
return next
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
i := vUint(c0.rval)
|
||||
v1 := genValueUint(c1)
|
||||
@@ -179,6 +155,15 @@ func {{$name}}(n *node) {
|
||||
{{- if $op.Float}}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueFloat(c0)
|
||||
v1 := genValueFloat(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, i := v0(f)
|
||||
_, j := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(i {{$op.Name}} j).Convert(typ))
|
||||
return next
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
i := vFloat(c0.rval)
|
||||
v1 := genValueFloat(c1)
|
||||
@@ -207,25 +192,32 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genComplex(c0)
|
||||
v1 := genComplex(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(v0(f) {{$op.Name}} v1(f)).Convert(typ))
|
||||
return next
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
r0 := vComplex(c0.rval)
|
||||
v1 := genValue(c1)
|
||||
v1 := genComplex(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetComplex(r0 {{$op.Name}} v1(f).Complex())
|
||||
dest(f).SetComplex(r0 {{$op.Name}} v1(f))
|
||||
return next
|
||||
}
|
||||
case c1.rval.IsValid():
|
||||
r1 := vComplex(c1.rval)
|
||||
v0 := genValue(c0)
|
||||
v0 := genComplex(c0)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetComplex(v0(f).Complex() {{$op.Name}} r1)
|
||||
dest(f).SetComplex(v0(f) {{$op.Name}} r1)
|
||||
return next
|
||||
}
|
||||
default:
|
||||
v0 := genValue(c0)
|
||||
v1 := genValue(c1)
|
||||
v0 := genComplex(c0)
|
||||
v1 := genComplex(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetComplex(v0(f).Complex() {{$op.Name}} v1(f).Complex())
|
||||
dest(f).SetComplex(v0(f) {{$op.Name}} v1(f))
|
||||
return next
|
||||
}
|
||||
}
|
||||
@@ -483,12 +475,24 @@ func {{$name}}Const(n *node) {
|
||||
func {{$name}}(n *node) {
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValueOutput(n, reflect.TypeOf(true))
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
c0, c1 := n.child[0], n.child[1]
|
||||
|
||||
{{- if or (eq $op.Name "==") (eq $op.Name "!=") }}
|
||||
|
||||
if c0.typ.cat == aliasT || c1.typ.cat == aliasT {
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValue(c0)
|
||||
v1 := genValue(c1)
|
||||
dest := genValue(n)
|
||||
n.exec = func(f *frame) bltn {
|
||||
i0 := v0(f).Interface()
|
||||
i1 := v1(f).Interface()
|
||||
dest(f).Set(reflect.ValueOf(i0 {{$op.Name}} i1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
i0 := c0.rval.Interface()
|
||||
v1 := genValue(c1)
|
||||
@@ -565,9 +569,18 @@ func {{$name}}(n *node) {
|
||||
switch t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf(); {
|
||||
case isString(t0) || isString(t1):
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueString(c0)
|
||||
v1 := genValueString(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, s0 := v0(f)
|
||||
_, s1 := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
s0 := vString(c0.rval)
|
||||
v1 := genValueString(n.child[1])
|
||||
v1 := genValueString(c1)
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
@@ -588,7 +601,7 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case c1.rval.IsValid():
|
||||
s1 := vString(c1.rval)
|
||||
v0 := genValueString(n.child[0])
|
||||
v0 := genValueString(c0)
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
@@ -608,8 +621,8 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
}
|
||||
default:
|
||||
v0 := genValueString(n.child[0])
|
||||
v1 := genValueString(n.child[1])
|
||||
v0 := genValueString(c0)
|
||||
v1 := genValueString(c1)
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
@@ -633,6 +646,15 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case isFloat(t0) || isFloat(t1):
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueFloat(c0)
|
||||
v1 := genValueFloat(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, s0 := v0(f)
|
||||
_, s1 := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
s0 := vFloat(c0.rval)
|
||||
v1 := genValueFloat(c1)
|
||||
@@ -703,6 +725,15 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case isUint(t0) || isUint(t1):
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueUint(c0)
|
||||
v1 := genValueUint(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, s0 := v0(f)
|
||||
_, s1 := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
s0 := vUint(c0.rval)
|
||||
v1 := genValueUint(c1)
|
||||
@@ -774,6 +805,15 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
case isInt(t0) || isInt(t1):
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValueInt(c0)
|
||||
v1 := genValueInt(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
_, s0 := v0(f)
|
||||
_, s1 := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
s0 := vInt(c0.rval)
|
||||
v1 := genValueInt(c1)
|
||||
@@ -846,6 +886,15 @@ func {{$name}}(n *node) {
|
||||
{{- if $op.Complex}}
|
||||
case isComplex(t0) || isComplex(t1):
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genComplex(c0)
|
||||
v1 := genComplex(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
s0 := v0(f)
|
||||
s1 := v1(f)
|
||||
dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
s0 := vComplex(c0.rval)
|
||||
v1 := genComplex(c1)
|
||||
@@ -890,8 +939,8 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
}
|
||||
default:
|
||||
v0 := genComplex(n.child[0])
|
||||
v1 := genComplex(n.child[1])
|
||||
v0 := genComplex(c0)
|
||||
v1 := genComplex(c1)
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
n.exec = func(f *frame) bltn {
|
||||
@@ -915,6 +964,15 @@ func {{$name}}(n *node) {
|
||||
}
|
||||
default:
|
||||
switch {
|
||||
case isInterface:
|
||||
v0 := genValue(c0)
|
||||
v1 := genValue(c1)
|
||||
n.exec = func(f *frame) bltn {
|
||||
i0 := v0(f).Interface()
|
||||
i1 := v1(f).Interface()
|
||||
dest(f).Set(reflect.ValueOf(i0 {{$op.Name}} i1).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
case c0.rval.IsValid():
|
||||
i0 := c0.rval.Interface()
|
||||
v1 := genValue(c1)
|
||||
|
||||
718
interp/op.go
718
interp/op.go
File diff suppressed because it is too large
Load Diff
131
interp/run.go
131
interp/run.go
@@ -1998,24 +1998,54 @@ func neg(n *node) {
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[0])
|
||||
next := getExec(n.tnext)
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
|
||||
switch n.typ.TypeOf().Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(-value(f).Int()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetInt(-value(f).Int())
|
||||
return next
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(-value(f).Uint()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetUint(-value(f).Uint())
|
||||
return next
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(-value(f).Float()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetFloat(-value(f).Float())
|
||||
return next
|
||||
}
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(-value(f).Complex()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetComplex(-value(f).Complex())
|
||||
return next
|
||||
@@ -2038,15 +2068,30 @@ func bitNot(n *node) {
|
||||
dest := genValue(n)
|
||||
value := genValue(n.child[0])
|
||||
next := getExec(n.tnext)
|
||||
typ := n.typ.TypeOf()
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
|
||||
switch typ.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(^value(f).Int()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetInt(^value(f).Int())
|
||||
return next
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(^value(f).Uint()).Convert(typ))
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetUint(^value(f).Uint())
|
||||
return next
|
||||
@@ -2059,6 +2104,8 @@ func land(n *node) {
|
||||
value1 := genValue(n.child[1])
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
@@ -2070,11 +2117,18 @@ func land(n *node) {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(value0(f).Bool() && value1(f).Bool())
|
||||
dest(f).Set(reflect.ValueOf(value0(f).Bool() && value1(f).Bool()).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(value0(f).Bool() && value1(f).Bool())
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2083,6 +2137,8 @@ func lor(n *node) {
|
||||
value1 := genValue(n.child[1])
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
@@ -2094,11 +2150,18 @@ func lor(n *node) {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(value0(f).Bool() || value1(f).Bool())
|
||||
dest(f).Set(reflect.ValueOf(value0(f).Bool() || value1(f).Bool()).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(value0(f).Bool() || value1(f).Bool())
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3556,24 +3619,49 @@ func isNil(n *node) {
|
||||
} else {
|
||||
value = genValue(c0)
|
||||
}
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
if n.fnext == nil {
|
||||
if c0.typ.cat != interfaceT {
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(value(f).IsNil()).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(value(f).IsNil())
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
v := value(f)
|
||||
var r bool
|
||||
if vi, ok := v.Interface().(valueInterface); ok {
|
||||
r = (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
|
||||
} else {
|
||||
r = v.IsNil()
|
||||
}
|
||||
dest(f).Set(reflect.ValueOf(r).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
v := value(f)
|
||||
var r bool
|
||||
if vi, ok := v.Interface().(valueInterface); ok {
|
||||
dest(f).SetBool(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
|
||||
r = (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
|
||||
} else {
|
||||
dest(f).SetBool(v.IsNil())
|
||||
r = v.IsNil()
|
||||
}
|
||||
dest(f).SetBool(r)
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
@@ -3620,11 +3708,20 @@ func isNotNil(n *node) {
|
||||
} else {
|
||||
value = genValue(c0)
|
||||
}
|
||||
typ := n.typ.concrete().TypeOf()
|
||||
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
if n.fnext == nil {
|
||||
if c0.typ.cat != interfaceT {
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).Set(reflect.ValueOf(!value(f).IsNil()).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(!value(f).IsNil())
|
||||
return tnext
|
||||
@@ -3632,13 +3729,29 @@ func isNotNil(n *node) {
|
||||
return
|
||||
}
|
||||
|
||||
if isInterface {
|
||||
n.exec = func(f *frame) bltn {
|
||||
v := value(f)
|
||||
var r bool
|
||||
if vi, ok := v.Interface().(valueInterface); ok {
|
||||
r = (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
|
||||
} else {
|
||||
r = v.IsNil()
|
||||
}
|
||||
dest(f).Set(reflect.ValueOf(!r).Convert(typ))
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
v := value(f)
|
||||
var r bool
|
||||
if vi, ok := v.Interface().(valueInterface); ok {
|
||||
dest(f).SetBool(!(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT))
|
||||
r = (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
|
||||
} else {
|
||||
dest(f).SetBool(!v.IsNil())
|
||||
r = v.IsNil()
|
||||
}
|
||||
dest(f).SetBool(!r)
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user