From 1fb863e50169df9f97221f058281148aeab955a1 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Sun, 8 Dec 2024 12:20:25 +0100 Subject: [PATCH 1/3] fix(gnovm): in op_binary, return typed booleans where appropriate --- gnovm/pkg/gnolang/op_binary.go | 35 +++++++++++++++++----------------- gnovm/tests/files/bool8.gno | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 gnovm/tests/files/bool8.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 6d26fa7ce54..3477fc61bdb 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -71,6 +71,17 @@ func (m *Machine) doOpLand() { lv.SetBool(lv.GetBool() && rv.GetBool()) } +// setMaybeUntypedBool sets lv to b; it will be untyped if both lv and rv are +// untyped; otherwise, it will be a typed bool. +func setMaybeUntypedBool(lv, rv *TypedValue, b bool) { + tp := BoolType + if isUntyped(lv.T) && isUntyped(rv.T) { + tp = UntypedBoolType + } + lv.T, lv.V = tp, nil + lv.SetBool(b) +} + func (m *Machine) doOpEql() { m.PopExpr() @@ -82,9 +93,7 @@ func (m *Machine) doOpEql() { } // set result in lv. res := isEql(m.Store, lv, rv) - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) + setMaybeUntypedBool(lv, rv, res) } func (m *Machine) doOpNeq() { @@ -99,9 +108,7 @@ func (m *Machine) doOpNeq() { // set result in lv. res := !isEql(m.Store, lv, rv) - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) + setMaybeUntypedBool(lv, rv, res) } func (m *Machine) doOpLss() { @@ -116,9 +123,7 @@ func (m *Machine) doOpLss() { // set the result in lv. res := isLss(lv, rv) - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) + setMaybeUntypedBool(lv, rv, res) } func (m *Machine) doOpLeq() { @@ -133,9 +138,7 @@ func (m *Machine) doOpLeq() { // set the result in lv. res := isLeq(lv, rv) - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) + setMaybeUntypedBool(lv, rv, res) } func (m *Machine) doOpGtr() { @@ -150,9 +153,7 @@ func (m *Machine) doOpGtr() { // set the result in lv. res := isGtr(lv, rv) - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) + setMaybeUntypedBool(lv, rv, res) } func (m *Machine) doOpGeq() { @@ -167,9 +168,7 @@ func (m *Machine) doOpGeq() { // set the result in lv. res := isGeq(lv, rv) - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) + setMaybeUntypedBool(lv, rv, res) } func (m *Machine) doOpAdd() { diff --git a/gnovm/tests/files/bool8.gno b/gnovm/tests/files/bool8.gno new file mode 100644 index 00000000000..9efbbbe6da2 --- /dev/null +++ b/gnovm/tests/files/bool8.gno @@ -0,0 +1,17 @@ +package main + +// results from comparisons should not be untyped bools + +var a interface{} = true + +func main() { + buf := "hello=" + isEqual(a, (buf[len(buf)-1] == '=')) +} + +func isEqual(v1, v2 interface{}) { + println("v1 == v2", v1 == v2) +} + +// Output: +// v1 == v2 true From f83eaa3e974ab3997d45d99582b540dc3247d20d Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Tue, 10 Dec 2024 18:47:49 +0100 Subject: [PATCH 2/3] use BoolType as result in checkOrConvertType --- gnovm/pkg/gnolang/op_binary.go | 35 +++++++++++++++++---------------- gnovm/pkg/gnolang/preprocess.go | 1 + 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 3477fc61bdb..6d26fa7ce54 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -71,17 +71,6 @@ func (m *Machine) doOpLand() { lv.SetBool(lv.GetBool() && rv.GetBool()) } -// setMaybeUntypedBool sets lv to b; it will be untyped if both lv and rv are -// untyped; otherwise, it will be a typed bool. -func setMaybeUntypedBool(lv, rv *TypedValue, b bool) { - tp := BoolType - if isUntyped(lv.T) && isUntyped(rv.T) { - tp = UntypedBoolType - } - lv.T, lv.V = tp, nil - lv.SetBool(b) -} - func (m *Machine) doOpEql() { m.PopExpr() @@ -93,7 +82,9 @@ func (m *Machine) doOpEql() { } // set result in lv. res := isEql(m.Store, lv, rv) - setMaybeUntypedBool(lv, rv, res) + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) } func (m *Machine) doOpNeq() { @@ -108,7 +99,9 @@ func (m *Machine) doOpNeq() { // set result in lv. res := !isEql(m.Store, lv, rv) - setMaybeUntypedBool(lv, rv, res) + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) } func (m *Machine) doOpLss() { @@ -123,7 +116,9 @@ func (m *Machine) doOpLss() { // set the result in lv. res := isLss(lv, rv) - setMaybeUntypedBool(lv, rv, res) + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) } func (m *Machine) doOpLeq() { @@ -138,7 +133,9 @@ func (m *Machine) doOpLeq() { // set the result in lv. res := isLeq(lv, rv) - setMaybeUntypedBool(lv, rv, res) + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) } func (m *Machine) doOpGtr() { @@ -153,7 +150,9 @@ func (m *Machine) doOpGtr() { // set the result in lv. res := isGtr(lv, rv) - setMaybeUntypedBool(lv, rv, res) + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) } func (m *Machine) doOpGeq() { @@ -168,7 +167,9 @@ func (m *Machine) doOpGeq() { // set the result in lv. res := isGeq(lv, rv) - setMaybeUntypedBool(lv, rv, res) + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) } func (m *Machine) doOpAdd() { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 78b11a4ebc5..8e646321396 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -3564,6 +3564,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Left, rt, autoNative) checkOrConvertType(store, last, &bx.Right, rt, autoNative) } + t = BoolType default: // do nothing } From ca91ef0a2ed1ad411438f0ee51d23f06429ca650 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Tue, 10 Dec 2024 18:52:34 +0100 Subject: [PATCH 3/3] comments --- gnovm/pkg/gnolang/preprocess.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 8e646321396..a71e8a38b33 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -3564,6 +3564,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Left, rt, autoNative) checkOrConvertType(store, last, &bx.Right, rt, autoNative) } + // this is not a constant expression; the result here should + // always be a BoolType. (in this scenario, we may have some + // UntypedBoolTypes) t = BoolType default: // do nothing