fix: correct handling of equality tests (#205)
This commit is contained in:
committed by
Ludovic Fernandez
parent
455a37e678
commit
025e4f924a
10
_test/a26.go
Normal file
10
_test/a26.go
Normal 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
14
_test/for5.go
Normal 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
14
_test/if0.go
Normal 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
13
_test/map15.go
Normal 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
21
_test/map16.go
Normal 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
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
142
interp/op.go
142
interp/op.go
@@ -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():
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user