fix: correct handling of equality tests (#205)

This commit is contained in:
Marc Vertes
2019-06-05 09:50:44 +02:00
committed by Ludovic Fernandez
parent 455a37e678
commit 025e4f924a
10 changed files with 307 additions and 3 deletions

10
_test/a26.go Normal file
View File

@@ -0,0 +1,10 @@
package main
func main() {
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
println(a == b)
}
// Output:
// true

14
_test/for5.go Normal file
View File

@@ -0,0 +1,14 @@
package main
func main() {
var a bool
for a {
println("nok")
break
}
println("bye")
}
// Output:
// bye

14
_test/if0.go Normal file
View File

@@ -0,0 +1,14 @@
package main
func main() {
var a bool
if a {
println("ok")
} else {
println("nok")
}
}
// Output:
// nok

13
_test/map15.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import "fmt"
func main() {
users := make(map[string]string)
v := users["a"]
fmt.Println("v:", v)
}
// Output:
// v:

21
_test/map16.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import "fmt"
func main() {
users := make(map[string]string)
v, exists := users["a"]
fmt.Println(v, exists)
if exists == true {
//if exists {
fmt.Println("exists", v)
} else {
fmt.Println("not exists")
}
}
// Output:
// false
// not exists

View File

@@ -497,7 +497,78 @@ func {{$name}}(n *Node) {
}
}
}
{{- end}}
default:
switch {
case c0.rval.IsValid():
i0 := c0.rval.Interface()
v1 := genValue(c1)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i1 := v1(f).Interface()
if i0 {{$op.Name}} i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i1 := v1(f).Interface()
dest(f).SetBool(i0 {{$op.Name}} i1)
return tnext
}
}
case c1.rval.IsValid():
i1 := c1.rval.Interface()
v0 := genValue(c0)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
if i0 {{$op.Name}} i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
dest(f).SetBool(i0 {{$op.Name}} i1)
return tnext
}
}
default:
v0 := genValue(c0)
v1 := genValue(c1)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
i1 := v1(f).Interface()
if i0 {{$op.Name}} i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
i1 := v1(f).Interface()
dest(f).SetBool(i0 {{$op.Name}} i1)
return tnext
}
}
}
{{- end}}
case isFloat(t0) || isFloat(t1):
switch {
case c0.rval.IsValid():

View File

@@ -880,6 +880,12 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
err = n.cfgError("use of builtin %s not in function call", n.ident)
}
}
if sym.kind == Var && sym.typ != nil && sym.typ.TypeOf().Kind() == reflect.Bool {
switch n.anc.kind {
case If0, If1, If2, If3, For1, For2, For3, For4:
n.gen = branch
}
}
}
if n.sym != nil {
n.recv = n.sym.recv

View File

@@ -172,8 +172,8 @@ func initUniverse() *Scope {
"uintptr": &Symbol{kind: Typ, typ: &Type{cat: UintptrT, name: "uintptr"}},
// predefined Go constants
"false": &Symbol{kind: Const, typ: &Type{cat: BoolT}, rval: reflect.ValueOf(false)},
"true": &Symbol{kind: Const, typ: &Type{cat: BoolT}, rval: reflect.ValueOf(true)},
"false": &Symbol{kind: Const, typ: &Type{cat: BoolT, name: "bool"}, rval: reflect.ValueOf(false)},
"true": &Symbol{kind: Const, typ: &Type{cat: BoolT, name: "bool"}, rval: reflect.ValueOf(true)},
"iota": &Symbol{kind: Const, typ: &Type{cat: IntT}},
// predefined Go zero value

View File

@@ -2007,6 +2007,77 @@ func equal(n *Node) {
}
}
}
default:
switch {
case c0.rval.IsValid():
i0 := c0.rval.Interface()
v1 := genValue(c1)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i1 := v1(f).Interface()
if i0 == i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i1 := v1(f).Interface()
dest(f).SetBool(i0 == i1)
return tnext
}
}
case c1.rval.IsValid():
i1 := c1.rval.Interface()
v0 := genValue(c0)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
if i0 == i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
dest(f).SetBool(i0 == i1)
return tnext
}
}
default:
v0 := genValue(c0)
v1 := genValue(c1)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
i1 := v1(f).Interface()
if i0 == i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
i1 := v1(f).Interface()
dest(f).SetBool(i0 == i1)
return tnext
}
}
}
case isFloat(t0) || isFloat(t1):
switch {
case c0.rval.IsValid():
@@ -3521,6 +3592,77 @@ func notEqual(n *Node) {
}
}
}
default:
switch {
case c0.rval.IsValid():
i0 := c0.rval.Interface()
v1 := genValue(c1)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i1 := v1(f).Interface()
if i0 != i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i1 := v1(f).Interface()
dest(f).SetBool(i0 != i1)
return tnext
}
}
case c1.rval.IsValid():
i1 := c1.rval.Interface()
v0 := genValue(c0)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
if i0 != i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
dest(f).SetBool(i0 != i1)
return tnext
}
}
default:
v0 := genValue(c0)
v1 := genValue(c1)
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
i1 := v1(f).Interface()
if i0 != i1 {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
} else {
dest := genValue(n)
n.exec = func(f *Frame) Builtin {
i0 := v0(f).Interface()
i1 := v1(f).Interface()
dest(f).SetBool(i0 != i1)
return tnext
}
}
}
case isFloat(t0) || isFloat(t1):
switch {
case c0.rval.IsValid():

View File

@@ -1174,6 +1174,19 @@ func nop(n *Node) {
}
}
func branch(n *Node) {
tnext := getExec(n.tnext)
fnext := getExec(n.fnext)
value := genValue(n)
n.exec = func(f *Frame) Builtin {
if value(f).Bool() {
return tnext
}
return fnext
}
}
func _return(n *Node) {
child := n.child
next := getExec(n.tnext)