Skip to content

Commit

Permalink
fix: correctly store boolean result for branching operations
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes committed Feb 14, 2020
1 parent 1b971b5 commit 7037424
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 28 deletions.
10 changes: 10 additions & 0 deletions _test/a41.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

var a = [...]bool{true, true}

func main() {
println(a[0] && true)
}

// Output:
// true
10 changes: 10 additions & 0 deletions _test/and3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

var a = true && true

func main() {
println(a)
}

// Output:
// true
12 changes: 12 additions & 0 deletions _test/chan8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

func main() {
messages := make(chan bool)

go func() { messages <- true }()

println(<-messages && true)
}

// Output:
// true
10 changes: 10 additions & 0 deletions _test/map20.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

var a = map[int]bool{1: true, 2: true}

func main() {
println(a[1] && true)
}

// Output:
// true
10 changes: 10 additions & 0 deletions _test/or2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

var a = false || true

func main() {
println(a)
}

// Output:
// true
10 changes: 10 additions & 0 deletions _test/ptr8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

var a = func() *bool { b := true; return &b }()

func main() {
println(*a && true)
}

// Output:
// true
14 changes: 14 additions & 0 deletions _test/struct31.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

type T struct {
bool
}

var t = T{true}

func main() {
println(t.bool && true)
}

// Output:
// true
93 changes: 65 additions & 28 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,16 +355,15 @@ func not(n *node) {
dest := genValue(n)
value := genValue(n.child[0])
tnext := getExec(n.tnext)
i := n.findex

if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if !value(f).Bool() {
f.data[i].SetBool(true)
dest(f).SetBool(true)
return tnext
}
f.data[i].SetBool(false)
dest(f).SetBool(false)
return fnext
}
} else {
Expand All @@ -389,17 +388,18 @@ func addr(n *node) {
func deref(n *node) {
value := genValue(n.child[0])
tnext := getExec(n.tnext)
i := n.findex

if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if value(f).Elem().Bool() {
f.data[i] = value(f).Elem()
if f.data[i].Bool() {
return tnext
}
return fnext
}
} else {
i := n.findex
n.exec = func(f *frame) bltn {
f.data[i] = value(f).Elem()
return tnext
Expand Down Expand Up @@ -978,21 +978,21 @@ func getIndexBinPtrMethod(n *node) {
func getIndexArray(n *node) {
tnext := getExec(n.tnext)
value0 := genValueArray(n.child[0]) // array
i := n.findex

if n.child[1].rval.IsValid() { // constant array index
ai := int(vInt(n.child[1].rval))
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if value0(f).Index(ai).Bool() {
f.data[i] = value0(f).Index(ai)
if f.data[i].Bool() {
return tnext
}
return fnext
}
} else {
i := n.findex
n.exec = func(f *frame) bltn {
// Can not use .Set due to constraint of being able to assign an array element
f.data[i] = value0(f).Index(ai)
return tnext
}
Expand All @@ -1004,16 +1004,15 @@ func getIndexArray(n *node) {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
_, vi := value1(f)
if value0(f).Index(int(vi)).Bool() {
f.data[i] = value0(f).Index(int(vi))
if f.data[i].Bool() {
return tnext
}
return fnext
}
} else {
i := n.findex
n.exec = func(f *frame) bltn {
_, vi := value1(f)
// Can not use .Set due to constraint of being able to assign an array element
f.data[i] = value0(f).Index(int(vi))
return tnext
}
Expand All @@ -1035,8 +1034,10 @@ func getIndexMap(n *node) {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if v := value0(f).MapIndex(mi); v.IsValid() && v.Bool() {
dest(f).SetBool(true)
return tnext
}
dest(f).Set(z)
return fnext
}
} else {
Expand All @@ -1056,8 +1057,10 @@ func getIndexMap(n *node) {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if v := value0(f).MapIndex(value1(f)); v.IsValid() && v.Bool() {
dest(f).SetBool(true)
return tnext
}
dest(f).Set(z)
return fnext
}
} else {
Expand Down Expand Up @@ -1155,17 +1158,28 @@ func getIndexSeq(n *node) {
value := genValue(n.child[0])
index := n.val.([]int)
tnext := getExec(n.tnext)
i := n.findex

// Note:
// Here we have to store the result using
// f.data[i] = value(...)
// instead of normal
// dest(f).Set(value(...)
// because the value returned by FieldByIndex() must be preserved
// for possible future Set operations on the struct field (avoid a
// dereference from Set, resulting in setting a copy of the
// original field).

if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if value(f).FieldByIndex(index).Bool() {
f.data[i] = value(f).FieldByIndex(index)
if f.data[i].Bool() {
return tnext
}
return fnext
}
} else {
i := n.findex
n.exec = func(f *frame) bltn {
f.data[i] = value(f).FieldByIndex(index)
return tnext
Expand All @@ -1183,17 +1197,18 @@ func getPtrIndexSeq(n *node) {
} else {
value = genValue(n.child[0])
}
i := n.findex

if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if value(f).Elem().FieldByIndex(index).Bool() {
f.data[i] = value(f).Elem().FieldByIndex(index)
if f.data[i].Bool() {
return tnext
}
return fnext
}
} else {
i := n.findex
n.exec = func(f *frame) bltn {
f.data[i] = value(f).Elem().FieldByIndex(index)
return tnext
Expand All @@ -1205,17 +1220,38 @@ func getIndexSeqField(n *node) {
value := genValue(n.child[0])
index := n.val.([]int)
i := n.findex
next := getExec(n.tnext)
tnext := getExec(n.tnext)

if n.child[0].typ.TypeOf().Kind() == reflect.Ptr {
n.exec = func(f *frame) bltn {
f.data[i] = value(f).Elem().FieldByIndex(index)
return next
if n.fnext != nil {
fnext := getExec(n.fnext)
if n.child[0].typ.TypeOf().Kind() == reflect.Ptr {
n.exec = func(f *frame) bltn {
f.data[i] = value(f).Elem().FieldByIndex(index)
if f.data[i].Bool() {
return tnext
}
return fnext
}
} else {
n.exec = func(f *frame) bltn {
f.data[i] = value(f).FieldByIndex(index)
if f.data[i].Bool() {
return tnext
}
return fnext
}
}
} else {
n.exec = func(f *frame) bltn {
f.data[i] = value(f).FieldByIndex(index)
return next
if n.child[0].typ.TypeOf().Kind() == reflect.Ptr {
n.exec = func(f *frame) bltn {
f.data[i] = value(f).Elem().FieldByIndex(index)
return tnext
}
} else {
n.exec = func(f *frame) bltn {
f.data[i] = value(f).FieldByIndex(index)
return tnext
}
}
}
}
Expand Down Expand Up @@ -2170,16 +2206,18 @@ func reset(n *node) {
func recv(n *node) {
value := genValue(n.child[0])
tnext := getExec(n.tnext)
i := n.findex

if n.interp.cancelChan {
// Cancellable channel read
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
ch := value(f)
// Fast: channel read doesn't block
if x, ok := ch.TryRecv(); ok {
if x.Bool() {
var ok bool
ch := value(f)
if f.data[i], ok = ch.TryRecv(); ok {
if f.data[i].Bool() {
return tnext
}
return fnext
Expand All @@ -2195,7 +2233,6 @@ func recv(n *node) {
return fnext
}
} else {
i := n.findex
n.exec = func(f *frame) bltn {
// Fast: channel read doesn't block
var ok bool
Expand All @@ -2217,7 +2254,7 @@ func recv(n *node) {
if n.fnext != nil {
fnext := getExec(n.fnext)
n.exec = func(f *frame) bltn {
if v, _ := value(f).Recv(); v.Bool() {
if f.data[i], _ = value(f).Recv(); f.data[i].Bool() {
return tnext
}
return fnext
Expand Down
3 changes: 3 additions & 0 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
}
}

case landExpr, lorExpr:
t.cat = boolT

case mapType:
t.cat = mapT
if t.key, err = nodeType(interp, sc, n.child[0]); err != nil {
Expand Down

0 comments on commit 7037424

Please sign in to comment.