From e22a43ce87e1f00fe4917f7685e7276002629e24 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 17 Nov 2023 11:57:54 +0800 Subject: [PATCH 001/193] outOfGas log clearly --- gno.land/pkg/sdk/vm/keeper.go | 25 +++++++++++++++++-------- tm2/pkg/crypto/keys/client/addpkg.go | 15 +++++++++++++-- tm2/pkg/sdk/baseapp.go | 18 ++++++++++++++---- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 6f695e98558..e5ef5c19fdd 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -197,12 +197,12 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { pkgPath := msg.PkgPath // to import fnc := msg.Func - store := vm.getGnoStore(ctx) + gnoStore := vm.getGnoStore(ctx) // Get the package and function type. - pv := store.GetPackage(pkgPath, false) + pv := gnoStore.GetPackage(pkgPath, false) pl := gno.PackageNodeLocation(pkgPath) - pn := store.GetBlockNode(pl).(*gno.PackageNode) - ft := pn.GetStaticTypeOf(store, gno.Name(fnc)).(*gno.FuncType) + pn := gnoStore.GetBlockNode(pl).(*gno.PackageNode) + ft := pn.GetStaticTypeOf(gnoStore, gno.Name(fnc)).(*gno.FuncType) // Make main Package with imports. mpn := gno.NewPackageNode("main", "main", nil) mpn.Define("pkg", gno.TypedValue{T: &gno.PackageType{}, V: pv}) @@ -256,16 +256,25 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { gno.MachineOptions{ PkgPath: "", Output: os.Stdout, // XXX - Store: store, + Store: gnoStore, Context: msgCtx, - Alloc: store.GetAllocator(), + Alloc: gnoStore.GetAllocator(), MaxCycles: vm.maxCycles, }) m.SetActivePackage(mpv) defer func() { if r := recover(); r != nil { - err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s\n", - r, m.String()) + switch ex := r.(type) { + case store.OutOfGasException: + log := fmt.Sprintf( + "out of gas in location: %v;", + ex.Descriptor) + err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s", + log, m.String()) + default: + err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s", + r, m.String()) + } return } m.Release() diff --git a/tm2/pkg/crypto/keys/client/addpkg.go b/tm2/pkg/crypto/keys/client/addpkg.go index 5bbd3f08ad0..a13f9063fd9 100644 --- a/tm2/pkg/crypto/keys/client/addpkg.go +++ b/tm2/pkg/crypto/keys/client/addpkg.go @@ -14,6 +14,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto/keys" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/std" + "strings" ) type addPkgCfg struct { @@ -208,10 +209,10 @@ func signAndBroadcast( return errors.Wrap(err, "broadcast tx") } if bres.CheckTx.IsErr() { - return errors.Wrap(bres.CheckTx.Error, "check transaction failed: log:%s", bres.CheckTx.Log) + return errors.Wrap(bres.CheckTx.Error, "check transaction failed: errMsg: \n%s", indentString(bres.CheckTx.Log, " ")) } if bres.DeliverTx.IsErr() { - return errors.Wrap(bres.DeliverTx.Error, "deliver transaction failed: log:%s", bres.DeliverTx.Log) + return errors.Wrap(bres.DeliverTx.Error, "deliver transaction failed: errMsg: %s", bres.DeliverTx.Log) } io.Println(string(bres.DeliverTx.Data)) io.Println("OK!") @@ -220,3 +221,13 @@ func signAndBroadcast( return nil } + +// indentString indents each line of a multi-line string. +func indentString(str, indent string) string { + var indentedLines []string + lines := strings.Split(str, "\n") + for _, line := range lines { + indentedLines = append(indentedLines, indent+line) + } + return strings.Join(indentedLines, "\n") +} diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 1d356f7ad65..c42d21f1675 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -653,15 +653,15 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res // stop execution and return on first failed message if !msgResult.IsOK() { msgLogs = append(msgLogs, - fmt.Sprintf("msg:%d,success:%v,log:%s,events:%v", - i, false, msgResult.Log, events)) + fmt.Sprintf("msg:%d,success:%v,events:%v,log start:------>\n%s<------end log", + i, false, events, indentString(msgResult.Log, " "))) err = msgResult.Error break } msgLogs = append(msgLogs, - fmt.Sprintf("msg:%d,success:%v,log:%s,events:%v", - i, true, msgResult.Log, events)) + fmt.Sprintf("msg:%d,success:%v,events:%v,log start:------>\n%s<------end log", + i, true, events, indentString(msgResult.Log, " "))) } result.Error = ABCIError(err) @@ -672,6 +672,16 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res return result } +// indentString indents each line of a multi-line string. +func indentString(str, indent string) string { + var indentedLines []string + lines := strings.Split(str, "\n") + for _, line := range lines { + indentedLines = append(indentedLines, indent+line) + } + return strings.Join(indentedLines, "\n") +} + // Returns the applications's deliverState if app is in RunTxModeDeliver, // otherwise it returns the application's checkstate. func (app *BaseApp) getState(mode RunTxMode) *state { From b9aa15e6d229f87640c521f4bb87b895853c785f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 20 Nov 2023 23:50:56 +0800 Subject: [PATCH 002/193] patch up --- .../demo/challenge/comparison_0_filetest.gno | 25 +++++++++++++ .../demo/challenge/comparison_1_filetest.gno | 25 +++++++++++++ .../demo/challenge/comparison_2_filetest.gno | 35 +++++++++++++++++++ .../demo/challenge/comparison_3_filetest.gno | 32 +++++++++++++++++ .../demo/challenge/comparison_4_filetest.gno | 16 +++++++++ .../demo/challenge/comparison_5_filetest.gno | 15 ++++++++ .../demo/challenge/comparison_6_filetest.gno | 11 ++++++ .../demo/challenge/comparison_6a_filetest.gno | 10 ++++++ .../demo/challenge/comparison_7_filetest.gno | 10 ++++++ gnovm/pkg/gnolang/op_binary.go | 32 ++++++++++++++++- gnovm/pkg/gnolang/preprocess.go | 34 ++++++++++++++++++ 11 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 examples/gno.land/p/demo/challenge/comparison_0_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_1_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_2_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_4_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_5_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_6_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_6a_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_7_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno new file mode 100644 index 00000000000..8290778fa5e --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +func main() { + if Error(0) == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/examples/gno.land/p/demo/challenge/comparison_1_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_1_filetest.gno new file mode 100644 index 00000000000..5261a99f1d1 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +func main() { + if Error(1) == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno new file mode 100644 index 00000000000..7e4c2e7da5a --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + if e1 == e2 { + println("what the firetruck?") + } else { + // supposed print this + println("something else") + } +} + +// Output: +// something else diff --git a/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno new file mode 100644 index 00000000000..2d26cee5535 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno @@ -0,0 +1,32 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + if Error1(0) == Error2(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:24: mismatch type for EQL or NEQ diff --git a/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno new file mode 100644 index 00000000000..305a567e3c6 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno @@ -0,0 +1,16 @@ +package main + +var a int = 0 +var b int64 = 0 + +func main() { + // suppose compile fail + if a == b { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_4_filetest.gno:8: mismatch type for EQL or NEQ diff --git a/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno new file mode 100644 index 00000000000..a2b82bc6fd1 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno @@ -0,0 +1,15 @@ +package main + +var a int = 0 +var b bool = false + +func main() { + if a == b { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_5_filetest.gno:7: mismatch type for EQL or NEQ diff --git a/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno new file mode 100644 index 00000000000..ab94dc8efc0 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno @@ -0,0 +1,11 @@ +package main + +var a int = 0 +var b int64 = 1 + +func main() { + println(a + b) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_6_filetest.gno:7: incompatible types in binary expression: a ADD b diff --git a/examples/gno.land/p/demo/challenge/comparison_6a_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_6a_filetest.gno new file mode 100644 index 00000000000..a106f1acb78 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_6a_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var b int64 = 1 + r := 0 + b // const + println(r) +} + +// Output: +// 1 diff --git a/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno new file mode 100644 index 00000000000..46759123dbb --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 0 + var b int64 = 0 + println(a == b) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_7_filetest.gno:6: mismatch type for EQL or NEQ diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index ddab8302d2d..474b9ae2de6 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -71,17 +71,40 @@ func (m *Machine) doOpLand() { } func (m *Machine) doOpEql() { + println("doOpEql") m.PopExpr() // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result + + fmt.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + fmt.Printf("lv typeID: %v, kind: %v \n", lv.T.TypeID(), lv.T.Kind()) + fmt.Printf("rv typeID: %v, kind: %v \n", rv.T.TypeID(), rv.T.Kind()) + if debug { assertEqualityTypes(lv.T, rv.T) } + //if lv.T.Kind() == InterfaceKind && + // IsImplementedBy(lv.T, rv.T) { + // println("left is interface, rt conforms it") + //} else if rv.T.Kind() == InterfaceKind && + // IsImplementedBy(rv.T, lv.T) { + // println("right is interface, left conforms it") + //} else if lv.T.Kind() == InterfaceKind && rv.T.Kind() == InterfaceKind { + // println("both interface") + //} + + var res bool + // strict type match check + if lv.T.TypeID() != rv.T.TypeID() { + fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "EQL", rv.T.TypeID()) + res = false + } else { + res = isEql(m.Store, lv, rv) + } // set result in lv. - res := isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -345,7 +368,9 @@ func isEql(store Store, lv, rv *TypedValue) bool { return false } if lnt, ok := lv.T.(*NativeType); ok { + println("left is native type") if rnt, ok := rv.T.(*NativeType); ok { + println("right is native type") if lnt.Type != rnt.Type { return false } @@ -370,6 +395,11 @@ func isEql(store Store, lv, rv *TypedValue) bool { case Int32Kind: return (lv.GetInt32() == rv.GetInt32()) case Int64Kind: + println("int64 kind") + println("lv kind: ", lv.T.Kind()) + println("rv kind: ", rv.T.Kind()) + println("lv int64", lv.GetInt64()) + println("rv int64", rv.GetInt64()) return (lv.GetInt64() == rv.GetInt64()) case UintKind: return (lv.GetUint() == rv.GetUint()) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 1a1edc41222..9d898ec45a4 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -739,6 +739,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: + println("---binary expr---") + fmt.Printf("OP: %v \n", n.Op) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. @@ -759,11 +761,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) if lic { + println("left is const") if ric { + println("right is const") // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. if !isShift { + if n.Op == EQL || n.Op == NEQ { + println("Op EQL") + fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) + fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) + // strict + if lt.TypeID() != rt.TypeID() { + panic("mismatch type for EQL or NEQ") + } + } cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // convert n.Left to right type. @@ -784,8 +797,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { + println("right not const, and lt untyped") // Left untyped const, Right not ---------------- if rnt, ok := rt.(*NativeType); ok { + println("right native type") if isShift { panic("should not happen") } @@ -809,12 +824,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { + println("right not native") if isShift { // nothing to do, right type is (already) uint type. // we don't yet know what this type should be, // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). } else { + println("convert") + println("left typeID, kind", lt.TypeID(), lt.Kind()) + println("right typeID, kind", rt.TypeID(), rt.Kind()) // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rt, false) } @@ -824,7 +843,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false) } } else if ric { + println("left not const, right is const") if isUntyped(rcx.T) { + println("right untyped") // Left not, Right untyped const ---------------- if isShift { if baseOf(rt) != UintType { @@ -864,8 +885,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Right, lt, false) } } else { + println("both not const") // Left not const, Right not const ------------------ if n.Op == EQL || n.Op == NEQ { + println("Op EQL") + fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) + fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) + // strict + if lt.TypeID() != rt.TypeID() { + panic("mismatch type for EQL or NEQ") + } + println("no conversions") // If == or !=, no conversions. } else if lnt, ok := lt.(*NativeType); ok { if debug { @@ -908,8 +938,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if n.Op == SHL || n.Op == SHR { // shift operator, nothing yet to do. } else { + println("out of eql, shift, left add, addAssign") // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) + println("liu", liu) + println("rie", riu) if liu { if riu { if lt.TypeID() != rt.TypeID() { @@ -918,6 +951,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Left, n.Op, n.Right)) } } else { + println("left untyped, right is typed") checkOrConvertType(store, last, &n.Left, rt, false) } } else { From 9f57ef7d761e25e84339e0f3e1991504541a716d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 21 Nov 2023 18:49:10 +0800 Subject: [PATCH 003/193] more test, cover more cases --- .../demo/challenge/comparison_3_filetest.gno | 6 +--- .../demo/challenge/comparison_3a_filetest.gno | 24 ++++++++++++++ .../demo/challenge/comparison_3b_filetest.gno | 26 ++++++++++++++++ .../demo/challenge/comparison_3c_filetest.gno | 25 +++++++++++++++ gnovm/pkg/gnolang/op_binary.go | 10 +++++- gnovm/pkg/gnolang/preprocess.go | 31 ++++++++++++++++--- 6 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3b_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3c_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno index 2d26cee5535..1bd2831b181 100644 --- a/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno @@ -4,10 +4,6 @@ import ( "strconv" ) -type E interface { - Error() string -} - type Error1 int64 func (e Error1) Error() string { @@ -29,4 +25,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:24: mismatch type for EQL or NEQ +// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:20: mismatch type for EQL || NEQ || ADD diff --git a/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno new file mode 100644 index 00000000000..19007a77457 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + println(Error1(0) + Error2(0)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3a_filetest.gno:20: mismatch type for EQL || NEQ || ADD diff --git a/examples/gno.land/p/demo/challenge/comparison_3b_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3b_filetest.gno new file mode 100644 index 00000000000..d3b0c363714 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3b_filetest.gno @@ -0,0 +1,26 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + e1 := Error1(0) + e2 := Error2(0) + e1 += e2 +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3b_filetest.gno:22: mismatch type for Assign diff --git a/examples/gno.land/p/demo/challenge/comparison_3c_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3c_filetest.gno new file mode 100644 index 00000000000..0862b3f3d3e --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3c_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + e1 = Error2(0) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3c_filetest.gno:21: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 474b9ae2de6..fe39c05d8be 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -120,8 +120,16 @@ func (m *Machine) doOpNeq() { assertEqualityTypes(lv.T, rv.T) } + var res bool + // strict type match check + if lv.T.TypeID() != rv.T.TypeID() { + fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "NEQ", rv.T.TypeID()) + res = false + } else { + res = isEql(m.Store, lv, rv) + } + // set result in lv. - res := !isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9d898ec45a4..bdbe3bcba17 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -768,13 +768,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. if !isShift { - if n.Op == EQL || n.Op == NEQ { + if n.Op == EQL || n.Op == NEQ || n.Op == ADD || n.Op == ADD_ASSIGN { println("Op EQL") fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // strict if lt.TypeID() != rt.TypeID() { - panic("mismatch type for EQL or NEQ") + panic("mismatch type for EQL || NEQ || ADD") } } cmp := cmpSpecificity(lcx.T, rcx.T) @@ -1522,6 +1522,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: + fmt.Printf("---AssignStmt, Op: %v \n", n.Op) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { // Rhs consts become default *ConstExprs. @@ -1596,6 +1597,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { // ASSIGN. + println("assign") // NOTE: Keep in sync with DEFINE above. if len(n.Lhs) > len(n.Rhs) { // TODO dry code w/ above. @@ -1635,12 +1637,33 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // Special case if shift assign <<= or >>=. checkOrConvertType(store, last, &n.Rhs[0], UintType, false) + } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { + fmt.Printf("op is %v \n", n.Op) + // e.g. a += b, single lhs and rhs, can add assign more than one RHS? + lt := evalStaticTypeOf(store, last, n.Lhs[0]) + rt := evalStaticTypeOf(store, last, n.Rhs[0]) + + // TODO: check other like sh* + if lt.TypeID() != rt.TypeID() { + panic("mismatch type for Assign") + } } else { + println("case: a, b = x, y") // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) - // converts if rx is "nil". - checkOrConvertType(store, last, &n.Rhs[i], lt, false) + + // is x or y is untyped, convert, else check type + rt := evalStaticTypeOf(store, last, n.Rhs[i]) + if isUntyped(rt) { + // converts if rx is "nil". + checkOrConvertType(store, last, &n.Rhs[i], lt, false) + } else { + // is untyped + if lt.TypeID() != rt.TypeID() { + panic("mismatch type for Assign, in case: a, b = x, y") + } + } } } } From 55e3af85c41342507380001cb12d752f89a88812 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 21 Nov 2023 23:23:14 +0800 Subject: [PATCH 004/193] fix assign type check --- .../demo/challenge/comparison_3d_filetest.gno | 35 +++++++++++++++++++ .../demo/challenge/comparison_3e_filetest.gno | 35 +++++++++++++++++++ .../demo/challenge/comparison_3f_filetest.gno | 30 ++++++++++++++++ .../demo/challenge/comparison_3g_filetest.gno | 30 ++++++++++++++++ .../demo/challenge/comparison_3h_filetest.gno | 14 ++++++++ .../demo/challenge/comparison_3i_filetest.gno | 10 ++++++ .../demo/challenge/comparison_3j_filetest.gno | 24 +++++++++++++ gnovm/pkg/gnolang/preprocess.go | 19 +++++++--- 8 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 examples/gno.land/p/demo/challenge/comparison_3d_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3e_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3f_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3g_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3h_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3i_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3j_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3d_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3d_filetest.gno new file mode 100644 index 00000000000..c6dd8c1cfd5 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3d_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error3 int64 + +func (e Error3) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + + e1, e2 = 0, 0 + + println(e1, e2) +} + +// Output: +// error: 0 error: 0 diff --git a/examples/gno.land/p/demo/challenge/comparison_3e_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3e_filetest.gno new file mode 100644 index 00000000000..cf4799deae5 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3e_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error3 int64 + +func (e Error3) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + + e1, e2 = 0, Error3(0) + + println(e1, e2) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3e_filetest.gno:29: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/comparison_3f_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3f_filetest.gno new file mode 100644 index 00000000000..4690ead2607 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3f_filetest.gno @@ -0,0 +1,30 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + var a int = 0 + + e1, e2 = a, 0 + + println(e1, e2) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3f_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/comparison_3g_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3g_filetest.gno new file mode 100644 index 00000000000..819be76c281 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3g_filetest.gno @@ -0,0 +1,30 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + var b int32 = 0 + + e1, e2 = 0, b + + println(e1, e2) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3g_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/comparison_3h_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3h_filetest.gno new file mode 100644 index 00000000000..ebb546282cc --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3h_filetest.gno @@ -0,0 +1,14 @@ +package main + +func main() { + + var a int = 0 + var i int32 = 1 + a += i + + println(a) + +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3h_filetest.gno:7: mismatch type for Assign diff --git a/examples/gno.land/p/demo/challenge/comparison_3i_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3i_filetest.gno new file mode 100644 index 00000000000..a8e8a2f47ef --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3i_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var a int = 0 + a += 1 + println(a) +} + +// Output: +// 1 diff --git a/examples/gno.land/p/demo/challenge/comparison_3j_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3j_filetest.gno new file mode 100644 index 00000000000..4b135e1b239 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3j_filetest.gno @@ -0,0 +1,24 @@ +package main + +func main() { + var a int = 1 + a -= 1 + println(a) //0 + + a += 1 + a *= 2 + println(a) //2 + + a /= 2 + println(a) //1 + + a += 2 //3 + a %= 2 //1 + println(a) +} + +// Output: +// 0 +// 2 +// 1 +// 1 diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index bdbe3bcba17..891b388c448 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1639,27 +1639,36 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Rhs[0], UintType, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { fmt.Printf("op is %v \n", n.Op) - // e.g. a += b, single lhs and rhs, can add assign more than one RHS? + // e.g. a += b, single value for lhs and rhs, + // TODO: assert length + println("len of LHS: ", len(n.Lhs)) + println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) rt := evalStaticTypeOf(store, last, n.Rhs[0]) // TODO: check other like sh* - if lt.TypeID() != rt.TypeID() { - panic("mismatch type for Assign") + // only check when rt is typed + if !isUntyped(rt) { + if lt.TypeID() != rt.TypeID() { + panic("mismatch type for Assign") + } + } else { + checkOrConvertType(store, last, &n.Rhs[0], lt, false) } } else { println("case: a, b = x, y") // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) - // is x or y is untyped, convert, else check type rt := evalStaticTypeOf(store, last, n.Rhs[i]) if isUntyped(rt) { + println("rt is untyped, convert") + // is untyped // converts if rx is "nil". checkOrConvertType(store, last, &n.Rhs[i], lt, false) } else { - // is untyped + println("rt not untyped, check strict") if lt.TypeID() != rt.TypeID() { panic("mismatch type for Assign, in case: a, b = x, y") } From af75c9eaaec938a9553fc01e9e672636ff748576 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 27 Nov 2023 11:05:16 +0800 Subject: [PATCH 005/193] fixup --- .../gno.land/p/demo/challenge/1_filetest.gno | 24 + .../gno.land/p/demo/challenge/1a_filetest.gno | 24 + .../gno.land/p/demo/challenge/1b_filetest.gno | 24 + .../gno.land/p/demo/challenge/2_filetest.gno | 28 + .../gno.land/p/demo/challenge/2a_filetest.gno | 26 + .../gno.land/p/demo/challenge/2b_filetest.gno | 27 + .../gno.land/p/demo/challenge/2c_filetest.gno | 25 + .../gno.land/p/demo/challenge/2d_filetest.gno | 31 + .../demo/challenge/comparison_0_filetest.gno | 4 +- .../demo/challenge/comparison_0a_filetest.gno | 29 + .../demo/challenge/comparison_0b_filetest.gno | 29 + .../demo/challenge/comparison_0c_filetest.gno | 25 + .../demo/challenge/comparison_0d_filetest.gno | 25 + .../demo/challenge/comparison_0e_filetest.gno | 25 + .../demo/challenge/comparison_0f_filetest.gno | 25 + .../demo/challenge/comparison_0g_filetest.gno | 25 + .../demo/challenge/comparison_0h_filetest.gno | 10 + .../demo/challenge/comparison_0i_filetest.gno | 8 + .../demo/challenge/comparison_0j_filetest.gno | 8 + .../demo/challenge/comparison_0k_filetest.gno | 8 + .../demo/challenge/comparison_0l_filetest.gno | 8 + .../demo/challenge/comparison_0m_filetest.gno | 8 + .../demo/challenge/comparison_0n_filetest.gno | 14 + .../demo/challenge/comparison_0z_filetest.gno | 11 + ...iletest.gno => comparison_1a_filetest.gno} | 8 +- .../demo/challenge/comparison_2_filetest.gno | 1 + .../demo/challenge/comparison_3_filetest.gno | 2 +- .../demo/challenge/comparison_3a_filetest.gno | 2 +- .../demo/challenge/comparison_3k_filetest.gno | 12 + .../demo/challenge/comparison_3l_filetest.gno | 11 + .../demo/challenge/comparison_4_filetest.gno | 2 +- .../demo/challenge/comparison_5_filetest.gno | 2 +- .../demo/challenge/comparison_6_filetest.gno | 2 +- .../demo/challenge/comparison_7_filetest.gno | 2 +- gnovm/pkg/gnolang/preprocess.go | 611 ++++++++++-------- gnovm/pkg/gnolang/types.go | 104 ++- 36 files changed, 951 insertions(+), 279 deletions(-) create mode 100644 examples/gno.land/p/demo/challenge/1_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/1a_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/1b_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/2_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/2a_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/2b_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/2c_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/2d_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0a_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0b_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0c_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0d_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0e_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0f_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0g_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0h_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0i_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0j_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0k_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0l_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0m_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0n_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_0z_filetest.gno rename examples/gno.land/p/demo/challenge/{comparison_1_filetest.gno => comparison_1a_filetest.gno} (71%) create mode 100644 examples/gno.land/p/demo/challenge/comparison_3k_filetest.gno create mode 100644 examples/gno.land/p/demo/challenge/comparison_3l_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/1_filetest.gno b/examples/gno.land/p/demo/challenge/1_filetest.gno new file mode 100644 index 00000000000..6b997c23642 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/1_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is typed const, right is untyped const +// this is legal since Error is a declared value +func main() { + if Error(1) == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// what the firetruck? diff --git a/examples/gno.land/p/demo/challenge/1a_filetest.gno b/examples/gno.land/p/demo/challenge/1a_filetest.gno new file mode 100644 index 00000000000..624e8dbab16 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/1a_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is untyped const, right is typed const +// this is legal since Error is a declared value +func main() { + if 1 == Error(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// what the firetruck? diff --git a/examples/gno.land/p/demo/challenge/1b_filetest.gno b/examples/gno.land/p/demo/challenge/1b_filetest.gno new file mode 100644 index 00000000000..675adbe7b31 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/1b_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is typed const, right is untyped const +// NOTE: overflow +func main() { + if Error(1) == 128 { // note, this would overflow as expected + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/1b_filetest.gno:16: bigint overflows target kind diff --git a/examples/gno.land/p/demo/challenge/2_filetest.gno b/examples/gno.land/p/demo/challenge/2_filetest.gno new file mode 100644 index 00000000000..e7151a8c571 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/2_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// left is untyped const, right is not const +// compile fail since the untyped 1 doesn't conform error interface +func main() { + if 1 == errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/2_filetest.gno:19: bigint does not implement .uverse.error diff --git a/examples/gno.land/p/demo/challenge/2a_filetest.gno b/examples/gno.land/p/demo/challenge/2a_filetest.gno new file mode 100644 index 00000000000..4de239c4158 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/2a_filetest.gno @@ -0,0 +1,26 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// left is typed const, right is not const, should not compile +func main() { + if int(1) == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/2a_filetest.gno:18: int does not implement .uverse.error diff --git a/examples/gno.land/p/demo/challenge/2b_filetest.gno b/examples/gno.land/p/demo/challenge/2b_filetest.gno new file mode 100644 index 00000000000..48f02f43abd --- /dev/null +++ b/examples/gno.land/p/demo/challenge/2b_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// both not const, should not compile +func main() { + var a int = 1 + if a == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/2b_filetest.gno:19: int does not implement .uverse.error diff --git a/examples/gno.land/p/demo/challenge/2c_filetest.gno b/examples/gno.land/p/demo/challenge/2c_filetest.gno new file mode 100644 index 00000000000..aa9b5a34f7c --- /dev/null +++ b/examples/gno.land/p/demo/challenge/2c_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +func main() { + if errCmp == int(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/2c_filetest.gno:17: int does not implement .uverse.error diff --git a/examples/gno.land/p/demo/challenge/2d_filetest.gno b/examples/gno.land/p/demo/challenge/2d_filetest.gno new file mode 100644 index 00000000000..e2561129fd5 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/2d_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 + e2) +} + +// Error: +// main/gno.land/p/demo/challenge/2d_filetest.gno:27: + should have operand number or string, while have: main.E diff --git a/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno index 8290778fa5e..939f5f9c46b 100644 --- a/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno @@ -13,8 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") +// left is typed const, right is not const +// compile pass since both conform to same interface func main() { - if Error(0) == errCmp { + if Error(0) == errCmp { // both conform same interface, compile pass, runtime evaluation not equal println("what the firetruck?") } else { println("something else") diff --git a/examples/gno.land/p/demo/challenge/comparison_0a_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0a_filetest.gno new file mode 100644 index 00000000000..67a0439dcca --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0a_filetest.gno @@ -0,0 +1,29 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, both typed, compile fail +func main() { + if Error1(0) == Error2(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0a_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0b_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0b_filetest.gno new file mode 100644 index 00000000000..76b7c0bd46f --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0b_filetest.gno @@ -0,0 +1,29 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + if Error1(0) != Error2(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0b_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0c_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0c_filetest.gno new file mode 100644 index 00000000000..27d63abceab --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0c_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) + Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0c_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0d_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0d_filetest.gno new file mode 100644 index 00000000000..f6598c1a69b --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0d_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) - Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0d_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0e_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0e_filetest.gno new file mode 100644 index 00000000000..b908906c6b6 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0e_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) * Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0e_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0f_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0f_filetest.gno new file mode 100644 index 00000000000..b5fc715f6bc --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0f_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) / Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0f_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0g_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0g_filetest.gno new file mode 100644 index 00000000000..9f04d0d800a --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0g_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) % Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0g_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_0h_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0h_filetest.gno new file mode 100644 index 00000000000..ab9827f79cc --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0h_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 0 + b := 1 + println(a & b) +} + +// Output: +// 0 diff --git a/examples/gno.land/p/demo/challenge/comparison_0i_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0i_filetest.gno new file mode 100644 index 00000000000..297af6dcd25 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0i_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(0 & 1) +} + +// Output: +// 0 diff --git a/examples/gno.land/p/demo/challenge/comparison_0j_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0j_filetest.gno new file mode 100644 index 00000000000..2c398df9a3d --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0j_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) & int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0j_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/comparison_0k_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0k_filetest.gno new file mode 100644 index 00000000000..3b0572e7dfc --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0k_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) | int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0k_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/comparison_0l_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0l_filetest.gno new file mode 100644 index 00000000000..378b1f5084f --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0l_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) ^ int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0l_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/comparison_0m_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0m_filetest.gno new file mode 100644 index 00000000000..1e28fef5014 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0m_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) &^ int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0m_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/comparison_0n_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0n_filetest.gno new file mode 100644 index 00000000000..319bd102ef5 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0n_filetest.gno @@ -0,0 +1,14 @@ +package main + +func main() { + println(int(0) & int(1)) + println(int(0) | int(1)) + println(int(0) ^ int(1)) + println(int(0) &^ int(1)) +} + +// Output: +// 0 +// 1 +// 1 +// 0 diff --git a/examples/gno.land/p/demo/challenge/comparison_0z_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_0z_filetest.gno new file mode 100644 index 00000000000..20a609fabfe --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_0z_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both not const +func main() { + a := 0 + b := "hi" + println(a & b) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0z_filetest.gno:7: cannot use int as string diff --git a/examples/gno.land/p/demo/challenge/comparison_1_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_1a_filetest.gno similarity index 71% rename from examples/gno.land/p/demo/challenge/comparison_1_filetest.gno rename to examples/gno.land/p/demo/challenge/comparison_1a_filetest.gno index 5261a99f1d1..7d2740709a5 100644 --- a/examples/gno.land/p/demo/challenge/comparison_1_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_1a_filetest.gno @@ -1,7 +1,6 @@ package main import ( - "errors" "strconv" ) @@ -11,10 +10,9 @@ func (e Error) Error() string { return "error: " + strconv.Itoa(int(e)) } -var errCmp = errors.New("XXXX") - +// left is const, right is const, left is untyped func main() { - if Error(1) == errCmp { + if 1 == Error(1) { println("what the firetruck?") } else { println("something else") @@ -22,4 +20,4 @@ func main() { } // Output: -// something else +// what the firetruck? diff --git a/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno index 7e4c2e7da5a..30899d4d981 100644 --- a/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno @@ -20,6 +20,7 @@ func (e Error2) Error() string { return "error: " + strconv.Itoa(int(e)) } +// both not const func main() { var e1 E = Error1(0) var e2 E = Error2(0) diff --git a/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno index 1bd2831b181..ac21c5b6bf5 100644 --- a/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:20: mismatch type for EQL || NEQ || ADD +// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno index 19007a77457..53fe7b61bbd 100644 --- a/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno @@ -21,4 +21,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_3a_filetest.gno:20: mismatch type for EQL || NEQ || ADD +// main/gno.land/p/demo/challenge/comparison_3a_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/comparison_3k_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3k_filetest.gno new file mode 100644 index 00000000000..9ccbc1b795a --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3k_filetest.gno @@ -0,0 +1,12 @@ +package main + +func main() { + a := 6 // a is 6 (binary 110) + b := 3 // b is 3 (binary 011) + a &= b // Now a is 2 (binary 010) + + println(a) +} + +// Output: +// 2 diff --git a/examples/gno.land/p/demo/challenge/comparison_3l_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_3l_filetest.gno new file mode 100644 index 00000000000..c903dc1b440 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/comparison_3l_filetest.gno @@ -0,0 +1,11 @@ +package main + +func main() { + a := 6 + b := "3" + a &= b // Error: mismatched types int and string + println(a) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3l_filetest.gno:6: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno index 305a567e3c6..c09475f2a01 100644 --- a/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno @@ -13,4 +13,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_4_filetest.gno:8: mismatch type for EQL or NEQ +// main/gno.land/p/demo/challenge/comparison_4_filetest.gno:8: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno index a2b82bc6fd1..c2cb3eb6472 100644 --- a/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_5_filetest.gno:7: mismatch type for EQL or NEQ +// main/gno.land/p/demo/challenge/comparison_5_filetest.gno:7: cannot use int as bool diff --git a/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno index ab94dc8efc0..db0f0e6e86f 100644 --- a/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_6_filetest.gno:7: incompatible types in binary expression: a ADD b +// main/gno.land/p/demo/challenge/comparison_6_filetest.gno:7: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno b/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno index 46759123dbb..f435f587ca8 100644 --- a/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno +++ b/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/comparison_7_filetest.gno:6: mismatch type for EQL or NEQ +// main/gno.land/p/demo/challenge/comparison_7_filetest.gno:6: cannot use int as int64 diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 891b388c448..d64a60d9f50 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -450,7 +450,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, cx := range n.Cases { cx = Preprocess( store, last, cx).(Expr) - checkOrConvertType(store, last, &cx, tt, false) // #nosec G601 + checkOrConvertType(store, last, &cx, tt, ILLEGAL, false) // #nosec G601 n.Cases[i] = cx } } @@ -744,6 +744,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. + // TODO: should check convertable? isShift := n.Op == SHL || n.Op == SHR if isShift && baseOf(rt) != UintType { // convert n.Right to (gno) uint type, @@ -768,36 +769,47 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. if !isShift { - if n.Op == EQL || n.Op == NEQ || n.Op == ADD || n.Op == ADD_ASSIGN { - println("Op EQL") - fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) - fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) - // strict - if lt.TypeID() != rt.TypeID() { - panic("mismatch type for EQL || NEQ || ADD") - } - } + println("not shift") + //// is this implied implicitly? rest of the binary operators after SHL and SHR is excluded + //// Note: this check happens only when left and right are both typed, if not, the checkOrConvert logic will be run if cmp not 0 + //// TODO: checkOrConvertType, same way around + //if !isUntyped(lcx.T) && !isUntyped(rcx.T) { + // if n.Op == EQL || n.Op == NEQ || n.Op == ADD || n.Op == SUB || n.Op == MUL || n.Op == QUO || n.Op == REM || n.Op == BAND || n.Op == BOR || n.Op == XOR || n.Op == BAND_NOT { + // fmt.Printf("Op: %v \n", n.Op) + // fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) + // fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) + // // strict + // if lt.TypeID() != rt.TypeID() { + // panic("mismatch type for EQL || NEQ || ADD") + // } + // } + //} + // at least one of left or right is untyped cmp := cmpSpecificity(lcx.T, rcx.T) - if cmp < 0 { + if cmp < 0 { // this always implies untyped>? + println("cmp < 0, ->") // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rcx.T, false) + checkOrConvertType(store, last, &n.Left, rcx.T, n.Op, false) } else if cmp == 0 { + println("cmp == 0") // NOTE: the following doesn't work. // TODO: make it work. // convert n.Left to right type, // or check for compatibility. // (the other way around would work too) - // checkOrConvertType(store, last, n.Left, rcx.T, false) - } else { + // also need to check + checkOrConvertType(store, last, &n.Left, rcx.T, n.Op, false) + } else { // this always implies untyped>? + println("cmp > 0, <-") // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lcx.T, false) + checkOrConvertType(store, last, &n.Right, lcx.T, n.Op, false) } } // Then, evaluate the expression. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { - println("right not const, and lt untyped") + println("left is untyped const, right not const") // Left untyped const, Right not ---------------- if rnt, ok := rt.(*NativeType); ok { println("right native type") @@ -807,7 +819,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, false) + checkOrConvertType(store, last, &n.Left, pt, n.Op, false) // convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. @@ -831,17 +843,31 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). } else { - println("convert") - println("left typeID, kind", lt.TypeID(), lt.Kind()) - println("right typeID, kind", rt.TypeID(), rt.Kind()) + println("not shift, convert") + fmt.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) + fmt.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } } + } else if !isUntyped(lcx.T) { // left is typed const, right is not const + println("left is typed const, right is not const, should check type too") + // NOTE: only in case == or !=, should using assert to make sure left and right equality + // in case of add, etc. should use checkOrConvert + // TODO: expand? + //if n.Op == EQL || n.Op == NEQ { + // assertTypeMatchStrict(lt, rt, n.Op) + //} else { + // checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + //} + checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + } else if lcx.T == nil { + println("lcx.T is nil") // convert n.Left to typed-nil type. - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } + } else if ric { println("left not const, right is const") if isUntyped(rcx.T) { @@ -850,7 +876,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { if baseOf(rt) != UintType { // convert n.Right to (gno) uint type. - checkOrConvertType(store, last, &n.Right, UintType, false) + checkOrConvertType(store, last, &n.Right, UintType, n.Op, false) } else { // leave n.Left as is and baseOf(n.Right) as UintType. } @@ -861,7 +887,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOrConvertType(store, last, &n.Right, pt, false) + checkOrConvertType(store, last, &n.Right, pt, n.Op, false) // and convert result back. tx := constType(n, lnt) // reset/create n2 to preprocess left child. @@ -877,26 +903,26 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lt, false) + checkOrConvertType(store, last, &n.Right, lt, n.Op, false) } } - } else if rcx.T == nil { + //} else if rcx.T == nil { + } else { // convert n.Right to typed-nil type. - checkOrConvertType(store, last, &n.Right, lt, false) + checkOrConvertType(store, last, &n.Right, lt, n.Op, false) } } else { - println("both not const") - // Left not const, Right not const ------------------ - if n.Op == EQL || n.Op == NEQ { - println("Op EQL") - fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) - fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) - // strict - if lt.TypeID() != rt.TypeID() { - panic("mismatch type for EQL or NEQ") - } - println("no conversions") - // If == or !=, no conversions. + fmt.Printf("both not const, lt: %v, rt:%v \n", lt, rt) + if n.Op == SHL || n.Op == SHR { + // shift operator, nothing yet to do. code like this will work + //package main + // + //type Error int8 + //type index int8 + // + //func main() { + // println(Error(1) << index(0)) + //} } else if lnt, ok := lt.(*NativeType); ok { if debug { if !isShift { @@ -935,10 +961,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always // computed in gno, never with // reflect. - } else if n.Op == SHL || n.Op == SHR { - // shift operator, nothing yet to do. } else { - println("out of eql, shift, left add, addAssign") + println("no-shift, non-const, need all go through check") // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) println("liu", liu) @@ -952,19 +976,18 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { println("left untyped, right is typed") - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } + } else if riu { + checkOrConvertType(store, last, &n.Right, lt, n.Op, false) } else { - if riu { - checkOrConvertType(store, last, &n.Right, lt, false) - } else { - // left is untyped, right is not. - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf( - "incompatible types in binary expression: %v %v %v", - n.Left, n.Op, n.Right)) - } - } + checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + //// left is untyped, right is not. + //if lt.TypeID() != rt.TypeID() { + // panic(fmt.Sprintf( + // "incompatible types in binary expression: %v %v %v", + // n.Left, n.Op, n.Right)) + //} } } } @@ -1153,12 +1176,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, tv := range argTVs { if hasVarg { if (len(spts) - 1) <= i { - checkType(tv.T, spts[len(spts)-1].Type.Elem(), true) + checkType(tv.T, spts[len(spts)-1].Type.Elem(), ILLEGAL, true) } else { - checkType(tv.T, spts[i].Type, true) + checkType(tv.T, spts[i].Type, ILLEGAL, true) } } else { - checkType(tv.T, spts[i].Type, true) + checkType(tv.T, spts[i].Type, ILLEGAL, true) } } } else { @@ -1169,16 +1192,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if len(spts) <= i { panic("expected final vargs slice but got many") } - checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) + checkOrConvertType(store, last, &n.Args[i], spts[i].Type, ILLEGAL, true) } else { checkOrConvertType(store, last, &n.Args[i], - spts[len(spts)-1].Type.Elem(), true) + spts[len(spts)-1].Type.Elem(), ILLEGAL, true) } } else { - checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) + checkOrConvertType(store, last, &n.Args[i], spts[i].Type, ILLEGAL, true) } } else { - checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) + checkOrConvertType(store, last, &n.Args[i], spts[i].Type, ILLEGAL, true) } } } @@ -1202,7 +1225,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertIntegerType(store, last, n.Index) case MapKind: mt := baseOf(gnoTypeOf(store, dt)).(*MapType) - checkOrConvertType(store, last, &n.Index, mt.Key, false) + checkOrConvertType(store, last, &n.Index, mt.Key, ILLEGAL, false) default: panic(fmt.Sprintf( "unexpected index base kind for type %s", @@ -1266,28 +1289,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { key := n.Elts[i].Key.(*NameExpr).Name path := cclt.GetPathForName(key) ft := cclt.GetStaticTypeOfAt(path) - checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) + checkOrConvertType(store, last, &n.Elts[i].Value, ft, ILLEGAL, false) } } else { for i := 0; i < len(n.Elts); i++ { ft := cclt.Fields[i].Type - checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) + checkOrConvertType(store, last, &n.Elts[i].Value, ft, ILLEGAL, false) } } case *ArrayType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, IntType, false) - checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) + checkOrConvertType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, ILLEGAL, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, IntType, false) - checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) + checkOrConvertType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, ILLEGAL, false) } case *MapType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, cclt.Key, false) - checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Value, false) + checkOrConvertType(store, last, &n.Elts[i].Key, cclt.Key, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Value, ILLEGAL, false) } case *NativeType: clt = cclt.GnoType(store) @@ -1636,7 +1659,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } // Special case if shift assign <<= or >>=. - checkOrConvertType(store, last, &n.Rhs[0], UintType, false) + checkOrConvertType(store, last, &n.Rhs[0], UintType, n.Op, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { fmt.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, @@ -1653,10 +1676,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("mismatch type for Assign") } } else { - checkOrConvertType(store, last, &n.Rhs[0], lt, false) + checkOrConvertType(store, last, &n.Rhs[0], lt, n.Op, false) } - } else { + } else { // all else, like BAND_ASSIGN, etc println("case: a, b = x, y") + fmt.Printf("Op: %v \n", n.Op) // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) @@ -1666,7 +1690,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { println("rt is untyped, convert") // is untyped // converts if rx is "nil". - checkOrConvertType(store, last, &n.Rhs[i], lt, false) + checkOrConvertType(store, last, &n.Rhs[i], lt, n.Op, false) } else { println("rt not untyped, check strict") if lt.TypeID() != rt.TypeID() { @@ -1707,12 +1731,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ForStmt: // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, false) + checkOrConvertType(store, last, &n.Cond, BoolType, ILLEGAL, false) // TRANS_LEAVE ----------------------- case *IfStmt: // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, false) + checkOrConvertType(store, last, &n.Cond, BoolType, ILLEGAL, false) // TRANS_LEAVE ----------------------- case *RangeStmt: @@ -1767,7 +1791,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // XXX how to deal? panic("not yet implemented") } else { - checkOrConvertType(store, last, &n.Results[i], rt, false) + checkOrConvertType(store, last, &n.Results[i], rt, ILLEGAL, false) } } } @@ -1775,7 +1799,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SendStmt: // Value consts become default *ConstExprs. - checkOrConvertType(store, last, &n.Value, nil, false) + checkOrConvertType(store, last, &n.Value, nil, ILLEGAL, false) // TRANS_LEAVE ----------------------- case *SelectCaseStmt: @@ -1863,7 +1887,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // convert if const to nt. for i := range n.Values { - checkOrConvertType(store, last, &n.Values[i], nt, false) + checkOrConvertType(store, last, &n.Values[i], nt, ILLEGAL, false) } } else if n.Const { // derive static type from values. @@ -2344,13 +2368,17 @@ func isConstType(x Expr) bool { } func cmpSpecificity(t1, t2 Type) int { + fmt.Printf("cmpSpecificity, t1:%v, t2:%v \n", t1, t2) t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { + println("t1 i prime type") t1s = t1p.Specificity() } if t2p, ok := t2.(PrimitiveType); ok { + println("t2 i prime type") t2s = t2p.Specificity() } + println("t1s, t2s: ", t1s, t2s) if t1s < t2s { // NOTE: higher specificity has lower value, so backwards. return 1 @@ -2367,16 +2395,22 @@ func cmpSpecificity(t1, t2 Type) int { // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() -func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { +func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { + fmt.Printf("checkOrConvertType, x: %v, t:%v, t.typeID: %v, t.kind:%v \n", x, t, t.TypeID(), t.Kind()) if cx, ok := (*x).(*ConstExpr); ok { + // here we should check too, e.g. primitive to declared type is convertable + checkType(cx.T, t, op, autoNative) + fmt.Printf("convertConst, cx: %v \n", cx) convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + println("SHL or SHR") // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Left, t, op, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { + println("else") xt := evalStaticTypeOf(store, last, *x) if t != nil { - checkType(xt, t, autoNative) + checkType(xt, t, op, autoNative) } if isUntyped(xt) { if t == nil { @@ -2388,12 +2422,12 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: // push t into bx.Left and bx.Right - checkOrConvertType(store, last, &bx.Left, t, autoNative) - checkOrConvertType(store, last, &bx.Right, t, autoNative) + checkOrConvertType(store, last, &bx.Left, t, op, autoNative) + checkOrConvertType(store, last, &bx.Right, t, op, autoNative) return case SHL, SHR: // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Left, t, op, autoNative) return // case EQL, LSS, GTR, NEQ, LEQ, GEQ: // default: @@ -2414,10 +2448,15 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { + fmt.Printf("convertConst, cx:%v, t:%v \n", cx, t) + // TODO: some constraint, panic if not convertable + // TODO: thought it should only be permmited to converted to default types, not convertable to interface not satisfied if t != nil && t.Kind() == InterfaceKind { + println("set t to nil, if its kind is interface") t = nil // signifies to convert to default type. } if isUntyped(cx.T) { + println("untyped") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) } else if t != nil { @@ -2430,227 +2469,269 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func checkType(xt Type, dt Type, autoNative bool) { - // Special case if dt is interface kind: - if dt.Kind() == InterfaceKind { - if idt, ok := baseOf(dt).(*InterfaceType); ok { - if idt.IsEmptyInterface() { - // if dt is an empty Gno interface, any x ok. - return // ok - } else if idt.IsImplementedBy(xt) { - // if dt implements idt, ok. - return // ok - } else { - panic(fmt.Sprintf( - "%s does not implement %s", - xt.String(), - dt.String())) - } - } else if ndt, ok := baseOf(dt).(*NativeType); ok { - nidt := ndt.Type - if nidt.NumMethod() == 0 { - // if dt is an empty Go native interface, ditto. - return // ok - } else if nxt, ok := baseOf(xt).(*NativeType); ok { - // if xt has native base, do the naive native. - if nxt.Type.AssignableTo(nidt) { +func checkType(xt Type, dt Type, op Word, autoNative bool) { + fmt.Printf("checkType, xt: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, dt, dt.Kind(), op) + // TODO: first check operands and Op + // two steps of check: + // first, check is the dt type satisfy op, the switch + // second, xt can be converted to dt, this is done below this + if op != ILLEGAL { // should check operand with op + println("check matchable with op") + switch op { + case ADD: // dt is the dest type, what we need check + if !isTypedNumber(dt) && !isTypedString(dt) { + panic(fmt.Sprintf("+ should have operand number or string, while have: %v", dt)) + } + case SUB: + if !isTypedNumber(dt) { + panic(fmt.Sprintf("- should have operand number, while have: %v", dt)) + } + case MUL: + if !isTypedNumber(dt) { + panic(fmt.Sprintf("* should have operand number, while have: %v", dt)) + } + case QUO, REM: + if !isTypedNumber(dt) { + panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) + } + default: + // do nothing + // TODO: should also check the divisor not zero + + } + } + if xt.TypeID() != dt.TypeID() { // check if convertable + // 1. convert with no op, e.g. elements in slice + // 2. convert with op, like int(1) + 0, will also need check convertable + println("check convertable") + // Special case if dt is interface kind: + if dt.Kind() == InterfaceKind { + if idt, ok := baseOf(dt).(*InterfaceType); ok { + if idt.IsEmptyInterface() { + // if dt is an empty Gno interface, any x ok. + return // ok + } else if idt.IsImplementedBy(xt) { + // if dt implements idt, ok. return // ok } else { panic(fmt.Sprintf( - "cannot use %s as %s", - nxt.String(), - nidt.String())) - } - } else if pxt, ok := baseOf(xt).(*PointerType); ok { - nxt, ok := pxt.Elt.(*NativeType) - if !ok { - panic(fmt.Sprintf( - "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", - pxt.String(), - nidt.String())) + "%s does not implement %s", + xt.String(), + dt.String())) } - // if xt has native base, do the naive native. - if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { + } else if ndt, ok := baseOf(dt).(*NativeType); ok { + nidt := ndt.Type + if nidt.NumMethod() == 0 { + // if dt is an empty Go native interface, ditto. return // ok + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nidt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + nxt.String(), + nidt.String())) + } + } else if pxt, ok := baseOf(xt).(*PointerType); ok { + nxt, ok := pxt.Elt.(*NativeType) + if !ok { + panic(fmt.Sprintf( + "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", + pxt.String(), + nidt.String())) + } + // if xt has native base, do the naive native. + if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + pxt.String(), + nidt.String())) + } } else { panic(fmt.Sprintf( - "cannot use %s as %s", - pxt.String(), - nidt.String())) + "unexpected type pair: cannot use %s as %s", + xt.String(), + dt.String())) } } else { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - xt.String(), - dt.String())) + panic("should not happen") } - } else { - panic("should not happen") } - } - // Special case if xt or dt is *PointerType to *NativeType, - // convert to *NativeType of pointer kind. - if pxt, ok := xt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - //nolint:misspell - if enxt, ok := pxt.Elt.(*NativeType); ok { - xt = &NativeType{ - Type: reflect.PtrTo(enxt.Type), + // Special case if xt or dt is *PointerType to *NativeType, + // convert to *NativeType of pointer kind. + if pxt, ok := xt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + //nolint:misspell + if enxt, ok := pxt.Elt.(*NativeType); ok { + xt = &NativeType{ + Type: reflect.PtrTo(enxt.Type), + } } } - } - if pdt, ok := dt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - if endt, ok := pdt.Elt.(*NativeType); ok { - dt = &NativeType{ - Type: reflect.PtrTo(endt.Type), + if pdt, ok := dt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + if endt, ok := pdt.Elt.(*NativeType); ok { + dt = &NativeType{ + Type: reflect.PtrTo(endt.Type), + } } } - } - // Special case of xt or dt is *DeclaredType, - // allow implicit conversion unless both are declared. - // TODO simplify with .IsNamedType(). - if dxt, ok := xt.(*DeclaredType); ok { - if ddt, ok := dt.(*DeclaredType); ok { - // types must match exactly. - if !dxt.sealed && !ddt.sealed && - dxt.PkgPath == ddt.PkgPath && - dxt.Name == ddt.Name { // not yet sealed - return // ok - } else if dxt.TypeID() == ddt.TypeID() { - return // ok + // Special case of xt or dt is *DeclaredType, + // allow implicit conversion unless both are declared. + // TODO simplify with .IsNamedType(). + if dxt, ok := xt.(*DeclaredType); ok { + if ddt, ok := dt.(*DeclaredType); ok { + // types must match exactly. + if !dxt.sealed && !ddt.sealed && + dxt.PkgPath == ddt.PkgPath && + dxt.Name == ddt.Name { // not yet sealed + return // ok + } else if dxt.TypeID() == ddt.TypeID() { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + ddt.String())) + } } else { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - ddt.String())) + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := dt.(PrimitiveType); ok { + //panic(fmt.Sprintf( + // "cannot use %s as %s without explicit conversion", + // dxt.String(), + // dt.String())) + xt = dxt.Base + } else { + // carry on with baseOf(dxt) + xt = dxt.Base + } } - } else { + } else if ddt, ok := dt.(*DeclaredType); ok { // special case if implicitly named primitive type. // TODO simplify with .IsNamedType(). - if _, ok := dt.(PrimitiveType); ok { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - dt.String())) + if _, ok := xt.(PrimitiveType); ok { + // type Error int, if Error(0) == 0 should be legal + // type Error string, if Error("hi") == 0 should be illegal + fmt.Printf("xt typeID: %v, default type of xt:%v, ddt.Base typeID: %v \n", xt.TypeID(), defaultTypeOf(xt), ddt.Base.TypeID()) + //if xt.TypeID() != ddt.Base.TypeID() { + //panic(fmt.Sprintf( + // "cannot use %s as %s without explicit conversion", + // xt.String(), + // ddt.String())) + //} + dt = ddt.Base } else { - // carry on with baseOf(dxt) - xt = dxt.Base + // carry on with baseOf(ddt) + dt = ddt.Base } } - } else if ddt, ok := dt.(*DeclaredType); ok { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := xt.(PrimitiveType); ok { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - xt.String(), - ddt.String())) - } else { - // carry on with baseOf(ddt) - dt = ddt.Base - } - } - // General cases. - switch cdt := dt.(type) { - case PrimitiveType: - // if xt is untyped, ensure dt is compatible. - switch xt { - case UntypedBoolType: - if dt.Kind() == BoolKind { + // General cases. + switch cdt := dt.(type) { + case PrimitiveType: + // if xt is untyped, ensure dt is compatible. + switch xt { + case UntypedBoolType: + if dt.Kind() == BoolKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped bool as %s", + dt.Kind())) + } + case UntypedStringType: + if dt.Kind() == StringKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped string as %s", + dt.Kind())) + } + case UntypedRuneType, UntypedBigintType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped rune as %s", + dt.Kind())) + } + default: + if isUntyped(xt) { + panic("unexpected untyped type") + } + if xt.TypeID() == cdt.TypeID() { + return // ok + } + } + case *PointerType: + if pt, ok := xt.(*PointerType); ok { + checkType(pt.Elt, cdt.Elt, ILLEGAL, false) return // ok - } else { - panic(fmt.Sprintf( - "cannot use untyped bool as %s", - dt.Kind())) } - case UntypedStringType: - if dt.Kind() == StringKind { + case *ArrayType: + if at, ok := xt.(*ArrayType); ok { + checkType(at.Elt, cdt.Elt, ILLEGAL, false) return // ok - } else { - panic(fmt.Sprintf( - "cannot use untyped string as %s", - dt.Kind())) - } - case UntypedRuneType, UntypedBigintType: - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind: + } + case *SliceType: + if st, ok := xt.(*SliceType); ok { + checkType(st.Elt, cdt.Elt, ILLEGAL, false) return // ok - default: - panic(fmt.Sprintf( - "cannot use untyped rune as %s", - dt.Kind())) } - default: - if isUntyped(xt) { - panic("unexpected untyped type") + case *MapType: + if mt, ok := xt.(*MapType); ok { + checkType(mt.Key, cdt.Key, ILLEGAL, false) + checkType(mt.Value, cdt.Value, ILLEGAL, false) + return // ok } + case *FuncType: if xt.TypeID() == cdt.TypeID() { return // ok } - } - case *PointerType: - if pt, ok := xt.(*PointerType); ok { - checkType(pt.Elt, cdt.Elt, false) - return // ok - } - case *ArrayType: - if at, ok := xt.(*ArrayType); ok { - checkType(at.Elt, cdt.Elt, false) - return // ok - } - case *SliceType: - if st, ok := xt.(*SliceType); ok { - checkType(st.Elt, cdt.Elt, false) - return // ok - } - case *MapType: - if mt, ok := xt.(*MapType); ok { - checkType(mt.Key, cdt.Key, false) - checkType(mt.Value, cdt.Value, false) - return // ok - } - case *FuncType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *InterfaceType: - panic("should not happen") - case *DeclaredType: - panic("should not happen") - case *StructType, *PackageType, *ChanType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *TypeType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *NativeType: - if !autoNative { + case *InterfaceType: + panic("should not happen") + case *DeclaredType: + panic("should not happen") + case *StructType, *PackageType, *ChanType: if xt.TypeID() == cdt.TypeID() { return // ok } - } else { - // autoNative, so check whether matches. - // xt: any type but a *DeclaredType; could be native. - // cdt: actual concrete native target type. - // ie, if cdt can match against xt. - if gno2GoTypeMatches(xt, cdt.Type) { + case *TypeType: + if xt.TypeID() == cdt.TypeID() { return // ok } + case *NativeType: + if !autoNative { + if xt.TypeID() == cdt.TypeID() { + return // ok + } + } else { + // autoNative, so check whether matches. + // xt: any type but a *DeclaredType; could be native. + // cdt: actual concrete native target type. + // ie, if cdt can match against xt. + if gno2GoTypeMatches(xt, cdt.Type) { + return // ok + } + } + default: + panic(fmt.Sprintf( + "unexpected type %s", + dt.String())) } - default: panic(fmt.Sprintf( - "unexpected type %s", + "cannot use %s as %s", + xt.String(), dt.String())) } - panic(fmt.Sprintf( - "cannot use %s as %s", - xt.String(), - dt.String())) } // Returns any names not yet defined nor predefined in expr. These happen diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 6aed71fcf9b..cfa5b5fb83e 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1985,6 +1985,34 @@ const ( RefTypeKind // not in go. ) +func isTypedNumber(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + switch t { + case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, Float32Type, Float64Type, BigintType, BigdecType: + return true + default: + return false + } + default: + return false + } +} + +func isTypedString(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + switch t { + case StringType: + return true + default: + return false + } + default: + return false + } +} + // This is generally slower than switching on baseOf(t). func KindOf(t Type) Kind { switch t := baseOf(t).(type) { @@ -2101,21 +2129,30 @@ func assertSameTypes(lt, rt Type) { // Like assertSameTypes(), but more relaxed, for == and !=. func assertEqualityTypes(lt, rt Type) { if lt == nil && rt == nil { + println("1") // both are nil. } else if lt == nil || rt == nil { + println("2") // one is nil. see function comment. } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { + println("3") // one is untyped of same kind. } else if lt.Kind() == InterfaceKind && IsImplementedBy(lt, rt) { + println("4") + // one is untyped of same kind. // rt implements lt (and lt is nil interface). } else if rt.Kind() == InterfaceKind && IsImplementedBy(rt, lt) { + println("5") // lt implements rt (and rt is nil interface). } else if lt.TypeID() == rt.TypeID() { + println("6") // non-nil types are identical. } else { + println("7") + //panic("7, incompatible operands") debug.Errorf( "incompatible operands in binary (eql/neq) expression: %s and %s", lt.String(), @@ -2124,6 +2161,69 @@ func assertEqualityTypes(lt, rt Type) { } } +// type-check rules: +// 1. this happens in binary expressions, assign stmt, call to a func(args and return values) +// 2. cases: (typed/untyped)const op not const, not const op (typed/untyped)const, not const/not const +// 3. steps: first check legal operands of an Op, requires operands on left and right are typed, and both legal with the Op, +// or if one of the operand is not legal with the Op(while the other is) but can be converted into the corresponding one. +// e.g. : 1 + "a" is illegal, or int(1) + 0 is legal after convert +// untyped 0 to int(0) implicitly(no cast), this is because "a" cannot be converted to 1, is untyped 0, which is +// untyped bigint can be converted to int(0). +// special case in here is declared types, is A is declared type of B, and baseOf(A) == B, A and B is convertable in both direction +// NOTE: Op like + - * / % ,etc. have a more strict constrain than equality == or != +// NOTE: if both a typed, but not in the rule of declared type, no conversion. just check if they match. + +// 2. if one of LHS or RHS is constExpr(typed or untyped), it would be converted to the type of its +// corresponding side(using checkOrConvertType, iff it's convertable, using checkType), e.g. int-> int8, int-> (type Error int), +// 3. if both LHS and RHS are not const, assertTypeMatchStrict + +// 4. Operators. need one place in asset* or checkType, to switch operators + +// TODO: merge this with checkType +//func assertTypeMatchStrict(lt, rt Type, op Word) { +// if lt == nil && rt == nil { +// println("1") +// // both are nil. +// } else if lt == nil || rt == nil { +// println("2") +// // one is nil. see function comment. +// } else if lt.Kind() == rt.Kind() && +// isUntyped(lt) || isUntyped(rt) { +// println("3") +// // one is untyped of same kind. +// } else if lt.Kind() == InterfaceKind && +// IsImplementedBy(lt, rt) { +// println("4") +// // one is untyped of same kind. +// // rt implements lt (and lt is nil interface). +// } else if rt.Kind() == InterfaceKind && +// IsImplementedBy(rt, lt) { +// println("5") +// // lt implements rt (and rt is nil interface). +// } else if lt.TypeID() == rt.TypeID() { +// println("6") +// // non-nil types are identical. +// } else { +// println("7") +// panic("7, incompatible operands") +// //debug.Errorf( +// // "incompatible operands in binary (eql/neq) expression: %s and %s", +// // lt.String(), +// // rt.String(), +// //) +// } +// // check special case, + - & / % +// switch op { +// case ADD: // assume untyped has been converted +// if lt.TypeID() != rt.TypeID() { +// panic("+ has mismatched operands") +// } +// if !isTypedNumber(lt) || !isTypedString(lt) { +// panic(fmt.Sprintf("+ should have operand number or string, while have: %v", lt)) +// } +// } +//} + // ---------------------------------------- // misc @@ -2362,7 +2462,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkType(spec, match.Elem(), false) + checkType(spec, match.Elem(), ILLEGAL, false) return // ok } else { // Panic here, because we don't know whether T @@ -2376,7 +2476,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkType(spec, match, false) + checkType(spec, match, ILLEGAL, false) return // ok } else { if isUntyped(spec) { From 2603f34df5478da14c3b03e83885f9776bd5f070 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 28 Nov 2023 16:58:34 +0800 Subject: [PATCH 006/193] more test --- .../p/demo/challenge/0c2_filetest.gno | 24 ++++ .../challenge/{ => others}/2d_filetest.gno | 2 +- .../{ => others}/comparison_0_filetest.gno | 0 .../{ => others}/comparison_0a_filetest.gno | 0 .../{ => others}/comparison_0b_filetest.gno | 0 .../{ => others}/comparison_0c_filetest.gno | 0 .../{ => others}/comparison_0d_filetest.gno | 0 .../{ => others}/comparison_0e_filetest.gno | 0 .../{ => others}/comparison_0f_filetest.gno | 0 .../{ => others}/comparison_0g_filetest.gno | 0 .../{ => others}/comparison_0h_filetest.gno | 0 .../{ => others}/comparison_0i_filetest.gno | 0 .../{ => others}/comparison_0j_filetest.gno | 0 .../{ => others}/comparison_0k_filetest.gno | 0 .../{ => others}/comparison_0l_filetest.gno | 0 .../{ => others}/comparison_0m_filetest.gno | 0 .../{ => others}/comparison_0n_filetest.gno | 0 .../{ => others}/comparison_0z_filetest.gno | 0 .../{ => others}/comparison_1a_filetest.gno | 0 .../{ => others}/comparison_2_filetest.gno | 0 .../{ => others}/comparison_3_filetest.gno | 0 .../{ => others}/comparison_3a_filetest.gno | 0 .../{ => others}/comparison_3b_filetest.gno | 0 .../{ => others}/comparison_3c_filetest.gno | 0 .../{ => others}/comparison_3d_filetest.gno | 0 .../{ => others}/comparison_3e_filetest.gno | 0 .../{ => others}/comparison_3f_filetest.gno | 0 .../{ => others}/comparison_3g_filetest.gno | 0 .../{ => others}/comparison_3h_filetest.gno | 0 .../{ => others}/comparison_3i_filetest.gno | 0 .../{ => others}/comparison_3j_filetest.gno | 0 .../{ => others}/comparison_3k_filetest.gno | 0 .../{ => others}/comparison_3l_filetest.gno | 0 .../{ => others}/comparison_4_filetest.gno | 0 .../{ => others}/comparison_5_filetest.gno | 0 .../{ => others}/comparison_6_filetest.gno | 0 .../{ => others}/comparison_6a_filetest.gno | 0 .../{ => others}/comparison_7_filetest.gno | 0 gnovm/tests/{ => files.bak}/files/a1.gno | 0 gnovm/tests/{ => files.bak}/files/a10.gno | 0 gnovm/tests/{ => files.bak}/files/a11.gno | 0 gnovm/tests/{ => files.bak}/files/a12.gno | 0 gnovm/tests/{ => files.bak}/files/a13.gno | 0 gnovm/tests/{ => files.bak}/files/a14.gno | 0 gnovm/tests/{ => files.bak}/files/a15.gno | 0 gnovm/tests/{ => files.bak}/files/a16.gno | 0 gnovm/tests/{ => files.bak}/files/a17.gno | 0 gnovm/tests/{ => files.bak}/files/a18.gno | 0 gnovm/tests/{ => files.bak}/files/a19.gno | 0 gnovm/tests/{ => files.bak}/files/a2.gno | 0 gnovm/tests/{ => files.bak}/files/a20.gno | 0 gnovm/tests/{ => files.bak}/files/a21.gno | 0 gnovm/tests/{ => files.bak}/files/a22.gno | 0 gnovm/tests/{ => files.bak}/files/a23.gno | 0 gnovm/tests/{ => files.bak}/files/a24.gno | 0 gnovm/tests/{ => files.bak}/files/a25.gno | 0 gnovm/tests/{ => files.bak}/files/a26.gno | 0 gnovm/tests/{ => files.bak}/files/a27.gno | 0 gnovm/tests/{ => files.bak}/files/a28.gno | 0 gnovm/tests/{ => files.bak}/files/a29.gno | 0 gnovm/tests/{ => files.bak}/files/a3.gno | 0 gnovm/tests/{ => files.bak}/files/a30.gno | 0 gnovm/tests/{ => files.bak}/files/a31.gno | 0 gnovm/tests/{ => files.bak}/files/a32.gno | 0 gnovm/tests/{ => files.bak}/files/a33.gno | 0 gnovm/tests/{ => files.bak}/files/a34.gno | 0 gnovm/tests/{ => files.bak}/files/a35.gno | 0 gnovm/tests/{ => files.bak}/files/a36.gno | 0 gnovm/tests/{ => files.bak}/files/a37.gno | 0 gnovm/tests/{ => files.bak}/files/a38.gno | 0 gnovm/tests/{ => files.bak}/files/a39.gno | 0 gnovm/tests/{ => files.bak}/files/a4.gno | 0 gnovm/tests/{ => files.bak}/files/a40.gno | 0 gnovm/tests/{ => files.bak}/files/a41.gno | 0 gnovm/tests/{ => files.bak}/files/a42.gno | 0 gnovm/tests/{ => files.bak}/files/a43.gno | 0 gnovm/tests/{ => files.bak}/files/a44.gno | 0 gnovm/tests/{ => files.bak}/files/a45.gno | 0 gnovm/tests/{ => files.bak}/files/a45a.gno | 0 gnovm/tests/{ => files.bak}/files/a46.gno | 0 gnovm/tests/{ => files.bak}/files/a5.gno | 0 gnovm/tests/{ => files.bak}/files/a6.gno | 0 gnovm/tests/{ => files.bak}/files/a7.gno | 0 gnovm/tests/{ => files.bak}/files/a8.gno | 0 gnovm/tests/{ => files.bak}/files/a9.gno | 0 gnovm/tests/{ => files.bak}/files/access0.gno | 0 gnovm/tests/{ => files.bak}/files/access1.gno | 0 gnovm/tests/{ => files.bak}/files/access2.gno | 0 gnovm/tests/{ => files.bak}/files/access3.gno | 0 gnovm/tests/{ => files.bak}/files/access4.gno | 0 gnovm/tests/{ => files.bak}/files/access5.gno | 0 gnovm/tests/{ => files.bak}/files/access6.gno | 0 gnovm/tests/{ => files.bak}/files/access7.gno | 0 gnovm/tests/{ => files.bak}/files/add0.gno | 0 gnovm/tests/{ => files.bak}/files/add1.gno | 0 gnovm/tests/{ => files.bak}/files/add2.gno | 0 .../{ => files.bak}/files/addr0b_native.gno | 0 .../{ => files.bak}/files/addr0b_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/addr1.gno | 0 gnovm/tests/{ => files.bak}/files/addr2b.gno | 0 gnovm/tests/{ => files.bak}/files/alias0.gno | 0 gnovm/tests/{ => files.bak}/files/alias1.gno | 0 gnovm/tests/{ => files.bak}/files/and.gno | 0 gnovm/tests/{ => files.bak}/files/and0.gno | 0 gnovm/tests/{ => files.bak}/files/and1.gno | 0 gnovm/tests/{ => files.bak}/files/and2.gno | 0 gnovm/tests/{ => files.bak}/files/and3.gno | 0 gnovm/tests/{ => files.bak}/files/append0.gno | 0 gnovm/tests/{ => files.bak}/files/append1.gno | 0 gnovm/tests/{ => files.bak}/files/append2.gno | 0 gnovm/tests/{ => files.bak}/files/append3.gno | 0 gnovm/tests/{ => files.bak}/files/append4.gno | 0 gnovm/tests/{ => files.bak}/files/append5.gno | 0 gnovm/tests/{ => files.bak}/files/array0.gno | 0 gnovm/tests/{ => files.bak}/files/array1.gno | 0 gnovm/tests/{ => files.bak}/files/array2.gno | 0 gnovm/tests/{ => files.bak}/files/array3.gno | 0 gnovm/tests/{ => files.bak}/files/array4.gno | 0 gnovm/tests/{ => files.bak}/files/array5.gno | 0 gnovm/tests/{ => files.bak}/files/assign.gno | 0 .../{ => files.bak}/files/assign0b_native.gno | 0 .../files/assign0b_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/assign1.gno | 0 .../tests/{ => files.bak}/files/assign10.gno | 0 .../tests/{ => files.bak}/files/assign11.gno | 0 .../tests/{ => files.bak}/files/assign12.gno | 0 .../tests/{ => files.bak}/files/assign16.gno | 0 gnovm/tests/{ => files.bak}/files/assign2.gno | 0 .../tests/{ => files.bak}/files/assign20.gno | 0 .../tests/{ => files.bak}/files/assign21.gno | 0 gnovm/tests/{ => files.bak}/files/assign3.gno | 0 gnovm/tests/{ => files.bak}/files/assign4.gno | 0 gnovm/tests/{ => files.bak}/files/assign5.gno | 0 gnovm/tests/{ => files.bak}/files/assign8.gno | 0 gnovm/tests/{ => files.bak}/files/assign9.gno | 0 gnovm/tests/{ => files.bak}/files/avl0.gno | 0 gnovm/tests/{ => files.bak}/files/avl1.gno | 0 gnovm/tests/{ => files.bak}/files/bin.gno | 0 gnovm/tests/{ => files.bak}/files/bin0.gno | 0 gnovm/tests/{ => files.bak}/files/bin1.gno | 0 gnovm/tests/{ => files.bak}/files/bin3.gno | 0 gnovm/tests/{ => files.bak}/files/bin4.gno | 0 gnovm/tests/{ => files.bak}/files/bin5.gno | 0 .../files/binstruct_ptr_map0.gno | 0 .../files/binstruct_ptr_slice0.gno | 0 .../files/binstruct_slice0.gno | 0 gnovm/tests/{ => files.bak}/files/bltn.gno | 0 gnovm/tests/{ => files.bak}/files/bltn0.gno | 0 gnovm/tests/{ => files.bak}/files/bool.gno | 0 gnovm/tests/{ => files.bak}/files/bool0.gno | 0 gnovm/tests/{ => files.bak}/files/bool1.gno | 0 gnovm/tests/{ => files.bak}/files/bool2.gno | 0 gnovm/tests/{ => files.bak}/files/bool3.gno | 0 gnovm/tests/{ => files.bak}/files/bool4.gno | 0 gnovm/tests/{ => files.bak}/files/bool5.gno | 0 gnovm/tests/{ => files.bak}/files/build0.gno | 0 gnovm/tests/{ => files.bak}/files/cap0.gno | 0 .../tests/{ => files.bak}/files/closure0.gno | 0 .../tests/{ => files.bak}/files/closure1.gno | 0 .../tests/{ => files.bak}/files/closure2.gno | 0 .../tests/{ => files.bak}/files/closure3.gno | 0 .../tests/{ => files.bak}/files/closure4.gno | 0 .../tests/{ => files.bak}/files/closure5.gno | 0 .../tests/{ => files.bak}/files/closure6.gno | 0 .../tests/{ => files.bak}/files/closure7.gno | 0 .../tests/{ => files.bak}/files/closure8.gno | 0 gnovm/tests/{ => files.bak}/files/comp1.gno | 0 gnovm/tests/{ => files.bak}/files/comp2.gno | 0 gnovm/tests/{ => files.bak}/files/comp3.gno | 0 .../{ => files.bak}/files/composite0.gno | 0 .../{ => files.bak}/files/composite1.gno | 0 .../{ => files.bak}/files/composite10.gno | 0 .../{ => files.bak}/files/composite11.gno | 0 .../{ => files.bak}/files/composite12.gno | 0 .../{ => files.bak}/files/composite13.gno | 0 .../{ => files.bak}/files/composite14.gno | 0 .../{ => files.bak}/files/composite15.gno | 0 .../{ => files.bak}/files/composite16.gno | 0 .../{ => files.bak}/files/composite17.gno | 0 .../{ => files.bak}/files/composite2.gno | 0 .../{ => files.bak}/files/composite3.gno | 0 .../{ => files.bak}/files/composite4.gno | 0 .../{ => files.bak}/files/composite5.gno | 0 .../{ => files.bak}/files/composite6.gno | 0 .../{ => files.bak}/files/composite7.gno | 0 .../{ => files.bak}/files/composite8.gno | 0 .../{ => files.bak}/files/composite8bis.gno | 0 .../{ => files.bak}/files/composite9.gno | 0 gnovm/tests/{ => files.bak}/files/const0.gno | 0 gnovm/tests/{ => files.bak}/files/const1.gno | 0 gnovm/tests/{ => files.bak}/files/const10.gno | 0 gnovm/tests/{ => files.bak}/files/const11.gno | 0 gnovm/tests/{ => files.bak}/files/const12.gno | 0 gnovm/tests/{ => files.bak}/files/const13.gno | 0 gnovm/tests/{ => files.bak}/files/const14.gno | 0 gnovm/tests/{ => files.bak}/files/const15.gno | 0 gnovm/tests/{ => files.bak}/files/const16.gno | 0 gnovm/tests/{ => files.bak}/files/const17.gno | 0 gnovm/tests/{ => files.bak}/files/const18.gno | 0 gnovm/tests/{ => files.bak}/files/const19.gno | 0 gnovm/tests/{ => files.bak}/files/const2.gno | 0 gnovm/tests/{ => files.bak}/files/const20.gno | 0 gnovm/tests/{ => files.bak}/files/const21.gno | 0 gnovm/tests/{ => files.bak}/files/const22.gno | 0 gnovm/tests/{ => files.bak}/files/const3.gno | 0 gnovm/tests/{ => files.bak}/files/const4.gno | 0 gnovm/tests/{ => files.bak}/files/const5.gno | 0 gnovm/tests/{ => files.bak}/files/const6.gno | 0 gnovm/tests/{ => files.bak}/files/const7.gno | 0 gnovm/tests/{ => files.bak}/files/const8.gno | 0 gnovm/tests/{ => files.bak}/files/const9.gno | 0 gnovm/tests/{ => files.bak}/files/cont.gno | 0 gnovm/tests/{ => files.bak}/files/cont0.gno | 0 gnovm/tests/{ => files.bak}/files/cont1.gno | 0 gnovm/tests/{ => files.bak}/files/context.gno | 0 .../tests/{ => files.bak}/files/context2.gno | 0 .../tests/{ => files.bak}/files/convert0.gno | 0 .../tests/{ => files.bak}/files/convert1.gno | 0 .../tests/{ => files.bak}/files/convert3.gno | 0 gnovm/tests/{ => files.bak}/files/copy0.gno | 0 gnovm/tests/{ => files.bak}/files/copy1.gno | 0 gnovm/tests/{ => files.bak}/files/copy2.gno | 0 gnovm/tests/{ => files.bak}/files/defer0.gno | 0 gnovm/tests/{ => files.bak}/files/defer1.gno | 0 gnovm/tests/{ => files.bak}/files/defer2.gno | 0 gnovm/tests/{ => files.bak}/files/defer3.gno | 0 gnovm/tests/{ => files.bak}/files/defer4.gno | 0 gnovm/tests/{ => files.bak}/files/defer5.gno | 0 gnovm/tests/{ => files.bak}/files/defer6.gno | 0 gnovm/tests/{ => files.bak}/files/defer7.gno | 0 gnovm/tests/{ => files.bak}/files/defer8.gno | 0 gnovm/tests/{ => files.bak}/files/defer9.gno | 0 gnovm/tests/{ => files.bak}/files/define0.gno | 0 gnovm/tests/{ => files.bak}/files/define1.gno | 0 gnovm/tests/{ => files.bak}/files/define2.gno | 0 gnovm/tests/{ => files.bak}/files/define3.gno | 0 gnovm/tests/{ => files.bak}/files/define4.gno | 0 gnovm/tests/{ => files.bak}/files/delete0.gno | 0 gnovm/tests/{ => files.bak}/files/errors.gno | 0 .../files/extern/b1/foo/foo.gno | 0 .../files/extern/b2/foo/foo.gno | 0 .../{ => files.bak}/files/extern/bar/quux.gno | 0 .../files/extern/baz-bat/baz-bat.gno | 0 .../{ => files.bak}/files/extern/baz/quux.gno | 0 .../{ => files.bak}/files/extern/c1/c1.gno | 0 .../{ => files.bak}/files/extern/c2/c2.gno | 0 .../files/extern/context/context.gno | 0 .../{ => files.bak}/files/extern/ct/ct1.gno | 0 .../{ => files.bak}/files/extern/ct/ct2.gno | 0 .../{ => files.bak}/files/extern/ct/ct3.gno | 0 .../{ => files.bak}/files/extern/ct1/ct1.gno | 0 .../files/extern/foo-bar/foo-bar.gno | 0 .../{ => files.bak}/files/extern/foo/bar.gno | 0 .../{ => files.bak}/files/extern/foo/bir.gno | 0 .../files/extern/foo/boo/boo.gno | 0 .../{ => files.bak}/files/extern/m1/main.gno | 0 .../files/extern/m1/main_test.gno | 0 .../files/extern/m2/m2_test.gno | 0 .../files/extern/net/http/http.gno | 0 .../extern/net/http/httptest/httptest.gno | 0 .../{ => files.bak}/files/extern/net/net.gno | 0 .../files/extern/net/url/url.gno | 0 .../{ => files.bak}/files/extern/p1/s1.gno | 0 .../{ => files.bak}/files/extern/p1/s2.gno | 0 .../files/extern/tata/tutu.gno | 0 .../files/extern/time/time.gno | 0 .../data-structures/tree/avl/avltree.gno | 0 .../timtadh/data-structures/tree/utils.gno | 0 .../data-structures/types/map_entry.gno | 0 .../timtadh/data-structures/types/string.gno | 0 .../timtadh/data-structures/types/types.gno | 0 .../timtadh/data-structures/types/util.gno | 0 .../files/extern/toto/titi.gno | 0 .../files/extern/vars/first.gno | 0 .../files/extern/vars/second.gno | 0 gnovm/tests/{ => files.bak}/files/fib0.gno | 0 gnovm/tests/{ => files.bak}/files/float0.gno | 0 gnovm/tests/{ => files.bak}/files/float1.gno | 0 gnovm/tests/{ => files.bak}/files/float2.gno | 0 gnovm/tests/{ => files.bak}/files/float3.gno | 0 gnovm/tests/{ => files.bak}/files/float4.gno | 0 .../{ => files.bak}/files/float5_native.gno | 0 .../{ => files.bak}/files/float5_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/float6.gno | 0 gnovm/tests/{ => files.bak}/files/float7.gno | 0 gnovm/tests/{ => files.bak}/files/for0.gno | 0 gnovm/tests/{ => files.bak}/files/for1.gno | 0 gnovm/tests/{ => files.bak}/files/for10.gno | 0 gnovm/tests/{ => files.bak}/files/for11.gno | 0 gnovm/tests/{ => files.bak}/files/for12.gno | 0 gnovm/tests/{ => files.bak}/files/for13.gno | 0 gnovm/tests/{ => files.bak}/files/for14.gno | 0 gnovm/tests/{ => files.bak}/files/for15.gno | 0 gnovm/tests/{ => files.bak}/files/for16.gno | 0 gnovm/tests/{ => files.bak}/files/for17.gno | 0 gnovm/tests/{ => files.bak}/files/for18.gno | 0 gnovm/tests/{ => files.bak}/files/for2.gno | 0 gnovm/tests/{ => files.bak}/files/for3.gno | 0 gnovm/tests/{ => files.bak}/files/for4.gno | 0 gnovm/tests/{ => files.bak}/files/for5.gno | 0 gnovm/tests/{ => files.bak}/files/for6.gno | 0 gnovm/tests/{ => files.bak}/files/for7.gno | 0 gnovm/tests/{ => files.bak}/files/for8.gno | 0 gnovm/tests/{ => files.bak}/files/for9.gno | 0 gnovm/tests/{ => files.bak}/files/fun.gno | 0 gnovm/tests/{ => files.bak}/files/fun10.gno | 0 gnovm/tests/{ => files.bak}/files/fun11.gno | 0 gnovm/tests/{ => files.bak}/files/fun12.gno | 0 gnovm/tests/{ => files.bak}/files/fun13.gno | 0 gnovm/tests/{ => files.bak}/files/fun14.gno | 0 gnovm/tests/{ => files.bak}/files/fun15.gno | 0 gnovm/tests/{ => files.bak}/files/fun16.gno | 0 gnovm/tests/{ => files.bak}/files/fun17.gno | 0 gnovm/tests/{ => files.bak}/files/fun18.gno | 0 gnovm/tests/{ => files.bak}/files/fun19b.gno | 0 gnovm/tests/{ => files.bak}/files/fun2.gno | 0 gnovm/tests/{ => files.bak}/files/fun20b.gno | 0 gnovm/tests/{ => files.bak}/files/fun21.gno | 0 gnovm/tests/{ => files.bak}/files/fun22.gno | 0 gnovm/tests/{ => files.bak}/files/fun23.gno | 0 gnovm/tests/{ => files.bak}/files/fun24.gno | 0 gnovm/tests/{ => files.bak}/files/fun25.gno | 0 gnovm/tests/{ => files.bak}/files/fun26.gno | 0 gnovm/tests/{ => files.bak}/files/fun3.gno | 0 gnovm/tests/{ => files.bak}/files/fun4.gno | 0 gnovm/tests/{ => files.bak}/files/fun5.gno | 0 gnovm/tests/{ => files.bak}/files/fun6.gno | 0 gnovm/tests/{ => files.bak}/files/fun6b.gno | 0 gnovm/tests/{ => files.bak}/files/fun7.gno | 0 gnovm/tests/{ => files.bak}/files/fun8.gno | 0 gnovm/tests/{ => files.bak}/files/fun9.gno | 0 gnovm/tests/{ => files.bak}/files/goto0.gno | 0 gnovm/tests/{ => files.bak}/files/goto1.gno | 0 gnovm/tests/{ => files.bak}/files/goto2.gno | 0 gnovm/tests/{ => files.bak}/files/goto3.gno | 0 gnovm/tests/{ => files.bak}/files/goto3a.gno | 0 gnovm/tests/{ => files.bak}/files/goto4.gno | 0 gnovm/tests/{ => files.bak}/files/goto5.gno | 0 gnovm/tests/{ => files.bak}/files/goto6.gno | 0 gnovm/tests/{ => files.bak}/files/if.gno | 0 gnovm/tests/{ => files.bak}/files/if0.gno | 0 gnovm/tests/{ => files.bak}/files/if1.gno | 0 gnovm/tests/{ => files.bak}/files/if2.gno | 0 gnovm/tests/{ => files.bak}/files/if3.gno | 0 gnovm/tests/{ => files.bak}/files/if4.gno | 0 gnovm/tests/{ => files.bak}/files/if5.gno | 0 gnovm/tests/{ => files.bak}/files/if6.gno | 0 gnovm/tests/{ => files.bak}/files/if7.gno | 0 gnovm/tests/{ => files.bak}/files/import0.gno | 0 gnovm/tests/{ => files.bak}/files/import1.gno | 0 .../tests/{ => files.bak}/files/import10.gno | 0 gnovm/tests/{ => files.bak}/files/import3.gno | 0 gnovm/tests/{ => files.bak}/files/import4.gno | 0 gnovm/tests/{ => files.bak}/files/import5.gno | 0 gnovm/tests/{ => files.bak}/files/import6.gno | 0 gnovm/tests/{ => files.bak}/files/import7.gno | 0 gnovm/tests/{ => files.bak}/files/import8.gno | 0 gnovm/tests/{ => files.bak}/files/import9.gno | 0 gnovm/tests/{ => files.bak}/files/inc.gno | 0 gnovm/tests/{ => files.bak}/files/index0.gno | 0 gnovm/tests/{ => files.bak}/files/init0.gno | 0 gnovm/tests/{ => files.bak}/files/init1.gno | 0 .../{ => files.bak}/files/interface0.gno | 0 .../{ => files.bak}/files/interface1.gno | 0 .../{ => files.bak}/files/interface10.gno | 0 .../{ => files.bak}/files/interface11.gno | 0 .../{ => files.bak}/files/interface12.gno | 0 .../{ => files.bak}/files/interface13.gno | 0 .../{ => files.bak}/files/interface14.gno | 0 .../{ => files.bak}/files/interface15.gno | 0 .../{ => files.bak}/files/interface16.gno | 0 .../{ => files.bak}/files/interface17.gno | 0 .../{ => files.bak}/files/interface18.gno | 0 .../{ => files.bak}/files/interface19.gno | 0 .../{ => files.bak}/files/interface2.gno | 0 .../{ => files.bak}/files/interface20.gno | 0 .../{ => files.bak}/files/interface21.gno | 0 .../{ => files.bak}/files/interface22.gno | 0 .../{ => files.bak}/files/interface23.gno | 0 .../{ => files.bak}/files/interface24.gno | 0 .../{ => files.bak}/files/interface25.gno | 0 .../{ => files.bak}/files/interface26.gno | 0 .../{ => files.bak}/files/interface27b.gno | 0 .../{ => files.bak}/files/interface28b.gno | 0 .../{ => files.bak}/files/interface29.gno | 0 .../{ => files.bak}/files/interface3.gno | 0 .../{ => files.bak}/files/interface30.gno | 0 .../{ => files.bak}/files/interface31.gno | 0 .../{ => files.bak}/files/interface32.gno | 0 .../{ => files.bak}/files/interface33.gno | 0 .../{ => files.bak}/files/interface34.gno | 0 .../{ => files.bak}/files/interface35.gno | 0 .../{ => files.bak}/files/interface36.gno | 0 .../{ => files.bak}/files/interface37.gno | 0 .../{ => files.bak}/files/interface38b.gno | 0 .../{ => files.bak}/files/interface39b.gno | 0 .../{ => files.bak}/files/interface4.gno | 0 .../{ => files.bak}/files/interface40b.gno | 0 .../{ => files.bak}/files/interface41b.gno | 0 .../{ => files.bak}/files/interface42.gno | 0 .../{ => files.bak}/files/interface43.gno | 0 .../{ => files.bak}/files/interface44.gno | 0 .../{ => files.bak}/files/interface45.gno | 0 .../{ => files.bak}/files/interface46.gno | 0 .../{ => files.bak}/files/interface5.gno | 0 .../{ => files.bak}/files/interface6.gno | 0 .../{ => files.bak}/files/interface7b.gno | 0 .../{ => files.bak}/files/interface8.gno | 0 .../{ => files.bak}/files/interface9b.gno | 0 gnovm/tests/{ => files.bak}/files/interp.gi | 0 gnovm/tests/{ => files.bak}/files/interp2.gi | 0 .../{ => files.bak}/files/io0_native.gno | 0 .../{ => files.bak}/files/io0_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/io1.gno | 0 gnovm/tests/{ => files.bak}/files/io2.gno | 0 gnovm/tests/{ => files.bak}/files/iota.gno | 0 gnovm/tests/{ => files.bak}/files/iota0.gno | 0 .../{ => files.bak}/files/ipp_as_key.gno | 0 .../{ => files.bak}/files/issue-1096.gno | 0 .../{ => files.bak}/files/issue-558b.gno | 0 .../tests/{ => files.bak}/files/issue-735.gno | 0 .../tests/{ => files.bak}/files/issue-776.gno | 0 .../tests/{ => files.bak}/files/issue-782.gno | 0 .../tests/{ => files.bak}/files/issue-784.gno | 0 .../tests/{ => files.bak}/files/issue-880.gno | 0 gnovm/tests/{ => files.bak}/files/l2_long.gno | 0 gnovm/tests/{ => files.bak}/files/l3_long.gno | 0 gnovm/tests/{ => files.bak}/files/l4_long.gno | 0 gnovm/tests/{ => files.bak}/files/l5_long.gno | 0 gnovm/tests/{ => files.bak}/files/len0.gno | 0 gnovm/tests/{ => files.bak}/files/make0.gno | 0 gnovm/tests/{ => files.bak}/files/make1.gno | 0 gnovm/tests/{ => files.bak}/files/make2.gno | 0 gnovm/tests/{ => files.bak}/files/map.gno | 0 gnovm/tests/{ => files.bak}/files/map0.gno | 0 gnovm/tests/{ => files.bak}/files/map1.gno | 0 gnovm/tests/{ => files.bak}/files/map10.gno | 0 gnovm/tests/{ => files.bak}/files/map11.gno | 0 gnovm/tests/{ => files.bak}/files/map12.gno | 0 gnovm/tests/{ => files.bak}/files/map13.gno | 0 gnovm/tests/{ => files.bak}/files/map14b.gno | 0 gnovm/tests/{ => files.bak}/files/map15.gno | 0 gnovm/tests/{ => files.bak}/files/map16.gno | 0 gnovm/tests/{ => files.bak}/files/map17.gno | 0 gnovm/tests/{ => files.bak}/files/map18.gno | 0 gnovm/tests/{ => files.bak}/files/map19b.gno | 0 gnovm/tests/{ => files.bak}/files/map2.gno | 0 gnovm/tests/{ => files.bak}/files/map20.gno | 0 gnovm/tests/{ => files.bak}/files/map21.gno | 0 gnovm/tests/{ => files.bak}/files/map22.gno | 0 gnovm/tests/{ => files.bak}/files/map23.gno | 0 gnovm/tests/{ => files.bak}/files/map24.gno | 0 gnovm/tests/{ => files.bak}/files/map25.gno | 0 gnovm/tests/{ => files.bak}/files/map26.gno | 0 gnovm/tests/{ => files.bak}/files/map27.gno | 0 gnovm/tests/{ => files.bak}/files/map28b.gno | 0 gnovm/tests/{ => files.bak}/files/map28c.gno | 0 .../{ => files.bak}/files/map29_native.gno | 0 .../{ => files.bak}/files/map29_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/map3.gno | 0 gnovm/tests/{ => files.bak}/files/map4.gno | 0 gnovm/tests/{ => files.bak}/files/map5.gno | 0 gnovm/tests/{ => files.bak}/files/map6.gno | 0 gnovm/tests/{ => files.bak}/files/map7.gno | 0 gnovm/tests/{ => files.bak}/files/map8.gno | 0 gnovm/tests/{ => files.bak}/files/map9.gno | 0 .../{ => files.bak}/files/math0_native.gno | 0 .../{ => files.bak}/files/math0_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/math2.gno | 0 gnovm/tests/{ => files.bak}/files/math3.gno | 0 .../files/maths_int16_long.gno | 0 .../{ => files.bak}/files/maths_int8.gno | 0 gnovm/tests/{ => files.bak}/files/method.gno | 0 gnovm/tests/{ => files.bak}/files/method0.gno | 0 gnovm/tests/{ => files.bak}/files/method1.gno | 0 .../tests/{ => files.bak}/files/method10.gno | 0 .../tests/{ => files.bak}/files/method11.gno | 0 .../tests/{ => files.bak}/files/method12.gno | 0 .../tests/{ => files.bak}/files/method13.gno | 0 .../tests/{ => files.bak}/files/method14.gno | 0 .../tests/{ => files.bak}/files/method15.gno | 0 .../tests/{ => files.bak}/files/method16b.gno | 0 .../tests/{ => files.bak}/files/method17b.gno | 0 .../tests/{ => files.bak}/files/method18.gno | 0 .../tests/{ => files.bak}/files/method19.gno | 0 gnovm/tests/{ => files.bak}/files/method2.gno | 0 .../tests/{ => files.bak}/files/method20.gno | 0 .../tests/{ => files.bak}/files/method21.gno | 0 .../tests/{ => files.bak}/files/method22.gno | 0 .../tests/{ => files.bak}/files/method23.gno | 0 .../tests/{ => files.bak}/files/method24.gno | 0 .../tests/{ => files.bak}/files/method25.gno | 0 .../tests/{ => files.bak}/files/method26.gno | 0 .../tests/{ => files.bak}/files/method27.gno | 0 .../tests/{ => files.bak}/files/method28.gno | 0 .../tests/{ => files.bak}/files/method29b.gno | 0 gnovm/tests/{ => files.bak}/files/method3.gno | 0 .../tests/{ => files.bak}/files/method30.gno | 0 .../tests/{ => files.bak}/files/method31b.gno | 0 .../tests/{ => files.bak}/files/method32.gno | 0 .../tests/{ => files.bak}/files/method33.gno | 0 .../tests/{ => files.bak}/files/method34.gno | 0 .../tests/{ => files.bak}/files/method35.gno | 0 .../tests/{ => files.bak}/files/method36.gno | 0 .../tests/{ => files.bak}/files/method37.gno | 0 gnovm/tests/{ => files.bak}/files/method4.gno | 0 gnovm/tests/{ => files.bak}/files/method5.gno | 0 gnovm/tests/{ => files.bak}/files/method6.gno | 0 gnovm/tests/{ => files.bak}/files/method7.gno | 0 gnovm/tests/{ => files.bak}/files/method8.gno | 0 gnovm/tests/{ => files.bak}/files/method9.gno | 0 gnovm/tests/{ => files.bak}/files/neg0.gno | 0 gnovm/tests/{ => files.bak}/files/new0.gno | 0 gnovm/tests/{ => files.bak}/files/new1.gno | 0 gnovm/tests/{ => files.bak}/files/new2.gno | 0 gnovm/tests/{ => files.bak}/files/new3.gno | 0 gnovm/tests/{ => files.bak}/files/nil0.gno | 0 gnovm/tests/{ => files.bak}/files/nil1.gno | 0 gnovm/tests/{ => files.bak}/files/nil2.gno | 0 gnovm/tests/{ => files.bak}/files/nil3.gno | 0 gnovm/tests/{ => files.bak}/files/not0.gno | 0 gnovm/tests/{ => files.bak}/files/not1.gno | 0 gnovm/tests/{ => files.bak}/files/not2.gno | 0 gnovm/tests/{ => files.bak}/files/op0.gno | 0 gnovm/tests/{ => files.bak}/files/op2.gno | 0 gnovm/tests/{ => files.bak}/files/op6.gno | 0 gnovm/tests/{ => files.bak}/files/op7.gno | 0 gnovm/tests/{ => files.bak}/files/op8.gno | 0 gnovm/tests/{ => files.bak}/files/opint16.gno | 0 gnovm/tests/{ => files.bak}/files/opint32.gno | 0 gnovm/tests/{ => files.bak}/files/opint64.gno | 0 gnovm/tests/{ => files.bak}/files/opint8.gno | 0 .../tests/{ => files.bak}/files/opstring.gno | 0 .../tests/{ => files.bak}/files/opuint16.gno | 0 .../tests/{ => files.bak}/files/opuint32.gno | 0 .../tests/{ => files.bak}/files/opuint64.gno | 0 gnovm/tests/{ => files.bak}/files/opuint8.gno | 0 gnovm/tests/{ => files.bak}/files/or0.gno | 0 gnovm/tests/{ => files.bak}/files/or1.gno | 0 gnovm/tests/{ => files.bak}/files/or2.gno | 0 gnovm/tests/{ => files.bak}/files/or3.gno | 0 gnovm/tests/{ => files.bak}/files/or4.gno | 0 gnovm/tests/{ => files.bak}/files/panic0.gno | 0 gnovm/tests/{ => files.bak}/files/panic0b.gno | 0 .../{ => files.bak}/files/persist_map.gno | 0 .../tests/{ => files.bak}/files/pkgname0.gno | 0 .../tests/{ => files.bak}/files/pkgname1.gno | 0 .../tests/{ => files.bak}/files/pkgname2.gno | 0 gnovm/tests/{ => files.bak}/files/primes.gno | 0 gnovm/tests/{ => files.bak}/files/print0.gno | 0 gnovm/tests/{ => files.bak}/files/ptr0.gno | 0 gnovm/tests/{ => files.bak}/files/ptr1.gno | 0 gnovm/tests/{ => files.bak}/files/ptr2.gno | 0 gnovm/tests/{ => files.bak}/files/ptr3.gno | 0 gnovm/tests/{ => files.bak}/files/ptr4.gno | 0 gnovm/tests/{ => files.bak}/files/ptr5.gno | 0 gnovm/tests/{ => files.bak}/files/ptr5a.gno | 0 gnovm/tests/{ => files.bak}/files/ptr6.gno | 0 gnovm/tests/{ => files.bak}/files/ptr7.gno | 0 gnovm/tests/{ => files.bak}/files/ptr8.gno | 0 .../{ => files.bak}/files/ptr_array0.gno | 0 .../{ => files.bak}/files/ptr_array1.gno | 0 .../{ => files.bak}/files/ptr_array2.gno | 0 .../{ => files.bak}/files/ptr_array3.gno | 0 gnovm/tests/{ => files.bak}/files/range0.gno | 0 gnovm/tests/{ => files.bak}/files/range1.gno | 0 gnovm/tests/{ => files.bak}/files/range2.gno | 0 gnovm/tests/{ => files.bak}/files/range3.gno | 0 gnovm/tests/{ => files.bak}/files/range4.gno | 0 gnovm/tests/{ => files.bak}/files/range5.gno | 0 gnovm/tests/{ => files.bak}/files/range6.gno | 0 gnovm/tests/{ => files.bak}/files/range7.gno | 0 .../tests/{ => files.bak}/files/recover0.gno | 0 .../tests/{ => files.bak}/files/recover1.gno | 0 .../tests/{ => files.bak}/files/recover1b.gno | 0 .../tests/{ => files.bak}/files/recover2.gno | 0 .../tests/{ => files.bak}/files/recover3.gno | 0 .../tests/{ => files.bak}/files/recover4.gno | 0 .../tests/{ => files.bak}/files/recover5.gno | 0 .../tests/{ => files.bak}/files/recover6.gno | 0 .../tests/{ => files.bak}/files/recover7.gno | 0 .../tests/{ => files.bak}/files/recurse0.gno | 0 .../files/redeclaration-global0.gno | 0 .../files/redeclaration-global1.gno | 0 .../files/redeclaration-global5.gno | 0 .../{ => files.bak}/files/redeclaration0.gno | 0 .../{ => files.bak}/files/redeclaration1.gno | 0 .../{ => files.bak}/files/redeclaration2.gno | 0 .../{ => files.bak}/files/redeclaration3.gno | 0 .../{ => files.bak}/files/redeclaration4.gno | 0 .../{ => files.bak}/files/redeclaration5.gno | 0 gnovm/tests/{ => files.bak}/files/ret1.gno | 0 gnovm/tests/{ => files.bak}/files/ret10.gno | 0 gnovm/tests/{ => files.bak}/files/ret11.gno | 0 gnovm/tests/{ => files.bak}/files/ret12.gno | 0 gnovm/tests/{ => files.bak}/files/ret13.gno | 0 gnovm/tests/{ => files.bak}/files/ret14.gno | 0 gnovm/tests/{ => files.bak}/files/ret2.gno | 0 gnovm/tests/{ => files.bak}/files/ret3.gno | 0 gnovm/tests/{ => files.bak}/files/ret4.gno | 0 gnovm/tests/{ => files.bak}/files/ret5.gno | 0 gnovm/tests/{ => files.bak}/files/ret6.gno | 0 gnovm/tests/{ => files.bak}/files/ret7.gno | 0 gnovm/tests/{ => files.bak}/files/ret8.gno | 0 gnovm/tests/{ => files.bak}/files/ret9.gno | 0 gnovm/tests/{ => files.bak}/files/run0.gno | 0 gnovm/tests/{ => files.bak}/files/run1.gno | 0 gnovm/tests/{ => files.bak}/files/run10.gno | 0 gnovm/tests/{ => files.bak}/files/run11.gno | 0 gnovm/tests/{ => files.bak}/files/run12.gno | 0 gnovm/tests/{ => files.bak}/files/run13.gno | 0 gnovm/tests/{ => files.bak}/files/run4.gno | 0 gnovm/tests/{ => files.bak}/files/run5.gno | 0 gnovm/tests/{ => files.bak}/files/run6.gno | 0 gnovm/tests/{ => files.bak}/files/run7.gno | 0 gnovm/tests/{ => files.bak}/files/run8.gno | 0 gnovm/tests/{ => files.bak}/files/run9.gno | 0 gnovm/tests/{ => files.bak}/files/rune0.gno | 0 gnovm/tests/{ => files.bak}/files/rune1.gno | 0 gnovm/tests/{ => files.bak}/files/rune2.gno | 0 .../tests/{ => files.bak}/files/sample.plugin | 0 gnovm/tests/{ => files.bak}/files/scope0.gno | 0 gnovm/tests/{ => files.bak}/files/scope1.gno | 0 gnovm/tests/{ => files.bak}/files/scope2.gno | 0 gnovm/tests/{ => files.bak}/files/scope3.gno | 0 gnovm/tests/{ => files.bak}/files/scope4.gno | 0 gnovm/tests/{ => files.bak}/files/scope5.gno | 0 gnovm/tests/{ => files.bak}/files/scope6.gno | 0 gnovm/tests/{ => files.bak}/files/scope7.gno | 0 gnovm/tests/{ => files.bak}/files/secure.gi | 0 gnovm/tests/{ => files.bak}/files/shift0.gno | 0 gnovm/tests/{ => files.bak}/files/shift1.gno | 0 gnovm/tests/{ => files.bak}/files/shift2.gno | 0 gnovm/tests/{ => files.bak}/files/shift3.gno | 0 gnovm/tests/{ => files.bak}/files/shift4.gno | 0 gnovm/tests/{ => files.bak}/files/shift5.gno | 0 gnovm/tests/{ => files.bak}/files/slice0.gno | 0 gnovm/tests/{ => files.bak}/files/slice1.gno | 0 gnovm/tests/{ => files.bak}/files/slice2.gno | 0 gnovm/tests/{ => files.bak}/files/std0.gno | 0 gnovm/tests/{ => files.bak}/files/std10.gno | 0 gnovm/tests/{ => files.bak}/files/std11.gno | 0 gnovm/tests/{ => files.bak}/files/std2.gno | 0 gnovm/tests/{ => files.bak}/files/std3.gno | 0 gnovm/tests/{ => files.bak}/files/std4.gno | 0 gnovm/tests/{ => files.bak}/files/std5.gno | 0 gnovm/tests/{ => files.bak}/files/std6.gno | 0 gnovm/tests/{ => files.bak}/files/std7.gno | 0 gnovm/tests/{ => files.bak}/files/std8.gno | 0 gnovm/tests/{ => files.bak}/files/std9.gno | 0 .../{ => files.bak}/files/stdlibs_native.gno | 0 .../{ => files.bak}/files/stdlibs_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/str.gno | 0 gnovm/tests/{ => files.bak}/files/str0.gno | 0 gnovm/tests/{ => files.bak}/files/str1.gno | 0 gnovm/tests/{ => files.bak}/files/str2.gno | 0 gnovm/tests/{ => files.bak}/files/str3.gno | 0 gnovm/tests/{ => files.bak}/files/str4.gno | 0 gnovm/tests/{ => files.bak}/files/struct.gno | 0 gnovm/tests/{ => files.bak}/files/struct0.gno | 0 .../tests/{ => files.bak}/files/struct0a.gno | 0 gnovm/tests/{ => files.bak}/files/struct1.gno | 0 .../tests/{ => files.bak}/files/struct10.gno | 0 .../tests/{ => files.bak}/files/struct11.gno | 0 .../tests/{ => files.bak}/files/struct11b.gno | 0 .../tests/{ => files.bak}/files/struct12.gno | 0 .../{ => files.bak}/files/struct13_native.gno | 0 .../files/struct13_stdlibs.gno | 0 .../tests/{ => files.bak}/files/struct14.gno | 0 .../tests/{ => files.bak}/files/struct16.gno | 0 .../tests/{ => files.bak}/files/struct17.gno | 0 .../tests/{ => files.bak}/files/struct19.gno | 0 gnovm/tests/{ => files.bak}/files/struct2.gno | 0 .../tests/{ => files.bak}/files/struct20.gno | 0 .../tests/{ => files.bak}/files/struct21.gno | 0 .../tests/{ => files.bak}/files/struct22.gno | 0 .../tests/{ => files.bak}/files/struct24.gno | 0 .../tests/{ => files.bak}/files/struct25.gno | 0 .../tests/{ => files.bak}/files/struct26.gno | 0 .../tests/{ => files.bak}/files/struct27.gno | 0 .../tests/{ => files.bak}/files/struct28b.gno | 0 .../tests/{ => files.bak}/files/struct29.gno | 0 .../tests/{ => files.bak}/files/struct2b.gno | 0 gnovm/tests/{ => files.bak}/files/struct3.gno | 0 .../tests/{ => files.bak}/files/struct30.gno | 0 .../tests/{ => files.bak}/files/struct31.gno | 0 .../tests/{ => files.bak}/files/struct32.gno | 0 .../tests/{ => files.bak}/files/struct33.gno | 0 .../tests/{ => files.bak}/files/struct34.gno | 0 .../tests/{ => files.bak}/files/struct35.gno | 0 .../tests/{ => files.bak}/files/struct36.gno | 0 .../tests/{ => files.bak}/files/struct37.gno | 0 .../tests/{ => files.bak}/files/struct38.gno | 0 .../tests/{ => files.bak}/files/struct39.gno | 0 gnovm/tests/{ => files.bak}/files/struct4.gno | 0 .../tests/{ => files.bak}/files/struct40.gno | 0 .../tests/{ => files.bak}/files/struct41.gno | 0 .../tests/{ => files.bak}/files/struct42.gno | 0 .../tests/{ => files.bak}/files/struct43.gno | 0 .../tests/{ => files.bak}/files/struct44.gno | 0 .../tests/{ => files.bak}/files/struct45.gno | 0 .../tests/{ => files.bak}/files/struct46.gno | 0 .../tests/{ => files.bak}/files/struct47.gno | 0 .../tests/{ => files.bak}/files/struct48.gno | 0 .../tests/{ => files.bak}/files/struct49.gno | 0 gnovm/tests/{ => files.bak}/files/struct5.gno | 0 .../tests/{ => files.bak}/files/struct50b.gno | 0 .../tests/{ => files.bak}/files/struct52b.gno | 0 .../tests/{ => files.bak}/files/struct53b.gno | 0 .../tests/{ => files.bak}/files/struct54.gno | 0 .../tests/{ => files.bak}/files/struct56.gno | 0 .../tests/{ => files.bak}/files/struct57.gno | 0 gnovm/tests/{ => files.bak}/files/struct6.gno | 0 gnovm/tests/{ => files.bak}/files/struct7.gno | 0 gnovm/tests/{ => files.bak}/files/struct8.gno | 0 gnovm/tests/{ => files.bak}/files/struct9.gno | 0 gnovm/tests/{ => files.bak}/files/switch.gno | 0 gnovm/tests/{ => files.bak}/files/switch0.gno | 0 gnovm/tests/{ => files.bak}/files/switch1.gno | 0 .../tests/{ => files.bak}/files/switch10.gno | 0 .../tests/{ => files.bak}/files/switch11.gno | 0 .../tests/{ => files.bak}/files/switch12.gno | 0 .../tests/{ => files.bak}/files/switch13.gno | 0 .../tests/{ => files.bak}/files/switch14.gno | 0 .../tests/{ => files.bak}/files/switch15.gno | 0 .../tests/{ => files.bak}/files/switch16.gno | 0 .../tests/{ => files.bak}/files/switch17.gno | 0 .../tests/{ => files.bak}/files/switch18.gno | 0 .../tests/{ => files.bak}/files/switch19.gno | 0 gnovm/tests/{ => files.bak}/files/switch2.gno | 0 .../tests/{ => files.bak}/files/switch20.gno | 0 .../tests/{ => files.bak}/files/switch21.gno | 0 .../tests/{ => files.bak}/files/switch22.gno | 0 .../tests/{ => files.bak}/files/switch23.gno | 0 .../tests/{ => files.bak}/files/switch24.gno | 0 .../tests/{ => files.bak}/files/switch25.gno | 0 .../tests/{ => files.bak}/files/switch26.gno | 0 .../tests/{ => files.bak}/files/switch27.gno | 0 .../tests/{ => files.bak}/files/switch28.gno | 0 .../tests/{ => files.bak}/files/switch29.gno | 0 gnovm/tests/{ => files.bak}/files/switch3.gno | 0 .../tests/{ => files.bak}/files/switch30.gno | 0 .../tests/{ => files.bak}/files/switch31.gno | 0 .../tests/{ => files.bak}/files/switch32.gno | 0 .../tests/{ => files.bak}/files/switch33.gno | 0 .../tests/{ => files.bak}/files/switch34.gno | 0 .../tests/{ => files.bak}/files/switch35.gno | 0 .../tests/{ => files.bak}/files/switch36.gno | 0 .../tests/{ => files.bak}/files/switch37.gno | 0 .../tests/{ => files.bak}/files/switch38.gno | 0 .../tests/{ => files.bak}/files/switch39.gno | 0 gnovm/tests/{ => files.bak}/files/switch4.gno | 0 .../tests/{ => files.bak}/files/switch40.gno | 0 .../tests/{ => files.bak}/files/switch41.gno | 0 gnovm/tests/{ => files.bak}/files/switch5.gno | 0 gnovm/tests/{ => files.bak}/files/switch6.gno | 0 .../tests/{ => files.bak}/files/switch6b.gno | 0 .../tests/{ => files.bak}/files/switch6c.gno | 0 gnovm/tests/{ => files.bak}/files/switch7.gno | 0 gnovm/tests/{ => files.bak}/files/switch8.gno | 0 .../tests/{ => files.bak}/files/switch8b.gno | 0 .../tests/{ => files.bak}/files/switch8c.gno | 0 gnovm/tests/{ => files.bak}/files/switch9.gno | 0 .../{ => files.bak}/files/time0_native.gno | 0 .../{ => files.bak}/files/time0_stdlibs.gno | 0 .../{ => files.bak}/files/time11_native.gno | 0 .../{ => files.bak}/files/time11_stdlibs.gno | 0 .../{ => files.bak}/files/time12_native.gno | 0 .../{ => files.bak}/files/time12_stdlibs.gno | 0 .../{ => files.bak}/files/time13_native.gno | 0 .../{ => files.bak}/files/time13_stdlibs.gno | 0 .../{ => files.bak}/files/time14_native.gno | 0 .../{ => files.bak}/files/time14_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/time15.gno | 0 .../{ => files.bak}/files/time1_native.gno | 0 .../{ => files.bak}/files/time1_stdlibs.gno | 0 .../{ => files.bak}/files/time2_native.gno | 0 .../{ => files.bak}/files/time2_stdlibs.gno | 0 .../{ => files.bak}/files/time3_native.gno | 0 .../{ => files.bak}/files/time3_stdlibs.gno | 0 .../{ => files.bak}/files/time4_native.gno | 0 .../{ => files.bak}/files/time4_stdlibs.gno | 0 .../{ => files.bak}/files/time6_native.gno | 0 .../{ => files.bak}/files/time6_stdlibs.gno | 0 .../{ => files.bak}/files/time7_native.gno | 0 .../{ => files.bak}/files/time7_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/time8.gno | 0 .../{ => files.bak}/files/time9_native.gno | 0 .../{ => files.bak}/files/time9_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/type0.gno | 0 gnovm/tests/{ => files.bak}/files/type1.gno | 0 gnovm/tests/{ => files.bak}/files/type11.gno | 0 gnovm/tests/{ => files.bak}/files/type12.gno | 0 gnovm/tests/{ => files.bak}/files/type13.gno | 0 gnovm/tests/{ => files.bak}/files/type14.gno | 0 gnovm/tests/{ => files.bak}/files/type15.gno | 0 gnovm/tests/{ => files.bak}/files/type16.gno | 0 gnovm/tests/{ => files.bak}/files/type17.gno | 0 gnovm/tests/{ => files.bak}/files/type18.gno | 0 gnovm/tests/{ => files.bak}/files/type19.gno | 0 gnovm/tests/{ => files.bak}/files/type20.gno | 0 gnovm/tests/{ => files.bak}/files/type22.gno | 0 gnovm/tests/{ => files.bak}/files/type23b.gno | 0 gnovm/tests/{ => files.bak}/files/type24b.gno | 0 .../{ => files.bak}/files/type2_native.gno | 0 .../{ => files.bak}/files/type2_stdlibs.gno | 0 gnovm/tests/{ => files.bak}/files/type3.gno | 0 gnovm/tests/{ => files.bak}/files/type30.gno | 0 gnovm/tests/{ => files.bak}/files/type31.gno | 0 gnovm/tests/{ => files.bak}/files/type32.gno | 0 gnovm/tests/{ => files.bak}/files/type7.gno | 0 gnovm/tests/{ => files.bak}/files/type8.gno | 0 gnovm/tests/{ => files.bak}/files/unary.gno | 0 gnovm/tests/{ => files.bak}/files/unary1.gno | 0 .../tests/{ => files.bak}/files/untyped0.gno | 0 .../tests/{ => files.bak}/files/untyped1.gno | 0 gnovm/tests/{ => files.bak}/files/var.gno | 0 gnovm/tests/{ => files.bak}/files/var10.gno | 0 gnovm/tests/{ => files.bak}/files/var11.gno | 0 gnovm/tests/{ => files.bak}/files/var12.gno | 0 gnovm/tests/{ => files.bak}/files/var13.gno | 0 gnovm/tests/{ => files.bak}/files/var14.gno | 0 gnovm/tests/{ => files.bak}/files/var15.gno | 0 gnovm/tests/{ => files.bak}/files/var16.gno | 0 gnovm/tests/{ => files.bak}/files/var17.gno | 0 gnovm/tests/{ => files.bak}/files/var2.gno | 0 gnovm/tests/{ => files.bak}/files/var3.gno | 0 gnovm/tests/{ => files.bak}/files/var4.gno | 0 gnovm/tests/{ => files.bak}/files/var5.gno | 0 gnovm/tests/{ => files.bak}/files/var6.gno | 0 gnovm/tests/{ => files.bak}/files/var7.gno | 0 gnovm/tests/{ => files.bak}/files/var9.gno | 0 .../tests/{ => files.bak}/files/variadic.gno | 0 .../tests/{ => files.bak}/files/variadic0.gno | 0 .../tests/{ => files.bak}/files/variadic1.gno | 0 .../tests/{ => files.bak}/files/variadic2.gno | 0 .../tests/{ => files.bak}/files/variadic3.gno | 0 .../tests/{ => files.bak}/files/variadic4.gno | 0 .../tests/{ => files.bak}/files/variadic5.gno | 0 .../tests/{ => files.bak}/files/variadic6.gno | 0 .../tests/{ => files.bak}/files/variadic9.gno | 0 .../{ => files.bak}/files/xfactor_long.gno | 0 .../tests/{ => files.bak}/files/xfib_long.gno | 0 .../tests/{ => files.bak}/files/zavltree.gno | 0 .../tests/{ => files.bak}/files/zavltree0.gno | 0 .../tests/{ => files.bak}/files/zavltree1.gno | 0 .../{ => files.bak}/files/zpersist_valids.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm0.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm1.gno | 0 .../tests/{ => files.bak}/files/zrealm10.gno | 0 .../tests/{ => files.bak}/files/zrealm11.gno | 0 .../tests/{ => files.bak}/files/zrealm12.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm2.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm3.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm4.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm5.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm6.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm7.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm8.gno | 0 gnovm/tests/{ => files.bak}/files/zrealm9.gno | 0 .../{ => files.bak}/files/zrealm_avl0.gno | 0 .../{ => files.bak}/files/zrealm_avl1.gno | 0 .../{ => files.bak}/files/zrealm_avl2.gno | 0 .../{ => files.bak}/files/zrealm_const.gno | 0 .../files/zrealm_crossrealm0.gno | 0 .../files/zrealm_crossrealm1.gno | 0 .../files/zrealm_crossrealm10.gno | 0 .../files/zrealm_crossrealm11.gno | 0 .../files/zrealm_crossrealm12.gno | 0 .../files/zrealm_crossrealm2.gno | 0 .../files/zrealm_crossrealm3.gno | 0 .../files/zrealm_crossrealm4.gno | 0 .../files/zrealm_crossrealm5.gno | 0 .../files/zrealm_crossrealm6.gno | 0 .../files/zrealm_crossrealm7.gno | 0 .../files/zrealm_crossrealm8.gno | 0 .../files/zrealm_crossrealm9.gno | 0 .../{ => files.bak}/files/zrealm_example.gno | 0 .../{ => files.bak}/files/zrealm_map0.gno | 0 .../{ => files.bak}/files/zrealm_std0.gno | 0 .../{ => files.bak}/files/zrealm_std1.gno | 0 .../{ => files.bak}/files/zrealm_std2.gno | 0 .../{ => files.bak}/files/zrealm_std3.gno | 0 .../{ => files.bak}/files/zrealm_std4.gno | 0 .../{ => files.bak}/files/zrealm_std5.gno | 0 .../{ => files.bak}/files/zrealm_std6.gno | 0 .../{ => files.bak}/files/zrealm_tests0.gno | 0 .../files/zrealm_testutils0.gno | 0 .../{ => files.bak}/files/zregexp_stdlibs.gno | 0 .../{ => files.bak}/files/zsolitaire_long.gno | 0 gnovm/tests/files/types/0a0_filetest.gno | 9 ++ gnovm/tests/files/types/0a1_filetest.gno | 9 ++ gnovm/tests/files/types/0a2_filetest.gno | 25 ++++ gnovm/tests/files/types/0a3_filetest.gno | 25 ++++ gnovm/tests/files/types/0a4_filetest.gno | 25 ++++ gnovm/tests/files/types/0a5_filetest.gno | 16 +++ gnovm/tests/files/types/0b0_filetest.gno | 26 ++++ .../tests/files/types/0b1_filetest.gno | 5 +- .../tests/files/types/0c0_filetest.gno | 1 - gnovm/tests/files/types/0c1_filetest.gno | 23 ++++ .../tests/files/types/0c2_filetest.gno | 2 +- gnovm/tests/files/types/0d0_filetest.gno | 11 ++ gnovm/tests/files/types/0e0_filetest.gno | 27 ++++ gnovm/tests/files/types/0e1_filetest.gno | 27 ++++ .../tests/files/types/0f0_filetest.gno | 9 +- gnovm/tests/files/types/0f10_filetest.gno | 31 +++++ .../tests/files/types/0f1_filetest.gno | 8 +- .../tests/files/types/0f2_filetest.gno | 9 +- gnovm/tests/files/types/0f3_filetest.gno | 28 +++++ gnovm/tests/files/types/0f4_filetest.gno | 28 +++++ gnovm/tests/files/types/0f5_filetest.gno | 28 +++++ gnovm/tests/files/types/0f6_filetest.gno | 8 ++ gnovm/tests/files/types/0f7_filetest.gno | 28 +++++ .../tests/files/types/0f8_filetest.gno | 9 +- gnovm/tests/files/types/0f9_filetest.gno | 31 +++++ gnovm/tests/files/types/1a0_filetest.gno | 9 ++ gnovm/tests/files/types/1a1_filetest.gno | 25 ++++ gnovm/tests/files/types/1b0_filetest.gno | 13 ++ gnovm/tests/files/types/1b1_filetest.gno | 21 ++++ gnovm/tests/files/types/1b2_filetest.gno | 9 ++ gnovm/tests/files/types/1b3_filetest.gno | 9 ++ gnovm/tests/files/types/1d0_filetest.gno | 12 ++ gnovm/tests/files/types/1d1_filetest.gno | 10 ++ gnovm/tests/files/types/1d2_filetest.gno | 13 ++ gnovm/tests/files/types/1d3_filetest.gno | 15 +++ gnovm/tests/files/types/1e0_filetest.gno | 27 ++++ gnovm/tests/files/types/1f0_filetest.gno | 23 ++++ gnovm/tests/files/types/1f1_filetest.gno | 23 ++++ gnovm/tests/files/types/1f2_filetest.gno | 31 +++++ gnovm/tests/files/types/2a0_filetest.gno | 9 ++ gnovm/tests/files/types/2a1_filetest.gno | 25 ++++ gnovm/tests/files/types/2b0_filetest.gno | 13 ++ gnovm/tests/files/types/2b1_filetest.gno | 21 ++++ gnovm/tests/files/types/2b2_filetest.gno | 9 ++ gnovm/tests/files/types/2b3_filetest.gno | 9 ++ gnovm/tests/files/types/2d0_filetest.gno | 12 ++ gnovm/tests/files/types/2d1_filetest.gno | 10 ++ gnovm/tests/files/types/2d2_filetest.gno | 13 ++ gnovm/tests/files/types/2d3_filetest.gno | 15 +++ gnovm/tests/files/types/2e0_filetest.gno | 27 ++++ gnovm/tests/files/types/2f0_filetest.gno | 23 ++++ gnovm/tests/files/types/2f1_filetest.gno | 23 ++++ gnovm/tests/files/types/2f2_filetest.gno | 31 +++++ gnovm/tests/files/types/3a0_filetest.gno | 9 ++ gnovm/tests/files/types/3a1_filetest.gno | 25 ++++ gnovm/tests/files/types/3b0_filetest.gno | 13 ++ gnovm/tests/files/types/3b1_filetest.gno | 21 ++++ gnovm/tests/files/types/3b2_filetest.gno | 9 ++ gnovm/tests/files/types/3b3_filetest.gno | 9 ++ gnovm/tests/files/types/3d0_filetest.gno | 12 ++ gnovm/tests/files/types/3d1_filetest.gno | 10 ++ gnovm/tests/files/types/3d2_filetest.gno | 13 ++ gnovm/tests/files/types/3d3_filetest.gno | 15 +++ gnovm/tests/files/types/3e0_filetest.gno | 27 ++++ gnovm/tests/files/types/3f0_filetest.gno | 23 ++++ gnovm/tests/files/types/3f1_filetest.gno | 23 ++++ gnovm/tests/files/types/3f2_filetest.gno | 31 +++++ gnovm/tests/files/types/4a0_filetest.gno | 9 ++ gnovm/tests/files/types/4a1_filetest.gno | 25 ++++ gnovm/tests/files/types/4b0_filetest.gno | 13 ++ gnovm/tests/files/types/4b1_filetest.gno | 21 ++++ gnovm/tests/files/types/4b2_filetest.gno | 9 ++ gnovm/tests/files/types/4b3_filetest.gno | 9 ++ gnovm/tests/files/types/4d0_filetest.gno | 11 ++ gnovm/tests/files/types/4d1_filetest.gno | 10 ++ gnovm/tests/files/types/4d2_filetest.gno | 13 ++ gnovm/tests/files/types/4d3_filetest.gno | 15 +++ gnovm/tests/files/types/4d4_filetest.gno | 10 ++ gnovm/tests/files/types/4e0_filetest.gno | 27 ++++ gnovm/tests/files/types/4f0_filetest.gno | 23 ++++ gnovm/tests/files/types/4f1_filetest.gno | 23 ++++ gnovm/tests/files/types/4f2_filetest.gno | 31 +++++ gnovm/tests/files/types/5a0_filetest.gno | 9 ++ gnovm/tests/files/types/5a1_filetest.gno | 25 ++++ gnovm/tests/files/types/5b0_filetest.gno | 13 ++ gnovm/tests/files/types/5b1_filetest.gno | 21 ++++ gnovm/tests/files/types/5b2_filetest.gno | 9 ++ gnovm/tests/files/types/5b3_filetest.gno | 9 ++ gnovm/tests/files/types/5d0_filetest.gno | 10 ++ gnovm/tests/files/types/5d1_filetest.gno | 10 ++ gnovm/tests/files/types/5d2_filetest.gno | 13 ++ gnovm/tests/files/types/5d3_filetest.gno | 15 +++ gnovm/tests/files/types/5d4_filetest.gno | 10 ++ gnovm/tests/files/types/5e0_filetest.gno | 27 ++++ gnovm/tests/files/types/5f0_filetest.gno | 23 ++++ gnovm/tests/files/types/5f1_filetest.gno | 23 ++++ gnovm/tests/files/types/5f2_filetest.gno | 31 +++++ gnovm/tests/files/types/6a0_filetest.gno | 9 ++ gnovm/tests/files/types/6a1_filetest.gno | 25 ++++ gnovm/tests/files/types/6b0_filetest.gno | 13 ++ gnovm/tests/files/types/6b1_filetest.gno | 21 ++++ gnovm/tests/files/types/6b2_filetest.gno | 9 ++ gnovm/tests/files/types/6b3_filetest.gno | 9 ++ gnovm/tests/files/types/6b4_filetest.gno | 9 ++ gnovm/tests/files/types/6d0_filetest.gno | 10 ++ gnovm/tests/files/types/6d1_filetest.gno | 10 ++ gnovm/tests/files/types/6d2_filetest.gno | 13 ++ gnovm/tests/files/types/6d3_filetest.gno | 15 +++ gnovm/tests/files/types/6d4_filetest.gno | 10 ++ gnovm/tests/files/types/6e0_filetest.gno | 27 ++++ gnovm/tests/files/types/6f0_filetest.gno | 23 ++++ gnovm/tests/files/types/6f1_filetest.gno | 23 ++++ gnovm/tests/files/types/6f2_filetest.gno | 31 +++++ gnovm/tests/files/types/7a0_filetest.gno | 9 ++ gnovm/tests/files/types/7a1_filetest.gno | 25 ++++ gnovm/tests/files/types/7b0_filetest.gno | 13 ++ gnovm/tests/files/types/7b1_filetest.gno | 21 ++++ gnovm/tests/files/types/7b2_filetest.gno | 9 ++ gnovm/tests/files/types/7b3_filetest.gno | 9 ++ gnovm/tests/files/types/7b4_filetest.gno | 9 ++ gnovm/tests/files/types/7d0_filetest.gno | 10 ++ gnovm/tests/files/types/7d1_filetest.gno | 10 ++ gnovm/tests/files/types/7d2_filetest.gno | 13 ++ gnovm/tests/files/types/7d3_filetest.gno | 15 +++ gnovm/tests/files/types/7d4_filetest.gno | 10 ++ gnovm/tests/files/types/7e0_filetest.gno | 27 ++++ gnovm/tests/files/types/7f0_filetest.gno | 23 ++++ gnovm/tests/files/types/7f1_filetest.gno | 23 ++++ gnovm/tests/files/types/7f2_filetest.gno | 31 +++++ gnovm/tests/files/types/8a0_filetest.gno | 9 ++ gnovm/tests/files/types/8a1_filetest.gno | 25 ++++ gnovm/tests/files/types/8b0_filetest.gno | 13 ++ gnovm/tests/files/types/8b1_filetest.gno | 21 ++++ gnovm/tests/files/types/8b2_filetest.gno | 9 ++ gnovm/tests/files/types/8b3_filetest.gno | 9 ++ gnovm/tests/files/types/8b4_filetest.gno | 9 ++ gnovm/tests/files/types/8d0_filetest.gno | 10 ++ gnovm/tests/files/types/8d1_filetest.gno | 10 ++ gnovm/tests/files/types/8d2_filetest.gno | 13 ++ gnovm/tests/files/types/8d3_filetest.gno | 15 +++ gnovm/tests/files/types/8d4_filetest.gno | 10 ++ gnovm/tests/files/types/8e0_filetest.gno | 27 ++++ gnovm/tests/files/types/8f0_filetest.gno | 23 ++++ gnovm/tests/files/types/8f1_filetest.gno | 23 ++++ gnovm/tests/files/types/8f2_filetest.gno | 31 +++++ .../tests/files/types/others/2d2_filetest.gno | 25 ++++ .../tests/files/types/others/2d_filetest.gno | 31 +++++ .../tests/files/types/others/2e_filetest.gno | 31 +++++ .../tests/files/types/others/2f_filetest.gno | 31 +++++ .../tests/files/types/others/2g_filetest.gno | 24 ++++ .../tests/files/types/others/2h_filetest.gno | 12 ++ .../tests/files/types/others/2i_filetest.gno | 8 ++ .../tests/files/types/others/2j_filetest.gno | 32 +++++ .../tests/files/types/others/2k_filetest.gno | 27 ++++ .../tests/files/types/others/2l_filetest.gno | 24 ++++ gnovm/tests/files/types/others/README.md | 115 ++++++++++++++++++ .../types/others/comparison_0_filetest.gno | 27 ++++ .../types/others/comparison_0a_filetest.gno | 29 +++++ .../types/others/comparison_0b_filetest.gno | 29 +++++ .../types/others/comparison_0c_filetest.gno | 25 ++++ .../types/others/comparison_0d_filetest.gno | 25 ++++ .../types/others/comparison_0e_filetest.gno | 25 ++++ .../types/others/comparison_0f_filetest.gno | 25 ++++ .../types/others/comparison_0g_filetest.gno | 25 ++++ .../types/others/comparison_0h_filetest.gno | 10 ++ .../types/others/comparison_0i_filetest.gno | 8 ++ .../types/others/comparison_0j_filetest.gno | 8 ++ .../types/others/comparison_0k_filetest.gno | 8 ++ .../types/others/comparison_0l_filetest.gno | 8 ++ .../types/others/comparison_0m_filetest.gno | 8 ++ .../types/others/comparison_0n_filetest.gno | 14 +++ .../types/others/comparison_0z_filetest.gno | 11 ++ .../types/others/comparison_1a_filetest.gno | 23 ++++ .../types/others/comparison_2_filetest.gno | 36 ++++++ .../types/others/comparison_3_filetest.gno | 28 +++++ .../types/others/comparison_3a_filetest.gno | 24 ++++ .../types/others/comparison_3b_filetest.gno | 26 ++++ .../types/others/comparison_3c_filetest.gno | 25 ++++ .../types/others/comparison_3d_filetest.gno | 35 ++++++ .../types/others/comparison_3e_filetest.gno | 35 ++++++ .../types/others/comparison_3f_filetest.gno | 30 +++++ .../types/others/comparison_3g_filetest.gno | 30 +++++ .../types/others/comparison_3h_filetest.gno | 14 +++ .../types/others/comparison_3i_filetest.gno | 10 ++ .../types/others/comparison_3j_filetest.gno | 24 ++++ .../types/others/comparison_3k_filetest.gno | 12 ++ .../types/others/comparison_3l_filetest.gno | 11 ++ .../types/others/comparison_4_filetest.gno | 16 +++ .../types/others/comparison_5_filetest.gno | 15 +++ .../types/others/comparison_6_filetest.gno | 11 ++ .../types/others/comparison_6a_filetest.gno | 10 ++ .../types/others/comparison_7_filetest.gno | 10 ++ 1082 files changed, 3511 insertions(+), 21 deletions(-) create mode 100644 examples/gno.land/p/demo/challenge/0c2_filetest.gno rename examples/gno.land/p/demo/challenge/{ => others}/2d_filetest.gno (94%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0a_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0b_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0c_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0d_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0e_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0f_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0g_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0h_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0i_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0j_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0k_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0l_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0m_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0n_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_0z_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_1a_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_2_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3a_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3b_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3c_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3d_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3e_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3f_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3g_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3h_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3i_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3j_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3k_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_3l_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_4_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_5_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_6_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_6a_filetest.gno (100%) rename examples/gno.land/p/demo/challenge/{ => others}/comparison_7_filetest.gno (100%) rename gnovm/tests/{ => files.bak}/files/a1.gno (100%) rename gnovm/tests/{ => files.bak}/files/a10.gno (100%) rename gnovm/tests/{ => files.bak}/files/a11.gno (100%) rename gnovm/tests/{ => files.bak}/files/a12.gno (100%) rename gnovm/tests/{ => files.bak}/files/a13.gno (100%) rename gnovm/tests/{ => files.bak}/files/a14.gno (100%) rename gnovm/tests/{ => files.bak}/files/a15.gno (100%) rename gnovm/tests/{ => files.bak}/files/a16.gno (100%) rename gnovm/tests/{ => files.bak}/files/a17.gno (100%) rename gnovm/tests/{ => files.bak}/files/a18.gno (100%) rename gnovm/tests/{ => files.bak}/files/a19.gno (100%) rename gnovm/tests/{ => files.bak}/files/a2.gno (100%) rename gnovm/tests/{ => files.bak}/files/a20.gno (100%) rename gnovm/tests/{ => files.bak}/files/a21.gno (100%) rename gnovm/tests/{ => files.bak}/files/a22.gno (100%) rename gnovm/tests/{ => files.bak}/files/a23.gno (100%) rename gnovm/tests/{ => files.bak}/files/a24.gno (100%) rename gnovm/tests/{ => files.bak}/files/a25.gno (100%) rename gnovm/tests/{ => files.bak}/files/a26.gno (100%) rename gnovm/tests/{ => files.bak}/files/a27.gno (100%) rename gnovm/tests/{ => files.bak}/files/a28.gno (100%) rename gnovm/tests/{ => files.bak}/files/a29.gno (100%) rename gnovm/tests/{ => files.bak}/files/a3.gno (100%) rename gnovm/tests/{ => files.bak}/files/a30.gno (100%) rename gnovm/tests/{ => files.bak}/files/a31.gno (100%) rename gnovm/tests/{ => files.bak}/files/a32.gno (100%) rename gnovm/tests/{ => files.bak}/files/a33.gno (100%) rename gnovm/tests/{ => files.bak}/files/a34.gno (100%) rename gnovm/tests/{ => files.bak}/files/a35.gno (100%) rename gnovm/tests/{ => files.bak}/files/a36.gno (100%) rename gnovm/tests/{ => files.bak}/files/a37.gno (100%) rename gnovm/tests/{ => files.bak}/files/a38.gno (100%) rename gnovm/tests/{ => files.bak}/files/a39.gno (100%) rename gnovm/tests/{ => files.bak}/files/a4.gno (100%) rename gnovm/tests/{ => files.bak}/files/a40.gno (100%) rename gnovm/tests/{ => files.bak}/files/a41.gno (100%) rename gnovm/tests/{ => files.bak}/files/a42.gno (100%) rename gnovm/tests/{ => files.bak}/files/a43.gno (100%) rename gnovm/tests/{ => files.bak}/files/a44.gno (100%) rename gnovm/tests/{ => files.bak}/files/a45.gno (100%) rename gnovm/tests/{ => files.bak}/files/a45a.gno (100%) rename gnovm/tests/{ => files.bak}/files/a46.gno (100%) rename gnovm/tests/{ => files.bak}/files/a5.gno (100%) rename gnovm/tests/{ => files.bak}/files/a6.gno (100%) rename gnovm/tests/{ => files.bak}/files/a7.gno (100%) rename gnovm/tests/{ => files.bak}/files/a8.gno (100%) rename gnovm/tests/{ => files.bak}/files/a9.gno (100%) rename gnovm/tests/{ => files.bak}/files/access0.gno (100%) rename gnovm/tests/{ => files.bak}/files/access1.gno (100%) rename gnovm/tests/{ => files.bak}/files/access2.gno (100%) rename gnovm/tests/{ => files.bak}/files/access3.gno (100%) rename gnovm/tests/{ => files.bak}/files/access4.gno (100%) rename gnovm/tests/{ => files.bak}/files/access5.gno (100%) rename gnovm/tests/{ => files.bak}/files/access6.gno (100%) rename gnovm/tests/{ => files.bak}/files/access7.gno (100%) rename gnovm/tests/{ => files.bak}/files/add0.gno (100%) rename gnovm/tests/{ => files.bak}/files/add1.gno (100%) rename gnovm/tests/{ => files.bak}/files/add2.gno (100%) rename gnovm/tests/{ => files.bak}/files/addr0b_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/addr0b_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/addr1.gno (100%) rename gnovm/tests/{ => files.bak}/files/addr2b.gno (100%) rename gnovm/tests/{ => files.bak}/files/alias0.gno (100%) rename gnovm/tests/{ => files.bak}/files/alias1.gno (100%) rename gnovm/tests/{ => files.bak}/files/and.gno (100%) rename gnovm/tests/{ => files.bak}/files/and0.gno (100%) rename gnovm/tests/{ => files.bak}/files/and1.gno (100%) rename gnovm/tests/{ => files.bak}/files/and2.gno (100%) rename gnovm/tests/{ => files.bak}/files/and3.gno (100%) rename gnovm/tests/{ => files.bak}/files/append0.gno (100%) rename gnovm/tests/{ => files.bak}/files/append1.gno (100%) rename gnovm/tests/{ => files.bak}/files/append2.gno (100%) rename gnovm/tests/{ => files.bak}/files/append3.gno (100%) rename gnovm/tests/{ => files.bak}/files/append4.gno (100%) rename gnovm/tests/{ => files.bak}/files/append5.gno (100%) rename gnovm/tests/{ => files.bak}/files/array0.gno (100%) rename gnovm/tests/{ => files.bak}/files/array1.gno (100%) rename gnovm/tests/{ => files.bak}/files/array2.gno (100%) rename gnovm/tests/{ => files.bak}/files/array3.gno (100%) rename gnovm/tests/{ => files.bak}/files/array4.gno (100%) rename gnovm/tests/{ => files.bak}/files/array5.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign0b_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign0b_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign1.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign10.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign11.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign12.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign16.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign2.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign20.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign21.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign3.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign4.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign5.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign8.gno (100%) rename gnovm/tests/{ => files.bak}/files/assign9.gno (100%) rename gnovm/tests/{ => files.bak}/files/avl0.gno (100%) rename gnovm/tests/{ => files.bak}/files/avl1.gno (100%) rename gnovm/tests/{ => files.bak}/files/bin.gno (100%) rename gnovm/tests/{ => files.bak}/files/bin0.gno (100%) rename gnovm/tests/{ => files.bak}/files/bin1.gno (100%) rename gnovm/tests/{ => files.bak}/files/bin3.gno (100%) rename gnovm/tests/{ => files.bak}/files/bin4.gno (100%) rename gnovm/tests/{ => files.bak}/files/bin5.gno (100%) rename gnovm/tests/{ => files.bak}/files/binstruct_ptr_map0.gno (100%) rename gnovm/tests/{ => files.bak}/files/binstruct_ptr_slice0.gno (100%) rename gnovm/tests/{ => files.bak}/files/binstruct_slice0.gno (100%) rename gnovm/tests/{ => files.bak}/files/bltn.gno (100%) rename gnovm/tests/{ => files.bak}/files/bltn0.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool0.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool1.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool2.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool3.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool4.gno (100%) rename gnovm/tests/{ => files.bak}/files/bool5.gno (100%) rename gnovm/tests/{ => files.bak}/files/build0.gno (100%) rename gnovm/tests/{ => files.bak}/files/cap0.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure0.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure1.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure2.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure3.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure4.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure5.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure6.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure7.gno (100%) rename gnovm/tests/{ => files.bak}/files/closure8.gno (100%) rename gnovm/tests/{ => files.bak}/files/comp1.gno (100%) rename gnovm/tests/{ => files.bak}/files/comp2.gno (100%) rename gnovm/tests/{ => files.bak}/files/comp3.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite0.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite1.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite10.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite11.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite12.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite13.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite14.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite15.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite16.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite17.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite2.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite3.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite4.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite5.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite6.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite7.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite8.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite8bis.gno (100%) rename gnovm/tests/{ => files.bak}/files/composite9.gno (100%) rename gnovm/tests/{ => files.bak}/files/const0.gno (100%) rename gnovm/tests/{ => files.bak}/files/const1.gno (100%) rename gnovm/tests/{ => files.bak}/files/const10.gno (100%) rename gnovm/tests/{ => files.bak}/files/const11.gno (100%) rename gnovm/tests/{ => files.bak}/files/const12.gno (100%) rename gnovm/tests/{ => files.bak}/files/const13.gno (100%) rename gnovm/tests/{ => files.bak}/files/const14.gno (100%) rename gnovm/tests/{ => files.bak}/files/const15.gno (100%) rename gnovm/tests/{ => files.bak}/files/const16.gno (100%) rename gnovm/tests/{ => files.bak}/files/const17.gno (100%) rename gnovm/tests/{ => files.bak}/files/const18.gno (100%) rename gnovm/tests/{ => files.bak}/files/const19.gno (100%) rename gnovm/tests/{ => files.bak}/files/const2.gno (100%) rename gnovm/tests/{ => files.bak}/files/const20.gno (100%) rename gnovm/tests/{ => files.bak}/files/const21.gno (100%) rename gnovm/tests/{ => files.bak}/files/const22.gno (100%) rename gnovm/tests/{ => files.bak}/files/const3.gno (100%) rename gnovm/tests/{ => files.bak}/files/const4.gno (100%) rename gnovm/tests/{ => files.bak}/files/const5.gno (100%) rename gnovm/tests/{ => files.bak}/files/const6.gno (100%) rename gnovm/tests/{ => files.bak}/files/const7.gno (100%) rename gnovm/tests/{ => files.bak}/files/const8.gno (100%) rename gnovm/tests/{ => files.bak}/files/const9.gno (100%) rename gnovm/tests/{ => files.bak}/files/cont.gno (100%) rename gnovm/tests/{ => files.bak}/files/cont0.gno (100%) rename gnovm/tests/{ => files.bak}/files/cont1.gno (100%) rename gnovm/tests/{ => files.bak}/files/context.gno (100%) rename gnovm/tests/{ => files.bak}/files/context2.gno (100%) rename gnovm/tests/{ => files.bak}/files/convert0.gno (100%) rename gnovm/tests/{ => files.bak}/files/convert1.gno (100%) rename gnovm/tests/{ => files.bak}/files/convert3.gno (100%) rename gnovm/tests/{ => files.bak}/files/copy0.gno (100%) rename gnovm/tests/{ => files.bak}/files/copy1.gno (100%) rename gnovm/tests/{ => files.bak}/files/copy2.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer0.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer1.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer2.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer3.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer4.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer5.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer6.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer7.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer8.gno (100%) rename gnovm/tests/{ => files.bak}/files/defer9.gno (100%) rename gnovm/tests/{ => files.bak}/files/define0.gno (100%) rename gnovm/tests/{ => files.bak}/files/define1.gno (100%) rename gnovm/tests/{ => files.bak}/files/define2.gno (100%) rename gnovm/tests/{ => files.bak}/files/define3.gno (100%) rename gnovm/tests/{ => files.bak}/files/define4.gno (100%) rename gnovm/tests/{ => files.bak}/files/delete0.gno (100%) rename gnovm/tests/{ => files.bak}/files/errors.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/b1/foo/foo.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/b2/foo/foo.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/bar/quux.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/baz-bat/baz-bat.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/baz/quux.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/c1/c1.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/c2/c2.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/context/context.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/ct/ct1.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/ct/ct2.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/ct/ct3.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/ct1/ct1.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/foo-bar/foo-bar.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/foo/bar.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/foo/bir.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/foo/boo/boo.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/m1/main.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/m1/main_test.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/m2/m2_test.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/net/http/http.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/net/http/httptest/httptest.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/net/net.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/net/url/url.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/p1/s1.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/p1/s2.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/tata/tutu.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/time/time.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/timtadh/data-structures/tree/avl/avltree.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/timtadh/data-structures/tree/utils.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/timtadh/data-structures/types/map_entry.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/timtadh/data-structures/types/string.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/timtadh/data-structures/types/types.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/timtadh/data-structures/types/util.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/toto/titi.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/vars/first.gno (100%) rename gnovm/tests/{ => files.bak}/files/extern/vars/second.gno (100%) rename gnovm/tests/{ => files.bak}/files/fib0.gno (100%) rename gnovm/tests/{ => files.bak}/files/float0.gno (100%) rename gnovm/tests/{ => files.bak}/files/float1.gno (100%) rename gnovm/tests/{ => files.bak}/files/float2.gno (100%) rename gnovm/tests/{ => files.bak}/files/float3.gno (100%) rename gnovm/tests/{ => files.bak}/files/float4.gno (100%) rename gnovm/tests/{ => files.bak}/files/float5_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/float5_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/float6.gno (100%) rename gnovm/tests/{ => files.bak}/files/float7.gno (100%) rename gnovm/tests/{ => files.bak}/files/for0.gno (100%) rename gnovm/tests/{ => files.bak}/files/for1.gno (100%) rename gnovm/tests/{ => files.bak}/files/for10.gno (100%) rename gnovm/tests/{ => files.bak}/files/for11.gno (100%) rename gnovm/tests/{ => files.bak}/files/for12.gno (100%) rename gnovm/tests/{ => files.bak}/files/for13.gno (100%) rename gnovm/tests/{ => files.bak}/files/for14.gno (100%) rename gnovm/tests/{ => files.bak}/files/for15.gno (100%) rename gnovm/tests/{ => files.bak}/files/for16.gno (100%) rename gnovm/tests/{ => files.bak}/files/for17.gno (100%) rename gnovm/tests/{ => files.bak}/files/for18.gno (100%) rename gnovm/tests/{ => files.bak}/files/for2.gno (100%) rename gnovm/tests/{ => files.bak}/files/for3.gno (100%) rename gnovm/tests/{ => files.bak}/files/for4.gno (100%) rename gnovm/tests/{ => files.bak}/files/for5.gno (100%) rename gnovm/tests/{ => files.bak}/files/for6.gno (100%) rename gnovm/tests/{ => files.bak}/files/for7.gno (100%) rename gnovm/tests/{ => files.bak}/files/for8.gno (100%) rename gnovm/tests/{ => files.bak}/files/for9.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun10.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun11.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun12.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun13.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun14.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun15.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun16.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun17.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun18.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun19b.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun2.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun20b.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun21.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun22.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun23.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun24.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun25.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun26.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun3.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun4.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun5.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun6.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun6b.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun7.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun8.gno (100%) rename gnovm/tests/{ => files.bak}/files/fun9.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto0.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto1.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto2.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto3.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto3a.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto4.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto5.gno (100%) rename gnovm/tests/{ => files.bak}/files/goto6.gno (100%) rename gnovm/tests/{ => files.bak}/files/if.gno (100%) rename gnovm/tests/{ => files.bak}/files/if0.gno (100%) rename gnovm/tests/{ => files.bak}/files/if1.gno (100%) rename gnovm/tests/{ => files.bak}/files/if2.gno (100%) rename gnovm/tests/{ => files.bak}/files/if3.gno (100%) rename gnovm/tests/{ => files.bak}/files/if4.gno (100%) rename gnovm/tests/{ => files.bak}/files/if5.gno (100%) rename gnovm/tests/{ => files.bak}/files/if6.gno (100%) rename gnovm/tests/{ => files.bak}/files/if7.gno (100%) rename gnovm/tests/{ => files.bak}/files/import0.gno (100%) rename gnovm/tests/{ => files.bak}/files/import1.gno (100%) rename gnovm/tests/{ => files.bak}/files/import10.gno (100%) rename gnovm/tests/{ => files.bak}/files/import3.gno (100%) rename gnovm/tests/{ => files.bak}/files/import4.gno (100%) rename gnovm/tests/{ => files.bak}/files/import5.gno (100%) rename gnovm/tests/{ => files.bak}/files/import6.gno (100%) rename gnovm/tests/{ => files.bak}/files/import7.gno (100%) rename gnovm/tests/{ => files.bak}/files/import8.gno (100%) rename gnovm/tests/{ => files.bak}/files/import9.gno (100%) rename gnovm/tests/{ => files.bak}/files/inc.gno (100%) rename gnovm/tests/{ => files.bak}/files/index0.gno (100%) rename gnovm/tests/{ => files.bak}/files/init0.gno (100%) rename gnovm/tests/{ => files.bak}/files/init1.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface0.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface1.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface10.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface11.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface12.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface13.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface14.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface15.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface16.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface17.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface18.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface19.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface2.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface20.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface21.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface22.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface23.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface24.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface25.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface26.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface27b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface28b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface29.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface3.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface30.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface31.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface32.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface33.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface34.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface35.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface36.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface37.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface38b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface39b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface4.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface40b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface41b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface42.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface43.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface44.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface45.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface46.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface5.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface6.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface7b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface8.gno (100%) rename gnovm/tests/{ => files.bak}/files/interface9b.gno (100%) rename gnovm/tests/{ => files.bak}/files/interp.gi (100%) rename gnovm/tests/{ => files.bak}/files/interp2.gi (100%) rename gnovm/tests/{ => files.bak}/files/io0_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/io0_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/io1.gno (100%) rename gnovm/tests/{ => files.bak}/files/io2.gno (100%) rename gnovm/tests/{ => files.bak}/files/iota.gno (100%) rename gnovm/tests/{ => files.bak}/files/iota0.gno (100%) rename gnovm/tests/{ => files.bak}/files/ipp_as_key.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-1096.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-558b.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-735.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-776.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-782.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-784.gno (100%) rename gnovm/tests/{ => files.bak}/files/issue-880.gno (100%) rename gnovm/tests/{ => files.bak}/files/l2_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/l3_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/l4_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/l5_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/len0.gno (100%) rename gnovm/tests/{ => files.bak}/files/make0.gno (100%) rename gnovm/tests/{ => files.bak}/files/make1.gno (100%) rename gnovm/tests/{ => files.bak}/files/make2.gno (100%) rename gnovm/tests/{ => files.bak}/files/map.gno (100%) rename gnovm/tests/{ => files.bak}/files/map0.gno (100%) rename gnovm/tests/{ => files.bak}/files/map1.gno (100%) rename gnovm/tests/{ => files.bak}/files/map10.gno (100%) rename gnovm/tests/{ => files.bak}/files/map11.gno (100%) rename gnovm/tests/{ => files.bak}/files/map12.gno (100%) rename gnovm/tests/{ => files.bak}/files/map13.gno (100%) rename gnovm/tests/{ => files.bak}/files/map14b.gno (100%) rename gnovm/tests/{ => files.bak}/files/map15.gno (100%) rename gnovm/tests/{ => files.bak}/files/map16.gno (100%) rename gnovm/tests/{ => files.bak}/files/map17.gno (100%) rename gnovm/tests/{ => files.bak}/files/map18.gno (100%) rename gnovm/tests/{ => files.bak}/files/map19b.gno (100%) rename gnovm/tests/{ => files.bak}/files/map2.gno (100%) rename gnovm/tests/{ => files.bak}/files/map20.gno (100%) rename gnovm/tests/{ => files.bak}/files/map21.gno (100%) rename gnovm/tests/{ => files.bak}/files/map22.gno (100%) rename gnovm/tests/{ => files.bak}/files/map23.gno (100%) rename gnovm/tests/{ => files.bak}/files/map24.gno (100%) rename gnovm/tests/{ => files.bak}/files/map25.gno (100%) rename gnovm/tests/{ => files.bak}/files/map26.gno (100%) rename gnovm/tests/{ => files.bak}/files/map27.gno (100%) rename gnovm/tests/{ => files.bak}/files/map28b.gno (100%) rename gnovm/tests/{ => files.bak}/files/map28c.gno (100%) rename gnovm/tests/{ => files.bak}/files/map29_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/map29_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/map3.gno (100%) rename gnovm/tests/{ => files.bak}/files/map4.gno (100%) rename gnovm/tests/{ => files.bak}/files/map5.gno (100%) rename gnovm/tests/{ => files.bak}/files/map6.gno (100%) rename gnovm/tests/{ => files.bak}/files/map7.gno (100%) rename gnovm/tests/{ => files.bak}/files/map8.gno (100%) rename gnovm/tests/{ => files.bak}/files/map9.gno (100%) rename gnovm/tests/{ => files.bak}/files/math0_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/math0_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/math2.gno (100%) rename gnovm/tests/{ => files.bak}/files/math3.gno (100%) rename gnovm/tests/{ => files.bak}/files/maths_int16_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/maths_int8.gno (100%) rename gnovm/tests/{ => files.bak}/files/method.gno (100%) rename gnovm/tests/{ => files.bak}/files/method0.gno (100%) rename gnovm/tests/{ => files.bak}/files/method1.gno (100%) rename gnovm/tests/{ => files.bak}/files/method10.gno (100%) rename gnovm/tests/{ => files.bak}/files/method11.gno (100%) rename gnovm/tests/{ => files.bak}/files/method12.gno (100%) rename gnovm/tests/{ => files.bak}/files/method13.gno (100%) rename gnovm/tests/{ => files.bak}/files/method14.gno (100%) rename gnovm/tests/{ => files.bak}/files/method15.gno (100%) rename gnovm/tests/{ => files.bak}/files/method16b.gno (100%) rename gnovm/tests/{ => files.bak}/files/method17b.gno (100%) rename gnovm/tests/{ => files.bak}/files/method18.gno (100%) rename gnovm/tests/{ => files.bak}/files/method19.gno (100%) rename gnovm/tests/{ => files.bak}/files/method2.gno (100%) rename gnovm/tests/{ => files.bak}/files/method20.gno (100%) rename gnovm/tests/{ => files.bak}/files/method21.gno (100%) rename gnovm/tests/{ => files.bak}/files/method22.gno (100%) rename gnovm/tests/{ => files.bak}/files/method23.gno (100%) rename gnovm/tests/{ => files.bak}/files/method24.gno (100%) rename gnovm/tests/{ => files.bak}/files/method25.gno (100%) rename gnovm/tests/{ => files.bak}/files/method26.gno (100%) rename gnovm/tests/{ => files.bak}/files/method27.gno (100%) rename gnovm/tests/{ => files.bak}/files/method28.gno (100%) rename gnovm/tests/{ => files.bak}/files/method29b.gno (100%) rename gnovm/tests/{ => files.bak}/files/method3.gno (100%) rename gnovm/tests/{ => files.bak}/files/method30.gno (100%) rename gnovm/tests/{ => files.bak}/files/method31b.gno (100%) rename gnovm/tests/{ => files.bak}/files/method32.gno (100%) rename gnovm/tests/{ => files.bak}/files/method33.gno (100%) rename gnovm/tests/{ => files.bak}/files/method34.gno (100%) rename gnovm/tests/{ => files.bak}/files/method35.gno (100%) rename gnovm/tests/{ => files.bak}/files/method36.gno (100%) rename gnovm/tests/{ => files.bak}/files/method37.gno (100%) rename gnovm/tests/{ => files.bak}/files/method4.gno (100%) rename gnovm/tests/{ => files.bak}/files/method5.gno (100%) rename gnovm/tests/{ => files.bak}/files/method6.gno (100%) rename gnovm/tests/{ => files.bak}/files/method7.gno (100%) rename gnovm/tests/{ => files.bak}/files/method8.gno (100%) rename gnovm/tests/{ => files.bak}/files/method9.gno (100%) rename gnovm/tests/{ => files.bak}/files/neg0.gno (100%) rename gnovm/tests/{ => files.bak}/files/new0.gno (100%) rename gnovm/tests/{ => files.bak}/files/new1.gno (100%) rename gnovm/tests/{ => files.bak}/files/new2.gno (100%) rename gnovm/tests/{ => files.bak}/files/new3.gno (100%) rename gnovm/tests/{ => files.bak}/files/nil0.gno (100%) rename gnovm/tests/{ => files.bak}/files/nil1.gno (100%) rename gnovm/tests/{ => files.bak}/files/nil2.gno (100%) rename gnovm/tests/{ => files.bak}/files/nil3.gno (100%) rename gnovm/tests/{ => files.bak}/files/not0.gno (100%) rename gnovm/tests/{ => files.bak}/files/not1.gno (100%) rename gnovm/tests/{ => files.bak}/files/not2.gno (100%) rename gnovm/tests/{ => files.bak}/files/op0.gno (100%) rename gnovm/tests/{ => files.bak}/files/op2.gno (100%) rename gnovm/tests/{ => files.bak}/files/op6.gno (100%) rename gnovm/tests/{ => files.bak}/files/op7.gno (100%) rename gnovm/tests/{ => files.bak}/files/op8.gno (100%) rename gnovm/tests/{ => files.bak}/files/opint16.gno (100%) rename gnovm/tests/{ => files.bak}/files/opint32.gno (100%) rename gnovm/tests/{ => files.bak}/files/opint64.gno (100%) rename gnovm/tests/{ => files.bak}/files/opint8.gno (100%) rename gnovm/tests/{ => files.bak}/files/opstring.gno (100%) rename gnovm/tests/{ => files.bak}/files/opuint16.gno (100%) rename gnovm/tests/{ => files.bak}/files/opuint32.gno (100%) rename gnovm/tests/{ => files.bak}/files/opuint64.gno (100%) rename gnovm/tests/{ => files.bak}/files/opuint8.gno (100%) rename gnovm/tests/{ => files.bak}/files/or0.gno (100%) rename gnovm/tests/{ => files.bak}/files/or1.gno (100%) rename gnovm/tests/{ => files.bak}/files/or2.gno (100%) rename gnovm/tests/{ => files.bak}/files/or3.gno (100%) rename gnovm/tests/{ => files.bak}/files/or4.gno (100%) rename gnovm/tests/{ => files.bak}/files/panic0.gno (100%) rename gnovm/tests/{ => files.bak}/files/panic0b.gno (100%) rename gnovm/tests/{ => files.bak}/files/persist_map.gno (100%) rename gnovm/tests/{ => files.bak}/files/pkgname0.gno (100%) rename gnovm/tests/{ => files.bak}/files/pkgname1.gno (100%) rename gnovm/tests/{ => files.bak}/files/pkgname2.gno (100%) rename gnovm/tests/{ => files.bak}/files/primes.gno (100%) rename gnovm/tests/{ => files.bak}/files/print0.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr0.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr1.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr2.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr3.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr4.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr5.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr5a.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr6.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr7.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr8.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr_array0.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr_array1.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr_array2.gno (100%) rename gnovm/tests/{ => files.bak}/files/ptr_array3.gno (100%) rename gnovm/tests/{ => files.bak}/files/range0.gno (100%) rename gnovm/tests/{ => files.bak}/files/range1.gno (100%) rename gnovm/tests/{ => files.bak}/files/range2.gno (100%) rename gnovm/tests/{ => files.bak}/files/range3.gno (100%) rename gnovm/tests/{ => files.bak}/files/range4.gno (100%) rename gnovm/tests/{ => files.bak}/files/range5.gno (100%) rename gnovm/tests/{ => files.bak}/files/range6.gno (100%) rename gnovm/tests/{ => files.bak}/files/range7.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover0.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover1.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover1b.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover2.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover3.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover4.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover5.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover6.gno (100%) rename gnovm/tests/{ => files.bak}/files/recover7.gno (100%) rename gnovm/tests/{ => files.bak}/files/recurse0.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration-global0.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration-global1.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration-global5.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration0.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration1.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration2.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration3.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration4.gno (100%) rename gnovm/tests/{ => files.bak}/files/redeclaration5.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret1.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret10.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret11.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret12.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret13.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret14.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret2.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret3.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret4.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret5.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret6.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret7.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret8.gno (100%) rename gnovm/tests/{ => files.bak}/files/ret9.gno (100%) rename gnovm/tests/{ => files.bak}/files/run0.gno (100%) rename gnovm/tests/{ => files.bak}/files/run1.gno (100%) rename gnovm/tests/{ => files.bak}/files/run10.gno (100%) rename gnovm/tests/{ => files.bak}/files/run11.gno (100%) rename gnovm/tests/{ => files.bak}/files/run12.gno (100%) rename gnovm/tests/{ => files.bak}/files/run13.gno (100%) rename gnovm/tests/{ => files.bak}/files/run4.gno (100%) rename gnovm/tests/{ => files.bak}/files/run5.gno (100%) rename gnovm/tests/{ => files.bak}/files/run6.gno (100%) rename gnovm/tests/{ => files.bak}/files/run7.gno (100%) rename gnovm/tests/{ => files.bak}/files/run8.gno (100%) rename gnovm/tests/{ => files.bak}/files/run9.gno (100%) rename gnovm/tests/{ => files.bak}/files/rune0.gno (100%) rename gnovm/tests/{ => files.bak}/files/rune1.gno (100%) rename gnovm/tests/{ => files.bak}/files/rune2.gno (100%) rename gnovm/tests/{ => files.bak}/files/sample.plugin (100%) rename gnovm/tests/{ => files.bak}/files/scope0.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope1.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope2.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope3.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope4.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope5.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope6.gno (100%) rename gnovm/tests/{ => files.bak}/files/scope7.gno (100%) rename gnovm/tests/{ => files.bak}/files/secure.gi (100%) rename gnovm/tests/{ => files.bak}/files/shift0.gno (100%) rename gnovm/tests/{ => files.bak}/files/shift1.gno (100%) rename gnovm/tests/{ => files.bak}/files/shift2.gno (100%) rename gnovm/tests/{ => files.bak}/files/shift3.gno (100%) rename gnovm/tests/{ => files.bak}/files/shift4.gno (100%) rename gnovm/tests/{ => files.bak}/files/shift5.gno (100%) rename gnovm/tests/{ => files.bak}/files/slice0.gno (100%) rename gnovm/tests/{ => files.bak}/files/slice1.gno (100%) rename gnovm/tests/{ => files.bak}/files/slice2.gno (100%) rename gnovm/tests/{ => files.bak}/files/std0.gno (100%) rename gnovm/tests/{ => files.bak}/files/std10.gno (100%) rename gnovm/tests/{ => files.bak}/files/std11.gno (100%) rename gnovm/tests/{ => files.bak}/files/std2.gno (100%) rename gnovm/tests/{ => files.bak}/files/std3.gno (100%) rename gnovm/tests/{ => files.bak}/files/std4.gno (100%) rename gnovm/tests/{ => files.bak}/files/std5.gno (100%) rename gnovm/tests/{ => files.bak}/files/std6.gno (100%) rename gnovm/tests/{ => files.bak}/files/std7.gno (100%) rename gnovm/tests/{ => files.bak}/files/std8.gno (100%) rename gnovm/tests/{ => files.bak}/files/std9.gno (100%) rename gnovm/tests/{ => files.bak}/files/stdlibs_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/stdlibs_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/str.gno (100%) rename gnovm/tests/{ => files.bak}/files/str0.gno (100%) rename gnovm/tests/{ => files.bak}/files/str1.gno (100%) rename gnovm/tests/{ => files.bak}/files/str2.gno (100%) rename gnovm/tests/{ => files.bak}/files/str3.gno (100%) rename gnovm/tests/{ => files.bak}/files/str4.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct0.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct0a.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct1.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct10.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct11.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct11b.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct12.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct13_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct13_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct14.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct16.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct17.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct19.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct2.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct20.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct21.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct22.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct24.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct25.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct26.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct27.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct28b.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct29.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct2b.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct3.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct30.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct31.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct32.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct33.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct34.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct35.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct36.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct37.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct38.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct39.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct4.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct40.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct41.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct42.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct43.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct44.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct45.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct46.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct47.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct48.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct49.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct5.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct50b.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct52b.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct53b.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct54.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct56.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct57.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct6.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct7.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct8.gno (100%) rename gnovm/tests/{ => files.bak}/files/struct9.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch0.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch1.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch10.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch11.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch12.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch13.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch14.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch15.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch16.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch17.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch18.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch19.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch2.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch20.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch21.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch22.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch23.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch24.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch25.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch26.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch27.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch28.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch29.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch3.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch30.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch31.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch32.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch33.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch34.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch35.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch36.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch37.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch38.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch39.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch4.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch40.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch41.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch5.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch6.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch6b.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch6c.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch7.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch8.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch8b.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch8c.gno (100%) rename gnovm/tests/{ => files.bak}/files/switch9.gno (100%) rename gnovm/tests/{ => files.bak}/files/time0_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time0_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time11_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time11_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time12_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time12_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time13_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time13_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time14_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time14_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time15.gno (100%) rename gnovm/tests/{ => files.bak}/files/time1_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time1_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time2_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time2_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time3_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time3_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time4_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time4_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time6_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time6_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time7_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time7_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/time8.gno (100%) rename gnovm/tests/{ => files.bak}/files/time9_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/time9_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/type0.gno (100%) rename gnovm/tests/{ => files.bak}/files/type1.gno (100%) rename gnovm/tests/{ => files.bak}/files/type11.gno (100%) rename gnovm/tests/{ => files.bak}/files/type12.gno (100%) rename gnovm/tests/{ => files.bak}/files/type13.gno (100%) rename gnovm/tests/{ => files.bak}/files/type14.gno (100%) rename gnovm/tests/{ => files.bak}/files/type15.gno (100%) rename gnovm/tests/{ => files.bak}/files/type16.gno (100%) rename gnovm/tests/{ => files.bak}/files/type17.gno (100%) rename gnovm/tests/{ => files.bak}/files/type18.gno (100%) rename gnovm/tests/{ => files.bak}/files/type19.gno (100%) rename gnovm/tests/{ => files.bak}/files/type20.gno (100%) rename gnovm/tests/{ => files.bak}/files/type22.gno (100%) rename gnovm/tests/{ => files.bak}/files/type23b.gno (100%) rename gnovm/tests/{ => files.bak}/files/type24b.gno (100%) rename gnovm/tests/{ => files.bak}/files/type2_native.gno (100%) rename gnovm/tests/{ => files.bak}/files/type2_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/type3.gno (100%) rename gnovm/tests/{ => files.bak}/files/type30.gno (100%) rename gnovm/tests/{ => files.bak}/files/type31.gno (100%) rename gnovm/tests/{ => files.bak}/files/type32.gno (100%) rename gnovm/tests/{ => files.bak}/files/type7.gno (100%) rename gnovm/tests/{ => files.bak}/files/type8.gno (100%) rename gnovm/tests/{ => files.bak}/files/unary.gno (100%) rename gnovm/tests/{ => files.bak}/files/unary1.gno (100%) rename gnovm/tests/{ => files.bak}/files/untyped0.gno (100%) rename gnovm/tests/{ => files.bak}/files/untyped1.gno (100%) rename gnovm/tests/{ => files.bak}/files/var.gno (100%) rename gnovm/tests/{ => files.bak}/files/var10.gno (100%) rename gnovm/tests/{ => files.bak}/files/var11.gno (100%) rename gnovm/tests/{ => files.bak}/files/var12.gno (100%) rename gnovm/tests/{ => files.bak}/files/var13.gno (100%) rename gnovm/tests/{ => files.bak}/files/var14.gno (100%) rename gnovm/tests/{ => files.bak}/files/var15.gno (100%) rename gnovm/tests/{ => files.bak}/files/var16.gno (100%) rename gnovm/tests/{ => files.bak}/files/var17.gno (100%) rename gnovm/tests/{ => files.bak}/files/var2.gno (100%) rename gnovm/tests/{ => files.bak}/files/var3.gno (100%) rename gnovm/tests/{ => files.bak}/files/var4.gno (100%) rename gnovm/tests/{ => files.bak}/files/var5.gno (100%) rename gnovm/tests/{ => files.bak}/files/var6.gno (100%) rename gnovm/tests/{ => files.bak}/files/var7.gno (100%) rename gnovm/tests/{ => files.bak}/files/var9.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic0.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic1.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic2.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic3.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic4.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic5.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic6.gno (100%) rename gnovm/tests/{ => files.bak}/files/variadic9.gno (100%) rename gnovm/tests/{ => files.bak}/files/xfactor_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/xfib_long.gno (100%) rename gnovm/tests/{ => files.bak}/files/zavltree.gno (100%) rename gnovm/tests/{ => files.bak}/files/zavltree0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zavltree1.gno (100%) rename gnovm/tests/{ => files.bak}/files/zpersist_valids.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm1.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm10.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm11.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm12.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm2.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm3.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm4.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm5.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm6.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm7.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm8.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm9.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_avl0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_avl1.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_avl2.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_const.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm1.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm10.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm11.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm12.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm2.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm3.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm4.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm5.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm6.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm7.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm8.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_crossrealm9.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_example.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_map0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std1.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std2.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std3.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std4.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std5.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_std6.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_tests0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zrealm_testutils0.gno (100%) rename gnovm/tests/{ => files.bak}/files/zregexp_stdlibs.gno (100%) rename gnovm/tests/{ => files.bak}/files/zsolitaire_long.gno (100%) create mode 100644 gnovm/tests/files/types/0a0_filetest.gno create mode 100644 gnovm/tests/files/types/0a1_filetest.gno create mode 100644 gnovm/tests/files/types/0a2_filetest.gno create mode 100644 gnovm/tests/files/types/0a3_filetest.gno create mode 100644 gnovm/tests/files/types/0a4_filetest.gno create mode 100644 gnovm/tests/files/types/0a5_filetest.gno create mode 100644 gnovm/tests/files/types/0b0_filetest.gno rename examples/gno.land/p/demo/challenge/1a_filetest.gno => gnovm/tests/files/types/0b1_filetest.gno (75%) rename examples/gno.land/p/demo/challenge/1_filetest.gno => gnovm/tests/files/types/0c0_filetest.gno (86%) create mode 100644 gnovm/tests/files/types/0c1_filetest.gno rename examples/gno.land/p/demo/challenge/1b_filetest.gno => gnovm/tests/files/types/0c2_filetest.gno (81%) create mode 100644 gnovm/tests/files/types/0d0_filetest.gno create mode 100644 gnovm/tests/files/types/0e0_filetest.gno create mode 100644 gnovm/tests/files/types/0e1_filetest.gno rename examples/gno.land/p/demo/challenge/2b_filetest.gno => gnovm/tests/files/types/0f0_filetest.gno (68%) create mode 100644 gnovm/tests/files/types/0f10_filetest.gno rename examples/gno.land/p/demo/challenge/2a_filetest.gno => gnovm/tests/files/types/0f1_filetest.gno (60%) rename examples/gno.land/p/demo/challenge/2c_filetest.gno => gnovm/tests/files/types/0f2_filetest.gno (68%) create mode 100644 gnovm/tests/files/types/0f3_filetest.gno create mode 100644 gnovm/tests/files/types/0f4_filetest.gno create mode 100644 gnovm/tests/files/types/0f5_filetest.gno create mode 100644 gnovm/tests/files/types/0f6_filetest.gno create mode 100644 gnovm/tests/files/types/0f7_filetest.gno rename examples/gno.land/p/demo/challenge/2_filetest.gno => gnovm/tests/files/types/0f8_filetest.gno (51%) create mode 100644 gnovm/tests/files/types/0f9_filetest.gno create mode 100644 gnovm/tests/files/types/1a0_filetest.gno create mode 100644 gnovm/tests/files/types/1a1_filetest.gno create mode 100644 gnovm/tests/files/types/1b0_filetest.gno create mode 100644 gnovm/tests/files/types/1b1_filetest.gno create mode 100644 gnovm/tests/files/types/1b2_filetest.gno create mode 100644 gnovm/tests/files/types/1b3_filetest.gno create mode 100644 gnovm/tests/files/types/1d0_filetest.gno create mode 100644 gnovm/tests/files/types/1d1_filetest.gno create mode 100644 gnovm/tests/files/types/1d2_filetest.gno create mode 100644 gnovm/tests/files/types/1d3_filetest.gno create mode 100644 gnovm/tests/files/types/1e0_filetest.gno create mode 100644 gnovm/tests/files/types/1f0_filetest.gno create mode 100644 gnovm/tests/files/types/1f1_filetest.gno create mode 100644 gnovm/tests/files/types/1f2_filetest.gno create mode 100644 gnovm/tests/files/types/2a0_filetest.gno create mode 100644 gnovm/tests/files/types/2a1_filetest.gno create mode 100644 gnovm/tests/files/types/2b0_filetest.gno create mode 100644 gnovm/tests/files/types/2b1_filetest.gno create mode 100644 gnovm/tests/files/types/2b2_filetest.gno create mode 100644 gnovm/tests/files/types/2b3_filetest.gno create mode 100644 gnovm/tests/files/types/2d0_filetest.gno create mode 100644 gnovm/tests/files/types/2d1_filetest.gno create mode 100644 gnovm/tests/files/types/2d2_filetest.gno create mode 100644 gnovm/tests/files/types/2d3_filetest.gno create mode 100644 gnovm/tests/files/types/2e0_filetest.gno create mode 100644 gnovm/tests/files/types/2f0_filetest.gno create mode 100644 gnovm/tests/files/types/2f1_filetest.gno create mode 100644 gnovm/tests/files/types/2f2_filetest.gno create mode 100644 gnovm/tests/files/types/3a0_filetest.gno create mode 100644 gnovm/tests/files/types/3a1_filetest.gno create mode 100644 gnovm/tests/files/types/3b0_filetest.gno create mode 100644 gnovm/tests/files/types/3b1_filetest.gno create mode 100644 gnovm/tests/files/types/3b2_filetest.gno create mode 100644 gnovm/tests/files/types/3b3_filetest.gno create mode 100644 gnovm/tests/files/types/3d0_filetest.gno create mode 100644 gnovm/tests/files/types/3d1_filetest.gno create mode 100644 gnovm/tests/files/types/3d2_filetest.gno create mode 100644 gnovm/tests/files/types/3d3_filetest.gno create mode 100644 gnovm/tests/files/types/3e0_filetest.gno create mode 100644 gnovm/tests/files/types/3f0_filetest.gno create mode 100644 gnovm/tests/files/types/3f1_filetest.gno create mode 100644 gnovm/tests/files/types/3f2_filetest.gno create mode 100644 gnovm/tests/files/types/4a0_filetest.gno create mode 100644 gnovm/tests/files/types/4a1_filetest.gno create mode 100644 gnovm/tests/files/types/4b0_filetest.gno create mode 100644 gnovm/tests/files/types/4b1_filetest.gno create mode 100644 gnovm/tests/files/types/4b2_filetest.gno create mode 100644 gnovm/tests/files/types/4b3_filetest.gno create mode 100644 gnovm/tests/files/types/4d0_filetest.gno create mode 100644 gnovm/tests/files/types/4d1_filetest.gno create mode 100644 gnovm/tests/files/types/4d2_filetest.gno create mode 100644 gnovm/tests/files/types/4d3_filetest.gno create mode 100644 gnovm/tests/files/types/4d4_filetest.gno create mode 100644 gnovm/tests/files/types/4e0_filetest.gno create mode 100644 gnovm/tests/files/types/4f0_filetest.gno create mode 100644 gnovm/tests/files/types/4f1_filetest.gno create mode 100644 gnovm/tests/files/types/4f2_filetest.gno create mode 100644 gnovm/tests/files/types/5a0_filetest.gno create mode 100644 gnovm/tests/files/types/5a1_filetest.gno create mode 100644 gnovm/tests/files/types/5b0_filetest.gno create mode 100644 gnovm/tests/files/types/5b1_filetest.gno create mode 100644 gnovm/tests/files/types/5b2_filetest.gno create mode 100644 gnovm/tests/files/types/5b3_filetest.gno create mode 100644 gnovm/tests/files/types/5d0_filetest.gno create mode 100644 gnovm/tests/files/types/5d1_filetest.gno create mode 100644 gnovm/tests/files/types/5d2_filetest.gno create mode 100644 gnovm/tests/files/types/5d3_filetest.gno create mode 100644 gnovm/tests/files/types/5d4_filetest.gno create mode 100644 gnovm/tests/files/types/5e0_filetest.gno create mode 100644 gnovm/tests/files/types/5f0_filetest.gno create mode 100644 gnovm/tests/files/types/5f1_filetest.gno create mode 100644 gnovm/tests/files/types/5f2_filetest.gno create mode 100644 gnovm/tests/files/types/6a0_filetest.gno create mode 100644 gnovm/tests/files/types/6a1_filetest.gno create mode 100644 gnovm/tests/files/types/6b0_filetest.gno create mode 100644 gnovm/tests/files/types/6b1_filetest.gno create mode 100644 gnovm/tests/files/types/6b2_filetest.gno create mode 100644 gnovm/tests/files/types/6b3_filetest.gno create mode 100644 gnovm/tests/files/types/6b4_filetest.gno create mode 100644 gnovm/tests/files/types/6d0_filetest.gno create mode 100644 gnovm/tests/files/types/6d1_filetest.gno create mode 100644 gnovm/tests/files/types/6d2_filetest.gno create mode 100644 gnovm/tests/files/types/6d3_filetest.gno create mode 100644 gnovm/tests/files/types/6d4_filetest.gno create mode 100644 gnovm/tests/files/types/6e0_filetest.gno create mode 100644 gnovm/tests/files/types/6f0_filetest.gno create mode 100644 gnovm/tests/files/types/6f1_filetest.gno create mode 100644 gnovm/tests/files/types/6f2_filetest.gno create mode 100644 gnovm/tests/files/types/7a0_filetest.gno create mode 100644 gnovm/tests/files/types/7a1_filetest.gno create mode 100644 gnovm/tests/files/types/7b0_filetest.gno create mode 100644 gnovm/tests/files/types/7b1_filetest.gno create mode 100644 gnovm/tests/files/types/7b2_filetest.gno create mode 100644 gnovm/tests/files/types/7b3_filetest.gno create mode 100644 gnovm/tests/files/types/7b4_filetest.gno create mode 100644 gnovm/tests/files/types/7d0_filetest.gno create mode 100644 gnovm/tests/files/types/7d1_filetest.gno create mode 100644 gnovm/tests/files/types/7d2_filetest.gno create mode 100644 gnovm/tests/files/types/7d3_filetest.gno create mode 100644 gnovm/tests/files/types/7d4_filetest.gno create mode 100644 gnovm/tests/files/types/7e0_filetest.gno create mode 100644 gnovm/tests/files/types/7f0_filetest.gno create mode 100644 gnovm/tests/files/types/7f1_filetest.gno create mode 100644 gnovm/tests/files/types/7f2_filetest.gno create mode 100644 gnovm/tests/files/types/8a0_filetest.gno create mode 100644 gnovm/tests/files/types/8a1_filetest.gno create mode 100644 gnovm/tests/files/types/8b0_filetest.gno create mode 100644 gnovm/tests/files/types/8b1_filetest.gno create mode 100644 gnovm/tests/files/types/8b2_filetest.gno create mode 100644 gnovm/tests/files/types/8b3_filetest.gno create mode 100644 gnovm/tests/files/types/8b4_filetest.gno create mode 100644 gnovm/tests/files/types/8d0_filetest.gno create mode 100644 gnovm/tests/files/types/8d1_filetest.gno create mode 100644 gnovm/tests/files/types/8d2_filetest.gno create mode 100644 gnovm/tests/files/types/8d3_filetest.gno create mode 100644 gnovm/tests/files/types/8d4_filetest.gno create mode 100644 gnovm/tests/files/types/8e0_filetest.gno create mode 100644 gnovm/tests/files/types/8f0_filetest.gno create mode 100644 gnovm/tests/files/types/8f1_filetest.gno create mode 100644 gnovm/tests/files/types/8f2_filetest.gno create mode 100644 gnovm/tests/files/types/others/2d2_filetest.gno create mode 100644 gnovm/tests/files/types/others/2d_filetest.gno create mode 100644 gnovm/tests/files/types/others/2e_filetest.gno create mode 100644 gnovm/tests/files/types/others/2f_filetest.gno create mode 100644 gnovm/tests/files/types/others/2g_filetest.gno create mode 100644 gnovm/tests/files/types/others/2h_filetest.gno create mode 100644 gnovm/tests/files/types/others/2i_filetest.gno create mode 100644 gnovm/tests/files/types/others/2j_filetest.gno create mode 100644 gnovm/tests/files/types/others/2k_filetest.gno create mode 100644 gnovm/tests/files/types/others/2l_filetest.gno create mode 100644 gnovm/tests/files/types/others/README.md create mode 100644 gnovm/tests/files/types/others/comparison_0_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0a_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0b_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0c_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0d_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0e_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0f_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0g_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0h_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0i_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0j_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0k_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0l_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0m_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0n_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_0z_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_1a_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_2_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3a_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3b_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3c_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3d_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3e_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3f_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3g_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3h_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3i_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3j_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3k_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_3l_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_4_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_5_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_6_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_6a_filetest.gno create mode 100644 gnovm/tests/files/types/others/comparison_7_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/0c2_filetest.gno b/examples/gno.land/p/demo/challenge/0c2_filetest.gno new file mode 100644 index 00000000000..19010b53804 --- /dev/null +++ b/examples/gno.land/p/demo/challenge/0c2_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is typed const, right is untyped const +// NOTE: overflow +func main() { + if Error(1) == 128 { // note, this would overflow as expected + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/0c2_filetest.gno:16: bigint overflows target kind diff --git a/examples/gno.land/p/demo/challenge/2d_filetest.gno b/examples/gno.land/p/demo/challenge/others/2d_filetest.gno similarity index 94% rename from examples/gno.land/p/demo/challenge/2d_filetest.gno rename to examples/gno.land/p/demo/challenge/others/2d_filetest.gno index e2561129fd5..62d952adae4 100644 --- a/examples/gno.land/p/demo/challenge/2d_filetest.gno +++ b/examples/gno.land/p/demo/challenge/others/2d_filetest.gno @@ -20,7 +20,7 @@ func (e Error2) Error() string { return "error: " + strconv.Itoa(int(e)) } -// both not const +// both not const, check + func main() { var e1 E = Error1(0) var e2 E = Error2(0) diff --git a/examples/gno.land/p/demo/challenge/comparison_0_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0a_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0a_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0a_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0b_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0b_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0b_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0b_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0c_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0c_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0c_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0c_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0d_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0d_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0d_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0d_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0e_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0e_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0e_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0e_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0f_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0f_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0f_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0f_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0g_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0g_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0g_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0g_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0h_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0h_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0h_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0h_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0i_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0i_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0i_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0i_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0j_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0j_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0j_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0j_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0k_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0k_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0k_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0k_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0l_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0l_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0l_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0l_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0m_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0m_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0m_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0m_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0n_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0n_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0n_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0n_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_0z_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0z_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_0z_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_0z_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_1a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_1a_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_1a_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_1a_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_2_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_2_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_2_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_2_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3a_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3a_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3a_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3b_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3b_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3b_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3b_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3c_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3c_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3c_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3c_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3d_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3d_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3d_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3d_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3e_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3e_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3e_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3e_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3f_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3f_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3f_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3f_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3g_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3g_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3g_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3g_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3h_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3h_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3h_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3h_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3i_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3i_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3i_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3i_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3j_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3j_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3j_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3j_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3k_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3k_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3k_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3k_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_3l_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3l_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_3l_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_3l_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_4_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_4_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_4_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_4_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_5_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_5_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_5_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_5_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_6_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_6_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_6_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_6_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_6a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_6a_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_6a_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_6a_filetest.gno diff --git a/examples/gno.land/p/demo/challenge/comparison_7_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_7_filetest.gno similarity index 100% rename from examples/gno.land/p/demo/challenge/comparison_7_filetest.gno rename to examples/gno.land/p/demo/challenge/others/comparison_7_filetest.gno diff --git a/gnovm/tests/files/a1.gno b/gnovm/tests/files.bak/files/a1.gno similarity index 100% rename from gnovm/tests/files/a1.gno rename to gnovm/tests/files.bak/files/a1.gno diff --git a/gnovm/tests/files/a10.gno b/gnovm/tests/files.bak/files/a10.gno similarity index 100% rename from gnovm/tests/files/a10.gno rename to gnovm/tests/files.bak/files/a10.gno diff --git a/gnovm/tests/files/a11.gno b/gnovm/tests/files.bak/files/a11.gno similarity index 100% rename from gnovm/tests/files/a11.gno rename to gnovm/tests/files.bak/files/a11.gno diff --git a/gnovm/tests/files/a12.gno b/gnovm/tests/files.bak/files/a12.gno similarity index 100% rename from gnovm/tests/files/a12.gno rename to gnovm/tests/files.bak/files/a12.gno diff --git a/gnovm/tests/files/a13.gno b/gnovm/tests/files.bak/files/a13.gno similarity index 100% rename from gnovm/tests/files/a13.gno rename to gnovm/tests/files.bak/files/a13.gno diff --git a/gnovm/tests/files/a14.gno b/gnovm/tests/files.bak/files/a14.gno similarity index 100% rename from gnovm/tests/files/a14.gno rename to gnovm/tests/files.bak/files/a14.gno diff --git a/gnovm/tests/files/a15.gno b/gnovm/tests/files.bak/files/a15.gno similarity index 100% rename from gnovm/tests/files/a15.gno rename to gnovm/tests/files.bak/files/a15.gno diff --git a/gnovm/tests/files/a16.gno b/gnovm/tests/files.bak/files/a16.gno similarity index 100% rename from gnovm/tests/files/a16.gno rename to gnovm/tests/files.bak/files/a16.gno diff --git a/gnovm/tests/files/a17.gno b/gnovm/tests/files.bak/files/a17.gno similarity index 100% rename from gnovm/tests/files/a17.gno rename to gnovm/tests/files.bak/files/a17.gno diff --git a/gnovm/tests/files/a18.gno b/gnovm/tests/files.bak/files/a18.gno similarity index 100% rename from gnovm/tests/files/a18.gno rename to gnovm/tests/files.bak/files/a18.gno diff --git a/gnovm/tests/files/a19.gno b/gnovm/tests/files.bak/files/a19.gno similarity index 100% rename from gnovm/tests/files/a19.gno rename to gnovm/tests/files.bak/files/a19.gno diff --git a/gnovm/tests/files/a2.gno b/gnovm/tests/files.bak/files/a2.gno similarity index 100% rename from gnovm/tests/files/a2.gno rename to gnovm/tests/files.bak/files/a2.gno diff --git a/gnovm/tests/files/a20.gno b/gnovm/tests/files.bak/files/a20.gno similarity index 100% rename from gnovm/tests/files/a20.gno rename to gnovm/tests/files.bak/files/a20.gno diff --git a/gnovm/tests/files/a21.gno b/gnovm/tests/files.bak/files/a21.gno similarity index 100% rename from gnovm/tests/files/a21.gno rename to gnovm/tests/files.bak/files/a21.gno diff --git a/gnovm/tests/files/a22.gno b/gnovm/tests/files.bak/files/a22.gno similarity index 100% rename from gnovm/tests/files/a22.gno rename to gnovm/tests/files.bak/files/a22.gno diff --git a/gnovm/tests/files/a23.gno b/gnovm/tests/files.bak/files/a23.gno similarity index 100% rename from gnovm/tests/files/a23.gno rename to gnovm/tests/files.bak/files/a23.gno diff --git a/gnovm/tests/files/a24.gno b/gnovm/tests/files.bak/files/a24.gno similarity index 100% rename from gnovm/tests/files/a24.gno rename to gnovm/tests/files.bak/files/a24.gno diff --git a/gnovm/tests/files/a25.gno b/gnovm/tests/files.bak/files/a25.gno similarity index 100% rename from gnovm/tests/files/a25.gno rename to gnovm/tests/files.bak/files/a25.gno diff --git a/gnovm/tests/files/a26.gno b/gnovm/tests/files.bak/files/a26.gno similarity index 100% rename from gnovm/tests/files/a26.gno rename to gnovm/tests/files.bak/files/a26.gno diff --git a/gnovm/tests/files/a27.gno b/gnovm/tests/files.bak/files/a27.gno similarity index 100% rename from gnovm/tests/files/a27.gno rename to gnovm/tests/files.bak/files/a27.gno diff --git a/gnovm/tests/files/a28.gno b/gnovm/tests/files.bak/files/a28.gno similarity index 100% rename from gnovm/tests/files/a28.gno rename to gnovm/tests/files.bak/files/a28.gno diff --git a/gnovm/tests/files/a29.gno b/gnovm/tests/files.bak/files/a29.gno similarity index 100% rename from gnovm/tests/files/a29.gno rename to gnovm/tests/files.bak/files/a29.gno diff --git a/gnovm/tests/files/a3.gno b/gnovm/tests/files.bak/files/a3.gno similarity index 100% rename from gnovm/tests/files/a3.gno rename to gnovm/tests/files.bak/files/a3.gno diff --git a/gnovm/tests/files/a30.gno b/gnovm/tests/files.bak/files/a30.gno similarity index 100% rename from gnovm/tests/files/a30.gno rename to gnovm/tests/files.bak/files/a30.gno diff --git a/gnovm/tests/files/a31.gno b/gnovm/tests/files.bak/files/a31.gno similarity index 100% rename from gnovm/tests/files/a31.gno rename to gnovm/tests/files.bak/files/a31.gno diff --git a/gnovm/tests/files/a32.gno b/gnovm/tests/files.bak/files/a32.gno similarity index 100% rename from gnovm/tests/files/a32.gno rename to gnovm/tests/files.bak/files/a32.gno diff --git a/gnovm/tests/files/a33.gno b/gnovm/tests/files.bak/files/a33.gno similarity index 100% rename from gnovm/tests/files/a33.gno rename to gnovm/tests/files.bak/files/a33.gno diff --git a/gnovm/tests/files/a34.gno b/gnovm/tests/files.bak/files/a34.gno similarity index 100% rename from gnovm/tests/files/a34.gno rename to gnovm/tests/files.bak/files/a34.gno diff --git a/gnovm/tests/files/a35.gno b/gnovm/tests/files.bak/files/a35.gno similarity index 100% rename from gnovm/tests/files/a35.gno rename to gnovm/tests/files.bak/files/a35.gno diff --git a/gnovm/tests/files/a36.gno b/gnovm/tests/files.bak/files/a36.gno similarity index 100% rename from gnovm/tests/files/a36.gno rename to gnovm/tests/files.bak/files/a36.gno diff --git a/gnovm/tests/files/a37.gno b/gnovm/tests/files.bak/files/a37.gno similarity index 100% rename from gnovm/tests/files/a37.gno rename to gnovm/tests/files.bak/files/a37.gno diff --git a/gnovm/tests/files/a38.gno b/gnovm/tests/files.bak/files/a38.gno similarity index 100% rename from gnovm/tests/files/a38.gno rename to gnovm/tests/files.bak/files/a38.gno diff --git a/gnovm/tests/files/a39.gno b/gnovm/tests/files.bak/files/a39.gno similarity index 100% rename from gnovm/tests/files/a39.gno rename to gnovm/tests/files.bak/files/a39.gno diff --git a/gnovm/tests/files/a4.gno b/gnovm/tests/files.bak/files/a4.gno similarity index 100% rename from gnovm/tests/files/a4.gno rename to gnovm/tests/files.bak/files/a4.gno diff --git a/gnovm/tests/files/a40.gno b/gnovm/tests/files.bak/files/a40.gno similarity index 100% rename from gnovm/tests/files/a40.gno rename to gnovm/tests/files.bak/files/a40.gno diff --git a/gnovm/tests/files/a41.gno b/gnovm/tests/files.bak/files/a41.gno similarity index 100% rename from gnovm/tests/files/a41.gno rename to gnovm/tests/files.bak/files/a41.gno diff --git a/gnovm/tests/files/a42.gno b/gnovm/tests/files.bak/files/a42.gno similarity index 100% rename from gnovm/tests/files/a42.gno rename to gnovm/tests/files.bak/files/a42.gno diff --git a/gnovm/tests/files/a43.gno b/gnovm/tests/files.bak/files/a43.gno similarity index 100% rename from gnovm/tests/files/a43.gno rename to gnovm/tests/files.bak/files/a43.gno diff --git a/gnovm/tests/files/a44.gno b/gnovm/tests/files.bak/files/a44.gno similarity index 100% rename from gnovm/tests/files/a44.gno rename to gnovm/tests/files.bak/files/a44.gno diff --git a/gnovm/tests/files/a45.gno b/gnovm/tests/files.bak/files/a45.gno similarity index 100% rename from gnovm/tests/files/a45.gno rename to gnovm/tests/files.bak/files/a45.gno diff --git a/gnovm/tests/files/a45a.gno b/gnovm/tests/files.bak/files/a45a.gno similarity index 100% rename from gnovm/tests/files/a45a.gno rename to gnovm/tests/files.bak/files/a45a.gno diff --git a/gnovm/tests/files/a46.gno b/gnovm/tests/files.bak/files/a46.gno similarity index 100% rename from gnovm/tests/files/a46.gno rename to gnovm/tests/files.bak/files/a46.gno diff --git a/gnovm/tests/files/a5.gno b/gnovm/tests/files.bak/files/a5.gno similarity index 100% rename from gnovm/tests/files/a5.gno rename to gnovm/tests/files.bak/files/a5.gno diff --git a/gnovm/tests/files/a6.gno b/gnovm/tests/files.bak/files/a6.gno similarity index 100% rename from gnovm/tests/files/a6.gno rename to gnovm/tests/files.bak/files/a6.gno diff --git a/gnovm/tests/files/a7.gno b/gnovm/tests/files.bak/files/a7.gno similarity index 100% rename from gnovm/tests/files/a7.gno rename to gnovm/tests/files.bak/files/a7.gno diff --git a/gnovm/tests/files/a8.gno b/gnovm/tests/files.bak/files/a8.gno similarity index 100% rename from gnovm/tests/files/a8.gno rename to gnovm/tests/files.bak/files/a8.gno diff --git a/gnovm/tests/files/a9.gno b/gnovm/tests/files.bak/files/a9.gno similarity index 100% rename from gnovm/tests/files/a9.gno rename to gnovm/tests/files.bak/files/a9.gno diff --git a/gnovm/tests/files/access0.gno b/gnovm/tests/files.bak/files/access0.gno similarity index 100% rename from gnovm/tests/files/access0.gno rename to gnovm/tests/files.bak/files/access0.gno diff --git a/gnovm/tests/files/access1.gno b/gnovm/tests/files.bak/files/access1.gno similarity index 100% rename from gnovm/tests/files/access1.gno rename to gnovm/tests/files.bak/files/access1.gno diff --git a/gnovm/tests/files/access2.gno b/gnovm/tests/files.bak/files/access2.gno similarity index 100% rename from gnovm/tests/files/access2.gno rename to gnovm/tests/files.bak/files/access2.gno diff --git a/gnovm/tests/files/access3.gno b/gnovm/tests/files.bak/files/access3.gno similarity index 100% rename from gnovm/tests/files/access3.gno rename to gnovm/tests/files.bak/files/access3.gno diff --git a/gnovm/tests/files/access4.gno b/gnovm/tests/files.bak/files/access4.gno similarity index 100% rename from gnovm/tests/files/access4.gno rename to gnovm/tests/files.bak/files/access4.gno diff --git a/gnovm/tests/files/access5.gno b/gnovm/tests/files.bak/files/access5.gno similarity index 100% rename from gnovm/tests/files/access5.gno rename to gnovm/tests/files.bak/files/access5.gno diff --git a/gnovm/tests/files/access6.gno b/gnovm/tests/files.bak/files/access6.gno similarity index 100% rename from gnovm/tests/files/access6.gno rename to gnovm/tests/files.bak/files/access6.gno diff --git a/gnovm/tests/files/access7.gno b/gnovm/tests/files.bak/files/access7.gno similarity index 100% rename from gnovm/tests/files/access7.gno rename to gnovm/tests/files.bak/files/access7.gno diff --git a/gnovm/tests/files/add0.gno b/gnovm/tests/files.bak/files/add0.gno similarity index 100% rename from gnovm/tests/files/add0.gno rename to gnovm/tests/files.bak/files/add0.gno diff --git a/gnovm/tests/files/add1.gno b/gnovm/tests/files.bak/files/add1.gno similarity index 100% rename from gnovm/tests/files/add1.gno rename to gnovm/tests/files.bak/files/add1.gno diff --git a/gnovm/tests/files/add2.gno b/gnovm/tests/files.bak/files/add2.gno similarity index 100% rename from gnovm/tests/files/add2.gno rename to gnovm/tests/files.bak/files/add2.gno diff --git a/gnovm/tests/files/addr0b_native.gno b/gnovm/tests/files.bak/files/addr0b_native.gno similarity index 100% rename from gnovm/tests/files/addr0b_native.gno rename to gnovm/tests/files.bak/files/addr0b_native.gno diff --git a/gnovm/tests/files/addr0b_stdlibs.gno b/gnovm/tests/files.bak/files/addr0b_stdlibs.gno similarity index 100% rename from gnovm/tests/files/addr0b_stdlibs.gno rename to gnovm/tests/files.bak/files/addr0b_stdlibs.gno diff --git a/gnovm/tests/files/addr1.gno b/gnovm/tests/files.bak/files/addr1.gno similarity index 100% rename from gnovm/tests/files/addr1.gno rename to gnovm/tests/files.bak/files/addr1.gno diff --git a/gnovm/tests/files/addr2b.gno b/gnovm/tests/files.bak/files/addr2b.gno similarity index 100% rename from gnovm/tests/files/addr2b.gno rename to gnovm/tests/files.bak/files/addr2b.gno diff --git a/gnovm/tests/files/alias0.gno b/gnovm/tests/files.bak/files/alias0.gno similarity index 100% rename from gnovm/tests/files/alias0.gno rename to gnovm/tests/files.bak/files/alias0.gno diff --git a/gnovm/tests/files/alias1.gno b/gnovm/tests/files.bak/files/alias1.gno similarity index 100% rename from gnovm/tests/files/alias1.gno rename to gnovm/tests/files.bak/files/alias1.gno diff --git a/gnovm/tests/files/and.gno b/gnovm/tests/files.bak/files/and.gno similarity index 100% rename from gnovm/tests/files/and.gno rename to gnovm/tests/files.bak/files/and.gno diff --git a/gnovm/tests/files/and0.gno b/gnovm/tests/files.bak/files/and0.gno similarity index 100% rename from gnovm/tests/files/and0.gno rename to gnovm/tests/files.bak/files/and0.gno diff --git a/gnovm/tests/files/and1.gno b/gnovm/tests/files.bak/files/and1.gno similarity index 100% rename from gnovm/tests/files/and1.gno rename to gnovm/tests/files.bak/files/and1.gno diff --git a/gnovm/tests/files/and2.gno b/gnovm/tests/files.bak/files/and2.gno similarity index 100% rename from gnovm/tests/files/and2.gno rename to gnovm/tests/files.bak/files/and2.gno diff --git a/gnovm/tests/files/and3.gno b/gnovm/tests/files.bak/files/and3.gno similarity index 100% rename from gnovm/tests/files/and3.gno rename to gnovm/tests/files.bak/files/and3.gno diff --git a/gnovm/tests/files/append0.gno b/gnovm/tests/files.bak/files/append0.gno similarity index 100% rename from gnovm/tests/files/append0.gno rename to gnovm/tests/files.bak/files/append0.gno diff --git a/gnovm/tests/files/append1.gno b/gnovm/tests/files.bak/files/append1.gno similarity index 100% rename from gnovm/tests/files/append1.gno rename to gnovm/tests/files.bak/files/append1.gno diff --git a/gnovm/tests/files/append2.gno b/gnovm/tests/files.bak/files/append2.gno similarity index 100% rename from gnovm/tests/files/append2.gno rename to gnovm/tests/files.bak/files/append2.gno diff --git a/gnovm/tests/files/append3.gno b/gnovm/tests/files.bak/files/append3.gno similarity index 100% rename from gnovm/tests/files/append3.gno rename to gnovm/tests/files.bak/files/append3.gno diff --git a/gnovm/tests/files/append4.gno b/gnovm/tests/files.bak/files/append4.gno similarity index 100% rename from gnovm/tests/files/append4.gno rename to gnovm/tests/files.bak/files/append4.gno diff --git a/gnovm/tests/files/append5.gno b/gnovm/tests/files.bak/files/append5.gno similarity index 100% rename from gnovm/tests/files/append5.gno rename to gnovm/tests/files.bak/files/append5.gno diff --git a/gnovm/tests/files/array0.gno b/gnovm/tests/files.bak/files/array0.gno similarity index 100% rename from gnovm/tests/files/array0.gno rename to gnovm/tests/files.bak/files/array0.gno diff --git a/gnovm/tests/files/array1.gno b/gnovm/tests/files.bak/files/array1.gno similarity index 100% rename from gnovm/tests/files/array1.gno rename to gnovm/tests/files.bak/files/array1.gno diff --git a/gnovm/tests/files/array2.gno b/gnovm/tests/files.bak/files/array2.gno similarity index 100% rename from gnovm/tests/files/array2.gno rename to gnovm/tests/files.bak/files/array2.gno diff --git a/gnovm/tests/files/array3.gno b/gnovm/tests/files.bak/files/array3.gno similarity index 100% rename from gnovm/tests/files/array3.gno rename to gnovm/tests/files.bak/files/array3.gno diff --git a/gnovm/tests/files/array4.gno b/gnovm/tests/files.bak/files/array4.gno similarity index 100% rename from gnovm/tests/files/array4.gno rename to gnovm/tests/files.bak/files/array4.gno diff --git a/gnovm/tests/files/array5.gno b/gnovm/tests/files.bak/files/array5.gno similarity index 100% rename from gnovm/tests/files/array5.gno rename to gnovm/tests/files.bak/files/array5.gno diff --git a/gnovm/tests/files/assign.gno b/gnovm/tests/files.bak/files/assign.gno similarity index 100% rename from gnovm/tests/files/assign.gno rename to gnovm/tests/files.bak/files/assign.gno diff --git a/gnovm/tests/files/assign0b_native.gno b/gnovm/tests/files.bak/files/assign0b_native.gno similarity index 100% rename from gnovm/tests/files/assign0b_native.gno rename to gnovm/tests/files.bak/files/assign0b_native.gno diff --git a/gnovm/tests/files/assign0b_stdlibs.gno b/gnovm/tests/files.bak/files/assign0b_stdlibs.gno similarity index 100% rename from gnovm/tests/files/assign0b_stdlibs.gno rename to gnovm/tests/files.bak/files/assign0b_stdlibs.gno diff --git a/gnovm/tests/files/assign1.gno b/gnovm/tests/files.bak/files/assign1.gno similarity index 100% rename from gnovm/tests/files/assign1.gno rename to gnovm/tests/files.bak/files/assign1.gno diff --git a/gnovm/tests/files/assign10.gno b/gnovm/tests/files.bak/files/assign10.gno similarity index 100% rename from gnovm/tests/files/assign10.gno rename to gnovm/tests/files.bak/files/assign10.gno diff --git a/gnovm/tests/files/assign11.gno b/gnovm/tests/files.bak/files/assign11.gno similarity index 100% rename from gnovm/tests/files/assign11.gno rename to gnovm/tests/files.bak/files/assign11.gno diff --git a/gnovm/tests/files/assign12.gno b/gnovm/tests/files.bak/files/assign12.gno similarity index 100% rename from gnovm/tests/files/assign12.gno rename to gnovm/tests/files.bak/files/assign12.gno diff --git a/gnovm/tests/files/assign16.gno b/gnovm/tests/files.bak/files/assign16.gno similarity index 100% rename from gnovm/tests/files/assign16.gno rename to gnovm/tests/files.bak/files/assign16.gno diff --git a/gnovm/tests/files/assign2.gno b/gnovm/tests/files.bak/files/assign2.gno similarity index 100% rename from gnovm/tests/files/assign2.gno rename to gnovm/tests/files.bak/files/assign2.gno diff --git a/gnovm/tests/files/assign20.gno b/gnovm/tests/files.bak/files/assign20.gno similarity index 100% rename from gnovm/tests/files/assign20.gno rename to gnovm/tests/files.bak/files/assign20.gno diff --git a/gnovm/tests/files/assign21.gno b/gnovm/tests/files.bak/files/assign21.gno similarity index 100% rename from gnovm/tests/files/assign21.gno rename to gnovm/tests/files.bak/files/assign21.gno diff --git a/gnovm/tests/files/assign3.gno b/gnovm/tests/files.bak/files/assign3.gno similarity index 100% rename from gnovm/tests/files/assign3.gno rename to gnovm/tests/files.bak/files/assign3.gno diff --git a/gnovm/tests/files/assign4.gno b/gnovm/tests/files.bak/files/assign4.gno similarity index 100% rename from gnovm/tests/files/assign4.gno rename to gnovm/tests/files.bak/files/assign4.gno diff --git a/gnovm/tests/files/assign5.gno b/gnovm/tests/files.bak/files/assign5.gno similarity index 100% rename from gnovm/tests/files/assign5.gno rename to gnovm/tests/files.bak/files/assign5.gno diff --git a/gnovm/tests/files/assign8.gno b/gnovm/tests/files.bak/files/assign8.gno similarity index 100% rename from gnovm/tests/files/assign8.gno rename to gnovm/tests/files.bak/files/assign8.gno diff --git a/gnovm/tests/files/assign9.gno b/gnovm/tests/files.bak/files/assign9.gno similarity index 100% rename from gnovm/tests/files/assign9.gno rename to gnovm/tests/files.bak/files/assign9.gno diff --git a/gnovm/tests/files/avl0.gno b/gnovm/tests/files.bak/files/avl0.gno similarity index 100% rename from gnovm/tests/files/avl0.gno rename to gnovm/tests/files.bak/files/avl0.gno diff --git a/gnovm/tests/files/avl1.gno b/gnovm/tests/files.bak/files/avl1.gno similarity index 100% rename from gnovm/tests/files/avl1.gno rename to gnovm/tests/files.bak/files/avl1.gno diff --git a/gnovm/tests/files/bin.gno b/gnovm/tests/files.bak/files/bin.gno similarity index 100% rename from gnovm/tests/files/bin.gno rename to gnovm/tests/files.bak/files/bin.gno diff --git a/gnovm/tests/files/bin0.gno b/gnovm/tests/files.bak/files/bin0.gno similarity index 100% rename from gnovm/tests/files/bin0.gno rename to gnovm/tests/files.bak/files/bin0.gno diff --git a/gnovm/tests/files/bin1.gno b/gnovm/tests/files.bak/files/bin1.gno similarity index 100% rename from gnovm/tests/files/bin1.gno rename to gnovm/tests/files.bak/files/bin1.gno diff --git a/gnovm/tests/files/bin3.gno b/gnovm/tests/files.bak/files/bin3.gno similarity index 100% rename from gnovm/tests/files/bin3.gno rename to gnovm/tests/files.bak/files/bin3.gno diff --git a/gnovm/tests/files/bin4.gno b/gnovm/tests/files.bak/files/bin4.gno similarity index 100% rename from gnovm/tests/files/bin4.gno rename to gnovm/tests/files.bak/files/bin4.gno diff --git a/gnovm/tests/files/bin5.gno b/gnovm/tests/files.bak/files/bin5.gno similarity index 100% rename from gnovm/tests/files/bin5.gno rename to gnovm/tests/files.bak/files/bin5.gno diff --git a/gnovm/tests/files/binstruct_ptr_map0.gno b/gnovm/tests/files.bak/files/binstruct_ptr_map0.gno similarity index 100% rename from gnovm/tests/files/binstruct_ptr_map0.gno rename to gnovm/tests/files.bak/files/binstruct_ptr_map0.gno diff --git a/gnovm/tests/files/binstruct_ptr_slice0.gno b/gnovm/tests/files.bak/files/binstruct_ptr_slice0.gno similarity index 100% rename from gnovm/tests/files/binstruct_ptr_slice0.gno rename to gnovm/tests/files.bak/files/binstruct_ptr_slice0.gno diff --git a/gnovm/tests/files/binstruct_slice0.gno b/gnovm/tests/files.bak/files/binstruct_slice0.gno similarity index 100% rename from gnovm/tests/files/binstruct_slice0.gno rename to gnovm/tests/files.bak/files/binstruct_slice0.gno diff --git a/gnovm/tests/files/bltn.gno b/gnovm/tests/files.bak/files/bltn.gno similarity index 100% rename from gnovm/tests/files/bltn.gno rename to gnovm/tests/files.bak/files/bltn.gno diff --git a/gnovm/tests/files/bltn0.gno b/gnovm/tests/files.bak/files/bltn0.gno similarity index 100% rename from gnovm/tests/files/bltn0.gno rename to gnovm/tests/files.bak/files/bltn0.gno diff --git a/gnovm/tests/files/bool.gno b/gnovm/tests/files.bak/files/bool.gno similarity index 100% rename from gnovm/tests/files/bool.gno rename to gnovm/tests/files.bak/files/bool.gno diff --git a/gnovm/tests/files/bool0.gno b/gnovm/tests/files.bak/files/bool0.gno similarity index 100% rename from gnovm/tests/files/bool0.gno rename to gnovm/tests/files.bak/files/bool0.gno diff --git a/gnovm/tests/files/bool1.gno b/gnovm/tests/files.bak/files/bool1.gno similarity index 100% rename from gnovm/tests/files/bool1.gno rename to gnovm/tests/files.bak/files/bool1.gno diff --git a/gnovm/tests/files/bool2.gno b/gnovm/tests/files.bak/files/bool2.gno similarity index 100% rename from gnovm/tests/files/bool2.gno rename to gnovm/tests/files.bak/files/bool2.gno diff --git a/gnovm/tests/files/bool3.gno b/gnovm/tests/files.bak/files/bool3.gno similarity index 100% rename from gnovm/tests/files/bool3.gno rename to gnovm/tests/files.bak/files/bool3.gno diff --git a/gnovm/tests/files/bool4.gno b/gnovm/tests/files.bak/files/bool4.gno similarity index 100% rename from gnovm/tests/files/bool4.gno rename to gnovm/tests/files.bak/files/bool4.gno diff --git a/gnovm/tests/files/bool5.gno b/gnovm/tests/files.bak/files/bool5.gno similarity index 100% rename from gnovm/tests/files/bool5.gno rename to gnovm/tests/files.bak/files/bool5.gno diff --git a/gnovm/tests/files/build0.gno b/gnovm/tests/files.bak/files/build0.gno similarity index 100% rename from gnovm/tests/files/build0.gno rename to gnovm/tests/files.bak/files/build0.gno diff --git a/gnovm/tests/files/cap0.gno b/gnovm/tests/files.bak/files/cap0.gno similarity index 100% rename from gnovm/tests/files/cap0.gno rename to gnovm/tests/files.bak/files/cap0.gno diff --git a/gnovm/tests/files/closure0.gno b/gnovm/tests/files.bak/files/closure0.gno similarity index 100% rename from gnovm/tests/files/closure0.gno rename to gnovm/tests/files.bak/files/closure0.gno diff --git a/gnovm/tests/files/closure1.gno b/gnovm/tests/files.bak/files/closure1.gno similarity index 100% rename from gnovm/tests/files/closure1.gno rename to gnovm/tests/files.bak/files/closure1.gno diff --git a/gnovm/tests/files/closure2.gno b/gnovm/tests/files.bak/files/closure2.gno similarity index 100% rename from gnovm/tests/files/closure2.gno rename to gnovm/tests/files.bak/files/closure2.gno diff --git a/gnovm/tests/files/closure3.gno b/gnovm/tests/files.bak/files/closure3.gno similarity index 100% rename from gnovm/tests/files/closure3.gno rename to gnovm/tests/files.bak/files/closure3.gno diff --git a/gnovm/tests/files/closure4.gno b/gnovm/tests/files.bak/files/closure4.gno similarity index 100% rename from gnovm/tests/files/closure4.gno rename to gnovm/tests/files.bak/files/closure4.gno diff --git a/gnovm/tests/files/closure5.gno b/gnovm/tests/files.bak/files/closure5.gno similarity index 100% rename from gnovm/tests/files/closure5.gno rename to gnovm/tests/files.bak/files/closure5.gno diff --git a/gnovm/tests/files/closure6.gno b/gnovm/tests/files.bak/files/closure6.gno similarity index 100% rename from gnovm/tests/files/closure6.gno rename to gnovm/tests/files.bak/files/closure6.gno diff --git a/gnovm/tests/files/closure7.gno b/gnovm/tests/files.bak/files/closure7.gno similarity index 100% rename from gnovm/tests/files/closure7.gno rename to gnovm/tests/files.bak/files/closure7.gno diff --git a/gnovm/tests/files/closure8.gno b/gnovm/tests/files.bak/files/closure8.gno similarity index 100% rename from gnovm/tests/files/closure8.gno rename to gnovm/tests/files.bak/files/closure8.gno diff --git a/gnovm/tests/files/comp1.gno b/gnovm/tests/files.bak/files/comp1.gno similarity index 100% rename from gnovm/tests/files/comp1.gno rename to gnovm/tests/files.bak/files/comp1.gno diff --git a/gnovm/tests/files/comp2.gno b/gnovm/tests/files.bak/files/comp2.gno similarity index 100% rename from gnovm/tests/files/comp2.gno rename to gnovm/tests/files.bak/files/comp2.gno diff --git a/gnovm/tests/files/comp3.gno b/gnovm/tests/files.bak/files/comp3.gno similarity index 100% rename from gnovm/tests/files/comp3.gno rename to gnovm/tests/files.bak/files/comp3.gno diff --git a/gnovm/tests/files/composite0.gno b/gnovm/tests/files.bak/files/composite0.gno similarity index 100% rename from gnovm/tests/files/composite0.gno rename to gnovm/tests/files.bak/files/composite0.gno diff --git a/gnovm/tests/files/composite1.gno b/gnovm/tests/files.bak/files/composite1.gno similarity index 100% rename from gnovm/tests/files/composite1.gno rename to gnovm/tests/files.bak/files/composite1.gno diff --git a/gnovm/tests/files/composite10.gno b/gnovm/tests/files.bak/files/composite10.gno similarity index 100% rename from gnovm/tests/files/composite10.gno rename to gnovm/tests/files.bak/files/composite10.gno diff --git a/gnovm/tests/files/composite11.gno b/gnovm/tests/files.bak/files/composite11.gno similarity index 100% rename from gnovm/tests/files/composite11.gno rename to gnovm/tests/files.bak/files/composite11.gno diff --git a/gnovm/tests/files/composite12.gno b/gnovm/tests/files.bak/files/composite12.gno similarity index 100% rename from gnovm/tests/files/composite12.gno rename to gnovm/tests/files.bak/files/composite12.gno diff --git a/gnovm/tests/files/composite13.gno b/gnovm/tests/files.bak/files/composite13.gno similarity index 100% rename from gnovm/tests/files/composite13.gno rename to gnovm/tests/files.bak/files/composite13.gno diff --git a/gnovm/tests/files/composite14.gno b/gnovm/tests/files.bak/files/composite14.gno similarity index 100% rename from gnovm/tests/files/composite14.gno rename to gnovm/tests/files.bak/files/composite14.gno diff --git a/gnovm/tests/files/composite15.gno b/gnovm/tests/files.bak/files/composite15.gno similarity index 100% rename from gnovm/tests/files/composite15.gno rename to gnovm/tests/files.bak/files/composite15.gno diff --git a/gnovm/tests/files/composite16.gno b/gnovm/tests/files.bak/files/composite16.gno similarity index 100% rename from gnovm/tests/files/composite16.gno rename to gnovm/tests/files.bak/files/composite16.gno diff --git a/gnovm/tests/files/composite17.gno b/gnovm/tests/files.bak/files/composite17.gno similarity index 100% rename from gnovm/tests/files/composite17.gno rename to gnovm/tests/files.bak/files/composite17.gno diff --git a/gnovm/tests/files/composite2.gno b/gnovm/tests/files.bak/files/composite2.gno similarity index 100% rename from gnovm/tests/files/composite2.gno rename to gnovm/tests/files.bak/files/composite2.gno diff --git a/gnovm/tests/files/composite3.gno b/gnovm/tests/files.bak/files/composite3.gno similarity index 100% rename from gnovm/tests/files/composite3.gno rename to gnovm/tests/files.bak/files/composite3.gno diff --git a/gnovm/tests/files/composite4.gno b/gnovm/tests/files.bak/files/composite4.gno similarity index 100% rename from gnovm/tests/files/composite4.gno rename to gnovm/tests/files.bak/files/composite4.gno diff --git a/gnovm/tests/files/composite5.gno b/gnovm/tests/files.bak/files/composite5.gno similarity index 100% rename from gnovm/tests/files/composite5.gno rename to gnovm/tests/files.bak/files/composite5.gno diff --git a/gnovm/tests/files/composite6.gno b/gnovm/tests/files.bak/files/composite6.gno similarity index 100% rename from gnovm/tests/files/composite6.gno rename to gnovm/tests/files.bak/files/composite6.gno diff --git a/gnovm/tests/files/composite7.gno b/gnovm/tests/files.bak/files/composite7.gno similarity index 100% rename from gnovm/tests/files/composite7.gno rename to gnovm/tests/files.bak/files/composite7.gno diff --git a/gnovm/tests/files/composite8.gno b/gnovm/tests/files.bak/files/composite8.gno similarity index 100% rename from gnovm/tests/files/composite8.gno rename to gnovm/tests/files.bak/files/composite8.gno diff --git a/gnovm/tests/files/composite8bis.gno b/gnovm/tests/files.bak/files/composite8bis.gno similarity index 100% rename from gnovm/tests/files/composite8bis.gno rename to gnovm/tests/files.bak/files/composite8bis.gno diff --git a/gnovm/tests/files/composite9.gno b/gnovm/tests/files.bak/files/composite9.gno similarity index 100% rename from gnovm/tests/files/composite9.gno rename to gnovm/tests/files.bak/files/composite9.gno diff --git a/gnovm/tests/files/const0.gno b/gnovm/tests/files.bak/files/const0.gno similarity index 100% rename from gnovm/tests/files/const0.gno rename to gnovm/tests/files.bak/files/const0.gno diff --git a/gnovm/tests/files/const1.gno b/gnovm/tests/files.bak/files/const1.gno similarity index 100% rename from gnovm/tests/files/const1.gno rename to gnovm/tests/files.bak/files/const1.gno diff --git a/gnovm/tests/files/const10.gno b/gnovm/tests/files.bak/files/const10.gno similarity index 100% rename from gnovm/tests/files/const10.gno rename to gnovm/tests/files.bak/files/const10.gno diff --git a/gnovm/tests/files/const11.gno b/gnovm/tests/files.bak/files/const11.gno similarity index 100% rename from gnovm/tests/files/const11.gno rename to gnovm/tests/files.bak/files/const11.gno diff --git a/gnovm/tests/files/const12.gno b/gnovm/tests/files.bak/files/const12.gno similarity index 100% rename from gnovm/tests/files/const12.gno rename to gnovm/tests/files.bak/files/const12.gno diff --git a/gnovm/tests/files/const13.gno b/gnovm/tests/files.bak/files/const13.gno similarity index 100% rename from gnovm/tests/files/const13.gno rename to gnovm/tests/files.bak/files/const13.gno diff --git a/gnovm/tests/files/const14.gno b/gnovm/tests/files.bak/files/const14.gno similarity index 100% rename from gnovm/tests/files/const14.gno rename to gnovm/tests/files.bak/files/const14.gno diff --git a/gnovm/tests/files/const15.gno b/gnovm/tests/files.bak/files/const15.gno similarity index 100% rename from gnovm/tests/files/const15.gno rename to gnovm/tests/files.bak/files/const15.gno diff --git a/gnovm/tests/files/const16.gno b/gnovm/tests/files.bak/files/const16.gno similarity index 100% rename from gnovm/tests/files/const16.gno rename to gnovm/tests/files.bak/files/const16.gno diff --git a/gnovm/tests/files/const17.gno b/gnovm/tests/files.bak/files/const17.gno similarity index 100% rename from gnovm/tests/files/const17.gno rename to gnovm/tests/files.bak/files/const17.gno diff --git a/gnovm/tests/files/const18.gno b/gnovm/tests/files.bak/files/const18.gno similarity index 100% rename from gnovm/tests/files/const18.gno rename to gnovm/tests/files.bak/files/const18.gno diff --git a/gnovm/tests/files/const19.gno b/gnovm/tests/files.bak/files/const19.gno similarity index 100% rename from gnovm/tests/files/const19.gno rename to gnovm/tests/files.bak/files/const19.gno diff --git a/gnovm/tests/files/const2.gno b/gnovm/tests/files.bak/files/const2.gno similarity index 100% rename from gnovm/tests/files/const2.gno rename to gnovm/tests/files.bak/files/const2.gno diff --git a/gnovm/tests/files/const20.gno b/gnovm/tests/files.bak/files/const20.gno similarity index 100% rename from gnovm/tests/files/const20.gno rename to gnovm/tests/files.bak/files/const20.gno diff --git a/gnovm/tests/files/const21.gno b/gnovm/tests/files.bak/files/const21.gno similarity index 100% rename from gnovm/tests/files/const21.gno rename to gnovm/tests/files.bak/files/const21.gno diff --git a/gnovm/tests/files/const22.gno b/gnovm/tests/files.bak/files/const22.gno similarity index 100% rename from gnovm/tests/files/const22.gno rename to gnovm/tests/files.bak/files/const22.gno diff --git a/gnovm/tests/files/const3.gno b/gnovm/tests/files.bak/files/const3.gno similarity index 100% rename from gnovm/tests/files/const3.gno rename to gnovm/tests/files.bak/files/const3.gno diff --git a/gnovm/tests/files/const4.gno b/gnovm/tests/files.bak/files/const4.gno similarity index 100% rename from gnovm/tests/files/const4.gno rename to gnovm/tests/files.bak/files/const4.gno diff --git a/gnovm/tests/files/const5.gno b/gnovm/tests/files.bak/files/const5.gno similarity index 100% rename from gnovm/tests/files/const5.gno rename to gnovm/tests/files.bak/files/const5.gno diff --git a/gnovm/tests/files/const6.gno b/gnovm/tests/files.bak/files/const6.gno similarity index 100% rename from gnovm/tests/files/const6.gno rename to gnovm/tests/files.bak/files/const6.gno diff --git a/gnovm/tests/files/const7.gno b/gnovm/tests/files.bak/files/const7.gno similarity index 100% rename from gnovm/tests/files/const7.gno rename to gnovm/tests/files.bak/files/const7.gno diff --git a/gnovm/tests/files/const8.gno b/gnovm/tests/files.bak/files/const8.gno similarity index 100% rename from gnovm/tests/files/const8.gno rename to gnovm/tests/files.bak/files/const8.gno diff --git a/gnovm/tests/files/const9.gno b/gnovm/tests/files.bak/files/const9.gno similarity index 100% rename from gnovm/tests/files/const9.gno rename to gnovm/tests/files.bak/files/const9.gno diff --git a/gnovm/tests/files/cont.gno b/gnovm/tests/files.bak/files/cont.gno similarity index 100% rename from gnovm/tests/files/cont.gno rename to gnovm/tests/files.bak/files/cont.gno diff --git a/gnovm/tests/files/cont0.gno b/gnovm/tests/files.bak/files/cont0.gno similarity index 100% rename from gnovm/tests/files/cont0.gno rename to gnovm/tests/files.bak/files/cont0.gno diff --git a/gnovm/tests/files/cont1.gno b/gnovm/tests/files.bak/files/cont1.gno similarity index 100% rename from gnovm/tests/files/cont1.gno rename to gnovm/tests/files.bak/files/cont1.gno diff --git a/gnovm/tests/files/context.gno b/gnovm/tests/files.bak/files/context.gno similarity index 100% rename from gnovm/tests/files/context.gno rename to gnovm/tests/files.bak/files/context.gno diff --git a/gnovm/tests/files/context2.gno b/gnovm/tests/files.bak/files/context2.gno similarity index 100% rename from gnovm/tests/files/context2.gno rename to gnovm/tests/files.bak/files/context2.gno diff --git a/gnovm/tests/files/convert0.gno b/gnovm/tests/files.bak/files/convert0.gno similarity index 100% rename from gnovm/tests/files/convert0.gno rename to gnovm/tests/files.bak/files/convert0.gno diff --git a/gnovm/tests/files/convert1.gno b/gnovm/tests/files.bak/files/convert1.gno similarity index 100% rename from gnovm/tests/files/convert1.gno rename to gnovm/tests/files.bak/files/convert1.gno diff --git a/gnovm/tests/files/convert3.gno b/gnovm/tests/files.bak/files/convert3.gno similarity index 100% rename from gnovm/tests/files/convert3.gno rename to gnovm/tests/files.bak/files/convert3.gno diff --git a/gnovm/tests/files/copy0.gno b/gnovm/tests/files.bak/files/copy0.gno similarity index 100% rename from gnovm/tests/files/copy0.gno rename to gnovm/tests/files.bak/files/copy0.gno diff --git a/gnovm/tests/files/copy1.gno b/gnovm/tests/files.bak/files/copy1.gno similarity index 100% rename from gnovm/tests/files/copy1.gno rename to gnovm/tests/files.bak/files/copy1.gno diff --git a/gnovm/tests/files/copy2.gno b/gnovm/tests/files.bak/files/copy2.gno similarity index 100% rename from gnovm/tests/files/copy2.gno rename to gnovm/tests/files.bak/files/copy2.gno diff --git a/gnovm/tests/files/defer0.gno b/gnovm/tests/files.bak/files/defer0.gno similarity index 100% rename from gnovm/tests/files/defer0.gno rename to gnovm/tests/files.bak/files/defer0.gno diff --git a/gnovm/tests/files/defer1.gno b/gnovm/tests/files.bak/files/defer1.gno similarity index 100% rename from gnovm/tests/files/defer1.gno rename to gnovm/tests/files.bak/files/defer1.gno diff --git a/gnovm/tests/files/defer2.gno b/gnovm/tests/files.bak/files/defer2.gno similarity index 100% rename from gnovm/tests/files/defer2.gno rename to gnovm/tests/files.bak/files/defer2.gno diff --git a/gnovm/tests/files/defer3.gno b/gnovm/tests/files.bak/files/defer3.gno similarity index 100% rename from gnovm/tests/files/defer3.gno rename to gnovm/tests/files.bak/files/defer3.gno diff --git a/gnovm/tests/files/defer4.gno b/gnovm/tests/files.bak/files/defer4.gno similarity index 100% rename from gnovm/tests/files/defer4.gno rename to gnovm/tests/files.bak/files/defer4.gno diff --git a/gnovm/tests/files/defer5.gno b/gnovm/tests/files.bak/files/defer5.gno similarity index 100% rename from gnovm/tests/files/defer5.gno rename to gnovm/tests/files.bak/files/defer5.gno diff --git a/gnovm/tests/files/defer6.gno b/gnovm/tests/files.bak/files/defer6.gno similarity index 100% rename from gnovm/tests/files/defer6.gno rename to gnovm/tests/files.bak/files/defer6.gno diff --git a/gnovm/tests/files/defer7.gno b/gnovm/tests/files.bak/files/defer7.gno similarity index 100% rename from gnovm/tests/files/defer7.gno rename to gnovm/tests/files.bak/files/defer7.gno diff --git a/gnovm/tests/files/defer8.gno b/gnovm/tests/files.bak/files/defer8.gno similarity index 100% rename from gnovm/tests/files/defer8.gno rename to gnovm/tests/files.bak/files/defer8.gno diff --git a/gnovm/tests/files/defer9.gno b/gnovm/tests/files.bak/files/defer9.gno similarity index 100% rename from gnovm/tests/files/defer9.gno rename to gnovm/tests/files.bak/files/defer9.gno diff --git a/gnovm/tests/files/define0.gno b/gnovm/tests/files.bak/files/define0.gno similarity index 100% rename from gnovm/tests/files/define0.gno rename to gnovm/tests/files.bak/files/define0.gno diff --git a/gnovm/tests/files/define1.gno b/gnovm/tests/files.bak/files/define1.gno similarity index 100% rename from gnovm/tests/files/define1.gno rename to gnovm/tests/files.bak/files/define1.gno diff --git a/gnovm/tests/files/define2.gno b/gnovm/tests/files.bak/files/define2.gno similarity index 100% rename from gnovm/tests/files/define2.gno rename to gnovm/tests/files.bak/files/define2.gno diff --git a/gnovm/tests/files/define3.gno b/gnovm/tests/files.bak/files/define3.gno similarity index 100% rename from gnovm/tests/files/define3.gno rename to gnovm/tests/files.bak/files/define3.gno diff --git a/gnovm/tests/files/define4.gno b/gnovm/tests/files.bak/files/define4.gno similarity index 100% rename from gnovm/tests/files/define4.gno rename to gnovm/tests/files.bak/files/define4.gno diff --git a/gnovm/tests/files/delete0.gno b/gnovm/tests/files.bak/files/delete0.gno similarity index 100% rename from gnovm/tests/files/delete0.gno rename to gnovm/tests/files.bak/files/delete0.gno diff --git a/gnovm/tests/files/errors.gno b/gnovm/tests/files.bak/files/errors.gno similarity index 100% rename from gnovm/tests/files/errors.gno rename to gnovm/tests/files.bak/files/errors.gno diff --git a/gnovm/tests/files/extern/b1/foo/foo.gno b/gnovm/tests/files.bak/files/extern/b1/foo/foo.gno similarity index 100% rename from gnovm/tests/files/extern/b1/foo/foo.gno rename to gnovm/tests/files.bak/files/extern/b1/foo/foo.gno diff --git a/gnovm/tests/files/extern/b2/foo/foo.gno b/gnovm/tests/files.bak/files/extern/b2/foo/foo.gno similarity index 100% rename from gnovm/tests/files/extern/b2/foo/foo.gno rename to gnovm/tests/files.bak/files/extern/b2/foo/foo.gno diff --git a/gnovm/tests/files/extern/bar/quux.gno b/gnovm/tests/files.bak/files/extern/bar/quux.gno similarity index 100% rename from gnovm/tests/files/extern/bar/quux.gno rename to gnovm/tests/files.bak/files/extern/bar/quux.gno diff --git a/gnovm/tests/files/extern/baz-bat/baz-bat.gno b/gnovm/tests/files.bak/files/extern/baz-bat/baz-bat.gno similarity index 100% rename from gnovm/tests/files/extern/baz-bat/baz-bat.gno rename to gnovm/tests/files.bak/files/extern/baz-bat/baz-bat.gno diff --git a/gnovm/tests/files/extern/baz/quux.gno b/gnovm/tests/files.bak/files/extern/baz/quux.gno similarity index 100% rename from gnovm/tests/files/extern/baz/quux.gno rename to gnovm/tests/files.bak/files/extern/baz/quux.gno diff --git a/gnovm/tests/files/extern/c1/c1.gno b/gnovm/tests/files.bak/files/extern/c1/c1.gno similarity index 100% rename from gnovm/tests/files/extern/c1/c1.gno rename to gnovm/tests/files.bak/files/extern/c1/c1.gno diff --git a/gnovm/tests/files/extern/c2/c2.gno b/gnovm/tests/files.bak/files/extern/c2/c2.gno similarity index 100% rename from gnovm/tests/files/extern/c2/c2.gno rename to gnovm/tests/files.bak/files/extern/c2/c2.gno diff --git a/gnovm/tests/files/extern/context/context.gno b/gnovm/tests/files.bak/files/extern/context/context.gno similarity index 100% rename from gnovm/tests/files/extern/context/context.gno rename to gnovm/tests/files.bak/files/extern/context/context.gno diff --git a/gnovm/tests/files/extern/ct/ct1.gno b/gnovm/tests/files.bak/files/extern/ct/ct1.gno similarity index 100% rename from gnovm/tests/files/extern/ct/ct1.gno rename to gnovm/tests/files.bak/files/extern/ct/ct1.gno diff --git a/gnovm/tests/files/extern/ct/ct2.gno b/gnovm/tests/files.bak/files/extern/ct/ct2.gno similarity index 100% rename from gnovm/tests/files/extern/ct/ct2.gno rename to gnovm/tests/files.bak/files/extern/ct/ct2.gno diff --git a/gnovm/tests/files/extern/ct/ct3.gno b/gnovm/tests/files.bak/files/extern/ct/ct3.gno similarity index 100% rename from gnovm/tests/files/extern/ct/ct3.gno rename to gnovm/tests/files.bak/files/extern/ct/ct3.gno diff --git a/gnovm/tests/files/extern/ct1/ct1.gno b/gnovm/tests/files.bak/files/extern/ct1/ct1.gno similarity index 100% rename from gnovm/tests/files/extern/ct1/ct1.gno rename to gnovm/tests/files.bak/files/extern/ct1/ct1.gno diff --git a/gnovm/tests/files/extern/foo-bar/foo-bar.gno b/gnovm/tests/files.bak/files/extern/foo-bar/foo-bar.gno similarity index 100% rename from gnovm/tests/files/extern/foo-bar/foo-bar.gno rename to gnovm/tests/files.bak/files/extern/foo-bar/foo-bar.gno diff --git a/gnovm/tests/files/extern/foo/bar.gno b/gnovm/tests/files.bak/files/extern/foo/bar.gno similarity index 100% rename from gnovm/tests/files/extern/foo/bar.gno rename to gnovm/tests/files.bak/files/extern/foo/bar.gno diff --git a/gnovm/tests/files/extern/foo/bir.gno b/gnovm/tests/files.bak/files/extern/foo/bir.gno similarity index 100% rename from gnovm/tests/files/extern/foo/bir.gno rename to gnovm/tests/files.bak/files/extern/foo/bir.gno diff --git a/gnovm/tests/files/extern/foo/boo/boo.gno b/gnovm/tests/files.bak/files/extern/foo/boo/boo.gno similarity index 100% rename from gnovm/tests/files/extern/foo/boo/boo.gno rename to gnovm/tests/files.bak/files/extern/foo/boo/boo.gno diff --git a/gnovm/tests/files/extern/m1/main.gno b/gnovm/tests/files.bak/files/extern/m1/main.gno similarity index 100% rename from gnovm/tests/files/extern/m1/main.gno rename to gnovm/tests/files.bak/files/extern/m1/main.gno diff --git a/gnovm/tests/files/extern/m1/main_test.gno b/gnovm/tests/files.bak/files/extern/m1/main_test.gno similarity index 100% rename from gnovm/tests/files/extern/m1/main_test.gno rename to gnovm/tests/files.bak/files/extern/m1/main_test.gno diff --git a/gnovm/tests/files/extern/m2/m2_test.gno b/gnovm/tests/files.bak/files/extern/m2/m2_test.gno similarity index 100% rename from gnovm/tests/files/extern/m2/m2_test.gno rename to gnovm/tests/files.bak/files/extern/m2/m2_test.gno diff --git a/gnovm/tests/files/extern/net/http/http.gno b/gnovm/tests/files.bak/files/extern/net/http/http.gno similarity index 100% rename from gnovm/tests/files/extern/net/http/http.gno rename to gnovm/tests/files.bak/files/extern/net/http/http.gno diff --git a/gnovm/tests/files/extern/net/http/httptest/httptest.gno b/gnovm/tests/files.bak/files/extern/net/http/httptest/httptest.gno similarity index 100% rename from gnovm/tests/files/extern/net/http/httptest/httptest.gno rename to gnovm/tests/files.bak/files/extern/net/http/httptest/httptest.gno diff --git a/gnovm/tests/files/extern/net/net.gno b/gnovm/tests/files.bak/files/extern/net/net.gno similarity index 100% rename from gnovm/tests/files/extern/net/net.gno rename to gnovm/tests/files.bak/files/extern/net/net.gno diff --git a/gnovm/tests/files/extern/net/url/url.gno b/gnovm/tests/files.bak/files/extern/net/url/url.gno similarity index 100% rename from gnovm/tests/files/extern/net/url/url.gno rename to gnovm/tests/files.bak/files/extern/net/url/url.gno diff --git a/gnovm/tests/files/extern/p1/s1.gno b/gnovm/tests/files.bak/files/extern/p1/s1.gno similarity index 100% rename from gnovm/tests/files/extern/p1/s1.gno rename to gnovm/tests/files.bak/files/extern/p1/s1.gno diff --git a/gnovm/tests/files/extern/p1/s2.gno b/gnovm/tests/files.bak/files/extern/p1/s2.gno similarity index 100% rename from gnovm/tests/files/extern/p1/s2.gno rename to gnovm/tests/files.bak/files/extern/p1/s2.gno diff --git a/gnovm/tests/files/extern/tata/tutu.gno b/gnovm/tests/files.bak/files/extern/tata/tutu.gno similarity index 100% rename from gnovm/tests/files/extern/tata/tutu.gno rename to gnovm/tests/files.bak/files/extern/tata/tutu.gno diff --git a/gnovm/tests/files/extern/time/time.gno b/gnovm/tests/files.bak/files/extern/time/time.gno similarity index 100% rename from gnovm/tests/files/extern/time/time.gno rename to gnovm/tests/files.bak/files/extern/time/time.gno diff --git a/gnovm/tests/files/extern/timtadh/data-structures/tree/avl/avltree.gno b/gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/avl/avltree.gno similarity index 100% rename from gnovm/tests/files/extern/timtadh/data-structures/tree/avl/avltree.gno rename to gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/avl/avltree.gno diff --git a/gnovm/tests/files/extern/timtadh/data-structures/tree/utils.gno b/gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/utils.gno similarity index 100% rename from gnovm/tests/files/extern/timtadh/data-structures/tree/utils.gno rename to gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/utils.gno diff --git a/gnovm/tests/files/extern/timtadh/data-structures/types/map_entry.gno b/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/map_entry.gno similarity index 100% rename from gnovm/tests/files/extern/timtadh/data-structures/types/map_entry.gno rename to gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/map_entry.gno diff --git a/gnovm/tests/files/extern/timtadh/data-structures/types/string.gno b/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/string.gno similarity index 100% rename from gnovm/tests/files/extern/timtadh/data-structures/types/string.gno rename to gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/string.gno diff --git a/gnovm/tests/files/extern/timtadh/data-structures/types/types.gno b/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/types.gno similarity index 100% rename from gnovm/tests/files/extern/timtadh/data-structures/types/types.gno rename to gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/types.gno diff --git a/gnovm/tests/files/extern/timtadh/data-structures/types/util.gno b/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/util.gno similarity index 100% rename from gnovm/tests/files/extern/timtadh/data-structures/types/util.gno rename to gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/util.gno diff --git a/gnovm/tests/files/extern/toto/titi.gno b/gnovm/tests/files.bak/files/extern/toto/titi.gno similarity index 100% rename from gnovm/tests/files/extern/toto/titi.gno rename to gnovm/tests/files.bak/files/extern/toto/titi.gno diff --git a/gnovm/tests/files/extern/vars/first.gno b/gnovm/tests/files.bak/files/extern/vars/first.gno similarity index 100% rename from gnovm/tests/files/extern/vars/first.gno rename to gnovm/tests/files.bak/files/extern/vars/first.gno diff --git a/gnovm/tests/files/extern/vars/second.gno b/gnovm/tests/files.bak/files/extern/vars/second.gno similarity index 100% rename from gnovm/tests/files/extern/vars/second.gno rename to gnovm/tests/files.bak/files/extern/vars/second.gno diff --git a/gnovm/tests/files/fib0.gno b/gnovm/tests/files.bak/files/fib0.gno similarity index 100% rename from gnovm/tests/files/fib0.gno rename to gnovm/tests/files.bak/files/fib0.gno diff --git a/gnovm/tests/files/float0.gno b/gnovm/tests/files.bak/files/float0.gno similarity index 100% rename from gnovm/tests/files/float0.gno rename to gnovm/tests/files.bak/files/float0.gno diff --git a/gnovm/tests/files/float1.gno b/gnovm/tests/files.bak/files/float1.gno similarity index 100% rename from gnovm/tests/files/float1.gno rename to gnovm/tests/files.bak/files/float1.gno diff --git a/gnovm/tests/files/float2.gno b/gnovm/tests/files.bak/files/float2.gno similarity index 100% rename from gnovm/tests/files/float2.gno rename to gnovm/tests/files.bak/files/float2.gno diff --git a/gnovm/tests/files/float3.gno b/gnovm/tests/files.bak/files/float3.gno similarity index 100% rename from gnovm/tests/files/float3.gno rename to gnovm/tests/files.bak/files/float3.gno diff --git a/gnovm/tests/files/float4.gno b/gnovm/tests/files.bak/files/float4.gno similarity index 100% rename from gnovm/tests/files/float4.gno rename to gnovm/tests/files.bak/files/float4.gno diff --git a/gnovm/tests/files/float5_native.gno b/gnovm/tests/files.bak/files/float5_native.gno similarity index 100% rename from gnovm/tests/files/float5_native.gno rename to gnovm/tests/files.bak/files/float5_native.gno diff --git a/gnovm/tests/files/float5_stdlibs.gno b/gnovm/tests/files.bak/files/float5_stdlibs.gno similarity index 100% rename from gnovm/tests/files/float5_stdlibs.gno rename to gnovm/tests/files.bak/files/float5_stdlibs.gno diff --git a/gnovm/tests/files/float6.gno b/gnovm/tests/files.bak/files/float6.gno similarity index 100% rename from gnovm/tests/files/float6.gno rename to gnovm/tests/files.bak/files/float6.gno diff --git a/gnovm/tests/files/float7.gno b/gnovm/tests/files.bak/files/float7.gno similarity index 100% rename from gnovm/tests/files/float7.gno rename to gnovm/tests/files.bak/files/float7.gno diff --git a/gnovm/tests/files/for0.gno b/gnovm/tests/files.bak/files/for0.gno similarity index 100% rename from gnovm/tests/files/for0.gno rename to gnovm/tests/files.bak/files/for0.gno diff --git a/gnovm/tests/files/for1.gno b/gnovm/tests/files.bak/files/for1.gno similarity index 100% rename from gnovm/tests/files/for1.gno rename to gnovm/tests/files.bak/files/for1.gno diff --git a/gnovm/tests/files/for10.gno b/gnovm/tests/files.bak/files/for10.gno similarity index 100% rename from gnovm/tests/files/for10.gno rename to gnovm/tests/files.bak/files/for10.gno diff --git a/gnovm/tests/files/for11.gno b/gnovm/tests/files.bak/files/for11.gno similarity index 100% rename from gnovm/tests/files/for11.gno rename to gnovm/tests/files.bak/files/for11.gno diff --git a/gnovm/tests/files/for12.gno b/gnovm/tests/files.bak/files/for12.gno similarity index 100% rename from gnovm/tests/files/for12.gno rename to gnovm/tests/files.bak/files/for12.gno diff --git a/gnovm/tests/files/for13.gno b/gnovm/tests/files.bak/files/for13.gno similarity index 100% rename from gnovm/tests/files/for13.gno rename to gnovm/tests/files.bak/files/for13.gno diff --git a/gnovm/tests/files/for14.gno b/gnovm/tests/files.bak/files/for14.gno similarity index 100% rename from gnovm/tests/files/for14.gno rename to gnovm/tests/files.bak/files/for14.gno diff --git a/gnovm/tests/files/for15.gno b/gnovm/tests/files.bak/files/for15.gno similarity index 100% rename from gnovm/tests/files/for15.gno rename to gnovm/tests/files.bak/files/for15.gno diff --git a/gnovm/tests/files/for16.gno b/gnovm/tests/files.bak/files/for16.gno similarity index 100% rename from gnovm/tests/files/for16.gno rename to gnovm/tests/files.bak/files/for16.gno diff --git a/gnovm/tests/files/for17.gno b/gnovm/tests/files.bak/files/for17.gno similarity index 100% rename from gnovm/tests/files/for17.gno rename to gnovm/tests/files.bak/files/for17.gno diff --git a/gnovm/tests/files/for18.gno b/gnovm/tests/files.bak/files/for18.gno similarity index 100% rename from gnovm/tests/files/for18.gno rename to gnovm/tests/files.bak/files/for18.gno diff --git a/gnovm/tests/files/for2.gno b/gnovm/tests/files.bak/files/for2.gno similarity index 100% rename from gnovm/tests/files/for2.gno rename to gnovm/tests/files.bak/files/for2.gno diff --git a/gnovm/tests/files/for3.gno b/gnovm/tests/files.bak/files/for3.gno similarity index 100% rename from gnovm/tests/files/for3.gno rename to gnovm/tests/files.bak/files/for3.gno diff --git a/gnovm/tests/files/for4.gno b/gnovm/tests/files.bak/files/for4.gno similarity index 100% rename from gnovm/tests/files/for4.gno rename to gnovm/tests/files.bak/files/for4.gno diff --git a/gnovm/tests/files/for5.gno b/gnovm/tests/files.bak/files/for5.gno similarity index 100% rename from gnovm/tests/files/for5.gno rename to gnovm/tests/files.bak/files/for5.gno diff --git a/gnovm/tests/files/for6.gno b/gnovm/tests/files.bak/files/for6.gno similarity index 100% rename from gnovm/tests/files/for6.gno rename to gnovm/tests/files.bak/files/for6.gno diff --git a/gnovm/tests/files/for7.gno b/gnovm/tests/files.bak/files/for7.gno similarity index 100% rename from gnovm/tests/files/for7.gno rename to gnovm/tests/files.bak/files/for7.gno diff --git a/gnovm/tests/files/for8.gno b/gnovm/tests/files.bak/files/for8.gno similarity index 100% rename from gnovm/tests/files/for8.gno rename to gnovm/tests/files.bak/files/for8.gno diff --git a/gnovm/tests/files/for9.gno b/gnovm/tests/files.bak/files/for9.gno similarity index 100% rename from gnovm/tests/files/for9.gno rename to gnovm/tests/files.bak/files/for9.gno diff --git a/gnovm/tests/files/fun.gno b/gnovm/tests/files.bak/files/fun.gno similarity index 100% rename from gnovm/tests/files/fun.gno rename to gnovm/tests/files.bak/files/fun.gno diff --git a/gnovm/tests/files/fun10.gno b/gnovm/tests/files.bak/files/fun10.gno similarity index 100% rename from gnovm/tests/files/fun10.gno rename to gnovm/tests/files.bak/files/fun10.gno diff --git a/gnovm/tests/files/fun11.gno b/gnovm/tests/files.bak/files/fun11.gno similarity index 100% rename from gnovm/tests/files/fun11.gno rename to gnovm/tests/files.bak/files/fun11.gno diff --git a/gnovm/tests/files/fun12.gno b/gnovm/tests/files.bak/files/fun12.gno similarity index 100% rename from gnovm/tests/files/fun12.gno rename to gnovm/tests/files.bak/files/fun12.gno diff --git a/gnovm/tests/files/fun13.gno b/gnovm/tests/files.bak/files/fun13.gno similarity index 100% rename from gnovm/tests/files/fun13.gno rename to gnovm/tests/files.bak/files/fun13.gno diff --git a/gnovm/tests/files/fun14.gno b/gnovm/tests/files.bak/files/fun14.gno similarity index 100% rename from gnovm/tests/files/fun14.gno rename to gnovm/tests/files.bak/files/fun14.gno diff --git a/gnovm/tests/files/fun15.gno b/gnovm/tests/files.bak/files/fun15.gno similarity index 100% rename from gnovm/tests/files/fun15.gno rename to gnovm/tests/files.bak/files/fun15.gno diff --git a/gnovm/tests/files/fun16.gno b/gnovm/tests/files.bak/files/fun16.gno similarity index 100% rename from gnovm/tests/files/fun16.gno rename to gnovm/tests/files.bak/files/fun16.gno diff --git a/gnovm/tests/files/fun17.gno b/gnovm/tests/files.bak/files/fun17.gno similarity index 100% rename from gnovm/tests/files/fun17.gno rename to gnovm/tests/files.bak/files/fun17.gno diff --git a/gnovm/tests/files/fun18.gno b/gnovm/tests/files.bak/files/fun18.gno similarity index 100% rename from gnovm/tests/files/fun18.gno rename to gnovm/tests/files.bak/files/fun18.gno diff --git a/gnovm/tests/files/fun19b.gno b/gnovm/tests/files.bak/files/fun19b.gno similarity index 100% rename from gnovm/tests/files/fun19b.gno rename to gnovm/tests/files.bak/files/fun19b.gno diff --git a/gnovm/tests/files/fun2.gno b/gnovm/tests/files.bak/files/fun2.gno similarity index 100% rename from gnovm/tests/files/fun2.gno rename to gnovm/tests/files.bak/files/fun2.gno diff --git a/gnovm/tests/files/fun20b.gno b/gnovm/tests/files.bak/files/fun20b.gno similarity index 100% rename from gnovm/tests/files/fun20b.gno rename to gnovm/tests/files.bak/files/fun20b.gno diff --git a/gnovm/tests/files/fun21.gno b/gnovm/tests/files.bak/files/fun21.gno similarity index 100% rename from gnovm/tests/files/fun21.gno rename to gnovm/tests/files.bak/files/fun21.gno diff --git a/gnovm/tests/files/fun22.gno b/gnovm/tests/files.bak/files/fun22.gno similarity index 100% rename from gnovm/tests/files/fun22.gno rename to gnovm/tests/files.bak/files/fun22.gno diff --git a/gnovm/tests/files/fun23.gno b/gnovm/tests/files.bak/files/fun23.gno similarity index 100% rename from gnovm/tests/files/fun23.gno rename to gnovm/tests/files.bak/files/fun23.gno diff --git a/gnovm/tests/files/fun24.gno b/gnovm/tests/files.bak/files/fun24.gno similarity index 100% rename from gnovm/tests/files/fun24.gno rename to gnovm/tests/files.bak/files/fun24.gno diff --git a/gnovm/tests/files/fun25.gno b/gnovm/tests/files.bak/files/fun25.gno similarity index 100% rename from gnovm/tests/files/fun25.gno rename to gnovm/tests/files.bak/files/fun25.gno diff --git a/gnovm/tests/files/fun26.gno b/gnovm/tests/files.bak/files/fun26.gno similarity index 100% rename from gnovm/tests/files/fun26.gno rename to gnovm/tests/files.bak/files/fun26.gno diff --git a/gnovm/tests/files/fun3.gno b/gnovm/tests/files.bak/files/fun3.gno similarity index 100% rename from gnovm/tests/files/fun3.gno rename to gnovm/tests/files.bak/files/fun3.gno diff --git a/gnovm/tests/files/fun4.gno b/gnovm/tests/files.bak/files/fun4.gno similarity index 100% rename from gnovm/tests/files/fun4.gno rename to gnovm/tests/files.bak/files/fun4.gno diff --git a/gnovm/tests/files/fun5.gno b/gnovm/tests/files.bak/files/fun5.gno similarity index 100% rename from gnovm/tests/files/fun5.gno rename to gnovm/tests/files.bak/files/fun5.gno diff --git a/gnovm/tests/files/fun6.gno b/gnovm/tests/files.bak/files/fun6.gno similarity index 100% rename from gnovm/tests/files/fun6.gno rename to gnovm/tests/files.bak/files/fun6.gno diff --git a/gnovm/tests/files/fun6b.gno b/gnovm/tests/files.bak/files/fun6b.gno similarity index 100% rename from gnovm/tests/files/fun6b.gno rename to gnovm/tests/files.bak/files/fun6b.gno diff --git a/gnovm/tests/files/fun7.gno b/gnovm/tests/files.bak/files/fun7.gno similarity index 100% rename from gnovm/tests/files/fun7.gno rename to gnovm/tests/files.bak/files/fun7.gno diff --git a/gnovm/tests/files/fun8.gno b/gnovm/tests/files.bak/files/fun8.gno similarity index 100% rename from gnovm/tests/files/fun8.gno rename to gnovm/tests/files.bak/files/fun8.gno diff --git a/gnovm/tests/files/fun9.gno b/gnovm/tests/files.bak/files/fun9.gno similarity index 100% rename from gnovm/tests/files/fun9.gno rename to gnovm/tests/files.bak/files/fun9.gno diff --git a/gnovm/tests/files/goto0.gno b/gnovm/tests/files.bak/files/goto0.gno similarity index 100% rename from gnovm/tests/files/goto0.gno rename to gnovm/tests/files.bak/files/goto0.gno diff --git a/gnovm/tests/files/goto1.gno b/gnovm/tests/files.bak/files/goto1.gno similarity index 100% rename from gnovm/tests/files/goto1.gno rename to gnovm/tests/files.bak/files/goto1.gno diff --git a/gnovm/tests/files/goto2.gno b/gnovm/tests/files.bak/files/goto2.gno similarity index 100% rename from gnovm/tests/files/goto2.gno rename to gnovm/tests/files.bak/files/goto2.gno diff --git a/gnovm/tests/files/goto3.gno b/gnovm/tests/files.bak/files/goto3.gno similarity index 100% rename from gnovm/tests/files/goto3.gno rename to gnovm/tests/files.bak/files/goto3.gno diff --git a/gnovm/tests/files/goto3a.gno b/gnovm/tests/files.bak/files/goto3a.gno similarity index 100% rename from gnovm/tests/files/goto3a.gno rename to gnovm/tests/files.bak/files/goto3a.gno diff --git a/gnovm/tests/files/goto4.gno b/gnovm/tests/files.bak/files/goto4.gno similarity index 100% rename from gnovm/tests/files/goto4.gno rename to gnovm/tests/files.bak/files/goto4.gno diff --git a/gnovm/tests/files/goto5.gno b/gnovm/tests/files.bak/files/goto5.gno similarity index 100% rename from gnovm/tests/files/goto5.gno rename to gnovm/tests/files.bak/files/goto5.gno diff --git a/gnovm/tests/files/goto6.gno b/gnovm/tests/files.bak/files/goto6.gno similarity index 100% rename from gnovm/tests/files/goto6.gno rename to gnovm/tests/files.bak/files/goto6.gno diff --git a/gnovm/tests/files/if.gno b/gnovm/tests/files.bak/files/if.gno similarity index 100% rename from gnovm/tests/files/if.gno rename to gnovm/tests/files.bak/files/if.gno diff --git a/gnovm/tests/files/if0.gno b/gnovm/tests/files.bak/files/if0.gno similarity index 100% rename from gnovm/tests/files/if0.gno rename to gnovm/tests/files.bak/files/if0.gno diff --git a/gnovm/tests/files/if1.gno b/gnovm/tests/files.bak/files/if1.gno similarity index 100% rename from gnovm/tests/files/if1.gno rename to gnovm/tests/files.bak/files/if1.gno diff --git a/gnovm/tests/files/if2.gno b/gnovm/tests/files.bak/files/if2.gno similarity index 100% rename from gnovm/tests/files/if2.gno rename to gnovm/tests/files.bak/files/if2.gno diff --git a/gnovm/tests/files/if3.gno b/gnovm/tests/files.bak/files/if3.gno similarity index 100% rename from gnovm/tests/files/if3.gno rename to gnovm/tests/files.bak/files/if3.gno diff --git a/gnovm/tests/files/if4.gno b/gnovm/tests/files.bak/files/if4.gno similarity index 100% rename from gnovm/tests/files/if4.gno rename to gnovm/tests/files.bak/files/if4.gno diff --git a/gnovm/tests/files/if5.gno b/gnovm/tests/files.bak/files/if5.gno similarity index 100% rename from gnovm/tests/files/if5.gno rename to gnovm/tests/files.bak/files/if5.gno diff --git a/gnovm/tests/files/if6.gno b/gnovm/tests/files.bak/files/if6.gno similarity index 100% rename from gnovm/tests/files/if6.gno rename to gnovm/tests/files.bak/files/if6.gno diff --git a/gnovm/tests/files/if7.gno b/gnovm/tests/files.bak/files/if7.gno similarity index 100% rename from gnovm/tests/files/if7.gno rename to gnovm/tests/files.bak/files/if7.gno diff --git a/gnovm/tests/files/import0.gno b/gnovm/tests/files.bak/files/import0.gno similarity index 100% rename from gnovm/tests/files/import0.gno rename to gnovm/tests/files.bak/files/import0.gno diff --git a/gnovm/tests/files/import1.gno b/gnovm/tests/files.bak/files/import1.gno similarity index 100% rename from gnovm/tests/files/import1.gno rename to gnovm/tests/files.bak/files/import1.gno diff --git a/gnovm/tests/files/import10.gno b/gnovm/tests/files.bak/files/import10.gno similarity index 100% rename from gnovm/tests/files/import10.gno rename to gnovm/tests/files.bak/files/import10.gno diff --git a/gnovm/tests/files/import3.gno b/gnovm/tests/files.bak/files/import3.gno similarity index 100% rename from gnovm/tests/files/import3.gno rename to gnovm/tests/files.bak/files/import3.gno diff --git a/gnovm/tests/files/import4.gno b/gnovm/tests/files.bak/files/import4.gno similarity index 100% rename from gnovm/tests/files/import4.gno rename to gnovm/tests/files.bak/files/import4.gno diff --git a/gnovm/tests/files/import5.gno b/gnovm/tests/files.bak/files/import5.gno similarity index 100% rename from gnovm/tests/files/import5.gno rename to gnovm/tests/files.bak/files/import5.gno diff --git a/gnovm/tests/files/import6.gno b/gnovm/tests/files.bak/files/import6.gno similarity index 100% rename from gnovm/tests/files/import6.gno rename to gnovm/tests/files.bak/files/import6.gno diff --git a/gnovm/tests/files/import7.gno b/gnovm/tests/files.bak/files/import7.gno similarity index 100% rename from gnovm/tests/files/import7.gno rename to gnovm/tests/files.bak/files/import7.gno diff --git a/gnovm/tests/files/import8.gno b/gnovm/tests/files.bak/files/import8.gno similarity index 100% rename from gnovm/tests/files/import8.gno rename to gnovm/tests/files.bak/files/import8.gno diff --git a/gnovm/tests/files/import9.gno b/gnovm/tests/files.bak/files/import9.gno similarity index 100% rename from gnovm/tests/files/import9.gno rename to gnovm/tests/files.bak/files/import9.gno diff --git a/gnovm/tests/files/inc.gno b/gnovm/tests/files.bak/files/inc.gno similarity index 100% rename from gnovm/tests/files/inc.gno rename to gnovm/tests/files.bak/files/inc.gno diff --git a/gnovm/tests/files/index0.gno b/gnovm/tests/files.bak/files/index0.gno similarity index 100% rename from gnovm/tests/files/index0.gno rename to gnovm/tests/files.bak/files/index0.gno diff --git a/gnovm/tests/files/init0.gno b/gnovm/tests/files.bak/files/init0.gno similarity index 100% rename from gnovm/tests/files/init0.gno rename to gnovm/tests/files.bak/files/init0.gno diff --git a/gnovm/tests/files/init1.gno b/gnovm/tests/files.bak/files/init1.gno similarity index 100% rename from gnovm/tests/files/init1.gno rename to gnovm/tests/files.bak/files/init1.gno diff --git a/gnovm/tests/files/interface0.gno b/gnovm/tests/files.bak/files/interface0.gno similarity index 100% rename from gnovm/tests/files/interface0.gno rename to gnovm/tests/files.bak/files/interface0.gno diff --git a/gnovm/tests/files/interface1.gno b/gnovm/tests/files.bak/files/interface1.gno similarity index 100% rename from gnovm/tests/files/interface1.gno rename to gnovm/tests/files.bak/files/interface1.gno diff --git a/gnovm/tests/files/interface10.gno b/gnovm/tests/files.bak/files/interface10.gno similarity index 100% rename from gnovm/tests/files/interface10.gno rename to gnovm/tests/files.bak/files/interface10.gno diff --git a/gnovm/tests/files/interface11.gno b/gnovm/tests/files.bak/files/interface11.gno similarity index 100% rename from gnovm/tests/files/interface11.gno rename to gnovm/tests/files.bak/files/interface11.gno diff --git a/gnovm/tests/files/interface12.gno b/gnovm/tests/files.bak/files/interface12.gno similarity index 100% rename from gnovm/tests/files/interface12.gno rename to gnovm/tests/files.bak/files/interface12.gno diff --git a/gnovm/tests/files/interface13.gno b/gnovm/tests/files.bak/files/interface13.gno similarity index 100% rename from gnovm/tests/files/interface13.gno rename to gnovm/tests/files.bak/files/interface13.gno diff --git a/gnovm/tests/files/interface14.gno b/gnovm/tests/files.bak/files/interface14.gno similarity index 100% rename from gnovm/tests/files/interface14.gno rename to gnovm/tests/files.bak/files/interface14.gno diff --git a/gnovm/tests/files/interface15.gno b/gnovm/tests/files.bak/files/interface15.gno similarity index 100% rename from gnovm/tests/files/interface15.gno rename to gnovm/tests/files.bak/files/interface15.gno diff --git a/gnovm/tests/files/interface16.gno b/gnovm/tests/files.bak/files/interface16.gno similarity index 100% rename from gnovm/tests/files/interface16.gno rename to gnovm/tests/files.bak/files/interface16.gno diff --git a/gnovm/tests/files/interface17.gno b/gnovm/tests/files.bak/files/interface17.gno similarity index 100% rename from gnovm/tests/files/interface17.gno rename to gnovm/tests/files.bak/files/interface17.gno diff --git a/gnovm/tests/files/interface18.gno b/gnovm/tests/files.bak/files/interface18.gno similarity index 100% rename from gnovm/tests/files/interface18.gno rename to gnovm/tests/files.bak/files/interface18.gno diff --git a/gnovm/tests/files/interface19.gno b/gnovm/tests/files.bak/files/interface19.gno similarity index 100% rename from gnovm/tests/files/interface19.gno rename to gnovm/tests/files.bak/files/interface19.gno diff --git a/gnovm/tests/files/interface2.gno b/gnovm/tests/files.bak/files/interface2.gno similarity index 100% rename from gnovm/tests/files/interface2.gno rename to gnovm/tests/files.bak/files/interface2.gno diff --git a/gnovm/tests/files/interface20.gno b/gnovm/tests/files.bak/files/interface20.gno similarity index 100% rename from gnovm/tests/files/interface20.gno rename to gnovm/tests/files.bak/files/interface20.gno diff --git a/gnovm/tests/files/interface21.gno b/gnovm/tests/files.bak/files/interface21.gno similarity index 100% rename from gnovm/tests/files/interface21.gno rename to gnovm/tests/files.bak/files/interface21.gno diff --git a/gnovm/tests/files/interface22.gno b/gnovm/tests/files.bak/files/interface22.gno similarity index 100% rename from gnovm/tests/files/interface22.gno rename to gnovm/tests/files.bak/files/interface22.gno diff --git a/gnovm/tests/files/interface23.gno b/gnovm/tests/files.bak/files/interface23.gno similarity index 100% rename from gnovm/tests/files/interface23.gno rename to gnovm/tests/files.bak/files/interface23.gno diff --git a/gnovm/tests/files/interface24.gno b/gnovm/tests/files.bak/files/interface24.gno similarity index 100% rename from gnovm/tests/files/interface24.gno rename to gnovm/tests/files.bak/files/interface24.gno diff --git a/gnovm/tests/files/interface25.gno b/gnovm/tests/files.bak/files/interface25.gno similarity index 100% rename from gnovm/tests/files/interface25.gno rename to gnovm/tests/files.bak/files/interface25.gno diff --git a/gnovm/tests/files/interface26.gno b/gnovm/tests/files.bak/files/interface26.gno similarity index 100% rename from gnovm/tests/files/interface26.gno rename to gnovm/tests/files.bak/files/interface26.gno diff --git a/gnovm/tests/files/interface27b.gno b/gnovm/tests/files.bak/files/interface27b.gno similarity index 100% rename from gnovm/tests/files/interface27b.gno rename to gnovm/tests/files.bak/files/interface27b.gno diff --git a/gnovm/tests/files/interface28b.gno b/gnovm/tests/files.bak/files/interface28b.gno similarity index 100% rename from gnovm/tests/files/interface28b.gno rename to gnovm/tests/files.bak/files/interface28b.gno diff --git a/gnovm/tests/files/interface29.gno b/gnovm/tests/files.bak/files/interface29.gno similarity index 100% rename from gnovm/tests/files/interface29.gno rename to gnovm/tests/files.bak/files/interface29.gno diff --git a/gnovm/tests/files/interface3.gno b/gnovm/tests/files.bak/files/interface3.gno similarity index 100% rename from gnovm/tests/files/interface3.gno rename to gnovm/tests/files.bak/files/interface3.gno diff --git a/gnovm/tests/files/interface30.gno b/gnovm/tests/files.bak/files/interface30.gno similarity index 100% rename from gnovm/tests/files/interface30.gno rename to gnovm/tests/files.bak/files/interface30.gno diff --git a/gnovm/tests/files/interface31.gno b/gnovm/tests/files.bak/files/interface31.gno similarity index 100% rename from gnovm/tests/files/interface31.gno rename to gnovm/tests/files.bak/files/interface31.gno diff --git a/gnovm/tests/files/interface32.gno b/gnovm/tests/files.bak/files/interface32.gno similarity index 100% rename from gnovm/tests/files/interface32.gno rename to gnovm/tests/files.bak/files/interface32.gno diff --git a/gnovm/tests/files/interface33.gno b/gnovm/tests/files.bak/files/interface33.gno similarity index 100% rename from gnovm/tests/files/interface33.gno rename to gnovm/tests/files.bak/files/interface33.gno diff --git a/gnovm/tests/files/interface34.gno b/gnovm/tests/files.bak/files/interface34.gno similarity index 100% rename from gnovm/tests/files/interface34.gno rename to gnovm/tests/files.bak/files/interface34.gno diff --git a/gnovm/tests/files/interface35.gno b/gnovm/tests/files.bak/files/interface35.gno similarity index 100% rename from gnovm/tests/files/interface35.gno rename to gnovm/tests/files.bak/files/interface35.gno diff --git a/gnovm/tests/files/interface36.gno b/gnovm/tests/files.bak/files/interface36.gno similarity index 100% rename from gnovm/tests/files/interface36.gno rename to gnovm/tests/files.bak/files/interface36.gno diff --git a/gnovm/tests/files/interface37.gno b/gnovm/tests/files.bak/files/interface37.gno similarity index 100% rename from gnovm/tests/files/interface37.gno rename to gnovm/tests/files.bak/files/interface37.gno diff --git a/gnovm/tests/files/interface38b.gno b/gnovm/tests/files.bak/files/interface38b.gno similarity index 100% rename from gnovm/tests/files/interface38b.gno rename to gnovm/tests/files.bak/files/interface38b.gno diff --git a/gnovm/tests/files/interface39b.gno b/gnovm/tests/files.bak/files/interface39b.gno similarity index 100% rename from gnovm/tests/files/interface39b.gno rename to gnovm/tests/files.bak/files/interface39b.gno diff --git a/gnovm/tests/files/interface4.gno b/gnovm/tests/files.bak/files/interface4.gno similarity index 100% rename from gnovm/tests/files/interface4.gno rename to gnovm/tests/files.bak/files/interface4.gno diff --git a/gnovm/tests/files/interface40b.gno b/gnovm/tests/files.bak/files/interface40b.gno similarity index 100% rename from gnovm/tests/files/interface40b.gno rename to gnovm/tests/files.bak/files/interface40b.gno diff --git a/gnovm/tests/files/interface41b.gno b/gnovm/tests/files.bak/files/interface41b.gno similarity index 100% rename from gnovm/tests/files/interface41b.gno rename to gnovm/tests/files.bak/files/interface41b.gno diff --git a/gnovm/tests/files/interface42.gno b/gnovm/tests/files.bak/files/interface42.gno similarity index 100% rename from gnovm/tests/files/interface42.gno rename to gnovm/tests/files.bak/files/interface42.gno diff --git a/gnovm/tests/files/interface43.gno b/gnovm/tests/files.bak/files/interface43.gno similarity index 100% rename from gnovm/tests/files/interface43.gno rename to gnovm/tests/files.bak/files/interface43.gno diff --git a/gnovm/tests/files/interface44.gno b/gnovm/tests/files.bak/files/interface44.gno similarity index 100% rename from gnovm/tests/files/interface44.gno rename to gnovm/tests/files.bak/files/interface44.gno diff --git a/gnovm/tests/files/interface45.gno b/gnovm/tests/files.bak/files/interface45.gno similarity index 100% rename from gnovm/tests/files/interface45.gno rename to gnovm/tests/files.bak/files/interface45.gno diff --git a/gnovm/tests/files/interface46.gno b/gnovm/tests/files.bak/files/interface46.gno similarity index 100% rename from gnovm/tests/files/interface46.gno rename to gnovm/tests/files.bak/files/interface46.gno diff --git a/gnovm/tests/files/interface5.gno b/gnovm/tests/files.bak/files/interface5.gno similarity index 100% rename from gnovm/tests/files/interface5.gno rename to gnovm/tests/files.bak/files/interface5.gno diff --git a/gnovm/tests/files/interface6.gno b/gnovm/tests/files.bak/files/interface6.gno similarity index 100% rename from gnovm/tests/files/interface6.gno rename to gnovm/tests/files.bak/files/interface6.gno diff --git a/gnovm/tests/files/interface7b.gno b/gnovm/tests/files.bak/files/interface7b.gno similarity index 100% rename from gnovm/tests/files/interface7b.gno rename to gnovm/tests/files.bak/files/interface7b.gno diff --git a/gnovm/tests/files/interface8.gno b/gnovm/tests/files.bak/files/interface8.gno similarity index 100% rename from gnovm/tests/files/interface8.gno rename to gnovm/tests/files.bak/files/interface8.gno diff --git a/gnovm/tests/files/interface9b.gno b/gnovm/tests/files.bak/files/interface9b.gno similarity index 100% rename from gnovm/tests/files/interface9b.gno rename to gnovm/tests/files.bak/files/interface9b.gno diff --git a/gnovm/tests/files/interp.gi b/gnovm/tests/files.bak/files/interp.gi similarity index 100% rename from gnovm/tests/files/interp.gi rename to gnovm/tests/files.bak/files/interp.gi diff --git a/gnovm/tests/files/interp2.gi b/gnovm/tests/files.bak/files/interp2.gi similarity index 100% rename from gnovm/tests/files/interp2.gi rename to gnovm/tests/files.bak/files/interp2.gi diff --git a/gnovm/tests/files/io0_native.gno b/gnovm/tests/files.bak/files/io0_native.gno similarity index 100% rename from gnovm/tests/files/io0_native.gno rename to gnovm/tests/files.bak/files/io0_native.gno diff --git a/gnovm/tests/files/io0_stdlibs.gno b/gnovm/tests/files.bak/files/io0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/io0_stdlibs.gno rename to gnovm/tests/files.bak/files/io0_stdlibs.gno diff --git a/gnovm/tests/files/io1.gno b/gnovm/tests/files.bak/files/io1.gno similarity index 100% rename from gnovm/tests/files/io1.gno rename to gnovm/tests/files.bak/files/io1.gno diff --git a/gnovm/tests/files/io2.gno b/gnovm/tests/files.bak/files/io2.gno similarity index 100% rename from gnovm/tests/files/io2.gno rename to gnovm/tests/files.bak/files/io2.gno diff --git a/gnovm/tests/files/iota.gno b/gnovm/tests/files.bak/files/iota.gno similarity index 100% rename from gnovm/tests/files/iota.gno rename to gnovm/tests/files.bak/files/iota.gno diff --git a/gnovm/tests/files/iota0.gno b/gnovm/tests/files.bak/files/iota0.gno similarity index 100% rename from gnovm/tests/files/iota0.gno rename to gnovm/tests/files.bak/files/iota0.gno diff --git a/gnovm/tests/files/ipp_as_key.gno b/gnovm/tests/files.bak/files/ipp_as_key.gno similarity index 100% rename from gnovm/tests/files/ipp_as_key.gno rename to gnovm/tests/files.bak/files/ipp_as_key.gno diff --git a/gnovm/tests/files/issue-1096.gno b/gnovm/tests/files.bak/files/issue-1096.gno similarity index 100% rename from gnovm/tests/files/issue-1096.gno rename to gnovm/tests/files.bak/files/issue-1096.gno diff --git a/gnovm/tests/files/issue-558b.gno b/gnovm/tests/files.bak/files/issue-558b.gno similarity index 100% rename from gnovm/tests/files/issue-558b.gno rename to gnovm/tests/files.bak/files/issue-558b.gno diff --git a/gnovm/tests/files/issue-735.gno b/gnovm/tests/files.bak/files/issue-735.gno similarity index 100% rename from gnovm/tests/files/issue-735.gno rename to gnovm/tests/files.bak/files/issue-735.gno diff --git a/gnovm/tests/files/issue-776.gno b/gnovm/tests/files.bak/files/issue-776.gno similarity index 100% rename from gnovm/tests/files/issue-776.gno rename to gnovm/tests/files.bak/files/issue-776.gno diff --git a/gnovm/tests/files/issue-782.gno b/gnovm/tests/files.bak/files/issue-782.gno similarity index 100% rename from gnovm/tests/files/issue-782.gno rename to gnovm/tests/files.bak/files/issue-782.gno diff --git a/gnovm/tests/files/issue-784.gno b/gnovm/tests/files.bak/files/issue-784.gno similarity index 100% rename from gnovm/tests/files/issue-784.gno rename to gnovm/tests/files.bak/files/issue-784.gno diff --git a/gnovm/tests/files/issue-880.gno b/gnovm/tests/files.bak/files/issue-880.gno similarity index 100% rename from gnovm/tests/files/issue-880.gno rename to gnovm/tests/files.bak/files/issue-880.gno diff --git a/gnovm/tests/files/l2_long.gno b/gnovm/tests/files.bak/files/l2_long.gno similarity index 100% rename from gnovm/tests/files/l2_long.gno rename to gnovm/tests/files.bak/files/l2_long.gno diff --git a/gnovm/tests/files/l3_long.gno b/gnovm/tests/files.bak/files/l3_long.gno similarity index 100% rename from gnovm/tests/files/l3_long.gno rename to gnovm/tests/files.bak/files/l3_long.gno diff --git a/gnovm/tests/files/l4_long.gno b/gnovm/tests/files.bak/files/l4_long.gno similarity index 100% rename from gnovm/tests/files/l4_long.gno rename to gnovm/tests/files.bak/files/l4_long.gno diff --git a/gnovm/tests/files/l5_long.gno b/gnovm/tests/files.bak/files/l5_long.gno similarity index 100% rename from gnovm/tests/files/l5_long.gno rename to gnovm/tests/files.bak/files/l5_long.gno diff --git a/gnovm/tests/files/len0.gno b/gnovm/tests/files.bak/files/len0.gno similarity index 100% rename from gnovm/tests/files/len0.gno rename to gnovm/tests/files.bak/files/len0.gno diff --git a/gnovm/tests/files/make0.gno b/gnovm/tests/files.bak/files/make0.gno similarity index 100% rename from gnovm/tests/files/make0.gno rename to gnovm/tests/files.bak/files/make0.gno diff --git a/gnovm/tests/files/make1.gno b/gnovm/tests/files.bak/files/make1.gno similarity index 100% rename from gnovm/tests/files/make1.gno rename to gnovm/tests/files.bak/files/make1.gno diff --git a/gnovm/tests/files/make2.gno b/gnovm/tests/files.bak/files/make2.gno similarity index 100% rename from gnovm/tests/files/make2.gno rename to gnovm/tests/files.bak/files/make2.gno diff --git a/gnovm/tests/files/map.gno b/gnovm/tests/files.bak/files/map.gno similarity index 100% rename from gnovm/tests/files/map.gno rename to gnovm/tests/files.bak/files/map.gno diff --git a/gnovm/tests/files/map0.gno b/gnovm/tests/files.bak/files/map0.gno similarity index 100% rename from gnovm/tests/files/map0.gno rename to gnovm/tests/files.bak/files/map0.gno diff --git a/gnovm/tests/files/map1.gno b/gnovm/tests/files.bak/files/map1.gno similarity index 100% rename from gnovm/tests/files/map1.gno rename to gnovm/tests/files.bak/files/map1.gno diff --git a/gnovm/tests/files/map10.gno b/gnovm/tests/files.bak/files/map10.gno similarity index 100% rename from gnovm/tests/files/map10.gno rename to gnovm/tests/files.bak/files/map10.gno diff --git a/gnovm/tests/files/map11.gno b/gnovm/tests/files.bak/files/map11.gno similarity index 100% rename from gnovm/tests/files/map11.gno rename to gnovm/tests/files.bak/files/map11.gno diff --git a/gnovm/tests/files/map12.gno b/gnovm/tests/files.bak/files/map12.gno similarity index 100% rename from gnovm/tests/files/map12.gno rename to gnovm/tests/files.bak/files/map12.gno diff --git a/gnovm/tests/files/map13.gno b/gnovm/tests/files.bak/files/map13.gno similarity index 100% rename from gnovm/tests/files/map13.gno rename to gnovm/tests/files.bak/files/map13.gno diff --git a/gnovm/tests/files/map14b.gno b/gnovm/tests/files.bak/files/map14b.gno similarity index 100% rename from gnovm/tests/files/map14b.gno rename to gnovm/tests/files.bak/files/map14b.gno diff --git a/gnovm/tests/files/map15.gno b/gnovm/tests/files.bak/files/map15.gno similarity index 100% rename from gnovm/tests/files/map15.gno rename to gnovm/tests/files.bak/files/map15.gno diff --git a/gnovm/tests/files/map16.gno b/gnovm/tests/files.bak/files/map16.gno similarity index 100% rename from gnovm/tests/files/map16.gno rename to gnovm/tests/files.bak/files/map16.gno diff --git a/gnovm/tests/files/map17.gno b/gnovm/tests/files.bak/files/map17.gno similarity index 100% rename from gnovm/tests/files/map17.gno rename to gnovm/tests/files.bak/files/map17.gno diff --git a/gnovm/tests/files/map18.gno b/gnovm/tests/files.bak/files/map18.gno similarity index 100% rename from gnovm/tests/files/map18.gno rename to gnovm/tests/files.bak/files/map18.gno diff --git a/gnovm/tests/files/map19b.gno b/gnovm/tests/files.bak/files/map19b.gno similarity index 100% rename from gnovm/tests/files/map19b.gno rename to gnovm/tests/files.bak/files/map19b.gno diff --git a/gnovm/tests/files/map2.gno b/gnovm/tests/files.bak/files/map2.gno similarity index 100% rename from gnovm/tests/files/map2.gno rename to gnovm/tests/files.bak/files/map2.gno diff --git a/gnovm/tests/files/map20.gno b/gnovm/tests/files.bak/files/map20.gno similarity index 100% rename from gnovm/tests/files/map20.gno rename to gnovm/tests/files.bak/files/map20.gno diff --git a/gnovm/tests/files/map21.gno b/gnovm/tests/files.bak/files/map21.gno similarity index 100% rename from gnovm/tests/files/map21.gno rename to gnovm/tests/files.bak/files/map21.gno diff --git a/gnovm/tests/files/map22.gno b/gnovm/tests/files.bak/files/map22.gno similarity index 100% rename from gnovm/tests/files/map22.gno rename to gnovm/tests/files.bak/files/map22.gno diff --git a/gnovm/tests/files/map23.gno b/gnovm/tests/files.bak/files/map23.gno similarity index 100% rename from gnovm/tests/files/map23.gno rename to gnovm/tests/files.bak/files/map23.gno diff --git a/gnovm/tests/files/map24.gno b/gnovm/tests/files.bak/files/map24.gno similarity index 100% rename from gnovm/tests/files/map24.gno rename to gnovm/tests/files.bak/files/map24.gno diff --git a/gnovm/tests/files/map25.gno b/gnovm/tests/files.bak/files/map25.gno similarity index 100% rename from gnovm/tests/files/map25.gno rename to gnovm/tests/files.bak/files/map25.gno diff --git a/gnovm/tests/files/map26.gno b/gnovm/tests/files.bak/files/map26.gno similarity index 100% rename from gnovm/tests/files/map26.gno rename to gnovm/tests/files.bak/files/map26.gno diff --git a/gnovm/tests/files/map27.gno b/gnovm/tests/files.bak/files/map27.gno similarity index 100% rename from gnovm/tests/files/map27.gno rename to gnovm/tests/files.bak/files/map27.gno diff --git a/gnovm/tests/files/map28b.gno b/gnovm/tests/files.bak/files/map28b.gno similarity index 100% rename from gnovm/tests/files/map28b.gno rename to gnovm/tests/files.bak/files/map28b.gno diff --git a/gnovm/tests/files/map28c.gno b/gnovm/tests/files.bak/files/map28c.gno similarity index 100% rename from gnovm/tests/files/map28c.gno rename to gnovm/tests/files.bak/files/map28c.gno diff --git a/gnovm/tests/files/map29_native.gno b/gnovm/tests/files.bak/files/map29_native.gno similarity index 100% rename from gnovm/tests/files/map29_native.gno rename to gnovm/tests/files.bak/files/map29_native.gno diff --git a/gnovm/tests/files/map29_stdlibs.gno b/gnovm/tests/files.bak/files/map29_stdlibs.gno similarity index 100% rename from gnovm/tests/files/map29_stdlibs.gno rename to gnovm/tests/files.bak/files/map29_stdlibs.gno diff --git a/gnovm/tests/files/map3.gno b/gnovm/tests/files.bak/files/map3.gno similarity index 100% rename from gnovm/tests/files/map3.gno rename to gnovm/tests/files.bak/files/map3.gno diff --git a/gnovm/tests/files/map4.gno b/gnovm/tests/files.bak/files/map4.gno similarity index 100% rename from gnovm/tests/files/map4.gno rename to gnovm/tests/files.bak/files/map4.gno diff --git a/gnovm/tests/files/map5.gno b/gnovm/tests/files.bak/files/map5.gno similarity index 100% rename from gnovm/tests/files/map5.gno rename to gnovm/tests/files.bak/files/map5.gno diff --git a/gnovm/tests/files/map6.gno b/gnovm/tests/files.bak/files/map6.gno similarity index 100% rename from gnovm/tests/files/map6.gno rename to gnovm/tests/files.bak/files/map6.gno diff --git a/gnovm/tests/files/map7.gno b/gnovm/tests/files.bak/files/map7.gno similarity index 100% rename from gnovm/tests/files/map7.gno rename to gnovm/tests/files.bak/files/map7.gno diff --git a/gnovm/tests/files/map8.gno b/gnovm/tests/files.bak/files/map8.gno similarity index 100% rename from gnovm/tests/files/map8.gno rename to gnovm/tests/files.bak/files/map8.gno diff --git a/gnovm/tests/files/map9.gno b/gnovm/tests/files.bak/files/map9.gno similarity index 100% rename from gnovm/tests/files/map9.gno rename to gnovm/tests/files.bak/files/map9.gno diff --git a/gnovm/tests/files/math0_native.gno b/gnovm/tests/files.bak/files/math0_native.gno similarity index 100% rename from gnovm/tests/files/math0_native.gno rename to gnovm/tests/files.bak/files/math0_native.gno diff --git a/gnovm/tests/files/math0_stdlibs.gno b/gnovm/tests/files.bak/files/math0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/math0_stdlibs.gno rename to gnovm/tests/files.bak/files/math0_stdlibs.gno diff --git a/gnovm/tests/files/math2.gno b/gnovm/tests/files.bak/files/math2.gno similarity index 100% rename from gnovm/tests/files/math2.gno rename to gnovm/tests/files.bak/files/math2.gno diff --git a/gnovm/tests/files/math3.gno b/gnovm/tests/files.bak/files/math3.gno similarity index 100% rename from gnovm/tests/files/math3.gno rename to gnovm/tests/files.bak/files/math3.gno diff --git a/gnovm/tests/files/maths_int16_long.gno b/gnovm/tests/files.bak/files/maths_int16_long.gno similarity index 100% rename from gnovm/tests/files/maths_int16_long.gno rename to gnovm/tests/files.bak/files/maths_int16_long.gno diff --git a/gnovm/tests/files/maths_int8.gno b/gnovm/tests/files.bak/files/maths_int8.gno similarity index 100% rename from gnovm/tests/files/maths_int8.gno rename to gnovm/tests/files.bak/files/maths_int8.gno diff --git a/gnovm/tests/files/method.gno b/gnovm/tests/files.bak/files/method.gno similarity index 100% rename from gnovm/tests/files/method.gno rename to gnovm/tests/files.bak/files/method.gno diff --git a/gnovm/tests/files/method0.gno b/gnovm/tests/files.bak/files/method0.gno similarity index 100% rename from gnovm/tests/files/method0.gno rename to gnovm/tests/files.bak/files/method0.gno diff --git a/gnovm/tests/files/method1.gno b/gnovm/tests/files.bak/files/method1.gno similarity index 100% rename from gnovm/tests/files/method1.gno rename to gnovm/tests/files.bak/files/method1.gno diff --git a/gnovm/tests/files/method10.gno b/gnovm/tests/files.bak/files/method10.gno similarity index 100% rename from gnovm/tests/files/method10.gno rename to gnovm/tests/files.bak/files/method10.gno diff --git a/gnovm/tests/files/method11.gno b/gnovm/tests/files.bak/files/method11.gno similarity index 100% rename from gnovm/tests/files/method11.gno rename to gnovm/tests/files.bak/files/method11.gno diff --git a/gnovm/tests/files/method12.gno b/gnovm/tests/files.bak/files/method12.gno similarity index 100% rename from gnovm/tests/files/method12.gno rename to gnovm/tests/files.bak/files/method12.gno diff --git a/gnovm/tests/files/method13.gno b/gnovm/tests/files.bak/files/method13.gno similarity index 100% rename from gnovm/tests/files/method13.gno rename to gnovm/tests/files.bak/files/method13.gno diff --git a/gnovm/tests/files/method14.gno b/gnovm/tests/files.bak/files/method14.gno similarity index 100% rename from gnovm/tests/files/method14.gno rename to gnovm/tests/files.bak/files/method14.gno diff --git a/gnovm/tests/files/method15.gno b/gnovm/tests/files.bak/files/method15.gno similarity index 100% rename from gnovm/tests/files/method15.gno rename to gnovm/tests/files.bak/files/method15.gno diff --git a/gnovm/tests/files/method16b.gno b/gnovm/tests/files.bak/files/method16b.gno similarity index 100% rename from gnovm/tests/files/method16b.gno rename to gnovm/tests/files.bak/files/method16b.gno diff --git a/gnovm/tests/files/method17b.gno b/gnovm/tests/files.bak/files/method17b.gno similarity index 100% rename from gnovm/tests/files/method17b.gno rename to gnovm/tests/files.bak/files/method17b.gno diff --git a/gnovm/tests/files/method18.gno b/gnovm/tests/files.bak/files/method18.gno similarity index 100% rename from gnovm/tests/files/method18.gno rename to gnovm/tests/files.bak/files/method18.gno diff --git a/gnovm/tests/files/method19.gno b/gnovm/tests/files.bak/files/method19.gno similarity index 100% rename from gnovm/tests/files/method19.gno rename to gnovm/tests/files.bak/files/method19.gno diff --git a/gnovm/tests/files/method2.gno b/gnovm/tests/files.bak/files/method2.gno similarity index 100% rename from gnovm/tests/files/method2.gno rename to gnovm/tests/files.bak/files/method2.gno diff --git a/gnovm/tests/files/method20.gno b/gnovm/tests/files.bak/files/method20.gno similarity index 100% rename from gnovm/tests/files/method20.gno rename to gnovm/tests/files.bak/files/method20.gno diff --git a/gnovm/tests/files/method21.gno b/gnovm/tests/files.bak/files/method21.gno similarity index 100% rename from gnovm/tests/files/method21.gno rename to gnovm/tests/files.bak/files/method21.gno diff --git a/gnovm/tests/files/method22.gno b/gnovm/tests/files.bak/files/method22.gno similarity index 100% rename from gnovm/tests/files/method22.gno rename to gnovm/tests/files.bak/files/method22.gno diff --git a/gnovm/tests/files/method23.gno b/gnovm/tests/files.bak/files/method23.gno similarity index 100% rename from gnovm/tests/files/method23.gno rename to gnovm/tests/files.bak/files/method23.gno diff --git a/gnovm/tests/files/method24.gno b/gnovm/tests/files.bak/files/method24.gno similarity index 100% rename from gnovm/tests/files/method24.gno rename to gnovm/tests/files.bak/files/method24.gno diff --git a/gnovm/tests/files/method25.gno b/gnovm/tests/files.bak/files/method25.gno similarity index 100% rename from gnovm/tests/files/method25.gno rename to gnovm/tests/files.bak/files/method25.gno diff --git a/gnovm/tests/files/method26.gno b/gnovm/tests/files.bak/files/method26.gno similarity index 100% rename from gnovm/tests/files/method26.gno rename to gnovm/tests/files.bak/files/method26.gno diff --git a/gnovm/tests/files/method27.gno b/gnovm/tests/files.bak/files/method27.gno similarity index 100% rename from gnovm/tests/files/method27.gno rename to gnovm/tests/files.bak/files/method27.gno diff --git a/gnovm/tests/files/method28.gno b/gnovm/tests/files.bak/files/method28.gno similarity index 100% rename from gnovm/tests/files/method28.gno rename to gnovm/tests/files.bak/files/method28.gno diff --git a/gnovm/tests/files/method29b.gno b/gnovm/tests/files.bak/files/method29b.gno similarity index 100% rename from gnovm/tests/files/method29b.gno rename to gnovm/tests/files.bak/files/method29b.gno diff --git a/gnovm/tests/files/method3.gno b/gnovm/tests/files.bak/files/method3.gno similarity index 100% rename from gnovm/tests/files/method3.gno rename to gnovm/tests/files.bak/files/method3.gno diff --git a/gnovm/tests/files/method30.gno b/gnovm/tests/files.bak/files/method30.gno similarity index 100% rename from gnovm/tests/files/method30.gno rename to gnovm/tests/files.bak/files/method30.gno diff --git a/gnovm/tests/files/method31b.gno b/gnovm/tests/files.bak/files/method31b.gno similarity index 100% rename from gnovm/tests/files/method31b.gno rename to gnovm/tests/files.bak/files/method31b.gno diff --git a/gnovm/tests/files/method32.gno b/gnovm/tests/files.bak/files/method32.gno similarity index 100% rename from gnovm/tests/files/method32.gno rename to gnovm/tests/files.bak/files/method32.gno diff --git a/gnovm/tests/files/method33.gno b/gnovm/tests/files.bak/files/method33.gno similarity index 100% rename from gnovm/tests/files/method33.gno rename to gnovm/tests/files.bak/files/method33.gno diff --git a/gnovm/tests/files/method34.gno b/gnovm/tests/files.bak/files/method34.gno similarity index 100% rename from gnovm/tests/files/method34.gno rename to gnovm/tests/files.bak/files/method34.gno diff --git a/gnovm/tests/files/method35.gno b/gnovm/tests/files.bak/files/method35.gno similarity index 100% rename from gnovm/tests/files/method35.gno rename to gnovm/tests/files.bak/files/method35.gno diff --git a/gnovm/tests/files/method36.gno b/gnovm/tests/files.bak/files/method36.gno similarity index 100% rename from gnovm/tests/files/method36.gno rename to gnovm/tests/files.bak/files/method36.gno diff --git a/gnovm/tests/files/method37.gno b/gnovm/tests/files.bak/files/method37.gno similarity index 100% rename from gnovm/tests/files/method37.gno rename to gnovm/tests/files.bak/files/method37.gno diff --git a/gnovm/tests/files/method4.gno b/gnovm/tests/files.bak/files/method4.gno similarity index 100% rename from gnovm/tests/files/method4.gno rename to gnovm/tests/files.bak/files/method4.gno diff --git a/gnovm/tests/files/method5.gno b/gnovm/tests/files.bak/files/method5.gno similarity index 100% rename from gnovm/tests/files/method5.gno rename to gnovm/tests/files.bak/files/method5.gno diff --git a/gnovm/tests/files/method6.gno b/gnovm/tests/files.bak/files/method6.gno similarity index 100% rename from gnovm/tests/files/method6.gno rename to gnovm/tests/files.bak/files/method6.gno diff --git a/gnovm/tests/files/method7.gno b/gnovm/tests/files.bak/files/method7.gno similarity index 100% rename from gnovm/tests/files/method7.gno rename to gnovm/tests/files.bak/files/method7.gno diff --git a/gnovm/tests/files/method8.gno b/gnovm/tests/files.bak/files/method8.gno similarity index 100% rename from gnovm/tests/files/method8.gno rename to gnovm/tests/files.bak/files/method8.gno diff --git a/gnovm/tests/files/method9.gno b/gnovm/tests/files.bak/files/method9.gno similarity index 100% rename from gnovm/tests/files/method9.gno rename to gnovm/tests/files.bak/files/method9.gno diff --git a/gnovm/tests/files/neg0.gno b/gnovm/tests/files.bak/files/neg0.gno similarity index 100% rename from gnovm/tests/files/neg0.gno rename to gnovm/tests/files.bak/files/neg0.gno diff --git a/gnovm/tests/files/new0.gno b/gnovm/tests/files.bak/files/new0.gno similarity index 100% rename from gnovm/tests/files/new0.gno rename to gnovm/tests/files.bak/files/new0.gno diff --git a/gnovm/tests/files/new1.gno b/gnovm/tests/files.bak/files/new1.gno similarity index 100% rename from gnovm/tests/files/new1.gno rename to gnovm/tests/files.bak/files/new1.gno diff --git a/gnovm/tests/files/new2.gno b/gnovm/tests/files.bak/files/new2.gno similarity index 100% rename from gnovm/tests/files/new2.gno rename to gnovm/tests/files.bak/files/new2.gno diff --git a/gnovm/tests/files/new3.gno b/gnovm/tests/files.bak/files/new3.gno similarity index 100% rename from gnovm/tests/files/new3.gno rename to gnovm/tests/files.bak/files/new3.gno diff --git a/gnovm/tests/files/nil0.gno b/gnovm/tests/files.bak/files/nil0.gno similarity index 100% rename from gnovm/tests/files/nil0.gno rename to gnovm/tests/files.bak/files/nil0.gno diff --git a/gnovm/tests/files/nil1.gno b/gnovm/tests/files.bak/files/nil1.gno similarity index 100% rename from gnovm/tests/files/nil1.gno rename to gnovm/tests/files.bak/files/nil1.gno diff --git a/gnovm/tests/files/nil2.gno b/gnovm/tests/files.bak/files/nil2.gno similarity index 100% rename from gnovm/tests/files/nil2.gno rename to gnovm/tests/files.bak/files/nil2.gno diff --git a/gnovm/tests/files/nil3.gno b/gnovm/tests/files.bak/files/nil3.gno similarity index 100% rename from gnovm/tests/files/nil3.gno rename to gnovm/tests/files.bak/files/nil3.gno diff --git a/gnovm/tests/files/not0.gno b/gnovm/tests/files.bak/files/not0.gno similarity index 100% rename from gnovm/tests/files/not0.gno rename to gnovm/tests/files.bak/files/not0.gno diff --git a/gnovm/tests/files/not1.gno b/gnovm/tests/files.bak/files/not1.gno similarity index 100% rename from gnovm/tests/files/not1.gno rename to gnovm/tests/files.bak/files/not1.gno diff --git a/gnovm/tests/files/not2.gno b/gnovm/tests/files.bak/files/not2.gno similarity index 100% rename from gnovm/tests/files/not2.gno rename to gnovm/tests/files.bak/files/not2.gno diff --git a/gnovm/tests/files/op0.gno b/gnovm/tests/files.bak/files/op0.gno similarity index 100% rename from gnovm/tests/files/op0.gno rename to gnovm/tests/files.bak/files/op0.gno diff --git a/gnovm/tests/files/op2.gno b/gnovm/tests/files.bak/files/op2.gno similarity index 100% rename from gnovm/tests/files/op2.gno rename to gnovm/tests/files.bak/files/op2.gno diff --git a/gnovm/tests/files/op6.gno b/gnovm/tests/files.bak/files/op6.gno similarity index 100% rename from gnovm/tests/files/op6.gno rename to gnovm/tests/files.bak/files/op6.gno diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files.bak/files/op7.gno similarity index 100% rename from gnovm/tests/files/op7.gno rename to gnovm/tests/files.bak/files/op7.gno diff --git a/gnovm/tests/files/op8.gno b/gnovm/tests/files.bak/files/op8.gno similarity index 100% rename from gnovm/tests/files/op8.gno rename to gnovm/tests/files.bak/files/op8.gno diff --git a/gnovm/tests/files/opint16.gno b/gnovm/tests/files.bak/files/opint16.gno similarity index 100% rename from gnovm/tests/files/opint16.gno rename to gnovm/tests/files.bak/files/opint16.gno diff --git a/gnovm/tests/files/opint32.gno b/gnovm/tests/files.bak/files/opint32.gno similarity index 100% rename from gnovm/tests/files/opint32.gno rename to gnovm/tests/files.bak/files/opint32.gno diff --git a/gnovm/tests/files/opint64.gno b/gnovm/tests/files.bak/files/opint64.gno similarity index 100% rename from gnovm/tests/files/opint64.gno rename to gnovm/tests/files.bak/files/opint64.gno diff --git a/gnovm/tests/files/opint8.gno b/gnovm/tests/files.bak/files/opint8.gno similarity index 100% rename from gnovm/tests/files/opint8.gno rename to gnovm/tests/files.bak/files/opint8.gno diff --git a/gnovm/tests/files/opstring.gno b/gnovm/tests/files.bak/files/opstring.gno similarity index 100% rename from gnovm/tests/files/opstring.gno rename to gnovm/tests/files.bak/files/opstring.gno diff --git a/gnovm/tests/files/opuint16.gno b/gnovm/tests/files.bak/files/opuint16.gno similarity index 100% rename from gnovm/tests/files/opuint16.gno rename to gnovm/tests/files.bak/files/opuint16.gno diff --git a/gnovm/tests/files/opuint32.gno b/gnovm/tests/files.bak/files/opuint32.gno similarity index 100% rename from gnovm/tests/files/opuint32.gno rename to gnovm/tests/files.bak/files/opuint32.gno diff --git a/gnovm/tests/files/opuint64.gno b/gnovm/tests/files.bak/files/opuint64.gno similarity index 100% rename from gnovm/tests/files/opuint64.gno rename to gnovm/tests/files.bak/files/opuint64.gno diff --git a/gnovm/tests/files/opuint8.gno b/gnovm/tests/files.bak/files/opuint8.gno similarity index 100% rename from gnovm/tests/files/opuint8.gno rename to gnovm/tests/files.bak/files/opuint8.gno diff --git a/gnovm/tests/files/or0.gno b/gnovm/tests/files.bak/files/or0.gno similarity index 100% rename from gnovm/tests/files/or0.gno rename to gnovm/tests/files.bak/files/or0.gno diff --git a/gnovm/tests/files/or1.gno b/gnovm/tests/files.bak/files/or1.gno similarity index 100% rename from gnovm/tests/files/or1.gno rename to gnovm/tests/files.bak/files/or1.gno diff --git a/gnovm/tests/files/or2.gno b/gnovm/tests/files.bak/files/or2.gno similarity index 100% rename from gnovm/tests/files/or2.gno rename to gnovm/tests/files.bak/files/or2.gno diff --git a/gnovm/tests/files/or3.gno b/gnovm/tests/files.bak/files/or3.gno similarity index 100% rename from gnovm/tests/files/or3.gno rename to gnovm/tests/files.bak/files/or3.gno diff --git a/gnovm/tests/files/or4.gno b/gnovm/tests/files.bak/files/or4.gno similarity index 100% rename from gnovm/tests/files/or4.gno rename to gnovm/tests/files.bak/files/or4.gno diff --git a/gnovm/tests/files/panic0.gno b/gnovm/tests/files.bak/files/panic0.gno similarity index 100% rename from gnovm/tests/files/panic0.gno rename to gnovm/tests/files.bak/files/panic0.gno diff --git a/gnovm/tests/files/panic0b.gno b/gnovm/tests/files.bak/files/panic0b.gno similarity index 100% rename from gnovm/tests/files/panic0b.gno rename to gnovm/tests/files.bak/files/panic0b.gno diff --git a/gnovm/tests/files/persist_map.gno b/gnovm/tests/files.bak/files/persist_map.gno similarity index 100% rename from gnovm/tests/files/persist_map.gno rename to gnovm/tests/files.bak/files/persist_map.gno diff --git a/gnovm/tests/files/pkgname0.gno b/gnovm/tests/files.bak/files/pkgname0.gno similarity index 100% rename from gnovm/tests/files/pkgname0.gno rename to gnovm/tests/files.bak/files/pkgname0.gno diff --git a/gnovm/tests/files/pkgname1.gno b/gnovm/tests/files.bak/files/pkgname1.gno similarity index 100% rename from gnovm/tests/files/pkgname1.gno rename to gnovm/tests/files.bak/files/pkgname1.gno diff --git a/gnovm/tests/files/pkgname2.gno b/gnovm/tests/files.bak/files/pkgname2.gno similarity index 100% rename from gnovm/tests/files/pkgname2.gno rename to gnovm/tests/files.bak/files/pkgname2.gno diff --git a/gnovm/tests/files/primes.gno b/gnovm/tests/files.bak/files/primes.gno similarity index 100% rename from gnovm/tests/files/primes.gno rename to gnovm/tests/files.bak/files/primes.gno diff --git a/gnovm/tests/files/print0.gno b/gnovm/tests/files.bak/files/print0.gno similarity index 100% rename from gnovm/tests/files/print0.gno rename to gnovm/tests/files.bak/files/print0.gno diff --git a/gnovm/tests/files/ptr0.gno b/gnovm/tests/files.bak/files/ptr0.gno similarity index 100% rename from gnovm/tests/files/ptr0.gno rename to gnovm/tests/files.bak/files/ptr0.gno diff --git a/gnovm/tests/files/ptr1.gno b/gnovm/tests/files.bak/files/ptr1.gno similarity index 100% rename from gnovm/tests/files/ptr1.gno rename to gnovm/tests/files.bak/files/ptr1.gno diff --git a/gnovm/tests/files/ptr2.gno b/gnovm/tests/files.bak/files/ptr2.gno similarity index 100% rename from gnovm/tests/files/ptr2.gno rename to gnovm/tests/files.bak/files/ptr2.gno diff --git a/gnovm/tests/files/ptr3.gno b/gnovm/tests/files.bak/files/ptr3.gno similarity index 100% rename from gnovm/tests/files/ptr3.gno rename to gnovm/tests/files.bak/files/ptr3.gno diff --git a/gnovm/tests/files/ptr4.gno b/gnovm/tests/files.bak/files/ptr4.gno similarity index 100% rename from gnovm/tests/files/ptr4.gno rename to gnovm/tests/files.bak/files/ptr4.gno diff --git a/gnovm/tests/files/ptr5.gno b/gnovm/tests/files.bak/files/ptr5.gno similarity index 100% rename from gnovm/tests/files/ptr5.gno rename to gnovm/tests/files.bak/files/ptr5.gno diff --git a/gnovm/tests/files/ptr5a.gno b/gnovm/tests/files.bak/files/ptr5a.gno similarity index 100% rename from gnovm/tests/files/ptr5a.gno rename to gnovm/tests/files.bak/files/ptr5a.gno diff --git a/gnovm/tests/files/ptr6.gno b/gnovm/tests/files.bak/files/ptr6.gno similarity index 100% rename from gnovm/tests/files/ptr6.gno rename to gnovm/tests/files.bak/files/ptr6.gno diff --git a/gnovm/tests/files/ptr7.gno b/gnovm/tests/files.bak/files/ptr7.gno similarity index 100% rename from gnovm/tests/files/ptr7.gno rename to gnovm/tests/files.bak/files/ptr7.gno diff --git a/gnovm/tests/files/ptr8.gno b/gnovm/tests/files.bak/files/ptr8.gno similarity index 100% rename from gnovm/tests/files/ptr8.gno rename to gnovm/tests/files.bak/files/ptr8.gno diff --git a/gnovm/tests/files/ptr_array0.gno b/gnovm/tests/files.bak/files/ptr_array0.gno similarity index 100% rename from gnovm/tests/files/ptr_array0.gno rename to gnovm/tests/files.bak/files/ptr_array0.gno diff --git a/gnovm/tests/files/ptr_array1.gno b/gnovm/tests/files.bak/files/ptr_array1.gno similarity index 100% rename from gnovm/tests/files/ptr_array1.gno rename to gnovm/tests/files.bak/files/ptr_array1.gno diff --git a/gnovm/tests/files/ptr_array2.gno b/gnovm/tests/files.bak/files/ptr_array2.gno similarity index 100% rename from gnovm/tests/files/ptr_array2.gno rename to gnovm/tests/files.bak/files/ptr_array2.gno diff --git a/gnovm/tests/files/ptr_array3.gno b/gnovm/tests/files.bak/files/ptr_array3.gno similarity index 100% rename from gnovm/tests/files/ptr_array3.gno rename to gnovm/tests/files.bak/files/ptr_array3.gno diff --git a/gnovm/tests/files/range0.gno b/gnovm/tests/files.bak/files/range0.gno similarity index 100% rename from gnovm/tests/files/range0.gno rename to gnovm/tests/files.bak/files/range0.gno diff --git a/gnovm/tests/files/range1.gno b/gnovm/tests/files.bak/files/range1.gno similarity index 100% rename from gnovm/tests/files/range1.gno rename to gnovm/tests/files.bak/files/range1.gno diff --git a/gnovm/tests/files/range2.gno b/gnovm/tests/files.bak/files/range2.gno similarity index 100% rename from gnovm/tests/files/range2.gno rename to gnovm/tests/files.bak/files/range2.gno diff --git a/gnovm/tests/files/range3.gno b/gnovm/tests/files.bak/files/range3.gno similarity index 100% rename from gnovm/tests/files/range3.gno rename to gnovm/tests/files.bak/files/range3.gno diff --git a/gnovm/tests/files/range4.gno b/gnovm/tests/files.bak/files/range4.gno similarity index 100% rename from gnovm/tests/files/range4.gno rename to gnovm/tests/files.bak/files/range4.gno diff --git a/gnovm/tests/files/range5.gno b/gnovm/tests/files.bak/files/range5.gno similarity index 100% rename from gnovm/tests/files/range5.gno rename to gnovm/tests/files.bak/files/range5.gno diff --git a/gnovm/tests/files/range6.gno b/gnovm/tests/files.bak/files/range6.gno similarity index 100% rename from gnovm/tests/files/range6.gno rename to gnovm/tests/files.bak/files/range6.gno diff --git a/gnovm/tests/files/range7.gno b/gnovm/tests/files.bak/files/range7.gno similarity index 100% rename from gnovm/tests/files/range7.gno rename to gnovm/tests/files.bak/files/range7.gno diff --git a/gnovm/tests/files/recover0.gno b/gnovm/tests/files.bak/files/recover0.gno similarity index 100% rename from gnovm/tests/files/recover0.gno rename to gnovm/tests/files.bak/files/recover0.gno diff --git a/gnovm/tests/files/recover1.gno b/gnovm/tests/files.bak/files/recover1.gno similarity index 100% rename from gnovm/tests/files/recover1.gno rename to gnovm/tests/files.bak/files/recover1.gno diff --git a/gnovm/tests/files/recover1b.gno b/gnovm/tests/files.bak/files/recover1b.gno similarity index 100% rename from gnovm/tests/files/recover1b.gno rename to gnovm/tests/files.bak/files/recover1b.gno diff --git a/gnovm/tests/files/recover2.gno b/gnovm/tests/files.bak/files/recover2.gno similarity index 100% rename from gnovm/tests/files/recover2.gno rename to gnovm/tests/files.bak/files/recover2.gno diff --git a/gnovm/tests/files/recover3.gno b/gnovm/tests/files.bak/files/recover3.gno similarity index 100% rename from gnovm/tests/files/recover3.gno rename to gnovm/tests/files.bak/files/recover3.gno diff --git a/gnovm/tests/files/recover4.gno b/gnovm/tests/files.bak/files/recover4.gno similarity index 100% rename from gnovm/tests/files/recover4.gno rename to gnovm/tests/files.bak/files/recover4.gno diff --git a/gnovm/tests/files/recover5.gno b/gnovm/tests/files.bak/files/recover5.gno similarity index 100% rename from gnovm/tests/files/recover5.gno rename to gnovm/tests/files.bak/files/recover5.gno diff --git a/gnovm/tests/files/recover6.gno b/gnovm/tests/files.bak/files/recover6.gno similarity index 100% rename from gnovm/tests/files/recover6.gno rename to gnovm/tests/files.bak/files/recover6.gno diff --git a/gnovm/tests/files/recover7.gno b/gnovm/tests/files.bak/files/recover7.gno similarity index 100% rename from gnovm/tests/files/recover7.gno rename to gnovm/tests/files.bak/files/recover7.gno diff --git a/gnovm/tests/files/recurse0.gno b/gnovm/tests/files.bak/files/recurse0.gno similarity index 100% rename from gnovm/tests/files/recurse0.gno rename to gnovm/tests/files.bak/files/recurse0.gno diff --git a/gnovm/tests/files/redeclaration-global0.gno b/gnovm/tests/files.bak/files/redeclaration-global0.gno similarity index 100% rename from gnovm/tests/files/redeclaration-global0.gno rename to gnovm/tests/files.bak/files/redeclaration-global0.gno diff --git a/gnovm/tests/files/redeclaration-global1.gno b/gnovm/tests/files.bak/files/redeclaration-global1.gno similarity index 100% rename from gnovm/tests/files/redeclaration-global1.gno rename to gnovm/tests/files.bak/files/redeclaration-global1.gno diff --git a/gnovm/tests/files/redeclaration-global5.gno b/gnovm/tests/files.bak/files/redeclaration-global5.gno similarity index 100% rename from gnovm/tests/files/redeclaration-global5.gno rename to gnovm/tests/files.bak/files/redeclaration-global5.gno diff --git a/gnovm/tests/files/redeclaration0.gno b/gnovm/tests/files.bak/files/redeclaration0.gno similarity index 100% rename from gnovm/tests/files/redeclaration0.gno rename to gnovm/tests/files.bak/files/redeclaration0.gno diff --git a/gnovm/tests/files/redeclaration1.gno b/gnovm/tests/files.bak/files/redeclaration1.gno similarity index 100% rename from gnovm/tests/files/redeclaration1.gno rename to gnovm/tests/files.bak/files/redeclaration1.gno diff --git a/gnovm/tests/files/redeclaration2.gno b/gnovm/tests/files.bak/files/redeclaration2.gno similarity index 100% rename from gnovm/tests/files/redeclaration2.gno rename to gnovm/tests/files.bak/files/redeclaration2.gno diff --git a/gnovm/tests/files/redeclaration3.gno b/gnovm/tests/files.bak/files/redeclaration3.gno similarity index 100% rename from gnovm/tests/files/redeclaration3.gno rename to gnovm/tests/files.bak/files/redeclaration3.gno diff --git a/gnovm/tests/files/redeclaration4.gno b/gnovm/tests/files.bak/files/redeclaration4.gno similarity index 100% rename from gnovm/tests/files/redeclaration4.gno rename to gnovm/tests/files.bak/files/redeclaration4.gno diff --git a/gnovm/tests/files/redeclaration5.gno b/gnovm/tests/files.bak/files/redeclaration5.gno similarity index 100% rename from gnovm/tests/files/redeclaration5.gno rename to gnovm/tests/files.bak/files/redeclaration5.gno diff --git a/gnovm/tests/files/ret1.gno b/gnovm/tests/files.bak/files/ret1.gno similarity index 100% rename from gnovm/tests/files/ret1.gno rename to gnovm/tests/files.bak/files/ret1.gno diff --git a/gnovm/tests/files/ret10.gno b/gnovm/tests/files.bak/files/ret10.gno similarity index 100% rename from gnovm/tests/files/ret10.gno rename to gnovm/tests/files.bak/files/ret10.gno diff --git a/gnovm/tests/files/ret11.gno b/gnovm/tests/files.bak/files/ret11.gno similarity index 100% rename from gnovm/tests/files/ret11.gno rename to gnovm/tests/files.bak/files/ret11.gno diff --git a/gnovm/tests/files/ret12.gno b/gnovm/tests/files.bak/files/ret12.gno similarity index 100% rename from gnovm/tests/files/ret12.gno rename to gnovm/tests/files.bak/files/ret12.gno diff --git a/gnovm/tests/files/ret13.gno b/gnovm/tests/files.bak/files/ret13.gno similarity index 100% rename from gnovm/tests/files/ret13.gno rename to gnovm/tests/files.bak/files/ret13.gno diff --git a/gnovm/tests/files/ret14.gno b/gnovm/tests/files.bak/files/ret14.gno similarity index 100% rename from gnovm/tests/files/ret14.gno rename to gnovm/tests/files.bak/files/ret14.gno diff --git a/gnovm/tests/files/ret2.gno b/gnovm/tests/files.bak/files/ret2.gno similarity index 100% rename from gnovm/tests/files/ret2.gno rename to gnovm/tests/files.bak/files/ret2.gno diff --git a/gnovm/tests/files/ret3.gno b/gnovm/tests/files.bak/files/ret3.gno similarity index 100% rename from gnovm/tests/files/ret3.gno rename to gnovm/tests/files.bak/files/ret3.gno diff --git a/gnovm/tests/files/ret4.gno b/gnovm/tests/files.bak/files/ret4.gno similarity index 100% rename from gnovm/tests/files/ret4.gno rename to gnovm/tests/files.bak/files/ret4.gno diff --git a/gnovm/tests/files/ret5.gno b/gnovm/tests/files.bak/files/ret5.gno similarity index 100% rename from gnovm/tests/files/ret5.gno rename to gnovm/tests/files.bak/files/ret5.gno diff --git a/gnovm/tests/files/ret6.gno b/gnovm/tests/files.bak/files/ret6.gno similarity index 100% rename from gnovm/tests/files/ret6.gno rename to gnovm/tests/files.bak/files/ret6.gno diff --git a/gnovm/tests/files/ret7.gno b/gnovm/tests/files.bak/files/ret7.gno similarity index 100% rename from gnovm/tests/files/ret7.gno rename to gnovm/tests/files.bak/files/ret7.gno diff --git a/gnovm/tests/files/ret8.gno b/gnovm/tests/files.bak/files/ret8.gno similarity index 100% rename from gnovm/tests/files/ret8.gno rename to gnovm/tests/files.bak/files/ret8.gno diff --git a/gnovm/tests/files/ret9.gno b/gnovm/tests/files.bak/files/ret9.gno similarity index 100% rename from gnovm/tests/files/ret9.gno rename to gnovm/tests/files.bak/files/ret9.gno diff --git a/gnovm/tests/files/run0.gno b/gnovm/tests/files.bak/files/run0.gno similarity index 100% rename from gnovm/tests/files/run0.gno rename to gnovm/tests/files.bak/files/run0.gno diff --git a/gnovm/tests/files/run1.gno b/gnovm/tests/files.bak/files/run1.gno similarity index 100% rename from gnovm/tests/files/run1.gno rename to gnovm/tests/files.bak/files/run1.gno diff --git a/gnovm/tests/files/run10.gno b/gnovm/tests/files.bak/files/run10.gno similarity index 100% rename from gnovm/tests/files/run10.gno rename to gnovm/tests/files.bak/files/run10.gno diff --git a/gnovm/tests/files/run11.gno b/gnovm/tests/files.bak/files/run11.gno similarity index 100% rename from gnovm/tests/files/run11.gno rename to gnovm/tests/files.bak/files/run11.gno diff --git a/gnovm/tests/files/run12.gno b/gnovm/tests/files.bak/files/run12.gno similarity index 100% rename from gnovm/tests/files/run12.gno rename to gnovm/tests/files.bak/files/run12.gno diff --git a/gnovm/tests/files/run13.gno b/gnovm/tests/files.bak/files/run13.gno similarity index 100% rename from gnovm/tests/files/run13.gno rename to gnovm/tests/files.bak/files/run13.gno diff --git a/gnovm/tests/files/run4.gno b/gnovm/tests/files.bak/files/run4.gno similarity index 100% rename from gnovm/tests/files/run4.gno rename to gnovm/tests/files.bak/files/run4.gno diff --git a/gnovm/tests/files/run5.gno b/gnovm/tests/files.bak/files/run5.gno similarity index 100% rename from gnovm/tests/files/run5.gno rename to gnovm/tests/files.bak/files/run5.gno diff --git a/gnovm/tests/files/run6.gno b/gnovm/tests/files.bak/files/run6.gno similarity index 100% rename from gnovm/tests/files/run6.gno rename to gnovm/tests/files.bak/files/run6.gno diff --git a/gnovm/tests/files/run7.gno b/gnovm/tests/files.bak/files/run7.gno similarity index 100% rename from gnovm/tests/files/run7.gno rename to gnovm/tests/files.bak/files/run7.gno diff --git a/gnovm/tests/files/run8.gno b/gnovm/tests/files.bak/files/run8.gno similarity index 100% rename from gnovm/tests/files/run8.gno rename to gnovm/tests/files.bak/files/run8.gno diff --git a/gnovm/tests/files/run9.gno b/gnovm/tests/files.bak/files/run9.gno similarity index 100% rename from gnovm/tests/files/run9.gno rename to gnovm/tests/files.bak/files/run9.gno diff --git a/gnovm/tests/files/rune0.gno b/gnovm/tests/files.bak/files/rune0.gno similarity index 100% rename from gnovm/tests/files/rune0.gno rename to gnovm/tests/files.bak/files/rune0.gno diff --git a/gnovm/tests/files/rune1.gno b/gnovm/tests/files.bak/files/rune1.gno similarity index 100% rename from gnovm/tests/files/rune1.gno rename to gnovm/tests/files.bak/files/rune1.gno diff --git a/gnovm/tests/files/rune2.gno b/gnovm/tests/files.bak/files/rune2.gno similarity index 100% rename from gnovm/tests/files/rune2.gno rename to gnovm/tests/files.bak/files/rune2.gno diff --git a/gnovm/tests/files/sample.plugin b/gnovm/tests/files.bak/files/sample.plugin similarity index 100% rename from gnovm/tests/files/sample.plugin rename to gnovm/tests/files.bak/files/sample.plugin diff --git a/gnovm/tests/files/scope0.gno b/gnovm/tests/files.bak/files/scope0.gno similarity index 100% rename from gnovm/tests/files/scope0.gno rename to gnovm/tests/files.bak/files/scope0.gno diff --git a/gnovm/tests/files/scope1.gno b/gnovm/tests/files.bak/files/scope1.gno similarity index 100% rename from gnovm/tests/files/scope1.gno rename to gnovm/tests/files.bak/files/scope1.gno diff --git a/gnovm/tests/files/scope2.gno b/gnovm/tests/files.bak/files/scope2.gno similarity index 100% rename from gnovm/tests/files/scope2.gno rename to gnovm/tests/files.bak/files/scope2.gno diff --git a/gnovm/tests/files/scope3.gno b/gnovm/tests/files.bak/files/scope3.gno similarity index 100% rename from gnovm/tests/files/scope3.gno rename to gnovm/tests/files.bak/files/scope3.gno diff --git a/gnovm/tests/files/scope4.gno b/gnovm/tests/files.bak/files/scope4.gno similarity index 100% rename from gnovm/tests/files/scope4.gno rename to gnovm/tests/files.bak/files/scope4.gno diff --git a/gnovm/tests/files/scope5.gno b/gnovm/tests/files.bak/files/scope5.gno similarity index 100% rename from gnovm/tests/files/scope5.gno rename to gnovm/tests/files.bak/files/scope5.gno diff --git a/gnovm/tests/files/scope6.gno b/gnovm/tests/files.bak/files/scope6.gno similarity index 100% rename from gnovm/tests/files/scope6.gno rename to gnovm/tests/files.bak/files/scope6.gno diff --git a/gnovm/tests/files/scope7.gno b/gnovm/tests/files.bak/files/scope7.gno similarity index 100% rename from gnovm/tests/files/scope7.gno rename to gnovm/tests/files.bak/files/scope7.gno diff --git a/gnovm/tests/files/secure.gi b/gnovm/tests/files.bak/files/secure.gi similarity index 100% rename from gnovm/tests/files/secure.gi rename to gnovm/tests/files.bak/files/secure.gi diff --git a/gnovm/tests/files/shift0.gno b/gnovm/tests/files.bak/files/shift0.gno similarity index 100% rename from gnovm/tests/files/shift0.gno rename to gnovm/tests/files.bak/files/shift0.gno diff --git a/gnovm/tests/files/shift1.gno b/gnovm/tests/files.bak/files/shift1.gno similarity index 100% rename from gnovm/tests/files/shift1.gno rename to gnovm/tests/files.bak/files/shift1.gno diff --git a/gnovm/tests/files/shift2.gno b/gnovm/tests/files.bak/files/shift2.gno similarity index 100% rename from gnovm/tests/files/shift2.gno rename to gnovm/tests/files.bak/files/shift2.gno diff --git a/gnovm/tests/files/shift3.gno b/gnovm/tests/files.bak/files/shift3.gno similarity index 100% rename from gnovm/tests/files/shift3.gno rename to gnovm/tests/files.bak/files/shift3.gno diff --git a/gnovm/tests/files/shift4.gno b/gnovm/tests/files.bak/files/shift4.gno similarity index 100% rename from gnovm/tests/files/shift4.gno rename to gnovm/tests/files.bak/files/shift4.gno diff --git a/gnovm/tests/files/shift5.gno b/gnovm/tests/files.bak/files/shift5.gno similarity index 100% rename from gnovm/tests/files/shift5.gno rename to gnovm/tests/files.bak/files/shift5.gno diff --git a/gnovm/tests/files/slice0.gno b/gnovm/tests/files.bak/files/slice0.gno similarity index 100% rename from gnovm/tests/files/slice0.gno rename to gnovm/tests/files.bak/files/slice0.gno diff --git a/gnovm/tests/files/slice1.gno b/gnovm/tests/files.bak/files/slice1.gno similarity index 100% rename from gnovm/tests/files/slice1.gno rename to gnovm/tests/files.bak/files/slice1.gno diff --git a/gnovm/tests/files/slice2.gno b/gnovm/tests/files.bak/files/slice2.gno similarity index 100% rename from gnovm/tests/files/slice2.gno rename to gnovm/tests/files.bak/files/slice2.gno diff --git a/gnovm/tests/files/std0.gno b/gnovm/tests/files.bak/files/std0.gno similarity index 100% rename from gnovm/tests/files/std0.gno rename to gnovm/tests/files.bak/files/std0.gno diff --git a/gnovm/tests/files/std10.gno b/gnovm/tests/files.bak/files/std10.gno similarity index 100% rename from gnovm/tests/files/std10.gno rename to gnovm/tests/files.bak/files/std10.gno diff --git a/gnovm/tests/files/std11.gno b/gnovm/tests/files.bak/files/std11.gno similarity index 100% rename from gnovm/tests/files/std11.gno rename to gnovm/tests/files.bak/files/std11.gno diff --git a/gnovm/tests/files/std2.gno b/gnovm/tests/files.bak/files/std2.gno similarity index 100% rename from gnovm/tests/files/std2.gno rename to gnovm/tests/files.bak/files/std2.gno diff --git a/gnovm/tests/files/std3.gno b/gnovm/tests/files.bak/files/std3.gno similarity index 100% rename from gnovm/tests/files/std3.gno rename to gnovm/tests/files.bak/files/std3.gno diff --git a/gnovm/tests/files/std4.gno b/gnovm/tests/files.bak/files/std4.gno similarity index 100% rename from gnovm/tests/files/std4.gno rename to gnovm/tests/files.bak/files/std4.gno diff --git a/gnovm/tests/files/std5.gno b/gnovm/tests/files.bak/files/std5.gno similarity index 100% rename from gnovm/tests/files/std5.gno rename to gnovm/tests/files.bak/files/std5.gno diff --git a/gnovm/tests/files/std6.gno b/gnovm/tests/files.bak/files/std6.gno similarity index 100% rename from gnovm/tests/files/std6.gno rename to gnovm/tests/files.bak/files/std6.gno diff --git a/gnovm/tests/files/std7.gno b/gnovm/tests/files.bak/files/std7.gno similarity index 100% rename from gnovm/tests/files/std7.gno rename to gnovm/tests/files.bak/files/std7.gno diff --git a/gnovm/tests/files/std8.gno b/gnovm/tests/files.bak/files/std8.gno similarity index 100% rename from gnovm/tests/files/std8.gno rename to gnovm/tests/files.bak/files/std8.gno diff --git a/gnovm/tests/files/std9.gno b/gnovm/tests/files.bak/files/std9.gno similarity index 100% rename from gnovm/tests/files/std9.gno rename to gnovm/tests/files.bak/files/std9.gno diff --git a/gnovm/tests/files/stdlibs_native.gno b/gnovm/tests/files.bak/files/stdlibs_native.gno similarity index 100% rename from gnovm/tests/files/stdlibs_native.gno rename to gnovm/tests/files.bak/files/stdlibs_native.gno diff --git a/gnovm/tests/files/stdlibs_stdlibs.gno b/gnovm/tests/files.bak/files/stdlibs_stdlibs.gno similarity index 100% rename from gnovm/tests/files/stdlibs_stdlibs.gno rename to gnovm/tests/files.bak/files/stdlibs_stdlibs.gno diff --git a/gnovm/tests/files/str.gno b/gnovm/tests/files.bak/files/str.gno similarity index 100% rename from gnovm/tests/files/str.gno rename to gnovm/tests/files.bak/files/str.gno diff --git a/gnovm/tests/files/str0.gno b/gnovm/tests/files.bak/files/str0.gno similarity index 100% rename from gnovm/tests/files/str0.gno rename to gnovm/tests/files.bak/files/str0.gno diff --git a/gnovm/tests/files/str1.gno b/gnovm/tests/files.bak/files/str1.gno similarity index 100% rename from gnovm/tests/files/str1.gno rename to gnovm/tests/files.bak/files/str1.gno diff --git a/gnovm/tests/files/str2.gno b/gnovm/tests/files.bak/files/str2.gno similarity index 100% rename from gnovm/tests/files/str2.gno rename to gnovm/tests/files.bak/files/str2.gno diff --git a/gnovm/tests/files/str3.gno b/gnovm/tests/files.bak/files/str3.gno similarity index 100% rename from gnovm/tests/files/str3.gno rename to gnovm/tests/files.bak/files/str3.gno diff --git a/gnovm/tests/files/str4.gno b/gnovm/tests/files.bak/files/str4.gno similarity index 100% rename from gnovm/tests/files/str4.gno rename to gnovm/tests/files.bak/files/str4.gno diff --git a/gnovm/tests/files/struct.gno b/gnovm/tests/files.bak/files/struct.gno similarity index 100% rename from gnovm/tests/files/struct.gno rename to gnovm/tests/files.bak/files/struct.gno diff --git a/gnovm/tests/files/struct0.gno b/gnovm/tests/files.bak/files/struct0.gno similarity index 100% rename from gnovm/tests/files/struct0.gno rename to gnovm/tests/files.bak/files/struct0.gno diff --git a/gnovm/tests/files/struct0a.gno b/gnovm/tests/files.bak/files/struct0a.gno similarity index 100% rename from gnovm/tests/files/struct0a.gno rename to gnovm/tests/files.bak/files/struct0a.gno diff --git a/gnovm/tests/files/struct1.gno b/gnovm/tests/files.bak/files/struct1.gno similarity index 100% rename from gnovm/tests/files/struct1.gno rename to gnovm/tests/files.bak/files/struct1.gno diff --git a/gnovm/tests/files/struct10.gno b/gnovm/tests/files.bak/files/struct10.gno similarity index 100% rename from gnovm/tests/files/struct10.gno rename to gnovm/tests/files.bak/files/struct10.gno diff --git a/gnovm/tests/files/struct11.gno b/gnovm/tests/files.bak/files/struct11.gno similarity index 100% rename from gnovm/tests/files/struct11.gno rename to gnovm/tests/files.bak/files/struct11.gno diff --git a/gnovm/tests/files/struct11b.gno b/gnovm/tests/files.bak/files/struct11b.gno similarity index 100% rename from gnovm/tests/files/struct11b.gno rename to gnovm/tests/files.bak/files/struct11b.gno diff --git a/gnovm/tests/files/struct12.gno b/gnovm/tests/files.bak/files/struct12.gno similarity index 100% rename from gnovm/tests/files/struct12.gno rename to gnovm/tests/files.bak/files/struct12.gno diff --git a/gnovm/tests/files/struct13_native.gno b/gnovm/tests/files.bak/files/struct13_native.gno similarity index 100% rename from gnovm/tests/files/struct13_native.gno rename to gnovm/tests/files.bak/files/struct13_native.gno diff --git a/gnovm/tests/files/struct13_stdlibs.gno b/gnovm/tests/files.bak/files/struct13_stdlibs.gno similarity index 100% rename from gnovm/tests/files/struct13_stdlibs.gno rename to gnovm/tests/files.bak/files/struct13_stdlibs.gno diff --git a/gnovm/tests/files/struct14.gno b/gnovm/tests/files.bak/files/struct14.gno similarity index 100% rename from gnovm/tests/files/struct14.gno rename to gnovm/tests/files.bak/files/struct14.gno diff --git a/gnovm/tests/files/struct16.gno b/gnovm/tests/files.bak/files/struct16.gno similarity index 100% rename from gnovm/tests/files/struct16.gno rename to gnovm/tests/files.bak/files/struct16.gno diff --git a/gnovm/tests/files/struct17.gno b/gnovm/tests/files.bak/files/struct17.gno similarity index 100% rename from gnovm/tests/files/struct17.gno rename to gnovm/tests/files.bak/files/struct17.gno diff --git a/gnovm/tests/files/struct19.gno b/gnovm/tests/files.bak/files/struct19.gno similarity index 100% rename from gnovm/tests/files/struct19.gno rename to gnovm/tests/files.bak/files/struct19.gno diff --git a/gnovm/tests/files/struct2.gno b/gnovm/tests/files.bak/files/struct2.gno similarity index 100% rename from gnovm/tests/files/struct2.gno rename to gnovm/tests/files.bak/files/struct2.gno diff --git a/gnovm/tests/files/struct20.gno b/gnovm/tests/files.bak/files/struct20.gno similarity index 100% rename from gnovm/tests/files/struct20.gno rename to gnovm/tests/files.bak/files/struct20.gno diff --git a/gnovm/tests/files/struct21.gno b/gnovm/tests/files.bak/files/struct21.gno similarity index 100% rename from gnovm/tests/files/struct21.gno rename to gnovm/tests/files.bak/files/struct21.gno diff --git a/gnovm/tests/files/struct22.gno b/gnovm/tests/files.bak/files/struct22.gno similarity index 100% rename from gnovm/tests/files/struct22.gno rename to gnovm/tests/files.bak/files/struct22.gno diff --git a/gnovm/tests/files/struct24.gno b/gnovm/tests/files.bak/files/struct24.gno similarity index 100% rename from gnovm/tests/files/struct24.gno rename to gnovm/tests/files.bak/files/struct24.gno diff --git a/gnovm/tests/files/struct25.gno b/gnovm/tests/files.bak/files/struct25.gno similarity index 100% rename from gnovm/tests/files/struct25.gno rename to gnovm/tests/files.bak/files/struct25.gno diff --git a/gnovm/tests/files/struct26.gno b/gnovm/tests/files.bak/files/struct26.gno similarity index 100% rename from gnovm/tests/files/struct26.gno rename to gnovm/tests/files.bak/files/struct26.gno diff --git a/gnovm/tests/files/struct27.gno b/gnovm/tests/files.bak/files/struct27.gno similarity index 100% rename from gnovm/tests/files/struct27.gno rename to gnovm/tests/files.bak/files/struct27.gno diff --git a/gnovm/tests/files/struct28b.gno b/gnovm/tests/files.bak/files/struct28b.gno similarity index 100% rename from gnovm/tests/files/struct28b.gno rename to gnovm/tests/files.bak/files/struct28b.gno diff --git a/gnovm/tests/files/struct29.gno b/gnovm/tests/files.bak/files/struct29.gno similarity index 100% rename from gnovm/tests/files/struct29.gno rename to gnovm/tests/files.bak/files/struct29.gno diff --git a/gnovm/tests/files/struct2b.gno b/gnovm/tests/files.bak/files/struct2b.gno similarity index 100% rename from gnovm/tests/files/struct2b.gno rename to gnovm/tests/files.bak/files/struct2b.gno diff --git a/gnovm/tests/files/struct3.gno b/gnovm/tests/files.bak/files/struct3.gno similarity index 100% rename from gnovm/tests/files/struct3.gno rename to gnovm/tests/files.bak/files/struct3.gno diff --git a/gnovm/tests/files/struct30.gno b/gnovm/tests/files.bak/files/struct30.gno similarity index 100% rename from gnovm/tests/files/struct30.gno rename to gnovm/tests/files.bak/files/struct30.gno diff --git a/gnovm/tests/files/struct31.gno b/gnovm/tests/files.bak/files/struct31.gno similarity index 100% rename from gnovm/tests/files/struct31.gno rename to gnovm/tests/files.bak/files/struct31.gno diff --git a/gnovm/tests/files/struct32.gno b/gnovm/tests/files.bak/files/struct32.gno similarity index 100% rename from gnovm/tests/files/struct32.gno rename to gnovm/tests/files.bak/files/struct32.gno diff --git a/gnovm/tests/files/struct33.gno b/gnovm/tests/files.bak/files/struct33.gno similarity index 100% rename from gnovm/tests/files/struct33.gno rename to gnovm/tests/files.bak/files/struct33.gno diff --git a/gnovm/tests/files/struct34.gno b/gnovm/tests/files.bak/files/struct34.gno similarity index 100% rename from gnovm/tests/files/struct34.gno rename to gnovm/tests/files.bak/files/struct34.gno diff --git a/gnovm/tests/files/struct35.gno b/gnovm/tests/files.bak/files/struct35.gno similarity index 100% rename from gnovm/tests/files/struct35.gno rename to gnovm/tests/files.bak/files/struct35.gno diff --git a/gnovm/tests/files/struct36.gno b/gnovm/tests/files.bak/files/struct36.gno similarity index 100% rename from gnovm/tests/files/struct36.gno rename to gnovm/tests/files.bak/files/struct36.gno diff --git a/gnovm/tests/files/struct37.gno b/gnovm/tests/files.bak/files/struct37.gno similarity index 100% rename from gnovm/tests/files/struct37.gno rename to gnovm/tests/files.bak/files/struct37.gno diff --git a/gnovm/tests/files/struct38.gno b/gnovm/tests/files.bak/files/struct38.gno similarity index 100% rename from gnovm/tests/files/struct38.gno rename to gnovm/tests/files.bak/files/struct38.gno diff --git a/gnovm/tests/files/struct39.gno b/gnovm/tests/files.bak/files/struct39.gno similarity index 100% rename from gnovm/tests/files/struct39.gno rename to gnovm/tests/files.bak/files/struct39.gno diff --git a/gnovm/tests/files/struct4.gno b/gnovm/tests/files.bak/files/struct4.gno similarity index 100% rename from gnovm/tests/files/struct4.gno rename to gnovm/tests/files.bak/files/struct4.gno diff --git a/gnovm/tests/files/struct40.gno b/gnovm/tests/files.bak/files/struct40.gno similarity index 100% rename from gnovm/tests/files/struct40.gno rename to gnovm/tests/files.bak/files/struct40.gno diff --git a/gnovm/tests/files/struct41.gno b/gnovm/tests/files.bak/files/struct41.gno similarity index 100% rename from gnovm/tests/files/struct41.gno rename to gnovm/tests/files.bak/files/struct41.gno diff --git a/gnovm/tests/files/struct42.gno b/gnovm/tests/files.bak/files/struct42.gno similarity index 100% rename from gnovm/tests/files/struct42.gno rename to gnovm/tests/files.bak/files/struct42.gno diff --git a/gnovm/tests/files/struct43.gno b/gnovm/tests/files.bak/files/struct43.gno similarity index 100% rename from gnovm/tests/files/struct43.gno rename to gnovm/tests/files.bak/files/struct43.gno diff --git a/gnovm/tests/files/struct44.gno b/gnovm/tests/files.bak/files/struct44.gno similarity index 100% rename from gnovm/tests/files/struct44.gno rename to gnovm/tests/files.bak/files/struct44.gno diff --git a/gnovm/tests/files/struct45.gno b/gnovm/tests/files.bak/files/struct45.gno similarity index 100% rename from gnovm/tests/files/struct45.gno rename to gnovm/tests/files.bak/files/struct45.gno diff --git a/gnovm/tests/files/struct46.gno b/gnovm/tests/files.bak/files/struct46.gno similarity index 100% rename from gnovm/tests/files/struct46.gno rename to gnovm/tests/files.bak/files/struct46.gno diff --git a/gnovm/tests/files/struct47.gno b/gnovm/tests/files.bak/files/struct47.gno similarity index 100% rename from gnovm/tests/files/struct47.gno rename to gnovm/tests/files.bak/files/struct47.gno diff --git a/gnovm/tests/files/struct48.gno b/gnovm/tests/files.bak/files/struct48.gno similarity index 100% rename from gnovm/tests/files/struct48.gno rename to gnovm/tests/files.bak/files/struct48.gno diff --git a/gnovm/tests/files/struct49.gno b/gnovm/tests/files.bak/files/struct49.gno similarity index 100% rename from gnovm/tests/files/struct49.gno rename to gnovm/tests/files.bak/files/struct49.gno diff --git a/gnovm/tests/files/struct5.gno b/gnovm/tests/files.bak/files/struct5.gno similarity index 100% rename from gnovm/tests/files/struct5.gno rename to gnovm/tests/files.bak/files/struct5.gno diff --git a/gnovm/tests/files/struct50b.gno b/gnovm/tests/files.bak/files/struct50b.gno similarity index 100% rename from gnovm/tests/files/struct50b.gno rename to gnovm/tests/files.bak/files/struct50b.gno diff --git a/gnovm/tests/files/struct52b.gno b/gnovm/tests/files.bak/files/struct52b.gno similarity index 100% rename from gnovm/tests/files/struct52b.gno rename to gnovm/tests/files.bak/files/struct52b.gno diff --git a/gnovm/tests/files/struct53b.gno b/gnovm/tests/files.bak/files/struct53b.gno similarity index 100% rename from gnovm/tests/files/struct53b.gno rename to gnovm/tests/files.bak/files/struct53b.gno diff --git a/gnovm/tests/files/struct54.gno b/gnovm/tests/files.bak/files/struct54.gno similarity index 100% rename from gnovm/tests/files/struct54.gno rename to gnovm/tests/files.bak/files/struct54.gno diff --git a/gnovm/tests/files/struct56.gno b/gnovm/tests/files.bak/files/struct56.gno similarity index 100% rename from gnovm/tests/files/struct56.gno rename to gnovm/tests/files.bak/files/struct56.gno diff --git a/gnovm/tests/files/struct57.gno b/gnovm/tests/files.bak/files/struct57.gno similarity index 100% rename from gnovm/tests/files/struct57.gno rename to gnovm/tests/files.bak/files/struct57.gno diff --git a/gnovm/tests/files/struct6.gno b/gnovm/tests/files.bak/files/struct6.gno similarity index 100% rename from gnovm/tests/files/struct6.gno rename to gnovm/tests/files.bak/files/struct6.gno diff --git a/gnovm/tests/files/struct7.gno b/gnovm/tests/files.bak/files/struct7.gno similarity index 100% rename from gnovm/tests/files/struct7.gno rename to gnovm/tests/files.bak/files/struct7.gno diff --git a/gnovm/tests/files/struct8.gno b/gnovm/tests/files.bak/files/struct8.gno similarity index 100% rename from gnovm/tests/files/struct8.gno rename to gnovm/tests/files.bak/files/struct8.gno diff --git a/gnovm/tests/files/struct9.gno b/gnovm/tests/files.bak/files/struct9.gno similarity index 100% rename from gnovm/tests/files/struct9.gno rename to gnovm/tests/files.bak/files/struct9.gno diff --git a/gnovm/tests/files/switch.gno b/gnovm/tests/files.bak/files/switch.gno similarity index 100% rename from gnovm/tests/files/switch.gno rename to gnovm/tests/files.bak/files/switch.gno diff --git a/gnovm/tests/files/switch0.gno b/gnovm/tests/files.bak/files/switch0.gno similarity index 100% rename from gnovm/tests/files/switch0.gno rename to gnovm/tests/files.bak/files/switch0.gno diff --git a/gnovm/tests/files/switch1.gno b/gnovm/tests/files.bak/files/switch1.gno similarity index 100% rename from gnovm/tests/files/switch1.gno rename to gnovm/tests/files.bak/files/switch1.gno diff --git a/gnovm/tests/files/switch10.gno b/gnovm/tests/files.bak/files/switch10.gno similarity index 100% rename from gnovm/tests/files/switch10.gno rename to gnovm/tests/files.bak/files/switch10.gno diff --git a/gnovm/tests/files/switch11.gno b/gnovm/tests/files.bak/files/switch11.gno similarity index 100% rename from gnovm/tests/files/switch11.gno rename to gnovm/tests/files.bak/files/switch11.gno diff --git a/gnovm/tests/files/switch12.gno b/gnovm/tests/files.bak/files/switch12.gno similarity index 100% rename from gnovm/tests/files/switch12.gno rename to gnovm/tests/files.bak/files/switch12.gno diff --git a/gnovm/tests/files/switch13.gno b/gnovm/tests/files.bak/files/switch13.gno similarity index 100% rename from gnovm/tests/files/switch13.gno rename to gnovm/tests/files.bak/files/switch13.gno diff --git a/gnovm/tests/files/switch14.gno b/gnovm/tests/files.bak/files/switch14.gno similarity index 100% rename from gnovm/tests/files/switch14.gno rename to gnovm/tests/files.bak/files/switch14.gno diff --git a/gnovm/tests/files/switch15.gno b/gnovm/tests/files.bak/files/switch15.gno similarity index 100% rename from gnovm/tests/files/switch15.gno rename to gnovm/tests/files.bak/files/switch15.gno diff --git a/gnovm/tests/files/switch16.gno b/gnovm/tests/files.bak/files/switch16.gno similarity index 100% rename from gnovm/tests/files/switch16.gno rename to gnovm/tests/files.bak/files/switch16.gno diff --git a/gnovm/tests/files/switch17.gno b/gnovm/tests/files.bak/files/switch17.gno similarity index 100% rename from gnovm/tests/files/switch17.gno rename to gnovm/tests/files.bak/files/switch17.gno diff --git a/gnovm/tests/files/switch18.gno b/gnovm/tests/files.bak/files/switch18.gno similarity index 100% rename from gnovm/tests/files/switch18.gno rename to gnovm/tests/files.bak/files/switch18.gno diff --git a/gnovm/tests/files/switch19.gno b/gnovm/tests/files.bak/files/switch19.gno similarity index 100% rename from gnovm/tests/files/switch19.gno rename to gnovm/tests/files.bak/files/switch19.gno diff --git a/gnovm/tests/files/switch2.gno b/gnovm/tests/files.bak/files/switch2.gno similarity index 100% rename from gnovm/tests/files/switch2.gno rename to gnovm/tests/files.bak/files/switch2.gno diff --git a/gnovm/tests/files/switch20.gno b/gnovm/tests/files.bak/files/switch20.gno similarity index 100% rename from gnovm/tests/files/switch20.gno rename to gnovm/tests/files.bak/files/switch20.gno diff --git a/gnovm/tests/files/switch21.gno b/gnovm/tests/files.bak/files/switch21.gno similarity index 100% rename from gnovm/tests/files/switch21.gno rename to gnovm/tests/files.bak/files/switch21.gno diff --git a/gnovm/tests/files/switch22.gno b/gnovm/tests/files.bak/files/switch22.gno similarity index 100% rename from gnovm/tests/files/switch22.gno rename to gnovm/tests/files.bak/files/switch22.gno diff --git a/gnovm/tests/files/switch23.gno b/gnovm/tests/files.bak/files/switch23.gno similarity index 100% rename from gnovm/tests/files/switch23.gno rename to gnovm/tests/files.bak/files/switch23.gno diff --git a/gnovm/tests/files/switch24.gno b/gnovm/tests/files.bak/files/switch24.gno similarity index 100% rename from gnovm/tests/files/switch24.gno rename to gnovm/tests/files.bak/files/switch24.gno diff --git a/gnovm/tests/files/switch25.gno b/gnovm/tests/files.bak/files/switch25.gno similarity index 100% rename from gnovm/tests/files/switch25.gno rename to gnovm/tests/files.bak/files/switch25.gno diff --git a/gnovm/tests/files/switch26.gno b/gnovm/tests/files.bak/files/switch26.gno similarity index 100% rename from gnovm/tests/files/switch26.gno rename to gnovm/tests/files.bak/files/switch26.gno diff --git a/gnovm/tests/files/switch27.gno b/gnovm/tests/files.bak/files/switch27.gno similarity index 100% rename from gnovm/tests/files/switch27.gno rename to gnovm/tests/files.bak/files/switch27.gno diff --git a/gnovm/tests/files/switch28.gno b/gnovm/tests/files.bak/files/switch28.gno similarity index 100% rename from gnovm/tests/files/switch28.gno rename to gnovm/tests/files.bak/files/switch28.gno diff --git a/gnovm/tests/files/switch29.gno b/gnovm/tests/files.bak/files/switch29.gno similarity index 100% rename from gnovm/tests/files/switch29.gno rename to gnovm/tests/files.bak/files/switch29.gno diff --git a/gnovm/tests/files/switch3.gno b/gnovm/tests/files.bak/files/switch3.gno similarity index 100% rename from gnovm/tests/files/switch3.gno rename to gnovm/tests/files.bak/files/switch3.gno diff --git a/gnovm/tests/files/switch30.gno b/gnovm/tests/files.bak/files/switch30.gno similarity index 100% rename from gnovm/tests/files/switch30.gno rename to gnovm/tests/files.bak/files/switch30.gno diff --git a/gnovm/tests/files/switch31.gno b/gnovm/tests/files.bak/files/switch31.gno similarity index 100% rename from gnovm/tests/files/switch31.gno rename to gnovm/tests/files.bak/files/switch31.gno diff --git a/gnovm/tests/files/switch32.gno b/gnovm/tests/files.bak/files/switch32.gno similarity index 100% rename from gnovm/tests/files/switch32.gno rename to gnovm/tests/files.bak/files/switch32.gno diff --git a/gnovm/tests/files/switch33.gno b/gnovm/tests/files.bak/files/switch33.gno similarity index 100% rename from gnovm/tests/files/switch33.gno rename to gnovm/tests/files.bak/files/switch33.gno diff --git a/gnovm/tests/files/switch34.gno b/gnovm/tests/files.bak/files/switch34.gno similarity index 100% rename from gnovm/tests/files/switch34.gno rename to gnovm/tests/files.bak/files/switch34.gno diff --git a/gnovm/tests/files/switch35.gno b/gnovm/tests/files.bak/files/switch35.gno similarity index 100% rename from gnovm/tests/files/switch35.gno rename to gnovm/tests/files.bak/files/switch35.gno diff --git a/gnovm/tests/files/switch36.gno b/gnovm/tests/files.bak/files/switch36.gno similarity index 100% rename from gnovm/tests/files/switch36.gno rename to gnovm/tests/files.bak/files/switch36.gno diff --git a/gnovm/tests/files/switch37.gno b/gnovm/tests/files.bak/files/switch37.gno similarity index 100% rename from gnovm/tests/files/switch37.gno rename to gnovm/tests/files.bak/files/switch37.gno diff --git a/gnovm/tests/files/switch38.gno b/gnovm/tests/files.bak/files/switch38.gno similarity index 100% rename from gnovm/tests/files/switch38.gno rename to gnovm/tests/files.bak/files/switch38.gno diff --git a/gnovm/tests/files/switch39.gno b/gnovm/tests/files.bak/files/switch39.gno similarity index 100% rename from gnovm/tests/files/switch39.gno rename to gnovm/tests/files.bak/files/switch39.gno diff --git a/gnovm/tests/files/switch4.gno b/gnovm/tests/files.bak/files/switch4.gno similarity index 100% rename from gnovm/tests/files/switch4.gno rename to gnovm/tests/files.bak/files/switch4.gno diff --git a/gnovm/tests/files/switch40.gno b/gnovm/tests/files.bak/files/switch40.gno similarity index 100% rename from gnovm/tests/files/switch40.gno rename to gnovm/tests/files.bak/files/switch40.gno diff --git a/gnovm/tests/files/switch41.gno b/gnovm/tests/files.bak/files/switch41.gno similarity index 100% rename from gnovm/tests/files/switch41.gno rename to gnovm/tests/files.bak/files/switch41.gno diff --git a/gnovm/tests/files/switch5.gno b/gnovm/tests/files.bak/files/switch5.gno similarity index 100% rename from gnovm/tests/files/switch5.gno rename to gnovm/tests/files.bak/files/switch5.gno diff --git a/gnovm/tests/files/switch6.gno b/gnovm/tests/files.bak/files/switch6.gno similarity index 100% rename from gnovm/tests/files/switch6.gno rename to gnovm/tests/files.bak/files/switch6.gno diff --git a/gnovm/tests/files/switch6b.gno b/gnovm/tests/files.bak/files/switch6b.gno similarity index 100% rename from gnovm/tests/files/switch6b.gno rename to gnovm/tests/files.bak/files/switch6b.gno diff --git a/gnovm/tests/files/switch6c.gno b/gnovm/tests/files.bak/files/switch6c.gno similarity index 100% rename from gnovm/tests/files/switch6c.gno rename to gnovm/tests/files.bak/files/switch6c.gno diff --git a/gnovm/tests/files/switch7.gno b/gnovm/tests/files.bak/files/switch7.gno similarity index 100% rename from gnovm/tests/files/switch7.gno rename to gnovm/tests/files.bak/files/switch7.gno diff --git a/gnovm/tests/files/switch8.gno b/gnovm/tests/files.bak/files/switch8.gno similarity index 100% rename from gnovm/tests/files/switch8.gno rename to gnovm/tests/files.bak/files/switch8.gno diff --git a/gnovm/tests/files/switch8b.gno b/gnovm/tests/files.bak/files/switch8b.gno similarity index 100% rename from gnovm/tests/files/switch8b.gno rename to gnovm/tests/files.bak/files/switch8b.gno diff --git a/gnovm/tests/files/switch8c.gno b/gnovm/tests/files.bak/files/switch8c.gno similarity index 100% rename from gnovm/tests/files/switch8c.gno rename to gnovm/tests/files.bak/files/switch8c.gno diff --git a/gnovm/tests/files/switch9.gno b/gnovm/tests/files.bak/files/switch9.gno similarity index 100% rename from gnovm/tests/files/switch9.gno rename to gnovm/tests/files.bak/files/switch9.gno diff --git a/gnovm/tests/files/time0_native.gno b/gnovm/tests/files.bak/files/time0_native.gno similarity index 100% rename from gnovm/tests/files/time0_native.gno rename to gnovm/tests/files.bak/files/time0_native.gno diff --git a/gnovm/tests/files/time0_stdlibs.gno b/gnovm/tests/files.bak/files/time0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time0_stdlibs.gno rename to gnovm/tests/files.bak/files/time0_stdlibs.gno diff --git a/gnovm/tests/files/time11_native.gno b/gnovm/tests/files.bak/files/time11_native.gno similarity index 100% rename from gnovm/tests/files/time11_native.gno rename to gnovm/tests/files.bak/files/time11_native.gno diff --git a/gnovm/tests/files/time11_stdlibs.gno b/gnovm/tests/files.bak/files/time11_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time11_stdlibs.gno rename to gnovm/tests/files.bak/files/time11_stdlibs.gno diff --git a/gnovm/tests/files/time12_native.gno b/gnovm/tests/files.bak/files/time12_native.gno similarity index 100% rename from gnovm/tests/files/time12_native.gno rename to gnovm/tests/files.bak/files/time12_native.gno diff --git a/gnovm/tests/files/time12_stdlibs.gno b/gnovm/tests/files.bak/files/time12_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time12_stdlibs.gno rename to gnovm/tests/files.bak/files/time12_stdlibs.gno diff --git a/gnovm/tests/files/time13_native.gno b/gnovm/tests/files.bak/files/time13_native.gno similarity index 100% rename from gnovm/tests/files/time13_native.gno rename to gnovm/tests/files.bak/files/time13_native.gno diff --git a/gnovm/tests/files/time13_stdlibs.gno b/gnovm/tests/files.bak/files/time13_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time13_stdlibs.gno rename to gnovm/tests/files.bak/files/time13_stdlibs.gno diff --git a/gnovm/tests/files/time14_native.gno b/gnovm/tests/files.bak/files/time14_native.gno similarity index 100% rename from gnovm/tests/files/time14_native.gno rename to gnovm/tests/files.bak/files/time14_native.gno diff --git a/gnovm/tests/files/time14_stdlibs.gno b/gnovm/tests/files.bak/files/time14_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time14_stdlibs.gno rename to gnovm/tests/files.bak/files/time14_stdlibs.gno diff --git a/gnovm/tests/files/time15.gno b/gnovm/tests/files.bak/files/time15.gno similarity index 100% rename from gnovm/tests/files/time15.gno rename to gnovm/tests/files.bak/files/time15.gno diff --git a/gnovm/tests/files/time1_native.gno b/gnovm/tests/files.bak/files/time1_native.gno similarity index 100% rename from gnovm/tests/files/time1_native.gno rename to gnovm/tests/files.bak/files/time1_native.gno diff --git a/gnovm/tests/files/time1_stdlibs.gno b/gnovm/tests/files.bak/files/time1_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time1_stdlibs.gno rename to gnovm/tests/files.bak/files/time1_stdlibs.gno diff --git a/gnovm/tests/files/time2_native.gno b/gnovm/tests/files.bak/files/time2_native.gno similarity index 100% rename from gnovm/tests/files/time2_native.gno rename to gnovm/tests/files.bak/files/time2_native.gno diff --git a/gnovm/tests/files/time2_stdlibs.gno b/gnovm/tests/files.bak/files/time2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time2_stdlibs.gno rename to gnovm/tests/files.bak/files/time2_stdlibs.gno diff --git a/gnovm/tests/files/time3_native.gno b/gnovm/tests/files.bak/files/time3_native.gno similarity index 100% rename from gnovm/tests/files/time3_native.gno rename to gnovm/tests/files.bak/files/time3_native.gno diff --git a/gnovm/tests/files/time3_stdlibs.gno b/gnovm/tests/files.bak/files/time3_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time3_stdlibs.gno rename to gnovm/tests/files.bak/files/time3_stdlibs.gno diff --git a/gnovm/tests/files/time4_native.gno b/gnovm/tests/files.bak/files/time4_native.gno similarity index 100% rename from gnovm/tests/files/time4_native.gno rename to gnovm/tests/files.bak/files/time4_native.gno diff --git a/gnovm/tests/files/time4_stdlibs.gno b/gnovm/tests/files.bak/files/time4_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time4_stdlibs.gno rename to gnovm/tests/files.bak/files/time4_stdlibs.gno diff --git a/gnovm/tests/files/time6_native.gno b/gnovm/tests/files.bak/files/time6_native.gno similarity index 100% rename from gnovm/tests/files/time6_native.gno rename to gnovm/tests/files.bak/files/time6_native.gno diff --git a/gnovm/tests/files/time6_stdlibs.gno b/gnovm/tests/files.bak/files/time6_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time6_stdlibs.gno rename to gnovm/tests/files.bak/files/time6_stdlibs.gno diff --git a/gnovm/tests/files/time7_native.gno b/gnovm/tests/files.bak/files/time7_native.gno similarity index 100% rename from gnovm/tests/files/time7_native.gno rename to gnovm/tests/files.bak/files/time7_native.gno diff --git a/gnovm/tests/files/time7_stdlibs.gno b/gnovm/tests/files.bak/files/time7_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time7_stdlibs.gno rename to gnovm/tests/files.bak/files/time7_stdlibs.gno diff --git a/gnovm/tests/files/time8.gno b/gnovm/tests/files.bak/files/time8.gno similarity index 100% rename from gnovm/tests/files/time8.gno rename to gnovm/tests/files.bak/files/time8.gno diff --git a/gnovm/tests/files/time9_native.gno b/gnovm/tests/files.bak/files/time9_native.gno similarity index 100% rename from gnovm/tests/files/time9_native.gno rename to gnovm/tests/files.bak/files/time9_native.gno diff --git a/gnovm/tests/files/time9_stdlibs.gno b/gnovm/tests/files.bak/files/time9_stdlibs.gno similarity index 100% rename from gnovm/tests/files/time9_stdlibs.gno rename to gnovm/tests/files.bak/files/time9_stdlibs.gno diff --git a/gnovm/tests/files/type0.gno b/gnovm/tests/files.bak/files/type0.gno similarity index 100% rename from gnovm/tests/files/type0.gno rename to gnovm/tests/files.bak/files/type0.gno diff --git a/gnovm/tests/files/type1.gno b/gnovm/tests/files.bak/files/type1.gno similarity index 100% rename from gnovm/tests/files/type1.gno rename to gnovm/tests/files.bak/files/type1.gno diff --git a/gnovm/tests/files/type11.gno b/gnovm/tests/files.bak/files/type11.gno similarity index 100% rename from gnovm/tests/files/type11.gno rename to gnovm/tests/files.bak/files/type11.gno diff --git a/gnovm/tests/files/type12.gno b/gnovm/tests/files.bak/files/type12.gno similarity index 100% rename from gnovm/tests/files/type12.gno rename to gnovm/tests/files.bak/files/type12.gno diff --git a/gnovm/tests/files/type13.gno b/gnovm/tests/files.bak/files/type13.gno similarity index 100% rename from gnovm/tests/files/type13.gno rename to gnovm/tests/files.bak/files/type13.gno diff --git a/gnovm/tests/files/type14.gno b/gnovm/tests/files.bak/files/type14.gno similarity index 100% rename from gnovm/tests/files/type14.gno rename to gnovm/tests/files.bak/files/type14.gno diff --git a/gnovm/tests/files/type15.gno b/gnovm/tests/files.bak/files/type15.gno similarity index 100% rename from gnovm/tests/files/type15.gno rename to gnovm/tests/files.bak/files/type15.gno diff --git a/gnovm/tests/files/type16.gno b/gnovm/tests/files.bak/files/type16.gno similarity index 100% rename from gnovm/tests/files/type16.gno rename to gnovm/tests/files.bak/files/type16.gno diff --git a/gnovm/tests/files/type17.gno b/gnovm/tests/files.bak/files/type17.gno similarity index 100% rename from gnovm/tests/files/type17.gno rename to gnovm/tests/files.bak/files/type17.gno diff --git a/gnovm/tests/files/type18.gno b/gnovm/tests/files.bak/files/type18.gno similarity index 100% rename from gnovm/tests/files/type18.gno rename to gnovm/tests/files.bak/files/type18.gno diff --git a/gnovm/tests/files/type19.gno b/gnovm/tests/files.bak/files/type19.gno similarity index 100% rename from gnovm/tests/files/type19.gno rename to gnovm/tests/files.bak/files/type19.gno diff --git a/gnovm/tests/files/type20.gno b/gnovm/tests/files.bak/files/type20.gno similarity index 100% rename from gnovm/tests/files/type20.gno rename to gnovm/tests/files.bak/files/type20.gno diff --git a/gnovm/tests/files/type22.gno b/gnovm/tests/files.bak/files/type22.gno similarity index 100% rename from gnovm/tests/files/type22.gno rename to gnovm/tests/files.bak/files/type22.gno diff --git a/gnovm/tests/files/type23b.gno b/gnovm/tests/files.bak/files/type23b.gno similarity index 100% rename from gnovm/tests/files/type23b.gno rename to gnovm/tests/files.bak/files/type23b.gno diff --git a/gnovm/tests/files/type24b.gno b/gnovm/tests/files.bak/files/type24b.gno similarity index 100% rename from gnovm/tests/files/type24b.gno rename to gnovm/tests/files.bak/files/type24b.gno diff --git a/gnovm/tests/files/type2_native.gno b/gnovm/tests/files.bak/files/type2_native.gno similarity index 100% rename from gnovm/tests/files/type2_native.gno rename to gnovm/tests/files.bak/files/type2_native.gno diff --git a/gnovm/tests/files/type2_stdlibs.gno b/gnovm/tests/files.bak/files/type2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/type2_stdlibs.gno rename to gnovm/tests/files.bak/files/type2_stdlibs.gno diff --git a/gnovm/tests/files/type3.gno b/gnovm/tests/files.bak/files/type3.gno similarity index 100% rename from gnovm/tests/files/type3.gno rename to gnovm/tests/files.bak/files/type3.gno diff --git a/gnovm/tests/files/type30.gno b/gnovm/tests/files.bak/files/type30.gno similarity index 100% rename from gnovm/tests/files/type30.gno rename to gnovm/tests/files.bak/files/type30.gno diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files.bak/files/type31.gno similarity index 100% rename from gnovm/tests/files/type31.gno rename to gnovm/tests/files.bak/files/type31.gno diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files.bak/files/type32.gno similarity index 100% rename from gnovm/tests/files/type32.gno rename to gnovm/tests/files.bak/files/type32.gno diff --git a/gnovm/tests/files/type7.gno b/gnovm/tests/files.bak/files/type7.gno similarity index 100% rename from gnovm/tests/files/type7.gno rename to gnovm/tests/files.bak/files/type7.gno diff --git a/gnovm/tests/files/type8.gno b/gnovm/tests/files.bak/files/type8.gno similarity index 100% rename from gnovm/tests/files/type8.gno rename to gnovm/tests/files.bak/files/type8.gno diff --git a/gnovm/tests/files/unary.gno b/gnovm/tests/files.bak/files/unary.gno similarity index 100% rename from gnovm/tests/files/unary.gno rename to gnovm/tests/files.bak/files/unary.gno diff --git a/gnovm/tests/files/unary1.gno b/gnovm/tests/files.bak/files/unary1.gno similarity index 100% rename from gnovm/tests/files/unary1.gno rename to gnovm/tests/files.bak/files/unary1.gno diff --git a/gnovm/tests/files/untyped0.gno b/gnovm/tests/files.bak/files/untyped0.gno similarity index 100% rename from gnovm/tests/files/untyped0.gno rename to gnovm/tests/files.bak/files/untyped0.gno diff --git a/gnovm/tests/files/untyped1.gno b/gnovm/tests/files.bak/files/untyped1.gno similarity index 100% rename from gnovm/tests/files/untyped1.gno rename to gnovm/tests/files.bak/files/untyped1.gno diff --git a/gnovm/tests/files/var.gno b/gnovm/tests/files.bak/files/var.gno similarity index 100% rename from gnovm/tests/files/var.gno rename to gnovm/tests/files.bak/files/var.gno diff --git a/gnovm/tests/files/var10.gno b/gnovm/tests/files.bak/files/var10.gno similarity index 100% rename from gnovm/tests/files/var10.gno rename to gnovm/tests/files.bak/files/var10.gno diff --git a/gnovm/tests/files/var11.gno b/gnovm/tests/files.bak/files/var11.gno similarity index 100% rename from gnovm/tests/files/var11.gno rename to gnovm/tests/files.bak/files/var11.gno diff --git a/gnovm/tests/files/var12.gno b/gnovm/tests/files.bak/files/var12.gno similarity index 100% rename from gnovm/tests/files/var12.gno rename to gnovm/tests/files.bak/files/var12.gno diff --git a/gnovm/tests/files/var13.gno b/gnovm/tests/files.bak/files/var13.gno similarity index 100% rename from gnovm/tests/files/var13.gno rename to gnovm/tests/files.bak/files/var13.gno diff --git a/gnovm/tests/files/var14.gno b/gnovm/tests/files.bak/files/var14.gno similarity index 100% rename from gnovm/tests/files/var14.gno rename to gnovm/tests/files.bak/files/var14.gno diff --git a/gnovm/tests/files/var15.gno b/gnovm/tests/files.bak/files/var15.gno similarity index 100% rename from gnovm/tests/files/var15.gno rename to gnovm/tests/files.bak/files/var15.gno diff --git a/gnovm/tests/files/var16.gno b/gnovm/tests/files.bak/files/var16.gno similarity index 100% rename from gnovm/tests/files/var16.gno rename to gnovm/tests/files.bak/files/var16.gno diff --git a/gnovm/tests/files/var17.gno b/gnovm/tests/files.bak/files/var17.gno similarity index 100% rename from gnovm/tests/files/var17.gno rename to gnovm/tests/files.bak/files/var17.gno diff --git a/gnovm/tests/files/var2.gno b/gnovm/tests/files.bak/files/var2.gno similarity index 100% rename from gnovm/tests/files/var2.gno rename to gnovm/tests/files.bak/files/var2.gno diff --git a/gnovm/tests/files/var3.gno b/gnovm/tests/files.bak/files/var3.gno similarity index 100% rename from gnovm/tests/files/var3.gno rename to gnovm/tests/files.bak/files/var3.gno diff --git a/gnovm/tests/files/var4.gno b/gnovm/tests/files.bak/files/var4.gno similarity index 100% rename from gnovm/tests/files/var4.gno rename to gnovm/tests/files.bak/files/var4.gno diff --git a/gnovm/tests/files/var5.gno b/gnovm/tests/files.bak/files/var5.gno similarity index 100% rename from gnovm/tests/files/var5.gno rename to gnovm/tests/files.bak/files/var5.gno diff --git a/gnovm/tests/files/var6.gno b/gnovm/tests/files.bak/files/var6.gno similarity index 100% rename from gnovm/tests/files/var6.gno rename to gnovm/tests/files.bak/files/var6.gno diff --git a/gnovm/tests/files/var7.gno b/gnovm/tests/files.bak/files/var7.gno similarity index 100% rename from gnovm/tests/files/var7.gno rename to gnovm/tests/files.bak/files/var7.gno diff --git a/gnovm/tests/files/var9.gno b/gnovm/tests/files.bak/files/var9.gno similarity index 100% rename from gnovm/tests/files/var9.gno rename to gnovm/tests/files.bak/files/var9.gno diff --git a/gnovm/tests/files/variadic.gno b/gnovm/tests/files.bak/files/variadic.gno similarity index 100% rename from gnovm/tests/files/variadic.gno rename to gnovm/tests/files.bak/files/variadic.gno diff --git a/gnovm/tests/files/variadic0.gno b/gnovm/tests/files.bak/files/variadic0.gno similarity index 100% rename from gnovm/tests/files/variadic0.gno rename to gnovm/tests/files.bak/files/variadic0.gno diff --git a/gnovm/tests/files/variadic1.gno b/gnovm/tests/files.bak/files/variadic1.gno similarity index 100% rename from gnovm/tests/files/variadic1.gno rename to gnovm/tests/files.bak/files/variadic1.gno diff --git a/gnovm/tests/files/variadic2.gno b/gnovm/tests/files.bak/files/variadic2.gno similarity index 100% rename from gnovm/tests/files/variadic2.gno rename to gnovm/tests/files.bak/files/variadic2.gno diff --git a/gnovm/tests/files/variadic3.gno b/gnovm/tests/files.bak/files/variadic3.gno similarity index 100% rename from gnovm/tests/files/variadic3.gno rename to gnovm/tests/files.bak/files/variadic3.gno diff --git a/gnovm/tests/files/variadic4.gno b/gnovm/tests/files.bak/files/variadic4.gno similarity index 100% rename from gnovm/tests/files/variadic4.gno rename to gnovm/tests/files.bak/files/variadic4.gno diff --git a/gnovm/tests/files/variadic5.gno b/gnovm/tests/files.bak/files/variadic5.gno similarity index 100% rename from gnovm/tests/files/variadic5.gno rename to gnovm/tests/files.bak/files/variadic5.gno diff --git a/gnovm/tests/files/variadic6.gno b/gnovm/tests/files.bak/files/variadic6.gno similarity index 100% rename from gnovm/tests/files/variadic6.gno rename to gnovm/tests/files.bak/files/variadic6.gno diff --git a/gnovm/tests/files/variadic9.gno b/gnovm/tests/files.bak/files/variadic9.gno similarity index 100% rename from gnovm/tests/files/variadic9.gno rename to gnovm/tests/files.bak/files/variadic9.gno diff --git a/gnovm/tests/files/xfactor_long.gno b/gnovm/tests/files.bak/files/xfactor_long.gno similarity index 100% rename from gnovm/tests/files/xfactor_long.gno rename to gnovm/tests/files.bak/files/xfactor_long.gno diff --git a/gnovm/tests/files/xfib_long.gno b/gnovm/tests/files.bak/files/xfib_long.gno similarity index 100% rename from gnovm/tests/files/xfib_long.gno rename to gnovm/tests/files.bak/files/xfib_long.gno diff --git a/gnovm/tests/files/zavltree.gno b/gnovm/tests/files.bak/files/zavltree.gno similarity index 100% rename from gnovm/tests/files/zavltree.gno rename to gnovm/tests/files.bak/files/zavltree.gno diff --git a/gnovm/tests/files/zavltree0.gno b/gnovm/tests/files.bak/files/zavltree0.gno similarity index 100% rename from gnovm/tests/files/zavltree0.gno rename to gnovm/tests/files.bak/files/zavltree0.gno diff --git a/gnovm/tests/files/zavltree1.gno b/gnovm/tests/files.bak/files/zavltree1.gno similarity index 100% rename from gnovm/tests/files/zavltree1.gno rename to gnovm/tests/files.bak/files/zavltree1.gno diff --git a/gnovm/tests/files/zpersist_valids.gno b/gnovm/tests/files.bak/files/zpersist_valids.gno similarity index 100% rename from gnovm/tests/files/zpersist_valids.gno rename to gnovm/tests/files.bak/files/zpersist_valids.gno diff --git a/gnovm/tests/files/zrealm0.gno b/gnovm/tests/files.bak/files/zrealm0.gno similarity index 100% rename from gnovm/tests/files/zrealm0.gno rename to gnovm/tests/files.bak/files/zrealm0.gno diff --git a/gnovm/tests/files/zrealm1.gno b/gnovm/tests/files.bak/files/zrealm1.gno similarity index 100% rename from gnovm/tests/files/zrealm1.gno rename to gnovm/tests/files.bak/files/zrealm1.gno diff --git a/gnovm/tests/files/zrealm10.gno b/gnovm/tests/files.bak/files/zrealm10.gno similarity index 100% rename from gnovm/tests/files/zrealm10.gno rename to gnovm/tests/files.bak/files/zrealm10.gno diff --git a/gnovm/tests/files/zrealm11.gno b/gnovm/tests/files.bak/files/zrealm11.gno similarity index 100% rename from gnovm/tests/files/zrealm11.gno rename to gnovm/tests/files.bak/files/zrealm11.gno diff --git a/gnovm/tests/files/zrealm12.gno b/gnovm/tests/files.bak/files/zrealm12.gno similarity index 100% rename from gnovm/tests/files/zrealm12.gno rename to gnovm/tests/files.bak/files/zrealm12.gno diff --git a/gnovm/tests/files/zrealm2.gno b/gnovm/tests/files.bak/files/zrealm2.gno similarity index 100% rename from gnovm/tests/files/zrealm2.gno rename to gnovm/tests/files.bak/files/zrealm2.gno diff --git a/gnovm/tests/files/zrealm3.gno b/gnovm/tests/files.bak/files/zrealm3.gno similarity index 100% rename from gnovm/tests/files/zrealm3.gno rename to gnovm/tests/files.bak/files/zrealm3.gno diff --git a/gnovm/tests/files/zrealm4.gno b/gnovm/tests/files.bak/files/zrealm4.gno similarity index 100% rename from gnovm/tests/files/zrealm4.gno rename to gnovm/tests/files.bak/files/zrealm4.gno diff --git a/gnovm/tests/files/zrealm5.gno b/gnovm/tests/files.bak/files/zrealm5.gno similarity index 100% rename from gnovm/tests/files/zrealm5.gno rename to gnovm/tests/files.bak/files/zrealm5.gno diff --git a/gnovm/tests/files/zrealm6.gno b/gnovm/tests/files.bak/files/zrealm6.gno similarity index 100% rename from gnovm/tests/files/zrealm6.gno rename to gnovm/tests/files.bak/files/zrealm6.gno diff --git a/gnovm/tests/files/zrealm7.gno b/gnovm/tests/files.bak/files/zrealm7.gno similarity index 100% rename from gnovm/tests/files/zrealm7.gno rename to gnovm/tests/files.bak/files/zrealm7.gno diff --git a/gnovm/tests/files/zrealm8.gno b/gnovm/tests/files.bak/files/zrealm8.gno similarity index 100% rename from gnovm/tests/files/zrealm8.gno rename to gnovm/tests/files.bak/files/zrealm8.gno diff --git a/gnovm/tests/files/zrealm9.gno b/gnovm/tests/files.bak/files/zrealm9.gno similarity index 100% rename from gnovm/tests/files/zrealm9.gno rename to gnovm/tests/files.bak/files/zrealm9.gno diff --git a/gnovm/tests/files/zrealm_avl0.gno b/gnovm/tests/files.bak/files/zrealm_avl0.gno similarity index 100% rename from gnovm/tests/files/zrealm_avl0.gno rename to gnovm/tests/files.bak/files/zrealm_avl0.gno diff --git a/gnovm/tests/files/zrealm_avl1.gno b/gnovm/tests/files.bak/files/zrealm_avl1.gno similarity index 100% rename from gnovm/tests/files/zrealm_avl1.gno rename to gnovm/tests/files.bak/files/zrealm_avl1.gno diff --git a/gnovm/tests/files/zrealm_avl2.gno b/gnovm/tests/files.bak/files/zrealm_avl2.gno similarity index 100% rename from gnovm/tests/files/zrealm_avl2.gno rename to gnovm/tests/files.bak/files/zrealm_avl2.gno diff --git a/gnovm/tests/files/zrealm_const.gno b/gnovm/tests/files.bak/files/zrealm_const.gno similarity index 100% rename from gnovm/tests/files/zrealm_const.gno rename to gnovm/tests/files.bak/files/zrealm_const.gno diff --git a/gnovm/tests/files/zrealm_crossrealm0.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm0.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm0.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm0.gno diff --git a/gnovm/tests/files/zrealm_crossrealm1.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm1.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm1.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm1.gno diff --git a/gnovm/tests/files/zrealm_crossrealm10.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm10.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm10.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm10.gno diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm11.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm11.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm11.gno diff --git a/gnovm/tests/files/zrealm_crossrealm12.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm12.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm12.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm12.gno diff --git a/gnovm/tests/files/zrealm_crossrealm2.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm2.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm2.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm2.gno diff --git a/gnovm/tests/files/zrealm_crossrealm3.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm3.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm3.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm3.gno diff --git a/gnovm/tests/files/zrealm_crossrealm4.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm4.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm4.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm4.gno diff --git a/gnovm/tests/files/zrealm_crossrealm5.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm5.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm5.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm5.gno diff --git a/gnovm/tests/files/zrealm_crossrealm6.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm6.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm6.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm6.gno diff --git a/gnovm/tests/files/zrealm_crossrealm7.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm7.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm7.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm7.gno diff --git a/gnovm/tests/files/zrealm_crossrealm8.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm8.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm8.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm8.gno diff --git a/gnovm/tests/files/zrealm_crossrealm9.gno b/gnovm/tests/files.bak/files/zrealm_crossrealm9.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm9.gno rename to gnovm/tests/files.bak/files/zrealm_crossrealm9.gno diff --git a/gnovm/tests/files/zrealm_example.gno b/gnovm/tests/files.bak/files/zrealm_example.gno similarity index 100% rename from gnovm/tests/files/zrealm_example.gno rename to gnovm/tests/files.bak/files/zrealm_example.gno diff --git a/gnovm/tests/files/zrealm_map0.gno b/gnovm/tests/files.bak/files/zrealm_map0.gno similarity index 100% rename from gnovm/tests/files/zrealm_map0.gno rename to gnovm/tests/files.bak/files/zrealm_map0.gno diff --git a/gnovm/tests/files/zrealm_std0.gno b/gnovm/tests/files.bak/files/zrealm_std0.gno similarity index 100% rename from gnovm/tests/files/zrealm_std0.gno rename to gnovm/tests/files.bak/files/zrealm_std0.gno diff --git a/gnovm/tests/files/zrealm_std1.gno b/gnovm/tests/files.bak/files/zrealm_std1.gno similarity index 100% rename from gnovm/tests/files/zrealm_std1.gno rename to gnovm/tests/files.bak/files/zrealm_std1.gno diff --git a/gnovm/tests/files/zrealm_std2.gno b/gnovm/tests/files.bak/files/zrealm_std2.gno similarity index 100% rename from gnovm/tests/files/zrealm_std2.gno rename to gnovm/tests/files.bak/files/zrealm_std2.gno diff --git a/gnovm/tests/files/zrealm_std3.gno b/gnovm/tests/files.bak/files/zrealm_std3.gno similarity index 100% rename from gnovm/tests/files/zrealm_std3.gno rename to gnovm/tests/files.bak/files/zrealm_std3.gno diff --git a/gnovm/tests/files/zrealm_std4.gno b/gnovm/tests/files.bak/files/zrealm_std4.gno similarity index 100% rename from gnovm/tests/files/zrealm_std4.gno rename to gnovm/tests/files.bak/files/zrealm_std4.gno diff --git a/gnovm/tests/files/zrealm_std5.gno b/gnovm/tests/files.bak/files/zrealm_std5.gno similarity index 100% rename from gnovm/tests/files/zrealm_std5.gno rename to gnovm/tests/files.bak/files/zrealm_std5.gno diff --git a/gnovm/tests/files/zrealm_std6.gno b/gnovm/tests/files.bak/files/zrealm_std6.gno similarity index 100% rename from gnovm/tests/files/zrealm_std6.gno rename to gnovm/tests/files.bak/files/zrealm_std6.gno diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files.bak/files/zrealm_tests0.gno similarity index 100% rename from gnovm/tests/files/zrealm_tests0.gno rename to gnovm/tests/files.bak/files/zrealm_tests0.gno diff --git a/gnovm/tests/files/zrealm_testutils0.gno b/gnovm/tests/files.bak/files/zrealm_testutils0.gno similarity index 100% rename from gnovm/tests/files/zrealm_testutils0.gno rename to gnovm/tests/files.bak/files/zrealm_testutils0.gno diff --git a/gnovm/tests/files/zregexp_stdlibs.gno b/gnovm/tests/files.bak/files/zregexp_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zregexp_stdlibs.gno rename to gnovm/tests/files.bak/files/zregexp_stdlibs.gno diff --git a/gnovm/tests/files/zsolitaire_long.gno b/gnovm/tests/files.bak/files/zsolitaire_long.gno similarity index 100% rename from gnovm/tests/files/zsolitaire_long.gno rename to gnovm/tests/files.bak/files/zsolitaire_long.gno diff --git a/gnovm/tests/files/types/0a0_filetest.gno b/gnovm/tests/files/types/0a0_filetest.gno new file mode 100644 index 00000000000..24fbd6b7516 --- /dev/null +++ b/gnovm/tests/files/types/0a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) == int8(1)) +} + +// Error: +// main/files/types/0a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/0a1_filetest.gno b/gnovm/tests/files/types/0a1_filetest.gno new file mode 100644 index 00000000000..10373e92992 --- /dev/null +++ b/gnovm/tests/files/types/0a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) != int8(1)) +} + +// Error: +// main/files/types/0a1_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/0a2_filetest.gno b/gnovm/tests/files/types/0a2_filetest.gno new file mode 100644 index 00000000000..3c28a8eb12c --- /dev/null +++ b/gnovm/tests/files/types/0a2_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) == Error2(0)) +} + +// Error: +// main/files/types/0a2_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0a3_filetest.gno b/gnovm/tests/files/types/0a3_filetest.gno new file mode 100644 index 00000000000..6767d7aae9f --- /dev/null +++ b/gnovm/tests/files/types/0a3_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) != Error2(0)) +} + +// Error: +// main/files/types/0a3_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0a4_filetest.gno b/gnovm/tests/files/types/0a4_filetest.gno new file mode 100644 index 00000000000..f44f895a779 --- /dev/null +++ b/gnovm/tests/files/types/0a4_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) != Error2(0)) +} + +// Error: +// main/files/types/0a4_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0a5_filetest.gno b/gnovm/tests/files/types/0a5_filetest.gno new file mode 100644 index 00000000000..fe05f7c1124 --- /dev/null +++ b/gnovm/tests/files/types/0a5_filetest.gno @@ -0,0 +1,16 @@ +package main + +var r rune + +// TODO: print right dec, float +func main() { + r = 'a' + println(r) + println(float32(r)) + println(float64(r)) +} + +// Output: +// 97 +// 97 +// 97 diff --git a/gnovm/tests/files/types/0b0_filetest.gno b/gnovm/tests/files/types/0b0_filetest.gno new file mode 100644 index 00000000000..ee1b1c11ac0 --- /dev/null +++ b/gnovm/tests/files/types/0b0_filetest.gno @@ -0,0 +1,26 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is untyped const, right is typed const +// untyped value can be converted to its correspondence value when: +// a) it's (untyped) const +// b) it's declared type of value, like type Error int8, 0 will be able to converted to Error +func main() { + if 1 == Error(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// what the firetruck? diff --git a/examples/gno.land/p/demo/challenge/1a_filetest.gno b/gnovm/tests/files/types/0b1_filetest.gno similarity index 75% rename from examples/gno.land/p/demo/challenge/1a_filetest.gno rename to gnovm/tests/files/types/0b1_filetest.gno index 624e8dbab16..a7bdf5275da 100644 --- a/examples/gno.land/p/demo/challenge/1a_filetest.gno +++ b/gnovm/tests/files/types/0b1_filetest.gno @@ -11,9 +11,8 @@ func (e Error) Error() string { } // left is untyped const, right is typed const -// this is legal since Error is a declared value func main() { - if 1 == Error(1) { + if 1 != Error(1) { println("what the firetruck?") } else { println("something else") @@ -21,4 +20,4 @@ func main() { } // Output: -// what the firetruck? +// something else diff --git a/examples/gno.land/p/demo/challenge/1_filetest.gno b/gnovm/tests/files/types/0c0_filetest.gno similarity index 86% rename from examples/gno.land/p/demo/challenge/1_filetest.gno rename to gnovm/tests/files/types/0c0_filetest.gno index 6b997c23642..c1692c8019c 100644 --- a/examples/gno.land/p/demo/challenge/1_filetest.gno +++ b/gnovm/tests/files/types/0c0_filetest.gno @@ -11,7 +11,6 @@ func (e Error) Error() string { } // left is typed const, right is untyped const -// this is legal since Error is a declared value func main() { if Error(1) == 1 { println("what the firetruck?") diff --git a/gnovm/tests/files/types/0c1_filetest.gno b/gnovm/tests/files/types/0c1_filetest.gno new file mode 100644 index 00000000000..5c597e8482c --- /dev/null +++ b/gnovm/tests/files/types/0c1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is typed const, right is untyped const +func main() { + if Error(1) != 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/examples/gno.land/p/demo/challenge/1b_filetest.gno b/gnovm/tests/files/types/0c2_filetest.gno similarity index 81% rename from examples/gno.land/p/demo/challenge/1b_filetest.gno rename to gnovm/tests/files/types/0c2_filetest.gno index 675adbe7b31..154d96d3623 100644 --- a/examples/gno.land/p/demo/challenge/1b_filetest.gno +++ b/gnovm/tests/files/types/0c2_filetest.gno @@ -21,4 +21,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/1b_filetest.gno:16: bigint overflows target kind +// main/files/types/0c2_filetest.gno:16: bigint overflows target kind diff --git a/gnovm/tests/files/types/0d0_filetest.gno b/gnovm/tests/files/types/0d0_filetest.gno new file mode 100644 index 00000000000..ac965bef23e --- /dev/null +++ b/gnovm/tests/files/types/0d0_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both untyped const +func main() { + println(1.0 == 1) + println(1.0 == 0) +} + +// Output: +// true +// false diff --git a/gnovm/tests/files/types/0e0_filetest.gno b/gnovm/tests/files/types/0e0_filetest.gno new file mode 100644 index 00000000000..fc845f73e1e --- /dev/null +++ b/gnovm/tests/files/types/0e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 == e2) +} + +// Error: +// main/files/types/0e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0e1_filetest.gno b/gnovm/tests/files/types/0e1_filetest.gno new file mode 100644 index 00000000000..ba937d9a110 --- /dev/null +++ b/gnovm/tests/files/types/0e1_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 != e2) +} + +// Error: +// main/files/types/0e1_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/2b_filetest.gno b/gnovm/tests/files/types/0f0_filetest.gno similarity index 68% rename from examples/gno.land/p/demo/challenge/2b_filetest.gno rename to gnovm/tests/files/types/0f0_filetest.gno index 48f02f43abd..d25609c8ab7 100644 --- a/examples/gno.land/p/demo/challenge/2b_filetest.gno +++ b/gnovm/tests/files/types/0f0_filetest.gno @@ -13,10 +13,11 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// both not const, should not compile +// specil case: +// one is interface func main() { - var a int = 1 - if a == errCmp { + if 1 == errCmp { + //if errCmp == 1 { println("what the firetruck?") } else { println("something else") @@ -24,4 +25,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/2b_filetest.gno:19: int does not implement .uverse.error +// main/files/types/0f0_filetest.gno:19: bigint does not implement .uverse.error diff --git a/gnovm/tests/files/types/0f10_filetest.gno b/gnovm/tests/files/types/0f10_filetest.gno new file mode 100644 index 00000000000..c2c99dea9c3 --- /dev/null +++ b/gnovm/tests/files/types/0f10_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 == e2) +} + +// Output: +// false diff --git a/examples/gno.land/p/demo/challenge/2a_filetest.gno b/gnovm/tests/files/types/0f1_filetest.gno similarity index 60% rename from examples/gno.land/p/demo/challenge/2a_filetest.gno rename to gnovm/tests/files/types/0f1_filetest.gno index 4de239c4158..255cfb2b170 100644 --- a/examples/gno.land/p/demo/challenge/2a_filetest.gno +++ b/gnovm/tests/files/types/0f1_filetest.gno @@ -13,9 +13,11 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// left is typed const, right is not const, should not compile +// specil case: +// one is interface func main() { - if int(1) == errCmp { + if int64(1) == errCmp { + //if errCmp == 1 { println("what the firetruck?") } else { println("something else") @@ -23,4 +25,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/2a_filetest.gno:18: int does not implement .uverse.error +// main/files/types/0f1_filetest.gno:19: int64 does not implement .uverse.error diff --git a/examples/gno.land/p/demo/challenge/2c_filetest.gno b/gnovm/tests/files/types/0f2_filetest.gno similarity index 68% rename from examples/gno.land/p/demo/challenge/2c_filetest.gno rename to gnovm/tests/files/types/0f2_filetest.gno index aa9b5a34f7c..d963f28565f 100644 --- a/examples/gno.land/p/demo/challenge/2c_filetest.gno +++ b/gnovm/tests/files/types/0f2_filetest.gno @@ -13,13 +13,16 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") +// specil case: +// one is interface func main() { - if errCmp == int(1) { + if Error(0) == errCmp { + //if errCmp == 1 { println("what the firetruck?") } else { println("something else") } } -// Error: -// main/gno.land/p/demo/challenge/2c_filetest.gno:17: int does not implement .uverse.error +// Output: +// something else diff --git a/gnovm/tests/files/types/0f3_filetest.gno b/gnovm/tests/files/types/0f3_filetest.gno new file mode 100644 index 00000000000..0e9b0987cb7 --- /dev/null +++ b/gnovm/tests/files/types/0f3_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(1) == errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/0f4_filetest.gno b/gnovm/tests/files/types/0f4_filetest.gno new file mode 100644 index 00000000000..e213b50e8de --- /dev/null +++ b/gnovm/tests/files/types/0f4_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) != errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/0f5_filetest.gno b/gnovm/tests/files/types/0f5_filetest.gno new file mode 100644 index 00000000000..7ab387f38c4 --- /dev/null +++ b/gnovm/tests/files/types/0f5_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(1) != errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/0f6_filetest.gno b/gnovm/tests/files/types/0f6_filetest.gno new file mode 100644 index 00000000000..501d54dce64 --- /dev/null +++ b/gnovm/tests/files/types/0f6_filetest.gno @@ -0,0 +1,8 @@ +package main + +// TODO: declared(unamed type) logic +type Error []string + +func main() { + +} diff --git a/gnovm/tests/files/types/0f7_filetest.gno b/gnovm/tests/files/types/0f7_filetest.gno new file mode 100644 index 00000000000..174ca2bca90 --- /dev/null +++ b/gnovm/tests/files/types/0f7_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if errCmp == Error(1) { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/examples/gno.land/p/demo/challenge/2_filetest.gno b/gnovm/tests/files/types/0f8_filetest.gno similarity index 51% rename from examples/gno.land/p/demo/challenge/2_filetest.gno rename to gnovm/tests/files/types/0f8_filetest.gno index e7151a8c571..114655295f5 100644 --- a/examples/gno.land/p/demo/challenge/2_filetest.gno +++ b/gnovm/tests/files/types/0f8_filetest.gno @@ -13,11 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// left is untyped const, right is not const -// compile fail since the untyped 1 doesn't conform error interface +// specil case: +// one is interface func main() { - if 1 == errCmp { - //if errCmp == 1 { + if errCmp == int64(1) { println("what the firetruck?") } else { println("something else") @@ -25,4 +24,4 @@ func main() { } // Error: -// main/gno.land/p/demo/challenge/2_filetest.gno:19: bigint does not implement .uverse.error +// main/files/types/0f8_filetest.gno:19: int64 does not implement .uverse.error diff --git a/gnovm/tests/files/types/0f9_filetest.gno b/gnovm/tests/files/types/0f9_filetest.gno new file mode 100644 index 00000000000..6abc84992ea --- /dev/null +++ b/gnovm/tests/files/types/0f9_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 == e2) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/1a0_filetest.gno b/gnovm/tests/files/types/1a0_filetest.gno new file mode 100644 index 00000000000..874c9a3d288 --- /dev/null +++ b/gnovm/tests/files/types/1a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) + int8(1)) +} + +// Error: +// main/files/types/1a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/1a1_filetest.gno b/gnovm/tests/files/types/1a1_filetest.gno new file mode 100644 index 00000000000..ff236a28012 --- /dev/null +++ b/gnovm/tests/files/types/1a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) + Error2(0)) +} + +// Error: +// main/files/types/1a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/1b0_filetest.gno b/gnovm/tests/files/types/1b0_filetest.gno new file mode 100644 index 00000000000..3790f9d7134 --- /dev/null +++ b/gnovm/tests/files/types/1b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 + Error(1)) + println(Error(1) + 1) +} + +// Output: +// (2 main.Error) +// (2 main.Error) diff --git a/gnovm/tests/files/types/1b1_filetest.gno b/gnovm/tests/files/types/1b1_filetest.gno new file mode 100644 index 00000000000..854ecaa9770 --- /dev/null +++ b/gnovm/tests/files/types/1b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 + Error(1)) + println(Error(1) + 1) +} + +// Output: +// error: 2 +// error: 2 diff --git a/gnovm/tests/files/types/1b2_filetest.gno b/gnovm/tests/files/types/1b2_filetest.gno new file mode 100644 index 00000000000..2181f0d8a77 --- /dev/null +++ b/gnovm/tests/files/types/1b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 + "a") +} + +// Error: +// main/files/types/1b2_filetest.gno:5: cannot use untyped Bigint/Bigdec as StringKind diff --git a/gnovm/tests/files/types/1b3_filetest.gno b/gnovm/tests/files/types/1b3_filetest.gno new file mode 100644 index 00000000000..c8a94c5b6ab --- /dev/null +++ b/gnovm/tests/files/types/1b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" + "a") +} + +// Output: +// ba diff --git a/gnovm/tests/files/types/1d0_filetest.gno b/gnovm/tests/files/types/1d0_filetest.gno new file mode 100644 index 00000000000..9899a65a098 --- /dev/null +++ b/gnovm/tests/files/types/1d0_filetest.gno @@ -0,0 +1,12 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 + 1) + println(1.0 + 0) +} + +// Output: +// 2 +// 1 diff --git a/gnovm/tests/files/types/1d1_filetest.gno b/gnovm/tests/files/types/1d1_filetest.gno new file mode 100644 index 00000000000..7bf7c26565a --- /dev/null +++ b/gnovm/tests/files/types/1d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' + 'b') +} + +// Output: +// 195 diff --git a/gnovm/tests/files/types/1d2_filetest.gno b/gnovm/tests/files/types/1d2_filetest.gno new file mode 100644 index 00000000000..7ea4924a594 --- /dev/null +++ b/gnovm/tests/files/types/1d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r + 'b') +} + +// Output: +// 195 diff --git a/gnovm/tests/files/types/1d3_filetest.gno b/gnovm/tests/files/types/1d3_filetest.gno new file mode 100644 index 00000000000..b130fc98b66 --- /dev/null +++ b/gnovm/tests/files/types/1d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 + r2) +} + +// Output: +// 195 diff --git a/gnovm/tests/files/types/1e0_filetest.gno b/gnovm/tests/files/types/1e0_filetest.gno new file mode 100644 index 00000000000..61c999ce0af --- /dev/null +++ b/gnovm/tests/files/types/1e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 + e2) +} + +// Error: +// main/files/types/1e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/1f0_filetest.gno b/gnovm/tests/files/types/1f0_filetest.gno new file mode 100644 index 00000000000..5353313abc8 --- /dev/null +++ b/gnovm/tests/files/types/1f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 + errCmp) +} + +// Error: +// main/files/types/1f0_filetest.gno:19: + should have operand number or string, while have: .uverse.error diff --git a/gnovm/tests/files/types/1f1_filetest.gno b/gnovm/tests/files/types/1f1_filetest.gno new file mode 100644 index 00000000000..503a138c1ae --- /dev/null +++ b/gnovm/tests/files/types/1f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) + errCmp) +} + +// Error: +// main/files/types/1f1_filetest.gno:19: + should have operand number or string, while have: .uverse.error diff --git a/gnovm/tests/files/types/1f2_filetest.gno b/gnovm/tests/files/types/1f2_filetest.gno new file mode 100644 index 00000000000..1f31ff81350 --- /dev/null +++ b/gnovm/tests/files/types/1f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 + e2) +} + +// Error: +// main/files/types/1f2_filetest.gno:27: + should have operand number or string, while have: main.E diff --git a/gnovm/tests/files/types/2a0_filetest.gno b/gnovm/tests/files/types/2a0_filetest.gno new file mode 100644 index 00000000000..4f3770c39c4 --- /dev/null +++ b/gnovm/tests/files/types/2a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) - int8(1)) +} + +// Error: +// main/files/types/2a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/2a1_filetest.gno b/gnovm/tests/files/types/2a1_filetest.gno new file mode 100644 index 00000000000..53ef6bf03db --- /dev/null +++ b/gnovm/tests/files/types/2a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) - Error2(0)) +} + +// Error: +// main/files/types/2a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/2b0_filetest.gno b/gnovm/tests/files/types/2b0_filetest.gno new file mode 100644 index 00000000000..e629f077bbf --- /dev/null +++ b/gnovm/tests/files/types/2b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 - Error(1)) + println(Error(1) - 1) +} + +// Output: +// (0 main.Error) +// (0 main.Error) diff --git a/gnovm/tests/files/types/2b1_filetest.gno b/gnovm/tests/files/types/2b1_filetest.gno new file mode 100644 index 00000000000..9b1f8975d6b --- /dev/null +++ b/gnovm/tests/files/types/2b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 - Error(1)) + println(Error(1) - 1) +} + +// Output: +// error: 0 +// error: 0 diff --git a/gnovm/tests/files/types/2b2_filetest.gno b/gnovm/tests/files/types/2b2_filetest.gno new file mode 100644 index 00000000000..58634bcf674 --- /dev/null +++ b/gnovm/tests/files/types/2b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 - "a") +} + +// Error: +// main/files/types/2b2_filetest.gno:5: - should have operand number, while have: string diff --git a/gnovm/tests/files/types/2b3_filetest.gno b/gnovm/tests/files/types/2b3_filetest.gno new file mode 100644 index 00000000000..2859fcf168d --- /dev/null +++ b/gnovm/tests/files/types/2b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" - "a") +} + +// Error: +// main/files/types/2b3_filetest.gno:5: - should have operand number, while have: string diff --git a/gnovm/tests/files/types/2d0_filetest.gno b/gnovm/tests/files/types/2d0_filetest.gno new file mode 100644 index 00000000000..d70c28a49ae --- /dev/null +++ b/gnovm/tests/files/types/2d0_filetest.gno @@ -0,0 +1,12 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 - 1) + println(1.0 - 0) +} + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/types/2d1_filetest.gno b/gnovm/tests/files/types/2d1_filetest.gno new file mode 100644 index 00000000000..b8e6b5d690a --- /dev/null +++ b/gnovm/tests/files/types/2d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' - 'b') +} + +// Output: +// -1 diff --git a/gnovm/tests/files/types/2d2_filetest.gno b/gnovm/tests/files/types/2d2_filetest.gno new file mode 100644 index 00000000000..033d27cab6a --- /dev/null +++ b/gnovm/tests/files/types/2d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r - 'b') +} + +// Output: +// -1 diff --git a/gnovm/tests/files/types/2d3_filetest.gno b/gnovm/tests/files/types/2d3_filetest.gno new file mode 100644 index 00000000000..a24b404a39d --- /dev/null +++ b/gnovm/tests/files/types/2d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 - r2) +} + +// Output: +// -1 diff --git a/gnovm/tests/files/types/2e0_filetest.gno b/gnovm/tests/files/types/2e0_filetest.gno new file mode 100644 index 00000000000..42d9b638e12 --- /dev/null +++ b/gnovm/tests/files/types/2e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 - e2) +} + +// Error: +// main/files/types/2e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/2f0_filetest.gno b/gnovm/tests/files/types/2f0_filetest.gno new file mode 100644 index 00000000000..fe76480b1ff --- /dev/null +++ b/gnovm/tests/files/types/2f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 - errCmp) +} + +// Error: +// main/files/types/2f0_filetest.gno:19: - should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/2f1_filetest.gno b/gnovm/tests/files/types/2f1_filetest.gno new file mode 100644 index 00000000000..86f5c3a2bbc --- /dev/null +++ b/gnovm/tests/files/types/2f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) - errCmp) +} + +// Error: +// main/files/types/2f1_filetest.gno:19: - should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/2f2_filetest.gno b/gnovm/tests/files/types/2f2_filetest.gno new file mode 100644 index 00000000000..f0c7382f16c --- /dev/null +++ b/gnovm/tests/files/types/2f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 - e2) +} + +// Error: +// main/files/types/2f2_filetest.gno:27: - should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/3a0_filetest.gno b/gnovm/tests/files/types/3a0_filetest.gno new file mode 100644 index 00000000000..53e130ddce7 --- /dev/null +++ b/gnovm/tests/files/types/3a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) * int8(1)) +} + +// Error: +// main/files/types/3a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/3a1_filetest.gno b/gnovm/tests/files/types/3a1_filetest.gno new file mode 100644 index 00000000000..0244780e786 --- /dev/null +++ b/gnovm/tests/files/types/3a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) * Error2(0)) +} + +// Error: +// main/files/types/3a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/3b0_filetest.gno b/gnovm/tests/files/types/3b0_filetest.gno new file mode 100644 index 00000000000..47e63fc0239 --- /dev/null +++ b/gnovm/tests/files/types/3b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 * Error(1)) + println(Error(1) * 1) +} + +// Output: +// (1 main.Error) +// (1 main.Error) diff --git a/gnovm/tests/files/types/3b1_filetest.gno b/gnovm/tests/files/types/3b1_filetest.gno new file mode 100644 index 00000000000..83287928d2c --- /dev/null +++ b/gnovm/tests/files/types/3b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 * Error(1)) + println(Error(1) * 1) +} + +// Output: +// error: 1 +// error: 1 diff --git a/gnovm/tests/files/types/3b2_filetest.gno b/gnovm/tests/files/types/3b2_filetest.gno new file mode 100644 index 00000000000..b31aca67a77 --- /dev/null +++ b/gnovm/tests/files/types/3b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 * "a") +} + +// Error: +// main/files/types/3b2_filetest.gno:5: * should have operand number, while have: string diff --git a/gnovm/tests/files/types/3b3_filetest.gno b/gnovm/tests/files/types/3b3_filetest.gno new file mode 100644 index 00000000000..a2c4186be7a --- /dev/null +++ b/gnovm/tests/files/types/3b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" * "a") +} + +// Error: +// main/files/types/3b3_filetest.gno:5: * should have operand number, while have: string diff --git a/gnovm/tests/files/types/3d0_filetest.gno b/gnovm/tests/files/types/3d0_filetest.gno new file mode 100644 index 00000000000..3744115197e --- /dev/null +++ b/gnovm/tests/files/types/3d0_filetest.gno @@ -0,0 +1,12 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 * 1) + println(1.0 * 0) +} + +// Output: +// 1 +// 0 diff --git a/gnovm/tests/files/types/3d1_filetest.gno b/gnovm/tests/files/types/3d1_filetest.gno new file mode 100644 index 00000000000..b8929345e2b --- /dev/null +++ b/gnovm/tests/files/types/3d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' * 'b') +} + +// Output: +// 9506 diff --git a/gnovm/tests/files/types/3d2_filetest.gno b/gnovm/tests/files/types/3d2_filetest.gno new file mode 100644 index 00000000000..b45d9d99b4c --- /dev/null +++ b/gnovm/tests/files/types/3d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r * 'b') +} + +// Output: +// 9506 diff --git a/gnovm/tests/files/types/3d3_filetest.gno b/gnovm/tests/files/types/3d3_filetest.gno new file mode 100644 index 00000000000..a24b404a39d --- /dev/null +++ b/gnovm/tests/files/types/3d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 - r2) +} + +// Output: +// -1 diff --git a/gnovm/tests/files/types/3e0_filetest.gno b/gnovm/tests/files/types/3e0_filetest.gno new file mode 100644 index 00000000000..0916d0acede --- /dev/null +++ b/gnovm/tests/files/types/3e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 * e2) +} + +// Error: +// main/files/types/3e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/3f0_filetest.gno b/gnovm/tests/files/types/3f0_filetest.gno new file mode 100644 index 00000000000..7cfe92453c9 --- /dev/null +++ b/gnovm/tests/files/types/3f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 * errCmp) +} + +// Error: +// main/files/types/3f0_filetest.gno:19: * should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/3f1_filetest.gno b/gnovm/tests/files/types/3f1_filetest.gno new file mode 100644 index 00000000000..d23cb28675f --- /dev/null +++ b/gnovm/tests/files/types/3f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) * errCmp) +} + +// Error: +// main/files/types/3f1_filetest.gno:19: * should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/3f2_filetest.gno b/gnovm/tests/files/types/3f2_filetest.gno new file mode 100644 index 00000000000..097e3e8ba1d --- /dev/null +++ b/gnovm/tests/files/types/3f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 * e2) +} + +// Error: +// main/files/types/3f2_filetest.gno:27: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/4a0_filetest.gno b/gnovm/tests/files/types/4a0_filetest.gno new file mode 100644 index 00000000000..6b9909c16d1 --- /dev/null +++ b/gnovm/tests/files/types/4a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) / int8(1)) +} + +// Error: +// main/files/types/4a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/4a1_filetest.gno b/gnovm/tests/files/types/4a1_filetest.gno new file mode 100644 index 00000000000..9142b04f57f --- /dev/null +++ b/gnovm/tests/files/types/4a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) / Error2(0)) +} + +// Error: +// main/files/types/4a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/4b0_filetest.gno b/gnovm/tests/files/types/4b0_filetest.gno new file mode 100644 index 00000000000..00b5091f9f7 --- /dev/null +++ b/gnovm/tests/files/types/4b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 / Error(1)) + println(Error(1) / 1) +} + +// Output: +// (1 main.Error) +// (1 main.Error) diff --git a/gnovm/tests/files/types/4b1_filetest.gno b/gnovm/tests/files/types/4b1_filetest.gno new file mode 100644 index 00000000000..af2b1839164 --- /dev/null +++ b/gnovm/tests/files/types/4b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 / Error(1)) + println(Error(1) / 1) +} + +// Output: +// error: 1 +// error: 1 diff --git a/gnovm/tests/files/types/4b2_filetest.gno b/gnovm/tests/files/types/4b2_filetest.gno new file mode 100644 index 00000000000..7279af2df62 --- /dev/null +++ b/gnovm/tests/files/types/4b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 / "a") +} + +// Error: +// main/files/types/4b2_filetest.gno:5: QUO or REM should have operand number, while have: string diff --git a/gnovm/tests/files/types/4b3_filetest.gno b/gnovm/tests/files/types/4b3_filetest.gno new file mode 100644 index 00000000000..b82ea58c37e --- /dev/null +++ b/gnovm/tests/files/types/4b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" / "a") +} + +// Error: +// main/files/types/4b3_filetest.gno:5: QUO or REM should have operand number, while have: string diff --git a/gnovm/tests/files/types/4d0_filetest.gno b/gnovm/tests/files/types/4d0_filetest.gno new file mode 100644 index 00000000000..fde15376a6a --- /dev/null +++ b/gnovm/tests/files/types/4d0_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 / 1) + //println(1.0 / 0) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/4d1_filetest.gno b/gnovm/tests/files/types/4d1_filetest.gno new file mode 100644 index 00000000000..3ace2671ecc --- /dev/null +++ b/gnovm/tests/files/types/4d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' / 'b') +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/4d2_filetest.gno b/gnovm/tests/files/types/4d2_filetest.gno new file mode 100644 index 00000000000..5098fda2662 --- /dev/null +++ b/gnovm/tests/files/types/4d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r / 'b') +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/4d3_filetest.gno b/gnovm/tests/files/types/4d3_filetest.gno new file mode 100644 index 00000000000..0234f80b846 --- /dev/null +++ b/gnovm/tests/files/types/4d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 / r2) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/4d4_filetest.gno b/gnovm/tests/files/types/4d4_filetest.gno new file mode 100644 index 00000000000..df023f067bd --- /dev/null +++ b/gnovm/tests/files/types/4d4_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 / 0) +} + +// Error: +// main/files/types/4d4_filetest.gno:6: bigdec division error: division by zero diff --git a/gnovm/tests/files/types/4e0_filetest.gno b/gnovm/tests/files/types/4e0_filetest.gno new file mode 100644 index 00000000000..6bc2276af1e --- /dev/null +++ b/gnovm/tests/files/types/4e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 / e2) +} + +// Error: +// main/files/types/4e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/4f0_filetest.gno b/gnovm/tests/files/types/4f0_filetest.gno new file mode 100644 index 00000000000..d7072b105c8 --- /dev/null +++ b/gnovm/tests/files/types/4f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 / errCmp) +} + +// Error: +// main/files/types/4f0_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/4f1_filetest.gno b/gnovm/tests/files/types/4f1_filetest.gno new file mode 100644 index 00000000000..5677b827abd --- /dev/null +++ b/gnovm/tests/files/types/4f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) / errCmp) +} + +// Error: +// main/files/types/4f1_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/4f2_filetest.gno b/gnovm/tests/files/types/4f2_filetest.gno new file mode 100644 index 00000000000..b9c345097a9 --- /dev/null +++ b/gnovm/tests/files/types/4f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 / e2) +} + +// Error: +// main/files/types/4f2_filetest.gno:27: QUO or REM should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/5a0_filetest.gno b/gnovm/tests/files/types/5a0_filetest.gno new file mode 100644 index 00000000000..eda3ca19569 --- /dev/null +++ b/gnovm/tests/files/types/5a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) % int8(1)) +} + +// Error: +// main/files/types/5a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/5a1_filetest.gno b/gnovm/tests/files/types/5a1_filetest.gno new file mode 100644 index 00000000000..6c7134acbc9 --- /dev/null +++ b/gnovm/tests/files/types/5a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) % Error2(0)) +} + +// Error: +// main/files/types/5a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/5b0_filetest.gno b/gnovm/tests/files/types/5b0_filetest.gno new file mode 100644 index 00000000000..9b5f82fb3b7 --- /dev/null +++ b/gnovm/tests/files/types/5b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 % Error(1)) + println(Error(1) % 1) +} + +// Output: +// (0 main.Error) +// (0 main.Error) diff --git a/gnovm/tests/files/types/5b1_filetest.gno b/gnovm/tests/files/types/5b1_filetest.gno new file mode 100644 index 00000000000..0d8f1d097ee --- /dev/null +++ b/gnovm/tests/files/types/5b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 % Error(1)) + println(Error(1) % 1) +} + +// Output: +// error: 0 +// error: 0 diff --git a/gnovm/tests/files/types/5b2_filetest.gno b/gnovm/tests/files/types/5b2_filetest.gno new file mode 100644 index 00000000000..9ecb05da049 --- /dev/null +++ b/gnovm/tests/files/types/5b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 % "a") +} + +// Error: +// main/files/types/5b2_filetest.gno:5: QUO or REM should have operand number, while have: string diff --git a/gnovm/tests/files/types/5b3_filetest.gno b/gnovm/tests/files/types/5b3_filetest.gno new file mode 100644 index 00000000000..b10138ae562 --- /dev/null +++ b/gnovm/tests/files/types/5b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" % "a") +} + +// Error: +// main/files/types/5b3_filetest.gno:5: QUO or REM should have operand number, while have: string diff --git a/gnovm/tests/files/types/5d0_filetest.gno b/gnovm/tests/files/types/5d0_filetest.gno new file mode 100644 index 00000000000..3d9e8857b74 --- /dev/null +++ b/gnovm/tests/files/types/5d0_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 % 1) +} + +// Error: +// main/files/types/5d0_filetest.gno:6: QUO or REM should have operand number, while have: bigdec diff --git a/gnovm/tests/files/types/5d1_filetest.gno b/gnovm/tests/files/types/5d1_filetest.gno new file mode 100644 index 00000000000..c05134707fb --- /dev/null +++ b/gnovm/tests/files/types/5d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' % 'b') +} + +// Output: +// 97 diff --git a/gnovm/tests/files/types/5d2_filetest.gno b/gnovm/tests/files/types/5d2_filetest.gno new file mode 100644 index 00000000000..fdd38eb3001 --- /dev/null +++ b/gnovm/tests/files/types/5d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r % 'b') +} + +// Output: +// 97 diff --git a/gnovm/tests/files/types/5d3_filetest.gno b/gnovm/tests/files/types/5d3_filetest.gno new file mode 100644 index 00000000000..4759fffe865 --- /dev/null +++ b/gnovm/tests/files/types/5d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 % r2) +} + +// Output: +// 97 diff --git a/gnovm/tests/files/types/5d4_filetest.gno b/gnovm/tests/files/types/5d4_filetest.gno new file mode 100644 index 00000000000..2c277911bfe --- /dev/null +++ b/gnovm/tests/files/types/5d4_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 % 0) +} + +// Error: +// main/files/types/5d4_filetest.gno:6: QUO or REM should have operand number, while have: bigdec diff --git a/gnovm/tests/files/types/5e0_filetest.gno b/gnovm/tests/files/types/5e0_filetest.gno new file mode 100644 index 00000000000..3dc5ebc4dd8 --- /dev/null +++ b/gnovm/tests/files/types/5e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 % e2) +} + +// Error: +// main/files/types/5e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/5f0_filetest.gno b/gnovm/tests/files/types/5f0_filetest.gno new file mode 100644 index 00000000000..00d2cb3acdc --- /dev/null +++ b/gnovm/tests/files/types/5f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 % errCmp) +} + +// Error: +// main/files/types/5f0_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/5f1_filetest.gno b/gnovm/tests/files/types/5f1_filetest.gno new file mode 100644 index 00000000000..1a2db718ce8 --- /dev/null +++ b/gnovm/tests/files/types/5f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) % errCmp) +} + +// Error: +// main/files/types/5f1_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error diff --git a/gnovm/tests/files/types/5f2_filetest.gno b/gnovm/tests/files/types/5f2_filetest.gno new file mode 100644 index 00000000000..22f34d6df6e --- /dev/null +++ b/gnovm/tests/files/types/5f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 % e2) +} + +// Error: +// main/files/types/5f2_filetest.gno:27: QUO or REM should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/6a0_filetest.gno b/gnovm/tests/files/types/6a0_filetest.gno new file mode 100644 index 00000000000..76ac2dcd4f9 --- /dev/null +++ b/gnovm/tests/files/types/6a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(0) & int8(1)) +} + +// Error: +// main/files/types/6a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/6a1_filetest.gno b/gnovm/tests/files/types/6a1_filetest.gno new file mode 100644 index 00000000000..81bfd16a3c5 --- /dev/null +++ b/gnovm/tests/files/types/6a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) & Error2(0)) +} + +// Error: +// main/files/types/6a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/6b0_filetest.gno b/gnovm/tests/files/types/6b0_filetest.gno new file mode 100644 index 00000000000..525796320e6 --- /dev/null +++ b/gnovm/tests/files/types/6b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 & Error(1)) + println(Error(1) & 1) +} + +// Output: +// (1 main.Error) +// (1 main.Error) diff --git a/gnovm/tests/files/types/6b1_filetest.gno b/gnovm/tests/files/types/6b1_filetest.gno new file mode 100644 index 00000000000..dc21fc3956b --- /dev/null +++ b/gnovm/tests/files/types/6b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 & Error(1)) + println(Error(1) & 1) +} + +// Output: +// error: 1 +// error: 1 diff --git a/gnovm/tests/files/types/6b2_filetest.gno b/gnovm/tests/files/types/6b2_filetest.gno new file mode 100644 index 00000000000..585772f2845 --- /dev/null +++ b/gnovm/tests/files/types/6b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 & "a") +} + +// Error: +// main/files/types/6b2_filetest.gno:5: operator & not defined on: string diff --git a/gnovm/tests/files/types/6b3_filetest.gno b/gnovm/tests/files/types/6b3_filetest.gno new file mode 100644 index 00000000000..eab5eb543b7 --- /dev/null +++ b/gnovm/tests/files/types/6b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" & "a") +} + +// Error: +// main/files/types/6b3_filetest.gno:5: operator & not defined on: string diff --git a/gnovm/tests/files/types/6b4_filetest.gno b/gnovm/tests/files/types/6b4_filetest.gno new file mode 100644 index 00000000000..725714eeafd --- /dev/null +++ b/gnovm/tests/files/types/6b4_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 & 'a') +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/6d0_filetest.gno b/gnovm/tests/files/types/6d0_filetest.gno new file mode 100644 index 00000000000..3f0e417adac --- /dev/null +++ b/gnovm/tests/files/types/6d0_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 & 1) +} + +// Error: +// main/files/types/6d0_filetest.gno:6: operator & not defined on: bigdec diff --git a/gnovm/tests/files/types/6d1_filetest.gno b/gnovm/tests/files/types/6d1_filetest.gno new file mode 100644 index 00000000000..232fff4d385 --- /dev/null +++ b/gnovm/tests/files/types/6d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' & 'b') +} + +// Output: +// 96 diff --git a/gnovm/tests/files/types/6d2_filetest.gno b/gnovm/tests/files/types/6d2_filetest.gno new file mode 100644 index 00000000000..f5c2660bafc --- /dev/null +++ b/gnovm/tests/files/types/6d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r & 'b') +} + +// Output: +// 96 diff --git a/gnovm/tests/files/types/6d3_filetest.gno b/gnovm/tests/files/types/6d3_filetest.gno new file mode 100644 index 00000000000..f5cb8075f24 --- /dev/null +++ b/gnovm/tests/files/types/6d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 & r2) +} + +// Output: +// 96 diff --git a/gnovm/tests/files/types/6d4_filetest.gno b/gnovm/tests/files/types/6d4_filetest.gno new file mode 100644 index 00000000000..253dee86ed4 --- /dev/null +++ b/gnovm/tests/files/types/6d4_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 & 0) +} + +// Error: +// main/files/types/6d4_filetest.gno:6: operator & not defined on: bigdec diff --git a/gnovm/tests/files/types/6e0_filetest.gno b/gnovm/tests/files/types/6e0_filetest.gno new file mode 100644 index 00000000000..6a82079919e --- /dev/null +++ b/gnovm/tests/files/types/6e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 & e2) +} + +// Error: +// main/files/types/6e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/6f0_filetest.gno b/gnovm/tests/files/types/6f0_filetest.gno new file mode 100644 index 00000000000..f7d3c3dbef6 --- /dev/null +++ b/gnovm/tests/files/types/6f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 & errCmp) +} + +// Error: +// main/files/types/6f0_filetest.gno:19: operator & not defined on: .uverse.error diff --git a/gnovm/tests/files/types/6f1_filetest.gno b/gnovm/tests/files/types/6f1_filetest.gno new file mode 100644 index 00000000000..f0e7a42c63c --- /dev/null +++ b/gnovm/tests/files/types/6f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) & errCmp) +} + +// Error: +// main/files/types/6f1_filetest.gno:19: operator & not defined on: .uverse.error diff --git a/gnovm/tests/files/types/6f2_filetest.gno b/gnovm/tests/files/types/6f2_filetest.gno new file mode 100644 index 00000000000..007d839bce7 --- /dev/null +++ b/gnovm/tests/files/types/6f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 & e2) +} + +// Error: +// main/files/types/6f2_filetest.gno:27: operator & not defined on: main.E diff --git a/gnovm/tests/files/types/7a0_filetest.gno b/gnovm/tests/files/types/7a0_filetest.gno new file mode 100644 index 00000000000..e20da0c8fe9 --- /dev/null +++ b/gnovm/tests/files/types/7a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(0) | int8(1)) +} + +// Error: +// main/files/types/7a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/7a1_filetest.gno b/gnovm/tests/files/types/7a1_filetest.gno new file mode 100644 index 00000000000..df1072fff7a --- /dev/null +++ b/gnovm/tests/files/types/7a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) | Error2(0)) +} + +// Error: +// main/files/types/7a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/7b0_filetest.gno b/gnovm/tests/files/types/7b0_filetest.gno new file mode 100644 index 00000000000..655121ee2f2 --- /dev/null +++ b/gnovm/tests/files/types/7b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 | Error(1)) + println(Error(1) | 1) +} + +// Output: +// (1 main.Error) +// (1 main.Error) diff --git a/gnovm/tests/files/types/7b1_filetest.gno b/gnovm/tests/files/types/7b1_filetest.gno new file mode 100644 index 00000000000..1616c4db687 --- /dev/null +++ b/gnovm/tests/files/types/7b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 | Error(1)) + println(Error(1) | 1) +} + +// Output: +// error: 1 +// error: 1 diff --git a/gnovm/tests/files/types/7b2_filetest.gno b/gnovm/tests/files/types/7b2_filetest.gno new file mode 100644 index 00000000000..9a8d3af24d9 --- /dev/null +++ b/gnovm/tests/files/types/7b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 | "a") +} + +// Error: +// main/files/types/7b2_filetest.gno:5: operator | not defined on: string diff --git a/gnovm/tests/files/types/7b3_filetest.gno b/gnovm/tests/files/types/7b3_filetest.gno new file mode 100644 index 00000000000..8ce21695e0b --- /dev/null +++ b/gnovm/tests/files/types/7b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" | "a") +} + +// Error: +// main/files/types/7b3_filetest.gno:5: operator | not defined on: string diff --git a/gnovm/tests/files/types/7b4_filetest.gno b/gnovm/tests/files/types/7b4_filetest.gno new file mode 100644 index 00000000000..54c50033ad1 --- /dev/null +++ b/gnovm/tests/files/types/7b4_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 | 'a') +} + +// Output: +// 97 diff --git a/gnovm/tests/files/types/7d0_filetest.gno b/gnovm/tests/files/types/7d0_filetest.gno new file mode 100644 index 00000000000..31a47cc066d --- /dev/null +++ b/gnovm/tests/files/types/7d0_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 | 1) +} + +// Error: +// main/files/types/7d0_filetest.gno:6: operator | not defined on: bigdec diff --git a/gnovm/tests/files/types/7d1_filetest.gno b/gnovm/tests/files/types/7d1_filetest.gno new file mode 100644 index 00000000000..ac2458a96a2 --- /dev/null +++ b/gnovm/tests/files/types/7d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' | 'b') +} + +// Output: +// 99 diff --git a/gnovm/tests/files/types/7d2_filetest.gno b/gnovm/tests/files/types/7d2_filetest.gno new file mode 100644 index 00000000000..0812ff926e7 --- /dev/null +++ b/gnovm/tests/files/types/7d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r | 'b') +} + +// Output: +// 99 diff --git a/gnovm/tests/files/types/7d3_filetest.gno b/gnovm/tests/files/types/7d3_filetest.gno new file mode 100644 index 00000000000..226c9423da5 --- /dev/null +++ b/gnovm/tests/files/types/7d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 | r2) +} + +// Output: +// 99 diff --git a/gnovm/tests/files/types/7d4_filetest.gno b/gnovm/tests/files/types/7d4_filetest.gno new file mode 100644 index 00000000000..87f4f6a7e1f --- /dev/null +++ b/gnovm/tests/files/types/7d4_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 | 0) +} + +// Error: +// main/files/types/7d4_filetest.gno:6: operator | not defined on: bigdec diff --git a/gnovm/tests/files/types/7e0_filetest.gno b/gnovm/tests/files/types/7e0_filetest.gno new file mode 100644 index 00000000000..f3dbe2f08cc --- /dev/null +++ b/gnovm/tests/files/types/7e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 | e2) +} + +// Error: +// main/files/types/7e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/7f0_filetest.gno b/gnovm/tests/files/types/7f0_filetest.gno new file mode 100644 index 00000000000..a90fd3e0902 --- /dev/null +++ b/gnovm/tests/files/types/7f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 | errCmp) +} + +// Error: +// main/files/types/7f0_filetest.gno:19: operator | not defined on: .uverse.error diff --git a/gnovm/tests/files/types/7f1_filetest.gno b/gnovm/tests/files/types/7f1_filetest.gno new file mode 100644 index 00000000000..d901e3af7ca --- /dev/null +++ b/gnovm/tests/files/types/7f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) | errCmp) +} + +// Error: +// main/files/types/7f1_filetest.gno:19: operator | not defined on: .uverse.error diff --git a/gnovm/tests/files/types/7f2_filetest.gno b/gnovm/tests/files/types/7f2_filetest.gno new file mode 100644 index 00000000000..3fb8c99496c --- /dev/null +++ b/gnovm/tests/files/types/7f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 | e2) +} + +// Error: +// main/files/types/7f2_filetest.gno:27: operator | not defined on: main.E diff --git a/gnovm/tests/files/types/8a0_filetest.gno b/gnovm/tests/files/types/8a0_filetest.gno new file mode 100644 index 00000000000..27582c36122 --- /dev/null +++ b/gnovm/tests/files/types/8a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(0) ^ int8(1)) +} + +// Error: +// main/files/types/8a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/8a1_filetest.gno b/gnovm/tests/files/types/8a1_filetest.gno new file mode 100644 index 00000000000..c4e63ba9986 --- /dev/null +++ b/gnovm/tests/files/types/8a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) ^ Error2(0)) +} + +// Error: +// main/files/types/8a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/8b0_filetest.gno b/gnovm/tests/files/types/8b0_filetest.gno new file mode 100644 index 00000000000..ef10ee9f93f --- /dev/null +++ b/gnovm/tests/files/types/8b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 ^ Error(1)) + println(Error(1) ^ 1) +} + +// Output: +// (0 main.Error) +// (0 main.Error) diff --git a/gnovm/tests/files/types/8b1_filetest.gno b/gnovm/tests/files/types/8b1_filetest.gno new file mode 100644 index 00000000000..7c192b72ad4 --- /dev/null +++ b/gnovm/tests/files/types/8b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 ^ Error(1)) + println(Error(1) ^ 1) +} + +// Output: +// error: 0 +// error: 0 diff --git a/gnovm/tests/files/types/8b2_filetest.gno b/gnovm/tests/files/types/8b2_filetest.gno new file mode 100644 index 00000000000..cbeb942dd8a --- /dev/null +++ b/gnovm/tests/files/types/8b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 ^ "a") +} + +// Error: +// main/files/types/8b2_filetest.gno:5: operator ^ not defined on: string diff --git a/gnovm/tests/files/types/8b3_filetest.gno b/gnovm/tests/files/types/8b3_filetest.gno new file mode 100644 index 00000000000..0cd6f8e5db6 --- /dev/null +++ b/gnovm/tests/files/types/8b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" ^ "a") +} + +// Error: +// main/files/types/8b3_filetest.gno:5: operator ^ not defined on: string diff --git a/gnovm/tests/files/types/8b4_filetest.gno b/gnovm/tests/files/types/8b4_filetest.gno new file mode 100644 index 00000000000..a0aaee98542 --- /dev/null +++ b/gnovm/tests/files/types/8b4_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 ^ 'a') +} + +// Output: +// 96 diff --git a/gnovm/tests/files/types/8d0_filetest.gno b/gnovm/tests/files/types/8d0_filetest.gno new file mode 100644 index 00000000000..8758edf619d --- /dev/null +++ b/gnovm/tests/files/types/8d0_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 ^ 1) +} + +// Error: +// main/files/types/8d0_filetest.gno:6: operator ^ not defined on: bigdec diff --git a/gnovm/tests/files/types/8d1_filetest.gno b/gnovm/tests/files/types/8d1_filetest.gno new file mode 100644 index 00000000000..eeb35c7ad3c --- /dev/null +++ b/gnovm/tests/files/types/8d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' ^ 'b') +} + +// Output: +// 3 diff --git a/gnovm/tests/files/types/8d2_filetest.gno b/gnovm/tests/files/types/8d2_filetest.gno new file mode 100644 index 00000000000..169cf12aba5 --- /dev/null +++ b/gnovm/tests/files/types/8d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r ^ 'b') +} + +// Output: +// 3 diff --git a/gnovm/tests/files/types/8d3_filetest.gno b/gnovm/tests/files/types/8d3_filetest.gno new file mode 100644 index 00000000000..feffa8aca21 --- /dev/null +++ b/gnovm/tests/files/types/8d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 ^ r2) +} + +// Output: +// 3 diff --git a/gnovm/tests/files/types/8d4_filetest.gno b/gnovm/tests/files/types/8d4_filetest.gno new file mode 100644 index 00000000000..7236bc12bb0 --- /dev/null +++ b/gnovm/tests/files/types/8d4_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 ^ 0) +} + +// Error: +// main/files/types/8d4_filetest.gno:6: operator ^ not defined on: bigdec diff --git a/gnovm/tests/files/types/8e0_filetest.gno b/gnovm/tests/files/types/8e0_filetest.gno new file mode 100644 index 00000000000..393c2d9be3d --- /dev/null +++ b/gnovm/tests/files/types/8e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 ^ e2) +} + +// Error: +// main/files/types/8e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/8f0_filetest.gno b/gnovm/tests/files/types/8f0_filetest.gno new file mode 100644 index 00000000000..6e0b3f76a03 --- /dev/null +++ b/gnovm/tests/files/types/8f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 ^ errCmp) +} + +// Error: +// main/files/types/8f0_filetest.gno:19: operator ^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/8f1_filetest.gno b/gnovm/tests/files/types/8f1_filetest.gno new file mode 100644 index 00000000000..9e72a7609f2 --- /dev/null +++ b/gnovm/tests/files/types/8f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) ^ errCmp) +} + +// Error: +// main/files/types/8f1_filetest.gno:19: operator ^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/8f2_filetest.gno b/gnovm/tests/files/types/8f2_filetest.gno new file mode 100644 index 00000000000..2f80ff3840d --- /dev/null +++ b/gnovm/tests/files/types/8f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 ^ e2) +} + +// Error: +// main/files/types/8f2_filetest.gno:27: operator ^ not defined on: main.E diff --git a/gnovm/tests/files/types/others/2d2_filetest.gno b/gnovm/tests/files/types/others/2d2_filetest.gno new file mode 100644 index 00000000000..63525588d3a --- /dev/null +++ b/gnovm/tests/files/types/others/2d2_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const, check + +func main() { + println(Error1(0) + Error2(0)) +} + +// Error: +// main/gno.land/p/demo/challenge/2d2_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/2d_filetest.gno b/gnovm/tests/files/types/others/2d_filetest.gno new file mode 100644 index 00000000000..62d952adae4 --- /dev/null +++ b/gnovm/tests/files/types/others/2d_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, check + +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 + e2) +} + +// Error: +// main/gno.land/p/demo/challenge/2d_filetest.gno:27: + should have operand number or string, while have: main.E diff --git a/gnovm/tests/files/types/others/2e_filetest.gno b/gnovm/tests/files/types/others/2e_filetest.gno new file mode 100644 index 00000000000..c7cbe4bc290 --- /dev/null +++ b/gnovm/tests/files/types/others/2e_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, check + +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 - e2) +} + +// Error: +// main/gno.land/p/demo/challenge/2e_filetest.gno:27: - should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2f_filetest.gno b/gnovm/tests/files/types/others/2f_filetest.gno new file mode 100644 index 00000000000..5b476552c40 --- /dev/null +++ b/gnovm/tests/files/types/others/2f_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, check + +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 * e2) +} + +// Error: +// main/gno.land/p/demo/challenge/2f_filetest.gno:27: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2g_filetest.gno b/gnovm/tests/files/types/others/2g_filetest.gno new file mode 100644 index 00000000000..bcfef66acf2 --- /dev/null +++ b/gnovm/tests/files/types/others/2g_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, check + +func main() { + var e1 E = Error1(0) + println(e1 * 0) +} + +// Error: +// main/gno.land/p/demo/challenge/2g_filetest.gno:20: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2h_filetest.gno b/gnovm/tests/files/types/others/2h_filetest.gno new file mode 100644 index 00000000000..9486642a29f --- /dev/null +++ b/gnovm/tests/files/types/others/2h_filetest.gno @@ -0,0 +1,12 @@ +package main + +// TODO: result still incorrect, should be decimal +func main() { + println(1.0 * 0) + println(1.0 * int(0)) + +} + +// Output: +// 0 +// 0 diff --git a/gnovm/tests/files/types/others/2i_filetest.gno b/gnovm/tests/files/types/others/2i_filetest.gno new file mode 100644 index 00000000000..b8bfcd9395e --- /dev/null +++ b/gnovm/tests/files/types/others/2i_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(float32(1.0) * int(0)) +} + +// Error: +// main/gno.land/p/demo/challenge/2i_filetest.gno:4: cannot use float32 as int diff --git a/gnovm/tests/files/types/others/2j_filetest.gno b/gnovm/tests/files/types/others/2j_filetest.gno new file mode 100644 index 00000000000..0b3c5f992e9 --- /dev/null +++ b/gnovm/tests/files/types/others/2j_filetest.gno @@ -0,0 +1,32 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 * e2) + println(int(0) * float32(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/2j_filetest.gno:27: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2k_filetest.gno b/gnovm/tests/files/types/others/2k_filetest.gno new file mode 100644 index 00000000000..4e398c6b566 --- /dev/null +++ b/gnovm/tests/files/types/others/2k_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// div +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 / e2) +} + +// Error: +// main/gno.land/p/demo/challenge/2k_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/2l_filetest.gno b/gnovm/tests/files/types/others/2l_filetest.gno new file mode 100644 index 00000000000..ac5d3132669 --- /dev/null +++ b/gnovm/tests/files/types/others/2l_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + println(Error1(0) / Error2(0)) +} + +// Error: +// main/gno.land/p/demo/challenge/2l_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/README.md b/gnovm/tests/files/types/others/README.md new file mode 100644 index 00000000000..a2a9bd4d5f5 --- /dev/null +++ b/gnovm/tests/files/types/others/README.md @@ -0,0 +1,115 @@ +Scenarios: + binary expression: + left expression [Op] right expression + + // both const + const [Op] const + left typed Op right typed + left untyped Op right typed + left typed Op right untyped + left untyped Op right untyped // println(1.0 * 0) + // one is const + Not const [Op] const + Not const [Op] untyped const + Not const [Op] typed const + const [Op] Not const + untyped const [Op] const + typed const [Op] const + + // both not const + Not const [Op] Not const + +Untyped Convert rule: + + here describes convert rules on both prime or composite values + + // untyped value can be converted to its correspondence value when: + // a) it's (untyped) const, and conform to convert rules, + e.g. println(int(0) + 1) will work + e.g. println(int(0) + "a") will not work + + // b) it's declared type of value, like type Error int8, 0 will be able to converted to Error + e.g. + type Error int64 + func main() { + println(Error(0) == "0") // will work + println(Error(0) == "a") // not work + println(Error(0) == []string{"hello"}) // not work + } + + actually, declard type is a special case of convert rule + +Special case: + + when one of LHS or RHS is interface, and the other implement the interface, it will comform some + `equlaity` rule, which means they are treated as equal in type-check in compile time, but do the + strict check in runtime. TODO: understand wo golang really do in runtime + + This is pretty similar with the `declared type rule` as above, the both conforms some specific constraint + +Operators: + + // general rule, arith operators has higher precedence, required `strict` check + // In contrast, equlity == or != has a lower precedence + // in case of +=, its precedence is a combination of + and =, it's given + precedence + + ADD // + + SUB // - + MUL // * + QUO // / + REM // % + + BAND // & + BOR // | + XOR // ^ + SHL // << + SHR // >> + BAND_NOT // &^ + + LAND // && + LOR // || + ARROW // <- + INC // ++ + DEC // -- + + ------------------------------------------------------- + + ADD_ASSIGN // += + SUB_ASSIGN // -= + MUL_ASSIGN // *= + QUO_ASSIGN // /= + REM_ASSIGN // %= + BAND_ASSIGN // &= + BOR_ASSIGN // |= + XOR_ASSIGN // ^= + SHL_ASSIGN // <<= + SHR_ASSIGN // >>= + BAND_NOT_ASSIGN // &^= + + ------------------------------------------------------- + + EQL // == + LSS // < + GTR // > + ASSIGN // = + NOT // ! + + NEQ // != + LEQ // <= + GEQ // >= + DEFINE // := + + +others: + callExpr + params, return value(multi) + + untyped composite value is not const, but a unamed type? + +thoughts: + rule based code gen, Peg? + + +TODOs: + + // TODO: dec value representation diff --git a/gnovm/tests/files/types/others/comparison_0_filetest.gno b/gnovm/tests/files/types/others/comparison_0_filetest.gno new file mode 100644 index 00000000000..939f5f9c46b --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// left is typed const, right is not const +// compile pass since both conform to same interface +func main() { + if Error(0) == errCmp { // both conform same interface, compile pass, runtime evaluation not equal + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/others/comparison_0a_filetest.gno b/gnovm/tests/files/types/others/comparison_0a_filetest.gno new file mode 100644 index 00000000000..67a0439dcca --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0a_filetest.gno @@ -0,0 +1,29 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, both typed, compile fail +func main() { + if Error1(0) == Error2(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0a_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0b_filetest.gno b/gnovm/tests/files/types/others/comparison_0b_filetest.gno new file mode 100644 index 00000000000..76b7c0bd46f --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0b_filetest.gno @@ -0,0 +1,29 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + if Error1(0) != Error2(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0b_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0c_filetest.gno b/gnovm/tests/files/types/others/comparison_0c_filetest.gno new file mode 100644 index 00000000000..27d63abceab --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0c_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) + Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0c_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0d_filetest.gno b/gnovm/tests/files/types/others/comparison_0d_filetest.gno new file mode 100644 index 00000000000..f6598c1a69b --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0d_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) - Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0d_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0e_filetest.gno b/gnovm/tests/files/types/others/comparison_0e_filetest.gno new file mode 100644 index 00000000000..b908906c6b6 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0e_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) * Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0e_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0f_filetest.gno b/gnovm/tests/files/types/others/comparison_0f_filetest.gno new file mode 100644 index 00000000000..b5fc715f6bc --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0f_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) / Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0f_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0g_filetest.gno b/gnovm/tests/files/types/others/comparison_0g_filetest.gno new file mode 100644 index 00000000000..9f04d0d800a --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0g_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, compile fail +func main() { + println(Error1(0) % Error2(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0g_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0h_filetest.gno b/gnovm/tests/files/types/others/comparison_0h_filetest.gno new file mode 100644 index 00000000000..ab9827f79cc --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0h_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 0 + b := 1 + println(a & b) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/others/comparison_0i_filetest.gno b/gnovm/tests/files/types/others/comparison_0i_filetest.gno new file mode 100644 index 00000000000..297af6dcd25 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0i_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(0 & 1) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/others/comparison_0j_filetest.gno b/gnovm/tests/files/types/others/comparison_0j_filetest.gno new file mode 100644 index 00000000000..2c398df9a3d --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0j_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) & int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0j_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0k_filetest.gno b/gnovm/tests/files/types/others/comparison_0k_filetest.gno new file mode 100644 index 00000000000..3b0572e7dfc --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0k_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) | int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0k_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0l_filetest.gno b/gnovm/tests/files/types/others/comparison_0l_filetest.gno new file mode 100644 index 00000000000..378b1f5084f --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0l_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) ^ int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0l_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0m_filetest.gno b/gnovm/tests/files/types/others/comparison_0m_filetest.gno new file mode 100644 index 00000000000..1e28fef5014 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0m_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) &^ int64(1)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0m_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0n_filetest.gno b/gnovm/tests/files/types/others/comparison_0n_filetest.gno new file mode 100644 index 00000000000..319bd102ef5 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0n_filetest.gno @@ -0,0 +1,14 @@ +package main + +func main() { + println(int(0) & int(1)) + println(int(0) | int(1)) + println(int(0) ^ int(1)) + println(int(0) &^ int(1)) +} + +// Output: +// 0 +// 1 +// 1 +// 0 diff --git a/gnovm/tests/files/types/others/comparison_0z_filetest.gno b/gnovm/tests/files/types/others/comparison_0z_filetest.gno new file mode 100644 index 00000000000..20a609fabfe --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_0z_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both not const +func main() { + a := 0 + b := "hi" + println(a & b) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_0z_filetest.gno:7: cannot use int as string diff --git a/gnovm/tests/files/types/others/comparison_1a_filetest.gno b/gnovm/tests/files/types/others/comparison_1a_filetest.gno new file mode 100644 index 00000000000..7d2740709a5 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_1a_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is const, right is const, left is untyped +func main() { + if 1 == Error(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// what the firetruck? diff --git a/gnovm/tests/files/types/others/comparison_2_filetest.gno b/gnovm/tests/files/types/others/comparison_2_filetest.gno new file mode 100644 index 00000000000..30899d4d981 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_2_filetest.gno @@ -0,0 +1,36 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + if e1 == e2 { + println("what the firetruck?") + } else { + // supposed print this + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/others/comparison_3_filetest.gno b/gnovm/tests/files/types/others/comparison_3_filetest.gno new file mode 100644 index 00000000000..ac21c5b6bf5 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + if Error1(0) == Error2(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_3a_filetest.gno b/gnovm/tests/files/types/others/comparison_3a_filetest.gno new file mode 100644 index 00000000000..53fe7b61bbd --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3a_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + println(Error1(0) + Error2(0)) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3a_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_3b_filetest.gno b/gnovm/tests/files/types/others/comparison_3b_filetest.gno new file mode 100644 index 00000000000..d3b0c363714 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3b_filetest.gno @@ -0,0 +1,26 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + e1 := Error1(0) + e2 := Error2(0) + e1 += e2 +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3b_filetest.gno:22: mismatch type for Assign diff --git a/gnovm/tests/files/types/others/comparison_3c_filetest.gno b/gnovm/tests/files/types/others/comparison_3c_filetest.gno new file mode 100644 index 00000000000..0862b3f3d3e --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3c_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + e1 = Error2(0) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3c_filetest.gno:21: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3d_filetest.gno b/gnovm/tests/files/types/others/comparison_3d_filetest.gno new file mode 100644 index 00000000000..c6dd8c1cfd5 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3d_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error3 int64 + +func (e Error3) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + + e1, e2 = 0, 0 + + println(e1, e2) +} + +// Output: +// error: 0 error: 0 diff --git a/gnovm/tests/files/types/others/comparison_3e_filetest.gno b/gnovm/tests/files/types/others/comparison_3e_filetest.gno new file mode 100644 index 00000000000..cf4799deae5 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3e_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error3 int64 + +func (e Error3) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + + e1, e2 = 0, Error3(0) + + println(e1, e2) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3e_filetest.gno:29: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3f_filetest.gno b/gnovm/tests/files/types/others/comparison_3f_filetest.gno new file mode 100644 index 00000000000..4690ead2607 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3f_filetest.gno @@ -0,0 +1,30 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + var a int = 0 + + e1, e2 = a, 0 + + println(e1, e2) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3f_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3g_filetest.gno b/gnovm/tests/files/types/others/comparison_3g_filetest.gno new file mode 100644 index 00000000000..819be76c281 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3g_filetest.gno @@ -0,0 +1,30 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int64 + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 + var e2 Error2 + var b int32 = 0 + + e1, e2 = 0, b + + println(e1, e2) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3g_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3h_filetest.gno b/gnovm/tests/files/types/others/comparison_3h_filetest.gno new file mode 100644 index 00000000000..ebb546282cc --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3h_filetest.gno @@ -0,0 +1,14 @@ +package main + +func main() { + + var a int = 0 + var i int32 = 1 + a += i + + println(a) + +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3h_filetest.gno:7: mismatch type for Assign diff --git a/gnovm/tests/files/types/others/comparison_3i_filetest.gno b/gnovm/tests/files/types/others/comparison_3i_filetest.gno new file mode 100644 index 00000000000..a8e8a2f47ef --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3i_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var a int = 0 + a += 1 + println(a) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/others/comparison_3j_filetest.gno b/gnovm/tests/files/types/others/comparison_3j_filetest.gno new file mode 100644 index 00000000000..4b135e1b239 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3j_filetest.gno @@ -0,0 +1,24 @@ +package main + +func main() { + var a int = 1 + a -= 1 + println(a) //0 + + a += 1 + a *= 2 + println(a) //2 + + a /= 2 + println(a) //1 + + a += 2 //3 + a %= 2 //1 + println(a) +} + +// Output: +// 0 +// 2 +// 1 +// 1 diff --git a/gnovm/tests/files/types/others/comparison_3k_filetest.gno b/gnovm/tests/files/types/others/comparison_3k_filetest.gno new file mode 100644 index 00000000000..9ccbc1b795a --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3k_filetest.gno @@ -0,0 +1,12 @@ +package main + +func main() { + a := 6 // a is 6 (binary 110) + b := 3 // b is 3 (binary 011) + a &= b // Now a is 2 (binary 010) + + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/others/comparison_3l_filetest.gno b/gnovm/tests/files/types/others/comparison_3l_filetest.gno new file mode 100644 index 00000000000..c903dc1b440 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_3l_filetest.gno @@ -0,0 +1,11 @@ +package main + +func main() { + a := 6 + b := "3" + a &= b // Error: mismatched types int and string + println(a) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_3l_filetest.gno:6: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_4_filetest.gno b/gnovm/tests/files/types/others/comparison_4_filetest.gno new file mode 100644 index 00000000000..c09475f2a01 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_4_filetest.gno @@ -0,0 +1,16 @@ +package main + +var a int = 0 +var b int64 = 0 + +func main() { + // suppose compile fail + if a == b { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_4_filetest.gno:8: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_5_filetest.gno b/gnovm/tests/files/types/others/comparison_5_filetest.gno new file mode 100644 index 00000000000..c2cb3eb6472 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_5_filetest.gno @@ -0,0 +1,15 @@ +package main + +var a int = 0 +var b bool = false + +func main() { + if a == b { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_5_filetest.gno:7: cannot use int as bool diff --git a/gnovm/tests/files/types/others/comparison_6_filetest.gno b/gnovm/tests/files/types/others/comparison_6_filetest.gno new file mode 100644 index 00000000000..db0f0e6e86f --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_6_filetest.gno @@ -0,0 +1,11 @@ +package main + +var a int = 0 +var b int64 = 1 + +func main() { + println(a + b) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_6_filetest.gno:7: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_6a_filetest.gno b/gnovm/tests/files/types/others/comparison_6a_filetest.gno new file mode 100644 index 00000000000..a106f1acb78 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_6a_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var b int64 = 1 + r := 0 + b // const + println(r) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/others/comparison_7_filetest.gno b/gnovm/tests/files/types/others/comparison_7_filetest.gno new file mode 100644 index 00000000000..f435f587ca8 --- /dev/null +++ b/gnovm/tests/files/types/others/comparison_7_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 0 + var b int64 = 0 + println(a == b) +} + +// Error: +// main/gno.land/p/demo/challenge/comparison_7_filetest.gno:6: cannot use int as int64 From 1275f9da6beea6ab0de07f63f3f5f2bffee1aa9f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 29 Nov 2023 23:41:14 +0800 Subject: [PATCH 007/193] fixup --- gnovm/Makefile | 2 + gnovm/pkg/gnolang/op_binary.go | 60 +- gnovm/pkg/gnolang/preprocess.go | 612 ++++++++++++------ gnovm/pkg/gnolang/types.go | 66 +- gnovm/pkg/gnolang/values_conversions.go | 3 + gnovm/tests/file_test.go | 5 + gnovm/tests/{files.bak => }/files/a1.gno | 0 gnovm/tests/{files.bak => }/files/a10.gno | 0 gnovm/tests/{files.bak => }/files/a11.gno | 0 gnovm/tests/{files.bak => }/files/a12.gno | 0 gnovm/tests/{files.bak => }/files/a13.gno | 0 gnovm/tests/{files.bak => }/files/a14.gno | 0 gnovm/tests/{files.bak => }/files/a15.gno | 0 gnovm/tests/{files.bak => }/files/a16.gno | 0 gnovm/tests/{files.bak => }/files/a17.gno | 0 gnovm/tests/{files.bak => }/files/a18.gno | 0 gnovm/tests/{files.bak => }/files/a19.gno | 0 gnovm/tests/{files.bak => }/files/a2.gno | 0 gnovm/tests/{files.bak => }/files/a20.gno | 0 gnovm/tests/{files.bak => }/files/a21.gno | 0 gnovm/tests/{files.bak => }/files/a22.gno | 0 gnovm/tests/{files.bak => }/files/a23.gno | 0 gnovm/tests/{files.bak => }/files/a24.gno | 0 gnovm/tests/{files.bak => }/files/a25.gno | 0 gnovm/tests/{files.bak => }/files/a26.gno | 0 gnovm/tests/{files.bak => }/files/a27.gno | 0 gnovm/tests/{files.bak => }/files/a28.gno | 0 gnovm/tests/{files.bak => }/files/a29.gno | 0 gnovm/tests/{files.bak => }/files/a3.gno | 0 gnovm/tests/{files.bak => }/files/a30.gno | 0 gnovm/tests/{files.bak => }/files/a31.gno | 0 gnovm/tests/{files.bak => }/files/a32.gno | 0 gnovm/tests/{files.bak => }/files/a33.gno | 0 gnovm/tests/{files.bak => }/files/a34.gno | 0 gnovm/tests/{files.bak => }/files/a35.gno | 0 gnovm/tests/{files.bak => }/files/a36.gno | 0 gnovm/tests/{files.bak => }/files/a37.gno | 0 gnovm/tests/{files.bak => }/files/a38.gno | 0 gnovm/tests/{files.bak => }/files/a39.gno | 0 gnovm/tests/{files.bak => }/files/a4.gno | 0 gnovm/tests/{files.bak => }/files/a40.gno | 0 gnovm/tests/{files.bak => }/files/a41.gno | 0 gnovm/tests/{files.bak => }/files/a42.gno | 0 gnovm/tests/{files.bak => }/files/a43.gno | 0 gnovm/tests/{files.bak => }/files/a44.gno | 0 gnovm/tests/{files.bak => }/files/a45.gno | 0 gnovm/tests/{files.bak => }/files/a45a.gno | 0 gnovm/tests/{files.bak => }/files/a46.gno | 0 gnovm/tests/{files.bak => }/files/a5.gno | 0 gnovm/tests/{files.bak => }/files/a6.gno | 0 gnovm/tests/{files.bak => }/files/a7.gno | 0 gnovm/tests/{files.bak => }/files/a8.gno | 0 gnovm/tests/{files.bak => }/files/a9.gno | 0 gnovm/tests/{files.bak => }/files/access0.gno | 0 gnovm/tests/{files.bak => }/files/access1.gno | 0 .../files/access2.gno => files/access2.gnoa} | 2 +- gnovm/tests/{files.bak => }/files/access3.gno | 0 gnovm/tests/{files.bak => }/files/access4.gno | 0 gnovm/tests/{files.bak => }/files/access5.gno | 0 gnovm/tests/{files.bak => }/files/access6.gno | 0 gnovm/tests/{files.bak => }/files/access7.gno | 0 gnovm/tests/{files.bak => }/files/add0.gno | 0 gnovm/tests/{files.bak => }/files/add1.gno | 0 gnovm/tests/{files.bak => }/files/add2.gno | 0 .../{files.bak => }/files/addr0b_native.gno | 0 .../{files.bak => }/files/addr0b_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/addr1.gno | 0 gnovm/tests/{files.bak => }/files/addr2b.gno | 0 gnovm/tests/{files.bak => }/files/alias0.gno | 0 gnovm/tests/{files.bak => }/files/alias1.gno | 0 gnovm/tests/{files.bak => }/files/and.gno | 0 gnovm/tests/{files.bak => }/files/and0.gno | 0 gnovm/tests/{files.bak => }/files/and1.gno | 0 gnovm/tests/{files.bak => }/files/and2.gno | 0 gnovm/tests/{files.bak => }/files/and3.gno | 0 gnovm/tests/{files.bak => }/files/append0.gno | 0 gnovm/tests/{files.bak => }/files/append1.gno | 0 gnovm/tests/{files.bak => }/files/append2.gno | 0 gnovm/tests/{files.bak => }/files/append3.gno | 0 gnovm/tests/{files.bak => }/files/append4.gno | 0 gnovm/tests/{files.bak => }/files/append5.gno | 0 gnovm/tests/{files.bak => }/files/array0.gno | 0 gnovm/tests/{files.bak => }/files/array1.gno | 0 gnovm/tests/{files.bak => }/files/array2.gno | 0 gnovm/tests/{files.bak => }/files/array3.gno | 0 gnovm/tests/{files.bak => }/files/array4.gno | 0 gnovm/tests/{files.bak => }/files/array5.gno | 0 gnovm/tests/{files.bak => }/files/assign.gno | 0 .../{files.bak => }/files/assign0b_native.gno | 0 .../files/assign0b_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/assign1.gno | 0 .../tests/{files.bak => }/files/assign10.gno | 0 .../tests/{files.bak => }/files/assign11.gno | 0 .../tests/{files.bak => }/files/assign12.gno | 0 .../tests/{files.bak => }/files/assign16.gno | 0 gnovm/tests/{files.bak => }/files/assign2.gno | 0 .../tests/{files.bak => }/files/assign20.gno | 0 .../tests/{files.bak => }/files/assign21.gno | 0 gnovm/tests/{files.bak => }/files/assign3.gno | 0 gnovm/tests/{files.bak => }/files/assign4.gno | 0 gnovm/tests/{files.bak => }/files/assign5.gno | 0 gnovm/tests/{files.bak => }/files/assign8.gno | 0 gnovm/tests/{files.bak => }/files/assign9.gno | 0 gnovm/tests/{files.bak => }/files/avl0.gno | 0 gnovm/tests/{files.bak => }/files/avl1.gno | 0 gnovm/tests/{files.bak => }/files/bin.gno | 0 gnovm/tests/{files.bak => }/files/bin0.gno | 0 gnovm/tests/{files.bak => }/files/bin1.gno | 0 gnovm/tests/{files.bak => }/files/bin3.gno | 0 gnovm/tests/{files.bak => }/files/bin4.gno | 0 gnovm/tests/{files.bak => }/files/bin5.gno | 0 .../files/binstruct_ptr_map0.gno | 0 .../files/binstruct_ptr_slice0.gno | 0 .../files/binstruct_slice0.gno | 0 gnovm/tests/{files.bak => }/files/bltn.gno | 0 gnovm/tests/{files.bak => }/files/bltn0.gno | 0 gnovm/tests/{files.bak => }/files/bool.gno | 0 gnovm/tests/{files.bak => }/files/bool0.gno | 0 gnovm/tests/{files.bak => }/files/bool1.gno | 0 gnovm/tests/{files.bak => }/files/bool2.gno | 0 gnovm/tests/{files.bak => }/files/bool3.gno | 0 gnovm/tests/{files.bak => }/files/bool4.gno | 0 gnovm/tests/{files.bak => }/files/bool5.gno | 0 gnovm/tests/{files.bak => }/files/build0.gno | 0 gnovm/tests/{files.bak => }/files/cap0.gno | 0 .../tests/{files.bak => }/files/closure0.gno | 0 .../tests/{files.bak => }/files/closure1.gno | 0 .../tests/{files.bak => }/files/closure2.gno | 0 .../tests/{files.bak => }/files/closure3.gno | 0 .../tests/{files.bak => }/files/closure4.gno | 0 .../tests/{files.bak => }/files/closure5.gno | 0 .../tests/{files.bak => }/files/closure6.gno | 0 .../tests/{files.bak => }/files/closure7.gno | 0 .../tests/{files.bak => }/files/closure8.gno | 0 gnovm/tests/{files.bak => }/files/comp1.gno | 0 gnovm/tests/{files.bak => }/files/comp2.gno | 0 gnovm/tests/{files.bak => }/files/comp3.gno | 0 .../{files.bak => }/files/composite0.gno | 0 .../{files.bak => }/files/composite1.gno | 0 .../{files.bak => }/files/composite10.gno | 0 .../{files.bak => }/files/composite11.gno | 0 .../{files.bak => }/files/composite12.gno | 0 .../{files.bak => }/files/composite13.gno | 0 .../{files.bak => }/files/composite14.gno | 0 .../{files.bak => }/files/composite15.gno | 0 .../{files.bak => }/files/composite16.gno | 0 .../{files.bak => }/files/composite17.gno | 0 .../{files.bak => }/files/composite2.gno | 0 .../{files.bak => }/files/composite3.gno | 0 .../{files.bak => }/files/composite4.gno | 0 .../{files.bak => }/files/composite5.gno | 0 .../{files.bak => }/files/composite6.gno | 0 .../{files.bak => }/files/composite7.gno | 0 .../{files.bak => }/files/composite8.gno | 0 .../{files.bak => }/files/composite8bis.gno | 0 .../{files.bak => }/files/composite9.gno | 0 gnovm/tests/{files.bak => }/files/const0.gno | 0 gnovm/tests/{files.bak => }/files/const1.gno | 0 gnovm/tests/{files.bak => }/files/const10.gno | 0 gnovm/tests/{files.bak => }/files/const11.gno | 0 gnovm/tests/{files.bak => }/files/const12.gno | 0 gnovm/tests/{files.bak => }/files/const13.gno | 0 gnovm/tests/{files.bak => }/files/const14.gno | 0 gnovm/tests/{files.bak => }/files/const15.gno | 0 gnovm/tests/{files.bak => }/files/const16.gno | 0 gnovm/tests/{files.bak => }/files/const17.gno | 0 gnovm/tests/{files.bak => }/files/const18.gno | 0 gnovm/tests/{files.bak => }/files/const19.gno | 0 gnovm/tests/{files.bak => }/files/const2.gno | 0 gnovm/tests/{files.bak => }/files/const20.gno | 0 gnovm/tests/{files.bak => }/files/const21.gno | 0 gnovm/tests/{files.bak => }/files/const22.gno | 0 gnovm/tests/{files.bak => }/files/const3.gno | 0 gnovm/tests/{files.bak => }/files/const4.gno | 0 gnovm/tests/{files.bak => }/files/const5.gno | 0 gnovm/tests/{files.bak => }/files/const6.gno | 0 gnovm/tests/{files.bak => }/files/const7.gno | 0 gnovm/tests/{files.bak => }/files/const8.gno | 0 gnovm/tests/{files.bak => }/files/const9.gno | 0 gnovm/tests/{files.bak => }/files/cont.gno | 0 gnovm/tests/{files.bak => }/files/cont0.gno | 0 gnovm/tests/{files.bak => }/files/cont1.gno | 0 gnovm/tests/{files.bak => }/files/context.gno | 0 .../tests/{files.bak => }/files/context2.gno | 0 .../tests/{files.bak => }/files/convert0.gno | 0 .../tests/{files.bak => }/files/convert1.gno | 0 .../tests/{files.bak => }/files/convert3.gno | 0 gnovm/tests/{files.bak => }/files/copy0.gno | 0 gnovm/tests/{files.bak => }/files/copy1.gno | 0 gnovm/tests/{files.bak => }/files/copy2.gno | 0 gnovm/tests/{files.bak => }/files/defer0.gno | 0 gnovm/tests/{files.bak => }/files/defer1.gno | 0 gnovm/tests/{files.bak => }/files/defer2.gno | 0 gnovm/tests/{files.bak => }/files/defer3.gno | 0 gnovm/tests/{files.bak => }/files/defer4.gno | 0 gnovm/tests/{files.bak => }/files/defer5.gno | 0 gnovm/tests/{files.bak => }/files/defer6.gno | 0 gnovm/tests/{files.bak => }/files/defer7.gno | 0 gnovm/tests/{files.bak => }/files/defer8.gno | 0 gnovm/tests/{files.bak => }/files/defer9.gno | 0 gnovm/tests/{files.bak => }/files/define0.gno | 0 gnovm/tests/{files.bak => }/files/define1.gno | 0 gnovm/tests/{files.bak => }/files/define2.gno | 0 gnovm/tests/{files.bak => }/files/define3.gno | 0 gnovm/tests/{files.bak => }/files/define4.gno | 0 gnovm/tests/{files.bak => }/files/delete0.gno | 0 gnovm/tests/{files.bak => }/files/errors.gno | 0 .../files/extern/b1/foo/foo.gno | 0 .../files/extern/b2/foo/foo.gno | 0 .../{files.bak => }/files/extern/bar/quux.gno | 0 .../files/extern/baz-bat/baz-bat.gno | 0 .../{files.bak => }/files/extern/baz/quux.gno | 0 .../{files.bak => }/files/extern/c1/c1.gno | 0 .../{files.bak => }/files/extern/c2/c2.gno | 0 .../files/extern/context/context.gno | 0 .../{files.bak => }/files/extern/ct/ct1.gno | 0 .../{files.bak => }/files/extern/ct/ct2.gno | 0 .../{files.bak => }/files/extern/ct/ct3.gno | 0 .../{files.bak => }/files/extern/ct1/ct1.gno | 0 .../files/extern/foo-bar/foo-bar.gno | 0 .../{files.bak => }/files/extern/foo/bar.gno | 0 .../{files.bak => }/files/extern/foo/bir.gno | 0 .../files/extern/foo/boo/boo.gno | 0 .../{files.bak => }/files/extern/m1/main.gno | 0 .../files/extern/m1/main_test.gno | 0 .../files/extern/m2/m2_test.gno | 0 .../files/extern/net/http/http.gno | 0 .../extern/net/http/httptest/httptest.gno | 0 .../{files.bak => }/files/extern/net/net.gno | 0 .../files/extern/net/url/url.gno | 0 .../{files.bak => }/files/extern/p1/s1.gno | 0 .../{files.bak => }/files/extern/p1/s2.gno | 0 .../files/extern/tata/tutu.gno | 0 .../files/extern/time/time.gno | 0 .../data-structures/tree/avl/avltree.gno | 0 .../timtadh/data-structures/tree/utils.gno | 0 .../data-structures/types/map_entry.gno | 0 .../timtadh/data-structures/types/string.gno | 0 .../timtadh/data-structures/types/types.gno | 0 .../timtadh/data-structures/types/util.gno | 0 .../files/extern/toto/titi.gno | 0 .../files/extern/vars/first.gno | 0 .../files/extern/vars/second.gno | 0 gnovm/tests/{files.bak => }/files/fib0.gno | 0 gnovm/tests/{files.bak => }/files/float0.gno | 0 gnovm/tests/{files.bak => }/files/float1.gno | 0 gnovm/tests/{files.bak => }/files/float2.gno | 0 gnovm/tests/{files.bak => }/files/float3.gno | 0 gnovm/tests/{files.bak => }/files/float4.gno | 0 .../{files.bak => }/files/float5_native.gno | 0 .../{files.bak => }/files/float5_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/float6.gno | 0 gnovm/tests/{files.bak => }/files/float7.gno | 0 gnovm/tests/{files.bak => }/files/for0.gno | 0 gnovm/tests/{files.bak => }/files/for1.gno | 0 gnovm/tests/{files.bak => }/files/for10.gno | 0 gnovm/tests/{files.bak => }/files/for11.gno | 0 gnovm/tests/{files.bak => }/files/for12.gno | 0 gnovm/tests/{files.bak => }/files/for13.gno | 0 gnovm/tests/{files.bak => }/files/for14.gno | 0 gnovm/tests/{files.bak => }/files/for15.gno | 0 gnovm/tests/{files.bak => }/files/for16.gno | 0 gnovm/tests/{files.bak => }/files/for17.gno | 0 gnovm/tests/{files.bak => }/files/for18.gno | 0 gnovm/tests/{files.bak => }/files/for2.gno | 0 gnovm/tests/{files.bak => }/files/for3.gno | 0 gnovm/tests/{files.bak => }/files/for4.gno | 0 gnovm/tests/{files.bak => }/files/for5.gno | 0 gnovm/tests/{files.bak => }/files/for6.gno | 0 gnovm/tests/{files.bak => }/files/for7.gno | 0 gnovm/tests/{files.bak => }/files/for8.gno | 0 gnovm/tests/{files.bak => }/files/for9.gno | 0 gnovm/tests/{files.bak => }/files/fun.gno | 0 gnovm/tests/{files.bak => }/files/fun10.gno | 0 gnovm/tests/{files.bak => }/files/fun11.gno | 0 gnovm/tests/{files.bak => }/files/fun12.gno | 0 gnovm/tests/{files.bak => }/files/fun13.gno | 0 gnovm/tests/{files.bak => }/files/fun14.gno | 0 gnovm/tests/{files.bak => }/files/fun15.gno | 0 gnovm/tests/{files.bak => }/files/fun16.gno | 0 gnovm/tests/{files.bak => }/files/fun17.gno | 0 gnovm/tests/{files.bak => }/files/fun18.gno | 0 gnovm/tests/{files.bak => }/files/fun19b.gno | 0 gnovm/tests/{files.bak => }/files/fun2.gno | 0 gnovm/tests/{files.bak => }/files/fun20b.gno | 0 gnovm/tests/{files.bak => }/files/fun21.gno | 0 gnovm/tests/{files.bak => }/files/fun22.gno | 0 gnovm/tests/{files.bak => }/files/fun23.gno | 0 gnovm/tests/{files.bak => }/files/fun24.gno | 2 +- gnovm/tests/{files.bak => }/files/fun25.gno | 0 gnovm/tests/{files.bak => }/files/fun26.gno | 0 gnovm/tests/{files.bak => }/files/fun3.gno | 0 gnovm/tests/{files.bak => }/files/fun4.gno | 0 gnovm/tests/{files.bak => }/files/fun5.gno | 0 gnovm/tests/{files.bak => }/files/fun6.gno | 0 gnovm/tests/{files.bak => }/files/fun6b.gno | 0 gnovm/tests/{files.bak => }/files/fun7.gno | 0 gnovm/tests/{files.bak => }/files/fun8.gno | 0 gnovm/tests/{files.bak => }/files/fun9.gno | 0 gnovm/tests/{files.bak => }/files/goto0.gno | 0 gnovm/tests/{files.bak => }/files/goto1.gno | 0 gnovm/tests/{files.bak => }/files/goto2.gno | 0 gnovm/tests/{files.bak => }/files/goto3.gno | 0 gnovm/tests/{files.bak => }/files/goto3a.gno | 0 gnovm/tests/{files.bak => }/files/goto4.gno | 0 gnovm/tests/{files.bak => }/files/goto5.gno | 0 gnovm/tests/{files.bak => }/files/goto6.gno | 0 gnovm/tests/{files.bak => }/files/if.gno | 0 gnovm/tests/{files.bak => }/files/if0.gno | 0 gnovm/tests/{files.bak => }/files/if1.gno | 0 gnovm/tests/{files.bak => }/files/if2.gno | 0 gnovm/tests/{files.bak => }/files/if3.gno | 0 gnovm/tests/{files.bak => }/files/if4.gno | 0 gnovm/tests/{files.bak => }/files/if5.gno | 0 gnovm/tests/{files.bak => }/files/if6.gno | 0 gnovm/tests/{files.bak => }/files/if7.gno | 0 gnovm/tests/{files.bak => }/files/import0.gno | 0 gnovm/tests/{files.bak => }/files/import1.gno | 0 .../tests/{files.bak => }/files/import10.gno | 0 gnovm/tests/{files.bak => }/files/import3.gno | 0 gnovm/tests/{files.bak => }/files/import4.gno | 0 gnovm/tests/{files.bak => }/files/import5.gno | 0 gnovm/tests/{files.bak => }/files/import6.gno | 0 gnovm/tests/{files.bak => }/files/import7.gno | 0 gnovm/tests/{files.bak => }/files/import8.gno | 0 gnovm/tests/{files.bak => }/files/import9.gno | 0 gnovm/tests/{files.bak => }/files/inc.gno | 0 gnovm/tests/{files.bak => }/files/index0.gno | 0 gnovm/tests/{files.bak => }/files/init0.gno | 0 gnovm/tests/{files.bak => }/files/init1.gno | 0 .../{files.bak => }/files/interface0.gno | 0 .../{files.bak => }/files/interface1.gno | 0 .../{files.bak => }/files/interface10.gno | 0 .../{files.bak => }/files/interface11.gno | 0 .../{files.bak => }/files/interface12.gno | 0 .../{files.bak => }/files/interface13.gno | 0 .../{files.bak => }/files/interface14.gno | 0 .../{files.bak => }/files/interface15.gno | 0 .../{files.bak => }/files/interface16.gno | 0 .../{files.bak => }/files/interface17.gno | 0 .../{files.bak => }/files/interface18.gno | 0 .../{files.bak => }/files/interface19.gno | 0 .../{files.bak => }/files/interface2.gno | 0 .../{files.bak => }/files/interface20.gno | 0 .../{files.bak => }/files/interface21.gno | 0 .../{files.bak => }/files/interface22.gno | 0 .../{files.bak => }/files/interface23.gno | 0 .../{files.bak => }/files/interface24.gno | 0 .../{files.bak => }/files/interface25.gno | 0 .../{files.bak => }/files/interface26.gno | 0 .../{files.bak => }/files/interface27b.gno | 0 .../{files.bak => }/files/interface28b.gno | 0 .../{files.bak => }/files/interface29.gno | 0 .../{files.bak => }/files/interface3.gno | 0 .../{files.bak => }/files/interface30.gno | 0 .../{files.bak => }/files/interface31.gno | 0 .../{files.bak => }/files/interface32.gno | 0 .../{files.bak => }/files/interface33.gno | 0 .../{files.bak => }/files/interface34.gno | 0 .../{files.bak => }/files/interface35.gno | 0 .../{files.bak => }/files/interface36.gno | 0 .../{files.bak => }/files/interface37.gno | 0 .../{files.bak => }/files/interface38b.gno | 0 .../{files.bak => }/files/interface39b.gno | 0 .../{files.bak => }/files/interface4.gno | 0 .../{files.bak => }/files/interface40b.gno | 0 .../{files.bak => }/files/interface41b.gno | 0 .../{files.bak => }/files/interface42.gno | 0 .../{files.bak => }/files/interface43.gno | 0 .../{files.bak => }/files/interface44.gno | 0 .../{files.bak => }/files/interface45.gno | 0 .../{files.bak => }/files/interface46.gno | 0 .../{files.bak => }/files/interface5.gno | 0 .../{files.bak => }/files/interface6.gno | 0 .../{files.bak => }/files/interface7b.gno | 0 .../{files.bak => }/files/interface8.gno | 0 .../{files.bak => }/files/interface9b.gno | 0 gnovm/tests/{files.bak => }/files/interp.gi | 0 gnovm/tests/{files.bak => }/files/interp2.gi | 0 .../{files.bak => }/files/io0_native.gno | 0 .../{files.bak => }/files/io0_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/io1.gno | 0 gnovm/tests/{files.bak => }/files/io2.gno | 0 gnovm/tests/{files.bak => }/files/iota.gno | 0 gnovm/tests/{files.bak => }/files/iota0.gno | 0 .../{files.bak => }/files/ipp_as_key.gno | 0 .../{files.bak => }/files/issue-1096.gno | 0 .../{files.bak => }/files/issue-558b.gno | 0 .../tests/{files.bak => }/files/issue-735.gno | 0 .../tests/{files.bak => }/files/issue-776.gno | 0 .../tests/{files.bak => }/files/issue-782.gno | 0 .../tests/{files.bak => }/files/issue-784.gno | 0 .../tests/{files.bak => }/files/issue-880.gno | 0 gnovm/tests/{files.bak => }/files/l2_long.gno | 0 gnovm/tests/{files.bak => }/files/l3_long.gno | 0 gnovm/tests/{files.bak => }/files/l4_long.gno | 0 gnovm/tests/{files.bak => }/files/l5_long.gno | 0 gnovm/tests/{files.bak => }/files/len0.gno | 0 gnovm/tests/{files.bak => }/files/make0.gno | 0 gnovm/tests/{files.bak => }/files/make1.gno | 0 gnovm/tests/{files.bak => }/files/make2.gno | 0 gnovm/tests/{files.bak => }/files/map.gno | 0 gnovm/tests/{files.bak => }/files/map0.gno | 0 gnovm/tests/{files.bak => }/files/map1.gno | 0 gnovm/tests/{files.bak => }/files/map10.gno | 0 gnovm/tests/{files.bak => }/files/map11.gno | 0 gnovm/tests/{files.bak => }/files/map12.gno | 0 gnovm/tests/{files.bak => }/files/map13.gno | 0 gnovm/tests/{files.bak => }/files/map14b.gno | 0 gnovm/tests/{files.bak => }/files/map15.gno | 0 gnovm/tests/{files.bak => }/files/map16.gno | 0 gnovm/tests/{files.bak => }/files/map17.gno | 0 gnovm/tests/{files.bak => }/files/map18.gno | 0 gnovm/tests/{files.bak => }/files/map19b.gno | 0 gnovm/tests/{files.bak => }/files/map2.gno | 0 gnovm/tests/{files.bak => }/files/map20.gno | 0 gnovm/tests/{files.bak => }/files/map21.gno | 0 gnovm/tests/{files.bak => }/files/map22.gno | 0 gnovm/tests/{files.bak => }/files/map23.gno | 0 gnovm/tests/{files.bak => }/files/map24.gno | 0 gnovm/tests/{files.bak => }/files/map25.gno | 0 gnovm/tests/{files.bak => }/files/map26.gno | 0 gnovm/tests/{files.bak => }/files/map27.gno | 0 gnovm/tests/{files.bak => }/files/map28b.gno | 0 gnovm/tests/{files.bak => }/files/map28c.gno | 0 .../{files.bak => }/files/map29_native.gno | 0 .../{files.bak => }/files/map29_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/map3.gno | 0 gnovm/tests/{files.bak => }/files/map4.gno | 0 gnovm/tests/{files.bak => }/files/map5.gno | 0 gnovm/tests/{files.bak => }/files/map6.gno | 0 gnovm/tests/{files.bak => }/files/map7.gno | 0 gnovm/tests/{files.bak => }/files/map8.gno | 0 gnovm/tests/{files.bak => }/files/map9.gno | 0 .../{files.bak => }/files/math0_native.gno | 0 .../{files.bak => }/files/math0_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/math2.gno | 0 gnovm/tests/{files.bak => }/files/math3.gno | 0 .../files/maths_int16_long.gno | 0 .../{files.bak => }/files/maths_int8.gno | 0 gnovm/tests/{files.bak => }/files/method.gno | 0 gnovm/tests/{files.bak => }/files/method0.gno | 0 gnovm/tests/{files.bak => }/files/method1.gno | 0 .../tests/{files.bak => }/files/method10.gno | 0 .../tests/{files.bak => }/files/method11.gno | 0 .../tests/{files.bak => }/files/method12.gno | 0 .../tests/{files.bak => }/files/method13.gno | 0 .../tests/{files.bak => }/files/method14.gno | 0 .../tests/{files.bak => }/files/method15.gno | 0 .../tests/{files.bak => }/files/method16b.gno | 0 .../tests/{files.bak => }/files/method17b.gno | 0 .../tests/{files.bak => }/files/method18.gno | 0 .../tests/{files.bak => }/files/method19.gno | 0 gnovm/tests/{files.bak => }/files/method2.gno | 0 .../tests/{files.bak => }/files/method20.gno | 0 .../tests/{files.bak => }/files/method21.gno | 0 .../tests/{files.bak => }/files/method22.gno | 0 .../tests/{files.bak => }/files/method23.gno | 0 .../tests/{files.bak => }/files/method24.gno | 0 .../tests/{files.bak => }/files/method25.gno | 0 .../tests/{files.bak => }/files/method26.gno | 0 .../tests/{files.bak => }/files/method27.gno | 0 .../tests/{files.bak => }/files/method28.gno | 0 .../tests/{files.bak => }/files/method29b.gno | 0 gnovm/tests/{files.bak => }/files/method3.gno | 0 .../tests/{files.bak => }/files/method30.gno | 0 .../tests/{files.bak => }/files/method31b.gno | 0 .../tests/{files.bak => }/files/method32.gno | 0 .../tests/{files.bak => }/files/method33.gno | 0 .../tests/{files.bak => }/files/method34.gno | 0 .../tests/{files.bak => }/files/method35.gno | 0 .../tests/{files.bak => }/files/method36.gno | 0 .../tests/{files.bak => }/files/method37.gno | 0 gnovm/tests/{files.bak => }/files/method4.gno | 0 gnovm/tests/{files.bak => }/files/method5.gno | 0 gnovm/tests/{files.bak => }/files/method6.gno | 0 gnovm/tests/{files.bak => }/files/method7.gno | 0 gnovm/tests/{files.bak => }/files/method8.gno | 0 gnovm/tests/{files.bak => }/files/method9.gno | 0 gnovm/tests/{files.bak => }/files/neg0.gno | 0 gnovm/tests/{files.bak => }/files/new0.gno | 0 gnovm/tests/{files.bak => }/files/new1.gno | 0 gnovm/tests/{files.bak => }/files/new2.gno | 0 gnovm/tests/{files.bak => }/files/new3.gno | 0 gnovm/tests/{files.bak => }/files/nil0.gno | 0 gnovm/tests/{files.bak => }/files/nil1.gno | 0 gnovm/tests/{files.bak => }/files/nil2.gno | 0 gnovm/tests/{files.bak => }/files/nil3.gno | 0 gnovm/tests/{files.bak => }/files/not0.gno | 0 gnovm/tests/{files.bak => }/files/not1.gno | 0 gnovm/tests/{files.bak => }/files/not2.gno | 0 gnovm/tests/{files.bak => }/files/op0.gno | 0 gnovm/tests/{files.bak => }/files/op2.gno | 0 gnovm/tests/{files.bak => }/files/op6.gno | 0 gnovm/tests/{files.bak => }/files/op7.gno | 2 +- gnovm/tests/{files.bak => }/files/op8.gno | 0 gnovm/tests/{files.bak => }/files/opint16.gno | 0 gnovm/tests/{files.bak => }/files/opint32.gno | 0 gnovm/tests/{files.bak => }/files/opint64.gno | 0 gnovm/tests/{files.bak => }/files/opint8.gno | 0 .../tests/{files.bak => }/files/opstring.gno | 0 .../tests/{files.bak => }/files/opuint16.gno | 0 .../tests/{files.bak => }/files/opuint32.gno | 0 .../tests/{files.bak => }/files/opuint64.gno | 0 gnovm/tests/{files.bak => }/files/opuint8.gno | 0 gnovm/tests/{files.bak => }/files/or0.gno | 0 gnovm/tests/{files.bak => }/files/or1.gno | 0 gnovm/tests/{files.bak => }/files/or2.gno | 0 gnovm/tests/{files.bak => }/files/or3.gno | 0 gnovm/tests/{files.bak => }/files/or4.gno | 0 gnovm/tests/{files.bak => }/files/panic0.gno | 0 gnovm/tests/{files.bak => }/files/panic0b.gno | 0 .../persist_map.gno.a} | 2 +- .../tests/{files.bak => }/files/pkgname0.gno | 0 .../tests/{files.bak => }/files/pkgname1.gno | 0 .../tests/{files.bak => }/files/pkgname2.gno | 0 gnovm/tests/{files.bak => }/files/primes.gno | 0 gnovm/tests/{files.bak => }/files/print0.gno | 0 gnovm/tests/{files.bak => }/files/ptr0.gno | 0 gnovm/tests/{files.bak => }/files/ptr1.gno | 0 gnovm/tests/{files.bak => }/files/ptr2.gno | 0 gnovm/tests/{files.bak => }/files/ptr3.gno | 0 gnovm/tests/{files.bak => }/files/ptr4.gno | 0 gnovm/tests/{files.bak => }/files/ptr5.gno | 0 gnovm/tests/{files.bak => }/files/ptr5a.gno | 0 gnovm/tests/{files.bak => }/files/ptr6.gno | 0 gnovm/tests/{files.bak => }/files/ptr7.gno | 0 gnovm/tests/{files.bak => }/files/ptr8.gno | 0 .../{files.bak => }/files/ptr_array0.gno | 0 .../{files.bak => }/files/ptr_array1.gno | 0 .../{files.bak => }/files/ptr_array2.gno | 0 .../{files.bak => }/files/ptr_array3.gno | 0 gnovm/tests/{files.bak => }/files/range0.gno | 0 gnovm/tests/{files.bak => }/files/range1.gno | 0 gnovm/tests/{files.bak => }/files/range2.gno | 0 gnovm/tests/{files.bak => }/files/range3.gno | 0 gnovm/tests/{files.bak => }/files/range4.gno | 0 gnovm/tests/{files.bak => }/files/range5.gno | 0 gnovm/tests/{files.bak => }/files/range6.gno | 0 gnovm/tests/{files.bak => }/files/range7.gno | 0 .../tests/{files.bak => }/files/recover0.gno | 0 .../tests/{files.bak => }/files/recover1.gno | 0 .../tests/{files.bak => }/files/recover1b.gno | 0 .../tests/{files.bak => }/files/recover2.gno | 0 .../tests/{files.bak => }/files/recover3.gno | 0 .../tests/{files.bak => }/files/recover4.gno | 0 .../tests/{files.bak => }/files/recover5.gno | 0 .../tests/{files.bak => }/files/recover6.gno | 0 .../tests/{files.bak => }/files/recover7.gno | 0 .../tests/{files.bak => }/files/recurse0.gno | 0 .../files/redeclaration-global0.gno | 0 .../files/redeclaration-global1.gno | 0 .../files/redeclaration-global5.gno | 0 .../{files.bak => }/files/redeclaration0.gno | 0 .../{files.bak => }/files/redeclaration1.gno | 0 .../{files.bak => }/files/redeclaration2.gno | 0 .../{files.bak => }/files/redeclaration3.gno | 0 .../{files.bak => }/files/redeclaration4.gno | 0 .../{files.bak => }/files/redeclaration5.gno | 0 gnovm/tests/{files.bak => }/files/ret1.gno | 0 gnovm/tests/{files.bak => }/files/ret10.gno | 0 gnovm/tests/{files.bak => }/files/ret11.gno | 0 gnovm/tests/{files.bak => }/files/ret12.gno | 0 gnovm/tests/{files.bak => }/files/ret13.gno | 0 gnovm/tests/{files.bak => }/files/ret14.gno | 0 gnovm/tests/{files.bak => }/files/ret2.gno | 0 gnovm/tests/{files.bak => }/files/ret3.gno | 0 gnovm/tests/{files.bak => }/files/ret4.gno | 0 gnovm/tests/{files.bak => }/files/ret5.gno | 0 gnovm/tests/{files.bak => }/files/ret6.gno | 0 gnovm/tests/{files.bak => }/files/ret7.gno | 0 gnovm/tests/{files.bak => }/files/ret8.gno | 0 gnovm/tests/{files.bak => }/files/ret9.gno | 0 gnovm/tests/{files.bak => }/files/run0.gno | 0 gnovm/tests/{files.bak => }/files/run1.gno | 0 gnovm/tests/{files.bak => }/files/run10.gno | 0 gnovm/tests/{files.bak => }/files/run11.gno | 0 gnovm/tests/{files.bak => }/files/run12.gno | 0 gnovm/tests/{files.bak => }/files/run13.gno | 0 gnovm/tests/{files.bak => }/files/run4.gno | 0 gnovm/tests/{files.bak => }/files/run5.gno | 0 gnovm/tests/{files.bak => }/files/run6.gno | 0 gnovm/tests/{files.bak => }/files/run7.gno | 0 gnovm/tests/{files.bak => }/files/run8.gno | 0 gnovm/tests/{files.bak => }/files/run9.gno | 0 gnovm/tests/{files.bak => }/files/rune0.gno | 0 gnovm/tests/{files.bak => }/files/rune1.gno | 0 gnovm/tests/{files.bak => }/files/rune2.gno | 0 .../tests/{files.bak => }/files/sample.plugin | 0 gnovm/tests/{files.bak => }/files/scope0.gno | 0 gnovm/tests/{files.bak => }/files/scope1.gno | 0 gnovm/tests/{files.bak => }/files/scope2.gno | 0 gnovm/tests/{files.bak => }/files/scope3.gno | 0 gnovm/tests/{files.bak => }/files/scope4.gno | 0 gnovm/tests/{files.bak => }/files/scope5.gno | 0 gnovm/tests/{files.bak => }/files/scope6.gno | 0 gnovm/tests/{files.bak => }/files/scope7.gno | 0 gnovm/tests/{files.bak => }/files/secure.gi | 0 gnovm/tests/{files.bak => }/files/shift0.gno | 0 gnovm/tests/{files.bak => }/files/shift1.gno | 0 gnovm/tests/{files.bak => }/files/shift2.gno | 0 gnovm/tests/{files.bak => }/files/shift3.gno | 0 gnovm/tests/{files.bak => }/files/shift4.gno | 0 gnovm/tests/{files.bak => }/files/shift5.gno | 0 gnovm/tests/{files.bak => }/files/slice0.gno | 0 gnovm/tests/{files.bak => }/files/slice1.gno | 0 gnovm/tests/{files.bak => }/files/slice2.gno | 0 gnovm/tests/{files.bak => }/files/std0.gno | 0 gnovm/tests/{files.bak => }/files/std10.gno | 0 gnovm/tests/{files.bak => }/files/std11.gno | 0 gnovm/tests/{files.bak => }/files/std2.gno | 0 gnovm/tests/{files.bak => }/files/std3.gno | 0 gnovm/tests/{files.bak => }/files/std4.gno | 0 gnovm/tests/{files.bak => }/files/std5.gno | 0 gnovm/tests/{files.bak => }/files/std6.gno | 0 gnovm/tests/{files.bak => }/files/std7.gno | 0 gnovm/tests/{files.bak => }/files/std8.gno | 0 gnovm/tests/{files.bak => }/files/std9.gno | 0 .../{files.bak => }/files/stdlibs_native.gno | 0 .../stdlibs_stdlibs.gnoa} | 2 +- gnovm/tests/{files.bak => }/files/str.gno | 0 gnovm/tests/{files.bak => }/files/str0.gno | 0 gnovm/tests/{files.bak => }/files/str1.gno | 0 gnovm/tests/{files.bak => }/files/str2.gno | 0 gnovm/tests/{files.bak => }/files/str3.gno | 0 gnovm/tests/{files.bak => }/files/str4.gno | 0 gnovm/tests/{files.bak => }/files/struct.gno | 0 gnovm/tests/{files.bak => }/files/struct0.gno | 0 .../tests/{files.bak => }/files/struct0a.gno | 0 gnovm/tests/{files.bak => }/files/struct1.gno | 0 .../tests/{files.bak => }/files/struct10.gno | 0 .../tests/{files.bak => }/files/struct11.gno | 0 .../tests/{files.bak => }/files/struct11b.gno | 0 .../tests/{files.bak => }/files/struct12.gno | 0 .../{files.bak => }/files/struct13_native.gno | 0 .../files/struct13_stdlibs.gno | 0 .../tests/{files.bak => }/files/struct14.gno | 0 .../tests/{files.bak => }/files/struct16.gno | 0 .../tests/{files.bak => }/files/struct17.gno | 0 .../tests/{files.bak => }/files/struct19.gno | 0 gnovm/tests/{files.bak => }/files/struct2.gno | 0 .../tests/{files.bak => }/files/struct20.gno | 0 .../tests/{files.bak => }/files/struct21.gno | 0 .../tests/{files.bak => }/files/struct22.gno | 0 .../tests/{files.bak => }/files/struct24.gno | 0 .../tests/{files.bak => }/files/struct25.gno | 0 .../tests/{files.bak => }/files/struct26.gno | 0 .../tests/{files.bak => }/files/struct27.gno | 0 .../tests/{files.bak => }/files/struct28b.gno | 0 .../tests/{files.bak => }/files/struct29.gno | 0 .../tests/{files.bak => }/files/struct2b.gno | 0 gnovm/tests/{files.bak => }/files/struct3.gno | 0 .../tests/{files.bak => }/files/struct30.gno | 0 .../tests/{files.bak => }/files/struct31.gno | 0 .../tests/{files.bak => }/files/struct32.gno | 0 .../tests/{files.bak => }/files/struct33.gno | 0 .../tests/{files.bak => }/files/struct34.gno | 0 .../tests/{files.bak => }/files/struct35.gno | 0 .../tests/{files.bak => }/files/struct36.gno | 0 .../tests/{files.bak => }/files/struct37.gno | 0 .../tests/{files.bak => }/files/struct38.gno | 0 .../tests/{files.bak => }/files/struct39.gno | 0 gnovm/tests/{files.bak => }/files/struct4.gno | 0 .../tests/{files.bak => }/files/struct40.gno | 0 .../tests/{files.bak => }/files/struct41.gno | 0 .../tests/{files.bak => }/files/struct42.gno | 0 .../tests/{files.bak => }/files/struct43.gno | 0 .../tests/{files.bak => }/files/struct44.gno | 0 .../tests/{files.bak => }/files/struct45.gno | 0 .../tests/{files.bak => }/files/struct46.gno | 0 .../tests/{files.bak => }/files/struct47.gno | 0 .../tests/{files.bak => }/files/struct48.gno | 0 .../tests/{files.bak => }/files/struct49.gno | 0 gnovm/tests/{files.bak => }/files/struct5.gno | 0 .../tests/{files.bak => }/files/struct50b.gno | 0 .../tests/{files.bak => }/files/struct52b.gno | 0 .../tests/{files.bak => }/files/struct53b.gno | 0 .../tests/{files.bak => }/files/struct54.gno | 0 .../tests/{files.bak => }/files/struct56.gno | 0 .../tests/{files.bak => }/files/struct57.gno | 0 gnovm/tests/{files.bak => }/files/struct6.gno | 0 gnovm/tests/{files.bak => }/files/struct7.gno | 0 gnovm/tests/{files.bak => }/files/struct8.gno | 0 gnovm/tests/{files.bak => }/files/struct9.gno | 0 gnovm/tests/{files.bak => }/files/switch.gno | 0 gnovm/tests/{files.bak => }/files/switch0.gno | 0 gnovm/tests/{files.bak => }/files/switch1.gno | 0 .../tests/{files.bak => }/files/switch10.gno | 0 .../tests/{files.bak => }/files/switch11.gno | 0 .../tests/{files.bak => }/files/switch12.gno | 0 .../tests/{files.bak => }/files/switch13.gno | 0 .../tests/{files.bak => }/files/switch14.gno | 0 .../tests/{files.bak => }/files/switch15.gno | 0 .../tests/{files.bak => }/files/switch16.gno | 0 .../tests/{files.bak => }/files/switch17.gno | 0 .../tests/{files.bak => }/files/switch18.gno | 0 .../tests/{files.bak => }/files/switch19.gno | 0 gnovm/tests/{files.bak => }/files/switch2.gno | 0 .../tests/{files.bak => }/files/switch20.gno | 0 .../tests/{files.bak => }/files/switch21.gno | 0 .../tests/{files.bak => }/files/switch22.gno | 0 .../tests/{files.bak => }/files/switch23.gno | 0 .../tests/{files.bak => }/files/switch24.gno | 0 .../tests/{files.bak => }/files/switch25.gno | 0 .../tests/{files.bak => }/files/switch26.gno | 0 .../tests/{files.bak => }/files/switch27.gno | 0 .../tests/{files.bak => }/files/switch28.gno | 0 .../tests/{files.bak => }/files/switch29.gno | 0 gnovm/tests/{files.bak => }/files/switch3.gno | 0 .../tests/{files.bak => }/files/switch30.gno | 0 .../tests/{files.bak => }/files/switch31.gno | 0 .../tests/{files.bak => }/files/switch32.gno | 0 .../tests/{files.bak => }/files/switch33.gno | 0 .../tests/{files.bak => }/files/switch34.gno | 0 .../tests/{files.bak => }/files/switch35.gno | 0 .../tests/{files.bak => }/files/switch36.gno | 0 .../tests/{files.bak => }/files/switch37.gno | 0 .../tests/{files.bak => }/files/switch38.gno | 0 .../tests/{files.bak => }/files/switch39.gno | 0 gnovm/tests/{files.bak => }/files/switch4.gno | 0 .../tests/{files.bak => }/files/switch40.gno | 0 .../tests/{files.bak => }/files/switch41.gno | 0 gnovm/tests/{files.bak => }/files/switch5.gno | 0 gnovm/tests/{files.bak => }/files/switch6.gno | 0 .../tests/{files.bak => }/files/switch6b.gno | 0 .../tests/{files.bak => }/files/switch6c.gno | 0 gnovm/tests/{files.bak => }/files/switch7.gno | 0 gnovm/tests/{files.bak => }/files/switch8.gno | 0 .../tests/{files.bak => }/files/switch8b.gno | 0 .../tests/{files.bak => }/files/switch8c.gno | 0 gnovm/tests/{files.bak => }/files/switch9.gno | 0 .../{files.bak => }/files/time0_native.gno | 0 .../{files.bak => }/files/time0_stdlibs.gno | 0 .../{files.bak => }/files/time11_native.gno | 0 .../{files.bak => }/files/time11_stdlibs.gno | 0 .../{files.bak => }/files/time12_native.gno | 0 .../{files.bak => }/files/time12_stdlibs.gno | 0 .../{files.bak => }/files/time13_native.gno | 0 .../{files.bak => }/files/time13_stdlibs.gno | 0 .../{files.bak => }/files/time14_native.gno | 0 .../{files.bak => }/files/time14_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/time15.gno | 0 .../{files.bak => }/files/time1_native.gno | 0 .../{files.bak => }/files/time1_stdlibs.gno | 0 .../{files.bak => }/files/time2_native.gno | 0 .../{files.bak => }/files/time2_stdlibs.gno | 0 .../{files.bak => }/files/time3_native.gno | 0 .../{files.bak => }/files/time3_stdlibs.gno | 0 .../{files.bak => }/files/time4_native.gno | 0 .../{files.bak => }/files/time4_stdlibs.gno | 0 .../{files.bak => }/files/time6_native.gno | 0 .../{files.bak => }/files/time6_stdlibs.gno | 0 .../{files.bak => }/files/time7_native.gno | 0 .../{files.bak => }/files/time7_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/time8.gno | 0 .../{files.bak => }/files/time9_native.gno | 0 .../{files.bak => }/files/time9_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/type0.gno | 0 gnovm/tests/{files.bak => }/files/type1.gno | 0 gnovm/tests/{files.bak => }/files/type11.gno | 0 gnovm/tests/{files.bak => }/files/type12.gno | 0 gnovm/tests/{files.bak => }/files/type13.gno | 0 gnovm/tests/{files.bak => }/files/type14.gno | 0 gnovm/tests/{files.bak => }/files/type15.gno | 0 gnovm/tests/{files.bak => }/files/type16.gno | 0 gnovm/tests/{files.bak => }/files/type17.gno | 0 gnovm/tests/{files.bak => }/files/type18.gno | 0 gnovm/tests/{files.bak => }/files/type19.gno | 0 gnovm/tests/{files.bak => }/files/type20.gno | 0 gnovm/tests/{files.bak => }/files/type22.gno | 0 gnovm/tests/{files.bak => }/files/type23b.gno | 0 gnovm/tests/{files.bak => }/files/type24b.gno | 0 .../{files.bak => }/files/type2_native.gno | 0 .../{files.bak => }/files/type2_stdlibs.gno | 0 gnovm/tests/{files.bak => }/files/type3.gno | 0 gnovm/tests/{files.bak => }/files/type30.gno | 0 gnovm/tests/{files.bak => }/files/type31.gno | 2 +- gnovm/tests/{files.bak => }/files/type32.gno | 2 +- gnovm/tests/{files.bak => }/files/type7.gno | 0 gnovm/tests/{files.bak => }/files/type8.gno | 0 gnovm/tests/files/types/0b2_filetest.gno | 22 + gnovm/tests/files/types/10a0_filetest.gno | 11 + gnovm/tests/files/types/10a1_filetest.gno | 11 + gnovm/tests/files/types/10a2_filetest.gno | 11 + gnovm/tests/files/types/10a3_filetest.gno | 10 + gnovm/tests/files/types/10a4_filetest.gno | 11 + gnovm/tests/files/types/10a5_filetest.gno | 10 + gnovm/tests/files/types/11a0_filetest.gno | 9 + gnovm/tests/files/types/11a1_filetest.gno | 9 + gnovm/tests/files/types/11a2_filetest.gno | 9 + gnovm/tests/files/types/11a3_filetest.gno | 15 + gnovm/tests/files/types/12a0_filetest.gno | 9 + gnovm/tests/files/types/12a1_filetest.gno | 9 + gnovm/tests/files/types/12a2_filetest.gno | 9 + gnovm/tests/files/types/12a3_filetest.gno | 15 + gnovm/tests/files/types/13a0_filetest.gno | 9 + gnovm/tests/files/types/13a1_filetest.gno | 25 + gnovm/tests/files/types/13b0_filetest.gno | 13 + gnovm/tests/files/types/13b1_filetest.gno | 13 + gnovm/tests/files/types/13b2_filetest.gno | 10 + gnovm/tests/files/types/13d0_filetest.gno | 12 + gnovm/tests/files/types/13e0_filetest.gno | 28 + gnovm/tests/files/types/13f0_filetest.gno | 25 + gnovm/tests/files/types/13f1_filetest.gno | 25 + gnovm/tests/files/types/13f2_filetest.gno | 25 + gnovm/tests/files/types/13f3_filetest.gno | 32 + gnovm/tests/files/types/18a0_filetest.gno | 10 + gnovm/tests/files/types/18a1_filetest.gno | 10 + gnovm/tests/files/types/18a2_filetest.gno | 10 + gnovm/tests/files/types/18a3_filetest.gno | 10 + gnovm/tests/files/types/19a0_filetest.gno | 14 + gnovm/tests/files/types/19a1_filetest.gno | 9 + gnovm/tests/files/types/20a0_filetest.gno | 8 + gnovm/tests/files/types/20a1_filetest.gno | 8 + gnovm/tests/files/types/20a2_filetest.gno | 8 + gnovm/tests/files/types/20a3_filetest.gno | 8 + gnovm/tests/files/types/20a4_filetest.gno | 8 + gnovm/tests/files/types/20a5_filetest.gno | 8 + gnovm/tests/files/types/21a0_filetest.gno | 10 + gnovm/tests/files/types/21a1_filetest.gno | 9 + gnovm/tests/files/types/22a0_filetest.gno | 18 + gnovm/tests/files/types/22a10_filetest.gno | 21 + gnovm/tests/files/types/22a11_filetest.gno | 22 + gnovm/tests/files/types/22a11a_filetest.gno | 21 + gnovm/tests/files/types/22a12_filetest.gno | 20 + gnovm/tests/files/types/22a13_filetest.gno | 20 + gnovm/tests/files/types/22a14_filetest.gno | 21 + gnovm/tests/files/types/22a15_filetest.gno | 18 + gnovm/tests/files/types/22a16_filetest.gno | 25 + gnovm/tests/files/types/22a17_filetest.gno | 15 + gnovm/tests/files/types/22a17a_filetest.gno | 15 + gnovm/tests/files/types/22a17b_filetest.gno | 16 + gnovm/tests/files/types/22a17c_filetest.gno | 20 + gnovm/tests/files/types/22a17d_filetest.gno | 20 + gnovm/tests/files/types/22a17e_filetest.gno | 23 + gnovm/tests/files/types/22a17f_filetest.gno | 26 + gnovm/tests/files/types/22a17g_filetest.gno | 36 ++ gnovm/tests/files/types/22a17h_filetest.gno | 31 + gnovm/tests/files/types/22a1_filetest.gno | 17 + gnovm/tests/files/types/22a1a_filetest.gno | 29 + gnovm/tests/files/types/22a2_filetest.gno | 25 + gnovm/tests/files/types/22a3_filetest.gno | 25 + gnovm/tests/files/types/22a4_filetest.gno | 25 + gnovm/tests/files/types/22a5_filetest.gno | 24 + gnovm/tests/files/types/22a6_filetest.gno | 20 + gnovm/tests/files/types/22a7_filetest.gno | 20 + gnovm/tests/files/types/22a8_filetest.gno | 24 + gnovm/tests/files/types/22a9_filetest.gno | 20 + gnovm/tests/files/types/9a0_filetest.gno | 9 + gnovm/tests/files/types/9a1_filetest.gno | 25 + gnovm/tests/files/types/9b0_filetest.gno | 13 + gnovm/tests/files/types/9b1_filetest.gno | 21 + gnovm/tests/files/types/9b2_filetest.gno | 9 + gnovm/tests/files/types/9b3_filetest.gno | 9 + gnovm/tests/files/types/9b4_filetest.gno | 9 + gnovm/tests/files/types/9d0_filetest.gno | 10 + gnovm/tests/files/types/9d1_filetest.gno | 10 + gnovm/tests/files/types/9d2_filetest.gno | 13 + gnovm/tests/files/types/9d3_filetest.gno | 15 + gnovm/tests/files/types/9d4_filetest.gno | 10 + gnovm/tests/files/types/9e0_filetest.gno | 27 + gnovm/tests/files/types/9f0_filetest.gno | 23 + gnovm/tests/files/types/9f1_filetest.gno | 23 + gnovm/tests/files/types/9f2_filetest.gno | 31 + gnovm/tests/{files.bak => }/files/unary.gno | 0 gnovm/tests/{files.bak => }/files/unary1.gno | 0 .../tests/{files.bak => }/files/untyped0.gno | 0 .../tests/{files.bak => }/files/untyped1.gno | 0 gnovm/tests/{files.bak => }/files/var.gno | 0 gnovm/tests/{files.bak => }/files/var10.gno | 0 gnovm/tests/{files.bak => }/files/var11.gno | 0 gnovm/tests/{files.bak => }/files/var12.gno | 0 gnovm/tests/{files.bak => }/files/var13.gno | 0 gnovm/tests/{files.bak => }/files/var14.gno | 0 gnovm/tests/{files.bak => }/files/var15.gno | 0 gnovm/tests/{files.bak => }/files/var16.gno | 0 gnovm/tests/{files.bak => }/files/var17.gno | 0 gnovm/tests/{files.bak => }/files/var2.gno | 0 gnovm/tests/{files.bak => }/files/var3.gno | 0 gnovm/tests/{files.bak => }/files/var4.gno | 0 gnovm/tests/{files.bak => }/files/var5.gno | 0 gnovm/tests/{files.bak => }/files/var6.gno | 0 gnovm/tests/{files.bak => }/files/var7.gno | 0 gnovm/tests/{files.bak => }/files/var9.gno | 0 .../tests/{files.bak => }/files/variadic.gno | 0 .../tests/{files.bak => }/files/variadic0.gno | 0 .../tests/{files.bak => }/files/variadic1.gno | 0 .../tests/{files.bak => }/files/variadic2.gno | 0 .../tests/{files.bak => }/files/variadic3.gno | 0 .../tests/{files.bak => }/files/variadic4.gno | 0 .../tests/{files.bak => }/files/variadic5.gno | 0 .../tests/{files.bak => }/files/variadic6.gno | 0 .../tests/{files.bak => }/files/variadic9.gno | 0 .../{files.bak => }/files/xfactor_long.gno | 0 .../tests/{files.bak => }/files/xfib_long.gno | 0 .../tests/{files.bak => }/files/zavltree.gno | 0 .../tests/{files.bak => }/files/zavltree0.gno | 0 .../tests/{files.bak => }/files/zavltree1.gno | 0 .../zpersist_valids.gnoa} | 2 +- .../files => files/zrealm}/zrealm0.gno | 2 +- .../files => files/zrealm}/zrealm1.gno | 2 +- .../files => files/zrealm}/zrealm10.gno | 2 +- .../files => files/zrealm}/zrealm11.gno | 2 +- .../files => files/zrealm}/zrealm12.gno | 2 +- .../files => files/zrealm}/zrealm2.gno | 2 +- .../files => files/zrealm}/zrealm3.gno | 2 +- .../files => files/zrealm}/zrealm4.gno | 2 +- .../files => files/zrealm}/zrealm5.gno | 2 +- .../files => files/zrealm}/zrealm6.gno | 2 +- .../files => files/zrealm}/zrealm7.gno | 2 +- .../files => files/zrealm}/zrealm8.gno | 2 +- .../files => files/zrealm}/zrealm9.gno | 2 +- .../files => files/zrealm}/zrealm_avl0.gno | 2 +- .../files => files/zrealm}/zrealm_avl1.gno | 2 +- .../files => files/zrealm}/zrealm_avl2.gno | 2 +- .../files => files/zrealm}/zrealm_const.gno | 2 +- .../zrealm}/zrealm_crossrealm0.gno | 2 +- .../zrealm}/zrealm_crossrealm1.gno | 2 +- .../zrealm}/zrealm_crossrealm10.gno | 2 +- .../zrealm}/zrealm_crossrealm11.gno | 7 +- .../zrealm}/zrealm_crossrealm12.gno | 14 +- .../zrealm}/zrealm_crossrealm2.gno | 2 +- .../zrealm}/zrealm_crossrealm3.gno | 2 +- .../zrealm}/zrealm_crossrealm4.gno | 2 +- .../zrealm}/zrealm_crossrealm5.gno | 2 +- .../zrealm}/zrealm_crossrealm6.gno | 2 +- .../zrealm}/zrealm_crossrealm7.gno | 2 +- .../zrealm}/zrealm_crossrealm8.gno | 2 +- .../zrealm}/zrealm_crossrealm9.gno | 2 +- .../files => files/zrealm}/zrealm_example.gno | 2 +- .../files => files/zrealm}/zrealm_map0.gno | 2 +- .../files => files/zrealm}/zrealm_std0.gno | 2 +- .../files => files/zrealm}/zrealm_std1.gno | 2 +- .../files => files/zrealm}/zrealm_std2.gno | 2 +- .../files => files/zrealm}/zrealm_std3.gno | 2 +- .../files => files/zrealm}/zrealm_std4.gno | 2 +- .../files => files/zrealm}/zrealm_std5.gno | 2 +- .../files => files/zrealm}/zrealm_std6.gno | 2 +- .../files => files/zrealm}/zrealm_tests0.gno | 2 +- .../zrealm}/zrealm_testutils0.gno | 2 +- .../{files.bak => }/files/zregexp_stdlibs.gno | 0 .../{files.bak => }/files/zsolitaire_long.gno | 0 942 files changed, 1951 insertions(+), 303 deletions(-) rename gnovm/tests/{files.bak => }/files/a1.gno (100%) rename gnovm/tests/{files.bak => }/files/a10.gno (100%) rename gnovm/tests/{files.bak => }/files/a11.gno (100%) rename gnovm/tests/{files.bak => }/files/a12.gno (100%) rename gnovm/tests/{files.bak => }/files/a13.gno (100%) rename gnovm/tests/{files.bak => }/files/a14.gno (100%) rename gnovm/tests/{files.bak => }/files/a15.gno (100%) rename gnovm/tests/{files.bak => }/files/a16.gno (100%) rename gnovm/tests/{files.bak => }/files/a17.gno (100%) rename gnovm/tests/{files.bak => }/files/a18.gno (100%) rename gnovm/tests/{files.bak => }/files/a19.gno (100%) rename gnovm/tests/{files.bak => }/files/a2.gno (100%) rename gnovm/tests/{files.bak => }/files/a20.gno (100%) rename gnovm/tests/{files.bak => }/files/a21.gno (100%) rename gnovm/tests/{files.bak => }/files/a22.gno (100%) rename gnovm/tests/{files.bak => }/files/a23.gno (100%) rename gnovm/tests/{files.bak => }/files/a24.gno (100%) rename gnovm/tests/{files.bak => }/files/a25.gno (100%) rename gnovm/tests/{files.bak => }/files/a26.gno (100%) rename gnovm/tests/{files.bak => }/files/a27.gno (100%) rename gnovm/tests/{files.bak => }/files/a28.gno (100%) rename gnovm/tests/{files.bak => }/files/a29.gno (100%) rename gnovm/tests/{files.bak => }/files/a3.gno (100%) rename gnovm/tests/{files.bak => }/files/a30.gno (100%) rename gnovm/tests/{files.bak => }/files/a31.gno (100%) rename gnovm/tests/{files.bak => }/files/a32.gno (100%) rename gnovm/tests/{files.bak => }/files/a33.gno (100%) rename gnovm/tests/{files.bak => }/files/a34.gno (100%) rename gnovm/tests/{files.bak => }/files/a35.gno (100%) rename gnovm/tests/{files.bak => }/files/a36.gno (100%) rename gnovm/tests/{files.bak => }/files/a37.gno (100%) rename gnovm/tests/{files.bak => }/files/a38.gno (100%) rename gnovm/tests/{files.bak => }/files/a39.gno (100%) rename gnovm/tests/{files.bak => }/files/a4.gno (100%) rename gnovm/tests/{files.bak => }/files/a40.gno (100%) rename gnovm/tests/{files.bak => }/files/a41.gno (100%) rename gnovm/tests/{files.bak => }/files/a42.gno (100%) rename gnovm/tests/{files.bak => }/files/a43.gno (100%) rename gnovm/tests/{files.bak => }/files/a44.gno (100%) rename gnovm/tests/{files.bak => }/files/a45.gno (100%) rename gnovm/tests/{files.bak => }/files/a45a.gno (100%) rename gnovm/tests/{files.bak => }/files/a46.gno (100%) rename gnovm/tests/{files.bak => }/files/a5.gno (100%) rename gnovm/tests/{files.bak => }/files/a6.gno (100%) rename gnovm/tests/{files.bak => }/files/a7.gno (100%) rename gnovm/tests/{files.bak => }/files/a8.gno (100%) rename gnovm/tests/{files.bak => }/files/a9.gno (100%) rename gnovm/tests/{files.bak => }/files/access0.gno (100%) rename gnovm/tests/{files.bak => }/files/access1.gno (100%) rename gnovm/tests/{files.bak/files/access2.gno => files/access2.gnoa} (91%) rename gnovm/tests/{files.bak => }/files/access3.gno (100%) rename gnovm/tests/{files.bak => }/files/access4.gno (100%) rename gnovm/tests/{files.bak => }/files/access5.gno (100%) rename gnovm/tests/{files.bak => }/files/access6.gno (100%) rename gnovm/tests/{files.bak => }/files/access7.gno (100%) rename gnovm/tests/{files.bak => }/files/add0.gno (100%) rename gnovm/tests/{files.bak => }/files/add1.gno (100%) rename gnovm/tests/{files.bak => }/files/add2.gno (100%) rename gnovm/tests/{files.bak => }/files/addr0b_native.gno (100%) rename gnovm/tests/{files.bak => }/files/addr0b_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/addr1.gno (100%) rename gnovm/tests/{files.bak => }/files/addr2b.gno (100%) rename gnovm/tests/{files.bak => }/files/alias0.gno (100%) rename gnovm/tests/{files.bak => }/files/alias1.gno (100%) rename gnovm/tests/{files.bak => }/files/and.gno (100%) rename gnovm/tests/{files.bak => }/files/and0.gno (100%) rename gnovm/tests/{files.bak => }/files/and1.gno (100%) rename gnovm/tests/{files.bak => }/files/and2.gno (100%) rename gnovm/tests/{files.bak => }/files/and3.gno (100%) rename gnovm/tests/{files.bak => }/files/append0.gno (100%) rename gnovm/tests/{files.bak => }/files/append1.gno (100%) rename gnovm/tests/{files.bak => }/files/append2.gno (100%) rename gnovm/tests/{files.bak => }/files/append3.gno (100%) rename gnovm/tests/{files.bak => }/files/append4.gno (100%) rename gnovm/tests/{files.bak => }/files/append5.gno (100%) rename gnovm/tests/{files.bak => }/files/array0.gno (100%) rename gnovm/tests/{files.bak => }/files/array1.gno (100%) rename gnovm/tests/{files.bak => }/files/array2.gno (100%) rename gnovm/tests/{files.bak => }/files/array3.gno (100%) rename gnovm/tests/{files.bak => }/files/array4.gno (100%) rename gnovm/tests/{files.bak => }/files/array5.gno (100%) rename gnovm/tests/{files.bak => }/files/assign.gno (100%) rename gnovm/tests/{files.bak => }/files/assign0b_native.gno (100%) rename gnovm/tests/{files.bak => }/files/assign0b_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/assign1.gno (100%) rename gnovm/tests/{files.bak => }/files/assign10.gno (100%) rename gnovm/tests/{files.bak => }/files/assign11.gno (100%) rename gnovm/tests/{files.bak => }/files/assign12.gno (100%) rename gnovm/tests/{files.bak => }/files/assign16.gno (100%) rename gnovm/tests/{files.bak => }/files/assign2.gno (100%) rename gnovm/tests/{files.bak => }/files/assign20.gno (100%) rename gnovm/tests/{files.bak => }/files/assign21.gno (100%) rename gnovm/tests/{files.bak => }/files/assign3.gno (100%) rename gnovm/tests/{files.bak => }/files/assign4.gno (100%) rename gnovm/tests/{files.bak => }/files/assign5.gno (100%) rename gnovm/tests/{files.bak => }/files/assign8.gno (100%) rename gnovm/tests/{files.bak => }/files/assign9.gno (100%) rename gnovm/tests/{files.bak => }/files/avl0.gno (100%) rename gnovm/tests/{files.bak => }/files/avl1.gno (100%) rename gnovm/tests/{files.bak => }/files/bin.gno (100%) rename gnovm/tests/{files.bak => }/files/bin0.gno (100%) rename gnovm/tests/{files.bak => }/files/bin1.gno (100%) rename gnovm/tests/{files.bak => }/files/bin3.gno (100%) rename gnovm/tests/{files.bak => }/files/bin4.gno (100%) rename gnovm/tests/{files.bak => }/files/bin5.gno (100%) rename gnovm/tests/{files.bak => }/files/binstruct_ptr_map0.gno (100%) rename gnovm/tests/{files.bak => }/files/binstruct_ptr_slice0.gno (100%) rename gnovm/tests/{files.bak => }/files/binstruct_slice0.gno (100%) rename gnovm/tests/{files.bak => }/files/bltn.gno (100%) rename gnovm/tests/{files.bak => }/files/bltn0.gno (100%) rename gnovm/tests/{files.bak => }/files/bool.gno (100%) rename gnovm/tests/{files.bak => }/files/bool0.gno (100%) rename gnovm/tests/{files.bak => }/files/bool1.gno (100%) rename gnovm/tests/{files.bak => }/files/bool2.gno (100%) rename gnovm/tests/{files.bak => }/files/bool3.gno (100%) rename gnovm/tests/{files.bak => }/files/bool4.gno (100%) rename gnovm/tests/{files.bak => }/files/bool5.gno (100%) rename gnovm/tests/{files.bak => }/files/build0.gno (100%) rename gnovm/tests/{files.bak => }/files/cap0.gno (100%) rename gnovm/tests/{files.bak => }/files/closure0.gno (100%) rename gnovm/tests/{files.bak => }/files/closure1.gno (100%) rename gnovm/tests/{files.bak => }/files/closure2.gno (100%) rename gnovm/tests/{files.bak => }/files/closure3.gno (100%) rename gnovm/tests/{files.bak => }/files/closure4.gno (100%) rename gnovm/tests/{files.bak => }/files/closure5.gno (100%) rename gnovm/tests/{files.bak => }/files/closure6.gno (100%) rename gnovm/tests/{files.bak => }/files/closure7.gno (100%) rename gnovm/tests/{files.bak => }/files/closure8.gno (100%) rename gnovm/tests/{files.bak => }/files/comp1.gno (100%) rename gnovm/tests/{files.bak => }/files/comp2.gno (100%) rename gnovm/tests/{files.bak => }/files/comp3.gno (100%) rename gnovm/tests/{files.bak => }/files/composite0.gno (100%) rename gnovm/tests/{files.bak => }/files/composite1.gno (100%) rename gnovm/tests/{files.bak => }/files/composite10.gno (100%) rename gnovm/tests/{files.bak => }/files/composite11.gno (100%) rename gnovm/tests/{files.bak => }/files/composite12.gno (100%) rename gnovm/tests/{files.bak => }/files/composite13.gno (100%) rename gnovm/tests/{files.bak => }/files/composite14.gno (100%) rename gnovm/tests/{files.bak => }/files/composite15.gno (100%) rename gnovm/tests/{files.bak => }/files/composite16.gno (100%) rename gnovm/tests/{files.bak => }/files/composite17.gno (100%) rename gnovm/tests/{files.bak => }/files/composite2.gno (100%) rename gnovm/tests/{files.bak => }/files/composite3.gno (100%) rename gnovm/tests/{files.bak => }/files/composite4.gno (100%) rename gnovm/tests/{files.bak => }/files/composite5.gno (100%) rename gnovm/tests/{files.bak => }/files/composite6.gno (100%) rename gnovm/tests/{files.bak => }/files/composite7.gno (100%) rename gnovm/tests/{files.bak => }/files/composite8.gno (100%) rename gnovm/tests/{files.bak => }/files/composite8bis.gno (100%) rename gnovm/tests/{files.bak => }/files/composite9.gno (100%) rename gnovm/tests/{files.bak => }/files/const0.gno (100%) rename gnovm/tests/{files.bak => }/files/const1.gno (100%) rename gnovm/tests/{files.bak => }/files/const10.gno (100%) rename gnovm/tests/{files.bak => }/files/const11.gno (100%) rename gnovm/tests/{files.bak => }/files/const12.gno (100%) rename gnovm/tests/{files.bak => }/files/const13.gno (100%) rename gnovm/tests/{files.bak => }/files/const14.gno (100%) rename gnovm/tests/{files.bak => }/files/const15.gno (100%) rename gnovm/tests/{files.bak => }/files/const16.gno (100%) rename gnovm/tests/{files.bak => }/files/const17.gno (100%) rename gnovm/tests/{files.bak => }/files/const18.gno (100%) rename gnovm/tests/{files.bak => }/files/const19.gno (100%) rename gnovm/tests/{files.bak => }/files/const2.gno (100%) rename gnovm/tests/{files.bak => }/files/const20.gno (100%) rename gnovm/tests/{files.bak => }/files/const21.gno (100%) rename gnovm/tests/{files.bak => }/files/const22.gno (100%) rename gnovm/tests/{files.bak => }/files/const3.gno (100%) rename gnovm/tests/{files.bak => }/files/const4.gno (100%) rename gnovm/tests/{files.bak => }/files/const5.gno (100%) rename gnovm/tests/{files.bak => }/files/const6.gno (100%) rename gnovm/tests/{files.bak => }/files/const7.gno (100%) rename gnovm/tests/{files.bak => }/files/const8.gno (100%) rename gnovm/tests/{files.bak => }/files/const9.gno (100%) rename gnovm/tests/{files.bak => }/files/cont.gno (100%) rename gnovm/tests/{files.bak => }/files/cont0.gno (100%) rename gnovm/tests/{files.bak => }/files/cont1.gno (100%) rename gnovm/tests/{files.bak => }/files/context.gno (100%) rename gnovm/tests/{files.bak => }/files/context2.gno (100%) rename gnovm/tests/{files.bak => }/files/convert0.gno (100%) rename gnovm/tests/{files.bak => }/files/convert1.gno (100%) rename gnovm/tests/{files.bak => }/files/convert3.gno (100%) rename gnovm/tests/{files.bak => }/files/copy0.gno (100%) rename gnovm/tests/{files.bak => }/files/copy1.gno (100%) rename gnovm/tests/{files.bak => }/files/copy2.gno (100%) rename gnovm/tests/{files.bak => }/files/defer0.gno (100%) rename gnovm/tests/{files.bak => }/files/defer1.gno (100%) rename gnovm/tests/{files.bak => }/files/defer2.gno (100%) rename gnovm/tests/{files.bak => }/files/defer3.gno (100%) rename gnovm/tests/{files.bak => }/files/defer4.gno (100%) rename gnovm/tests/{files.bak => }/files/defer5.gno (100%) rename gnovm/tests/{files.bak => }/files/defer6.gno (100%) rename gnovm/tests/{files.bak => }/files/defer7.gno (100%) rename gnovm/tests/{files.bak => }/files/defer8.gno (100%) rename gnovm/tests/{files.bak => }/files/defer9.gno (100%) rename gnovm/tests/{files.bak => }/files/define0.gno (100%) rename gnovm/tests/{files.bak => }/files/define1.gno (100%) rename gnovm/tests/{files.bak => }/files/define2.gno (100%) rename gnovm/tests/{files.bak => }/files/define3.gno (100%) rename gnovm/tests/{files.bak => }/files/define4.gno (100%) rename gnovm/tests/{files.bak => }/files/delete0.gno (100%) rename gnovm/tests/{files.bak => }/files/errors.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/b1/foo/foo.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/b2/foo/foo.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/bar/quux.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/baz-bat/baz-bat.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/baz/quux.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/c1/c1.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/c2/c2.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/context/context.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/ct/ct1.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/ct/ct2.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/ct/ct3.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/ct1/ct1.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/foo-bar/foo-bar.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/foo/bar.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/foo/bir.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/foo/boo/boo.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/m1/main.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/m1/main_test.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/m2/m2_test.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/net/http/http.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/net/http/httptest/httptest.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/net/net.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/net/url/url.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/p1/s1.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/p1/s2.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/tata/tutu.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/time/time.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/timtadh/data-structures/tree/avl/avltree.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/timtadh/data-structures/tree/utils.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/timtadh/data-structures/types/map_entry.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/timtadh/data-structures/types/string.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/timtadh/data-structures/types/types.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/timtadh/data-structures/types/util.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/toto/titi.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/vars/first.gno (100%) rename gnovm/tests/{files.bak => }/files/extern/vars/second.gno (100%) rename gnovm/tests/{files.bak => }/files/fib0.gno (100%) rename gnovm/tests/{files.bak => }/files/float0.gno (100%) rename gnovm/tests/{files.bak => }/files/float1.gno (100%) rename gnovm/tests/{files.bak => }/files/float2.gno (100%) rename gnovm/tests/{files.bak => }/files/float3.gno (100%) rename gnovm/tests/{files.bak => }/files/float4.gno (100%) rename gnovm/tests/{files.bak => }/files/float5_native.gno (100%) rename gnovm/tests/{files.bak => }/files/float5_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/float6.gno (100%) rename gnovm/tests/{files.bak => }/files/float7.gno (100%) rename gnovm/tests/{files.bak => }/files/for0.gno (100%) rename gnovm/tests/{files.bak => }/files/for1.gno (100%) rename gnovm/tests/{files.bak => }/files/for10.gno (100%) rename gnovm/tests/{files.bak => }/files/for11.gno (100%) rename gnovm/tests/{files.bak => }/files/for12.gno (100%) rename gnovm/tests/{files.bak => }/files/for13.gno (100%) rename gnovm/tests/{files.bak => }/files/for14.gno (100%) rename gnovm/tests/{files.bak => }/files/for15.gno (100%) rename gnovm/tests/{files.bak => }/files/for16.gno (100%) rename gnovm/tests/{files.bak => }/files/for17.gno (100%) rename gnovm/tests/{files.bak => }/files/for18.gno (100%) rename gnovm/tests/{files.bak => }/files/for2.gno (100%) rename gnovm/tests/{files.bak => }/files/for3.gno (100%) rename gnovm/tests/{files.bak => }/files/for4.gno (100%) rename gnovm/tests/{files.bak => }/files/for5.gno (100%) rename gnovm/tests/{files.bak => }/files/for6.gno (100%) rename gnovm/tests/{files.bak => }/files/for7.gno (100%) rename gnovm/tests/{files.bak => }/files/for8.gno (100%) rename gnovm/tests/{files.bak => }/files/for9.gno (100%) rename gnovm/tests/{files.bak => }/files/fun.gno (100%) rename gnovm/tests/{files.bak => }/files/fun10.gno (100%) rename gnovm/tests/{files.bak => }/files/fun11.gno (100%) rename gnovm/tests/{files.bak => }/files/fun12.gno (100%) rename gnovm/tests/{files.bak => }/files/fun13.gno (100%) rename gnovm/tests/{files.bak => }/files/fun14.gno (100%) rename gnovm/tests/{files.bak => }/files/fun15.gno (100%) rename gnovm/tests/{files.bak => }/files/fun16.gno (100%) rename gnovm/tests/{files.bak => }/files/fun17.gno (100%) rename gnovm/tests/{files.bak => }/files/fun18.gno (100%) rename gnovm/tests/{files.bak => }/files/fun19b.gno (100%) rename gnovm/tests/{files.bak => }/files/fun2.gno (100%) rename gnovm/tests/{files.bak => }/files/fun20b.gno (100%) rename gnovm/tests/{files.bak => }/files/fun21.gno (100%) rename gnovm/tests/{files.bak => }/files/fun22.gno (100%) rename gnovm/tests/{files.bak => }/files/fun23.gno (100%) rename gnovm/tests/{files.bak => }/files/fun24.gno (61%) rename gnovm/tests/{files.bak => }/files/fun25.gno (100%) rename gnovm/tests/{files.bak => }/files/fun26.gno (100%) rename gnovm/tests/{files.bak => }/files/fun3.gno (100%) rename gnovm/tests/{files.bak => }/files/fun4.gno (100%) rename gnovm/tests/{files.bak => }/files/fun5.gno (100%) rename gnovm/tests/{files.bak => }/files/fun6.gno (100%) rename gnovm/tests/{files.bak => }/files/fun6b.gno (100%) rename gnovm/tests/{files.bak => }/files/fun7.gno (100%) rename gnovm/tests/{files.bak => }/files/fun8.gno (100%) rename gnovm/tests/{files.bak => }/files/fun9.gno (100%) rename gnovm/tests/{files.bak => }/files/goto0.gno (100%) rename gnovm/tests/{files.bak => }/files/goto1.gno (100%) rename gnovm/tests/{files.bak => }/files/goto2.gno (100%) rename gnovm/tests/{files.bak => }/files/goto3.gno (100%) rename gnovm/tests/{files.bak => }/files/goto3a.gno (100%) rename gnovm/tests/{files.bak => }/files/goto4.gno (100%) rename gnovm/tests/{files.bak => }/files/goto5.gno (100%) rename gnovm/tests/{files.bak => }/files/goto6.gno (100%) rename gnovm/tests/{files.bak => }/files/if.gno (100%) rename gnovm/tests/{files.bak => }/files/if0.gno (100%) rename gnovm/tests/{files.bak => }/files/if1.gno (100%) rename gnovm/tests/{files.bak => }/files/if2.gno (100%) rename gnovm/tests/{files.bak => }/files/if3.gno (100%) rename gnovm/tests/{files.bak => }/files/if4.gno (100%) rename gnovm/tests/{files.bak => }/files/if5.gno (100%) rename gnovm/tests/{files.bak => }/files/if6.gno (100%) rename gnovm/tests/{files.bak => }/files/if7.gno (100%) rename gnovm/tests/{files.bak => }/files/import0.gno (100%) rename gnovm/tests/{files.bak => }/files/import1.gno (100%) rename gnovm/tests/{files.bak => }/files/import10.gno (100%) rename gnovm/tests/{files.bak => }/files/import3.gno (100%) rename gnovm/tests/{files.bak => }/files/import4.gno (100%) rename gnovm/tests/{files.bak => }/files/import5.gno (100%) rename gnovm/tests/{files.bak => }/files/import6.gno (100%) rename gnovm/tests/{files.bak => }/files/import7.gno (100%) rename gnovm/tests/{files.bak => }/files/import8.gno (100%) rename gnovm/tests/{files.bak => }/files/import9.gno (100%) rename gnovm/tests/{files.bak => }/files/inc.gno (100%) rename gnovm/tests/{files.bak => }/files/index0.gno (100%) rename gnovm/tests/{files.bak => }/files/init0.gno (100%) rename gnovm/tests/{files.bak => }/files/init1.gno (100%) rename gnovm/tests/{files.bak => }/files/interface0.gno (100%) rename gnovm/tests/{files.bak => }/files/interface1.gno (100%) rename gnovm/tests/{files.bak => }/files/interface10.gno (100%) rename gnovm/tests/{files.bak => }/files/interface11.gno (100%) rename gnovm/tests/{files.bak => }/files/interface12.gno (100%) rename gnovm/tests/{files.bak => }/files/interface13.gno (100%) rename gnovm/tests/{files.bak => }/files/interface14.gno (100%) rename gnovm/tests/{files.bak => }/files/interface15.gno (100%) rename gnovm/tests/{files.bak => }/files/interface16.gno (100%) rename gnovm/tests/{files.bak => }/files/interface17.gno (100%) rename gnovm/tests/{files.bak => }/files/interface18.gno (100%) rename gnovm/tests/{files.bak => }/files/interface19.gno (100%) rename gnovm/tests/{files.bak => }/files/interface2.gno (100%) rename gnovm/tests/{files.bak => }/files/interface20.gno (100%) rename gnovm/tests/{files.bak => }/files/interface21.gno (100%) rename gnovm/tests/{files.bak => }/files/interface22.gno (100%) rename gnovm/tests/{files.bak => }/files/interface23.gno (100%) rename gnovm/tests/{files.bak => }/files/interface24.gno (100%) rename gnovm/tests/{files.bak => }/files/interface25.gno (100%) rename gnovm/tests/{files.bak => }/files/interface26.gno (100%) rename gnovm/tests/{files.bak => }/files/interface27b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface28b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface29.gno (100%) rename gnovm/tests/{files.bak => }/files/interface3.gno (100%) rename gnovm/tests/{files.bak => }/files/interface30.gno (100%) rename gnovm/tests/{files.bak => }/files/interface31.gno (100%) rename gnovm/tests/{files.bak => }/files/interface32.gno (100%) rename gnovm/tests/{files.bak => }/files/interface33.gno (100%) rename gnovm/tests/{files.bak => }/files/interface34.gno (100%) rename gnovm/tests/{files.bak => }/files/interface35.gno (100%) rename gnovm/tests/{files.bak => }/files/interface36.gno (100%) rename gnovm/tests/{files.bak => }/files/interface37.gno (100%) rename gnovm/tests/{files.bak => }/files/interface38b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface39b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface4.gno (100%) rename gnovm/tests/{files.bak => }/files/interface40b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface41b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface42.gno (100%) rename gnovm/tests/{files.bak => }/files/interface43.gno (100%) rename gnovm/tests/{files.bak => }/files/interface44.gno (100%) rename gnovm/tests/{files.bak => }/files/interface45.gno (100%) rename gnovm/tests/{files.bak => }/files/interface46.gno (100%) rename gnovm/tests/{files.bak => }/files/interface5.gno (100%) rename gnovm/tests/{files.bak => }/files/interface6.gno (100%) rename gnovm/tests/{files.bak => }/files/interface7b.gno (100%) rename gnovm/tests/{files.bak => }/files/interface8.gno (100%) rename gnovm/tests/{files.bak => }/files/interface9b.gno (100%) rename gnovm/tests/{files.bak => }/files/interp.gi (100%) rename gnovm/tests/{files.bak => }/files/interp2.gi (100%) rename gnovm/tests/{files.bak => }/files/io0_native.gno (100%) rename gnovm/tests/{files.bak => }/files/io0_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/io1.gno (100%) rename gnovm/tests/{files.bak => }/files/io2.gno (100%) rename gnovm/tests/{files.bak => }/files/iota.gno (100%) rename gnovm/tests/{files.bak => }/files/iota0.gno (100%) rename gnovm/tests/{files.bak => }/files/ipp_as_key.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-1096.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-558b.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-735.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-776.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-782.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-784.gno (100%) rename gnovm/tests/{files.bak => }/files/issue-880.gno (100%) rename gnovm/tests/{files.bak => }/files/l2_long.gno (100%) rename gnovm/tests/{files.bak => }/files/l3_long.gno (100%) rename gnovm/tests/{files.bak => }/files/l4_long.gno (100%) rename gnovm/tests/{files.bak => }/files/l5_long.gno (100%) rename gnovm/tests/{files.bak => }/files/len0.gno (100%) rename gnovm/tests/{files.bak => }/files/make0.gno (100%) rename gnovm/tests/{files.bak => }/files/make1.gno (100%) rename gnovm/tests/{files.bak => }/files/make2.gno (100%) rename gnovm/tests/{files.bak => }/files/map.gno (100%) rename gnovm/tests/{files.bak => }/files/map0.gno (100%) rename gnovm/tests/{files.bak => }/files/map1.gno (100%) rename gnovm/tests/{files.bak => }/files/map10.gno (100%) rename gnovm/tests/{files.bak => }/files/map11.gno (100%) rename gnovm/tests/{files.bak => }/files/map12.gno (100%) rename gnovm/tests/{files.bak => }/files/map13.gno (100%) rename gnovm/tests/{files.bak => }/files/map14b.gno (100%) rename gnovm/tests/{files.bak => }/files/map15.gno (100%) rename gnovm/tests/{files.bak => }/files/map16.gno (100%) rename gnovm/tests/{files.bak => }/files/map17.gno (100%) rename gnovm/tests/{files.bak => }/files/map18.gno (100%) rename gnovm/tests/{files.bak => }/files/map19b.gno (100%) rename gnovm/tests/{files.bak => }/files/map2.gno (100%) rename gnovm/tests/{files.bak => }/files/map20.gno (100%) rename gnovm/tests/{files.bak => }/files/map21.gno (100%) rename gnovm/tests/{files.bak => }/files/map22.gno (100%) rename gnovm/tests/{files.bak => }/files/map23.gno (100%) rename gnovm/tests/{files.bak => }/files/map24.gno (100%) rename gnovm/tests/{files.bak => }/files/map25.gno (100%) rename gnovm/tests/{files.bak => }/files/map26.gno (100%) rename gnovm/tests/{files.bak => }/files/map27.gno (100%) rename gnovm/tests/{files.bak => }/files/map28b.gno (100%) rename gnovm/tests/{files.bak => }/files/map28c.gno (100%) rename gnovm/tests/{files.bak => }/files/map29_native.gno (100%) rename gnovm/tests/{files.bak => }/files/map29_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/map3.gno (100%) rename gnovm/tests/{files.bak => }/files/map4.gno (100%) rename gnovm/tests/{files.bak => }/files/map5.gno (100%) rename gnovm/tests/{files.bak => }/files/map6.gno (100%) rename gnovm/tests/{files.bak => }/files/map7.gno (100%) rename gnovm/tests/{files.bak => }/files/map8.gno (100%) rename gnovm/tests/{files.bak => }/files/map9.gno (100%) rename gnovm/tests/{files.bak => }/files/math0_native.gno (100%) rename gnovm/tests/{files.bak => }/files/math0_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/math2.gno (100%) rename gnovm/tests/{files.bak => }/files/math3.gno (100%) rename gnovm/tests/{files.bak => }/files/maths_int16_long.gno (100%) rename gnovm/tests/{files.bak => }/files/maths_int8.gno (100%) rename gnovm/tests/{files.bak => }/files/method.gno (100%) rename gnovm/tests/{files.bak => }/files/method0.gno (100%) rename gnovm/tests/{files.bak => }/files/method1.gno (100%) rename gnovm/tests/{files.bak => }/files/method10.gno (100%) rename gnovm/tests/{files.bak => }/files/method11.gno (100%) rename gnovm/tests/{files.bak => }/files/method12.gno (100%) rename gnovm/tests/{files.bak => }/files/method13.gno (100%) rename gnovm/tests/{files.bak => }/files/method14.gno (100%) rename gnovm/tests/{files.bak => }/files/method15.gno (100%) rename gnovm/tests/{files.bak => }/files/method16b.gno (100%) rename gnovm/tests/{files.bak => }/files/method17b.gno (100%) rename gnovm/tests/{files.bak => }/files/method18.gno (100%) rename gnovm/tests/{files.bak => }/files/method19.gno (100%) rename gnovm/tests/{files.bak => }/files/method2.gno (100%) rename gnovm/tests/{files.bak => }/files/method20.gno (100%) rename gnovm/tests/{files.bak => }/files/method21.gno (100%) rename gnovm/tests/{files.bak => }/files/method22.gno (100%) rename gnovm/tests/{files.bak => }/files/method23.gno (100%) rename gnovm/tests/{files.bak => }/files/method24.gno (100%) rename gnovm/tests/{files.bak => }/files/method25.gno (100%) rename gnovm/tests/{files.bak => }/files/method26.gno (100%) rename gnovm/tests/{files.bak => }/files/method27.gno (100%) rename gnovm/tests/{files.bak => }/files/method28.gno (100%) rename gnovm/tests/{files.bak => }/files/method29b.gno (100%) rename gnovm/tests/{files.bak => }/files/method3.gno (100%) rename gnovm/tests/{files.bak => }/files/method30.gno (100%) rename gnovm/tests/{files.bak => }/files/method31b.gno (100%) rename gnovm/tests/{files.bak => }/files/method32.gno (100%) rename gnovm/tests/{files.bak => }/files/method33.gno (100%) rename gnovm/tests/{files.bak => }/files/method34.gno (100%) rename gnovm/tests/{files.bak => }/files/method35.gno (100%) rename gnovm/tests/{files.bak => }/files/method36.gno (100%) rename gnovm/tests/{files.bak => }/files/method37.gno (100%) rename gnovm/tests/{files.bak => }/files/method4.gno (100%) rename gnovm/tests/{files.bak => }/files/method5.gno (100%) rename gnovm/tests/{files.bak => }/files/method6.gno (100%) rename gnovm/tests/{files.bak => }/files/method7.gno (100%) rename gnovm/tests/{files.bak => }/files/method8.gno (100%) rename gnovm/tests/{files.bak => }/files/method9.gno (100%) rename gnovm/tests/{files.bak => }/files/neg0.gno (100%) rename gnovm/tests/{files.bak => }/files/new0.gno (100%) rename gnovm/tests/{files.bak => }/files/new1.gno (100%) rename gnovm/tests/{files.bak => }/files/new2.gno (100%) rename gnovm/tests/{files.bak => }/files/new3.gno (100%) rename gnovm/tests/{files.bak => }/files/nil0.gno (100%) rename gnovm/tests/{files.bak => }/files/nil1.gno (100%) rename gnovm/tests/{files.bak => }/files/nil2.gno (100%) rename gnovm/tests/{files.bak => }/files/nil3.gno (100%) rename gnovm/tests/{files.bak => }/files/not0.gno (100%) rename gnovm/tests/{files.bak => }/files/not1.gno (100%) rename gnovm/tests/{files.bak => }/files/not2.gno (100%) rename gnovm/tests/{files.bak => }/files/op0.gno (100%) rename gnovm/tests/{files.bak => }/files/op2.gno (100%) rename gnovm/tests/{files.bak => }/files/op6.gno (100%) rename gnovm/tests/{files.bak => }/files/op7.gno (60%) rename gnovm/tests/{files.bak => }/files/op8.gno (100%) rename gnovm/tests/{files.bak => }/files/opint16.gno (100%) rename gnovm/tests/{files.bak => }/files/opint32.gno (100%) rename gnovm/tests/{files.bak => }/files/opint64.gno (100%) rename gnovm/tests/{files.bak => }/files/opint8.gno (100%) rename gnovm/tests/{files.bak => }/files/opstring.gno (100%) rename gnovm/tests/{files.bak => }/files/opuint16.gno (100%) rename gnovm/tests/{files.bak => }/files/opuint32.gno (100%) rename gnovm/tests/{files.bak => }/files/opuint64.gno (100%) rename gnovm/tests/{files.bak => }/files/opuint8.gno (100%) rename gnovm/tests/{files.bak => }/files/or0.gno (100%) rename gnovm/tests/{files.bak => }/files/or1.gno (100%) rename gnovm/tests/{files.bak => }/files/or2.gno (100%) rename gnovm/tests/{files.bak => }/files/or3.gno (100%) rename gnovm/tests/{files.bak => }/files/or4.gno (100%) rename gnovm/tests/{files.bak => }/files/panic0.gno (100%) rename gnovm/tests/{files.bak => }/files/panic0b.gno (100%) rename gnovm/tests/{files.bak/files/persist_map.gno => files/persist_map.gno.a} (96%) rename gnovm/tests/{files.bak => }/files/pkgname0.gno (100%) rename gnovm/tests/{files.bak => }/files/pkgname1.gno (100%) rename gnovm/tests/{files.bak => }/files/pkgname2.gno (100%) rename gnovm/tests/{files.bak => }/files/primes.gno (100%) rename gnovm/tests/{files.bak => }/files/print0.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr0.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr1.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr2.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr3.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr4.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr5.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr5a.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr6.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr7.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr8.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr_array0.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr_array1.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr_array2.gno (100%) rename gnovm/tests/{files.bak => }/files/ptr_array3.gno (100%) rename gnovm/tests/{files.bak => }/files/range0.gno (100%) rename gnovm/tests/{files.bak => }/files/range1.gno (100%) rename gnovm/tests/{files.bak => }/files/range2.gno (100%) rename gnovm/tests/{files.bak => }/files/range3.gno (100%) rename gnovm/tests/{files.bak => }/files/range4.gno (100%) rename gnovm/tests/{files.bak => }/files/range5.gno (100%) rename gnovm/tests/{files.bak => }/files/range6.gno (100%) rename gnovm/tests/{files.bak => }/files/range7.gno (100%) rename gnovm/tests/{files.bak => }/files/recover0.gno (100%) rename gnovm/tests/{files.bak => }/files/recover1.gno (100%) rename gnovm/tests/{files.bak => }/files/recover1b.gno (100%) rename gnovm/tests/{files.bak => }/files/recover2.gno (100%) rename gnovm/tests/{files.bak => }/files/recover3.gno (100%) rename gnovm/tests/{files.bak => }/files/recover4.gno (100%) rename gnovm/tests/{files.bak => }/files/recover5.gno (100%) rename gnovm/tests/{files.bak => }/files/recover6.gno (100%) rename gnovm/tests/{files.bak => }/files/recover7.gno (100%) rename gnovm/tests/{files.bak => }/files/recurse0.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration-global0.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration-global1.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration-global5.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration0.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration1.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration2.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration3.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration4.gno (100%) rename gnovm/tests/{files.bak => }/files/redeclaration5.gno (100%) rename gnovm/tests/{files.bak => }/files/ret1.gno (100%) rename gnovm/tests/{files.bak => }/files/ret10.gno (100%) rename gnovm/tests/{files.bak => }/files/ret11.gno (100%) rename gnovm/tests/{files.bak => }/files/ret12.gno (100%) rename gnovm/tests/{files.bak => }/files/ret13.gno (100%) rename gnovm/tests/{files.bak => }/files/ret14.gno (100%) rename gnovm/tests/{files.bak => }/files/ret2.gno (100%) rename gnovm/tests/{files.bak => }/files/ret3.gno (100%) rename gnovm/tests/{files.bak => }/files/ret4.gno (100%) rename gnovm/tests/{files.bak => }/files/ret5.gno (100%) rename gnovm/tests/{files.bak => }/files/ret6.gno (100%) rename gnovm/tests/{files.bak => }/files/ret7.gno (100%) rename gnovm/tests/{files.bak => }/files/ret8.gno (100%) rename gnovm/tests/{files.bak => }/files/ret9.gno (100%) rename gnovm/tests/{files.bak => }/files/run0.gno (100%) rename gnovm/tests/{files.bak => }/files/run1.gno (100%) rename gnovm/tests/{files.bak => }/files/run10.gno (100%) rename gnovm/tests/{files.bak => }/files/run11.gno (100%) rename gnovm/tests/{files.bak => }/files/run12.gno (100%) rename gnovm/tests/{files.bak => }/files/run13.gno (100%) rename gnovm/tests/{files.bak => }/files/run4.gno (100%) rename gnovm/tests/{files.bak => }/files/run5.gno (100%) rename gnovm/tests/{files.bak => }/files/run6.gno (100%) rename gnovm/tests/{files.bak => }/files/run7.gno (100%) rename gnovm/tests/{files.bak => }/files/run8.gno (100%) rename gnovm/tests/{files.bak => }/files/run9.gno (100%) rename gnovm/tests/{files.bak => }/files/rune0.gno (100%) rename gnovm/tests/{files.bak => }/files/rune1.gno (100%) rename gnovm/tests/{files.bak => }/files/rune2.gno (100%) rename gnovm/tests/{files.bak => }/files/sample.plugin (100%) rename gnovm/tests/{files.bak => }/files/scope0.gno (100%) rename gnovm/tests/{files.bak => }/files/scope1.gno (100%) rename gnovm/tests/{files.bak => }/files/scope2.gno (100%) rename gnovm/tests/{files.bak => }/files/scope3.gno (100%) rename gnovm/tests/{files.bak => }/files/scope4.gno (100%) rename gnovm/tests/{files.bak => }/files/scope5.gno (100%) rename gnovm/tests/{files.bak => }/files/scope6.gno (100%) rename gnovm/tests/{files.bak => }/files/scope7.gno (100%) rename gnovm/tests/{files.bak => }/files/secure.gi (100%) rename gnovm/tests/{files.bak => }/files/shift0.gno (100%) rename gnovm/tests/{files.bak => }/files/shift1.gno (100%) rename gnovm/tests/{files.bak => }/files/shift2.gno (100%) rename gnovm/tests/{files.bak => }/files/shift3.gno (100%) rename gnovm/tests/{files.bak => }/files/shift4.gno (100%) rename gnovm/tests/{files.bak => }/files/shift5.gno (100%) rename gnovm/tests/{files.bak => }/files/slice0.gno (100%) rename gnovm/tests/{files.bak => }/files/slice1.gno (100%) rename gnovm/tests/{files.bak => }/files/slice2.gno (100%) rename gnovm/tests/{files.bak => }/files/std0.gno (100%) rename gnovm/tests/{files.bak => }/files/std10.gno (100%) rename gnovm/tests/{files.bak => }/files/std11.gno (100%) rename gnovm/tests/{files.bak => }/files/std2.gno (100%) rename gnovm/tests/{files.bak => }/files/std3.gno (100%) rename gnovm/tests/{files.bak => }/files/std4.gno (100%) rename gnovm/tests/{files.bak => }/files/std5.gno (100%) rename gnovm/tests/{files.bak => }/files/std6.gno (100%) rename gnovm/tests/{files.bak => }/files/std7.gno (100%) rename gnovm/tests/{files.bak => }/files/std8.gno (100%) rename gnovm/tests/{files.bak => }/files/std9.gno (100%) rename gnovm/tests/{files.bak => }/files/stdlibs_native.gno (100%) rename gnovm/tests/{files.bak/files/stdlibs_stdlibs.gno => files/stdlibs_stdlibs.gnoa} (94%) rename gnovm/tests/{files.bak => }/files/str.gno (100%) rename gnovm/tests/{files.bak => }/files/str0.gno (100%) rename gnovm/tests/{files.bak => }/files/str1.gno (100%) rename gnovm/tests/{files.bak => }/files/str2.gno (100%) rename gnovm/tests/{files.bak => }/files/str3.gno (100%) rename gnovm/tests/{files.bak => }/files/str4.gno (100%) rename gnovm/tests/{files.bak => }/files/struct.gno (100%) rename gnovm/tests/{files.bak => }/files/struct0.gno (100%) rename gnovm/tests/{files.bak => }/files/struct0a.gno (100%) rename gnovm/tests/{files.bak => }/files/struct1.gno (100%) rename gnovm/tests/{files.bak => }/files/struct10.gno (100%) rename gnovm/tests/{files.bak => }/files/struct11.gno (100%) rename gnovm/tests/{files.bak => }/files/struct11b.gno (100%) rename gnovm/tests/{files.bak => }/files/struct12.gno (100%) rename gnovm/tests/{files.bak => }/files/struct13_native.gno (100%) rename gnovm/tests/{files.bak => }/files/struct13_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/struct14.gno (100%) rename gnovm/tests/{files.bak => }/files/struct16.gno (100%) rename gnovm/tests/{files.bak => }/files/struct17.gno (100%) rename gnovm/tests/{files.bak => }/files/struct19.gno (100%) rename gnovm/tests/{files.bak => }/files/struct2.gno (100%) rename gnovm/tests/{files.bak => }/files/struct20.gno (100%) rename gnovm/tests/{files.bak => }/files/struct21.gno (100%) rename gnovm/tests/{files.bak => }/files/struct22.gno (100%) rename gnovm/tests/{files.bak => }/files/struct24.gno (100%) rename gnovm/tests/{files.bak => }/files/struct25.gno (100%) rename gnovm/tests/{files.bak => }/files/struct26.gno (100%) rename gnovm/tests/{files.bak => }/files/struct27.gno (100%) rename gnovm/tests/{files.bak => }/files/struct28b.gno (100%) rename gnovm/tests/{files.bak => }/files/struct29.gno (100%) rename gnovm/tests/{files.bak => }/files/struct2b.gno (100%) rename gnovm/tests/{files.bak => }/files/struct3.gno (100%) rename gnovm/tests/{files.bak => }/files/struct30.gno (100%) rename gnovm/tests/{files.bak => }/files/struct31.gno (100%) rename gnovm/tests/{files.bak => }/files/struct32.gno (100%) rename gnovm/tests/{files.bak => }/files/struct33.gno (100%) rename gnovm/tests/{files.bak => }/files/struct34.gno (100%) rename gnovm/tests/{files.bak => }/files/struct35.gno (100%) rename gnovm/tests/{files.bak => }/files/struct36.gno (100%) rename gnovm/tests/{files.bak => }/files/struct37.gno (100%) rename gnovm/tests/{files.bak => }/files/struct38.gno (100%) rename gnovm/tests/{files.bak => }/files/struct39.gno (100%) rename gnovm/tests/{files.bak => }/files/struct4.gno (100%) rename gnovm/tests/{files.bak => }/files/struct40.gno (100%) rename gnovm/tests/{files.bak => }/files/struct41.gno (100%) rename gnovm/tests/{files.bak => }/files/struct42.gno (100%) rename gnovm/tests/{files.bak => }/files/struct43.gno (100%) rename gnovm/tests/{files.bak => }/files/struct44.gno (100%) rename gnovm/tests/{files.bak => }/files/struct45.gno (100%) rename gnovm/tests/{files.bak => }/files/struct46.gno (100%) rename gnovm/tests/{files.bak => }/files/struct47.gno (100%) rename gnovm/tests/{files.bak => }/files/struct48.gno (100%) rename gnovm/tests/{files.bak => }/files/struct49.gno (100%) rename gnovm/tests/{files.bak => }/files/struct5.gno (100%) rename gnovm/tests/{files.bak => }/files/struct50b.gno (100%) rename gnovm/tests/{files.bak => }/files/struct52b.gno (100%) rename gnovm/tests/{files.bak => }/files/struct53b.gno (100%) rename gnovm/tests/{files.bak => }/files/struct54.gno (100%) rename gnovm/tests/{files.bak => }/files/struct56.gno (100%) rename gnovm/tests/{files.bak => }/files/struct57.gno (100%) rename gnovm/tests/{files.bak => }/files/struct6.gno (100%) rename gnovm/tests/{files.bak => }/files/struct7.gno (100%) rename gnovm/tests/{files.bak => }/files/struct8.gno (100%) rename gnovm/tests/{files.bak => }/files/struct9.gno (100%) rename gnovm/tests/{files.bak => }/files/switch.gno (100%) rename gnovm/tests/{files.bak => }/files/switch0.gno (100%) rename gnovm/tests/{files.bak => }/files/switch1.gno (100%) rename gnovm/tests/{files.bak => }/files/switch10.gno (100%) rename gnovm/tests/{files.bak => }/files/switch11.gno (100%) rename gnovm/tests/{files.bak => }/files/switch12.gno (100%) rename gnovm/tests/{files.bak => }/files/switch13.gno (100%) rename gnovm/tests/{files.bak => }/files/switch14.gno (100%) rename gnovm/tests/{files.bak => }/files/switch15.gno (100%) rename gnovm/tests/{files.bak => }/files/switch16.gno (100%) rename gnovm/tests/{files.bak => }/files/switch17.gno (100%) rename gnovm/tests/{files.bak => }/files/switch18.gno (100%) rename gnovm/tests/{files.bak => }/files/switch19.gno (100%) rename gnovm/tests/{files.bak => }/files/switch2.gno (100%) rename gnovm/tests/{files.bak => }/files/switch20.gno (100%) rename gnovm/tests/{files.bak => }/files/switch21.gno (100%) rename gnovm/tests/{files.bak => }/files/switch22.gno (100%) rename gnovm/tests/{files.bak => }/files/switch23.gno (100%) rename gnovm/tests/{files.bak => }/files/switch24.gno (100%) rename gnovm/tests/{files.bak => }/files/switch25.gno (100%) rename gnovm/tests/{files.bak => }/files/switch26.gno (100%) rename gnovm/tests/{files.bak => }/files/switch27.gno (100%) rename gnovm/tests/{files.bak => }/files/switch28.gno (100%) rename gnovm/tests/{files.bak => }/files/switch29.gno (100%) rename gnovm/tests/{files.bak => }/files/switch3.gno (100%) rename gnovm/tests/{files.bak => }/files/switch30.gno (100%) rename gnovm/tests/{files.bak => }/files/switch31.gno (100%) rename gnovm/tests/{files.bak => }/files/switch32.gno (100%) rename gnovm/tests/{files.bak => }/files/switch33.gno (100%) rename gnovm/tests/{files.bak => }/files/switch34.gno (100%) rename gnovm/tests/{files.bak => }/files/switch35.gno (100%) rename gnovm/tests/{files.bak => }/files/switch36.gno (100%) rename gnovm/tests/{files.bak => }/files/switch37.gno (100%) rename gnovm/tests/{files.bak => }/files/switch38.gno (100%) rename gnovm/tests/{files.bak => }/files/switch39.gno (100%) rename gnovm/tests/{files.bak => }/files/switch4.gno (100%) rename gnovm/tests/{files.bak => }/files/switch40.gno (100%) rename gnovm/tests/{files.bak => }/files/switch41.gno (100%) rename gnovm/tests/{files.bak => }/files/switch5.gno (100%) rename gnovm/tests/{files.bak => }/files/switch6.gno (100%) rename gnovm/tests/{files.bak => }/files/switch6b.gno (100%) rename gnovm/tests/{files.bak => }/files/switch6c.gno (100%) rename gnovm/tests/{files.bak => }/files/switch7.gno (100%) rename gnovm/tests/{files.bak => }/files/switch8.gno (100%) rename gnovm/tests/{files.bak => }/files/switch8b.gno (100%) rename gnovm/tests/{files.bak => }/files/switch8c.gno (100%) rename gnovm/tests/{files.bak => }/files/switch9.gno (100%) rename gnovm/tests/{files.bak => }/files/time0_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time0_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time11_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time11_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time12_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time12_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time13_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time13_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time14_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time14_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time15.gno (100%) rename gnovm/tests/{files.bak => }/files/time1_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time1_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time2_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time2_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time3_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time3_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time4_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time4_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time6_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time6_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time7_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time7_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/time8.gno (100%) rename gnovm/tests/{files.bak => }/files/time9_native.gno (100%) rename gnovm/tests/{files.bak => }/files/time9_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/type0.gno (100%) rename gnovm/tests/{files.bak => }/files/type1.gno (100%) rename gnovm/tests/{files.bak => }/files/type11.gno (100%) rename gnovm/tests/{files.bak => }/files/type12.gno (100%) rename gnovm/tests/{files.bak => }/files/type13.gno (100%) rename gnovm/tests/{files.bak => }/files/type14.gno (100%) rename gnovm/tests/{files.bak => }/files/type15.gno (100%) rename gnovm/tests/{files.bak => }/files/type16.gno (100%) rename gnovm/tests/{files.bak => }/files/type17.gno (100%) rename gnovm/tests/{files.bak => }/files/type18.gno (100%) rename gnovm/tests/{files.bak => }/files/type19.gno (100%) rename gnovm/tests/{files.bak => }/files/type20.gno (100%) rename gnovm/tests/{files.bak => }/files/type22.gno (100%) rename gnovm/tests/{files.bak => }/files/type23b.gno (100%) rename gnovm/tests/{files.bak => }/files/type24b.gno (100%) rename gnovm/tests/{files.bak => }/files/type2_native.gno (100%) rename gnovm/tests/{files.bak => }/files/type2_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/type3.gno (100%) rename gnovm/tests/{files.bak => }/files/type30.gno (100%) rename gnovm/tests/{files.bak => }/files/type31.gno (50%) rename gnovm/tests/{files.bak => }/files/type32.gno (51%) rename gnovm/tests/{files.bak => }/files/type7.gno (100%) rename gnovm/tests/{files.bak => }/files/type8.gno (100%) create mode 100644 gnovm/tests/files/types/0b2_filetest.gno create mode 100644 gnovm/tests/files/types/10a0_filetest.gno create mode 100644 gnovm/tests/files/types/10a1_filetest.gno create mode 100644 gnovm/tests/files/types/10a2_filetest.gno create mode 100644 gnovm/tests/files/types/10a3_filetest.gno create mode 100644 gnovm/tests/files/types/10a4_filetest.gno create mode 100644 gnovm/tests/files/types/10a5_filetest.gno create mode 100644 gnovm/tests/files/types/11a0_filetest.gno create mode 100644 gnovm/tests/files/types/11a1_filetest.gno create mode 100644 gnovm/tests/files/types/11a2_filetest.gno create mode 100644 gnovm/tests/files/types/11a3_filetest.gno create mode 100644 gnovm/tests/files/types/12a0_filetest.gno create mode 100644 gnovm/tests/files/types/12a1_filetest.gno create mode 100644 gnovm/tests/files/types/12a2_filetest.gno create mode 100644 gnovm/tests/files/types/12a3_filetest.gno create mode 100644 gnovm/tests/files/types/13a0_filetest.gno create mode 100644 gnovm/tests/files/types/13a1_filetest.gno create mode 100644 gnovm/tests/files/types/13b0_filetest.gno create mode 100644 gnovm/tests/files/types/13b1_filetest.gno create mode 100644 gnovm/tests/files/types/13b2_filetest.gno create mode 100644 gnovm/tests/files/types/13d0_filetest.gno create mode 100644 gnovm/tests/files/types/13e0_filetest.gno create mode 100644 gnovm/tests/files/types/13f0_filetest.gno create mode 100644 gnovm/tests/files/types/13f1_filetest.gno create mode 100644 gnovm/tests/files/types/13f2_filetest.gno create mode 100644 gnovm/tests/files/types/13f3_filetest.gno create mode 100644 gnovm/tests/files/types/18a0_filetest.gno create mode 100644 gnovm/tests/files/types/18a1_filetest.gno create mode 100644 gnovm/tests/files/types/18a2_filetest.gno create mode 100644 gnovm/tests/files/types/18a3_filetest.gno create mode 100644 gnovm/tests/files/types/19a0_filetest.gno create mode 100644 gnovm/tests/files/types/19a1_filetest.gno create mode 100644 gnovm/tests/files/types/20a0_filetest.gno create mode 100644 gnovm/tests/files/types/20a1_filetest.gno create mode 100644 gnovm/tests/files/types/20a2_filetest.gno create mode 100644 gnovm/tests/files/types/20a3_filetest.gno create mode 100644 gnovm/tests/files/types/20a4_filetest.gno create mode 100644 gnovm/tests/files/types/20a5_filetest.gno create mode 100644 gnovm/tests/files/types/21a0_filetest.gno create mode 100644 gnovm/tests/files/types/21a1_filetest.gno create mode 100644 gnovm/tests/files/types/22a0_filetest.gno create mode 100644 gnovm/tests/files/types/22a10_filetest.gno create mode 100644 gnovm/tests/files/types/22a11_filetest.gno create mode 100644 gnovm/tests/files/types/22a11a_filetest.gno create mode 100644 gnovm/tests/files/types/22a12_filetest.gno create mode 100644 gnovm/tests/files/types/22a13_filetest.gno create mode 100644 gnovm/tests/files/types/22a14_filetest.gno create mode 100644 gnovm/tests/files/types/22a15_filetest.gno create mode 100644 gnovm/tests/files/types/22a16_filetest.gno create mode 100644 gnovm/tests/files/types/22a17_filetest.gno create mode 100644 gnovm/tests/files/types/22a17a_filetest.gno create mode 100644 gnovm/tests/files/types/22a17b_filetest.gno create mode 100644 gnovm/tests/files/types/22a17c_filetest.gno create mode 100644 gnovm/tests/files/types/22a17d_filetest.gno create mode 100644 gnovm/tests/files/types/22a17e_filetest.gno create mode 100644 gnovm/tests/files/types/22a17f_filetest.gno create mode 100644 gnovm/tests/files/types/22a17g_filetest.gno create mode 100644 gnovm/tests/files/types/22a17h_filetest.gno create mode 100644 gnovm/tests/files/types/22a1_filetest.gno create mode 100644 gnovm/tests/files/types/22a1a_filetest.gno create mode 100644 gnovm/tests/files/types/22a2_filetest.gno create mode 100644 gnovm/tests/files/types/22a3_filetest.gno create mode 100644 gnovm/tests/files/types/22a4_filetest.gno create mode 100644 gnovm/tests/files/types/22a5_filetest.gno create mode 100644 gnovm/tests/files/types/22a6_filetest.gno create mode 100644 gnovm/tests/files/types/22a7_filetest.gno create mode 100644 gnovm/tests/files/types/22a8_filetest.gno create mode 100644 gnovm/tests/files/types/22a9_filetest.gno create mode 100644 gnovm/tests/files/types/9a0_filetest.gno create mode 100644 gnovm/tests/files/types/9a1_filetest.gno create mode 100644 gnovm/tests/files/types/9b0_filetest.gno create mode 100644 gnovm/tests/files/types/9b1_filetest.gno create mode 100644 gnovm/tests/files/types/9b2_filetest.gno create mode 100644 gnovm/tests/files/types/9b3_filetest.gno create mode 100644 gnovm/tests/files/types/9b4_filetest.gno create mode 100644 gnovm/tests/files/types/9d0_filetest.gno create mode 100644 gnovm/tests/files/types/9d1_filetest.gno create mode 100644 gnovm/tests/files/types/9d2_filetest.gno create mode 100644 gnovm/tests/files/types/9d3_filetest.gno create mode 100644 gnovm/tests/files/types/9d4_filetest.gno create mode 100644 gnovm/tests/files/types/9e0_filetest.gno create mode 100644 gnovm/tests/files/types/9f0_filetest.gno create mode 100644 gnovm/tests/files/types/9f1_filetest.gno create mode 100644 gnovm/tests/files/types/9f2_filetest.gno rename gnovm/tests/{files.bak => }/files/unary.gno (100%) rename gnovm/tests/{files.bak => }/files/unary1.gno (100%) rename gnovm/tests/{files.bak => }/files/untyped0.gno (100%) rename gnovm/tests/{files.bak => }/files/untyped1.gno (100%) rename gnovm/tests/{files.bak => }/files/var.gno (100%) rename gnovm/tests/{files.bak => }/files/var10.gno (100%) rename gnovm/tests/{files.bak => }/files/var11.gno (100%) rename gnovm/tests/{files.bak => }/files/var12.gno (100%) rename gnovm/tests/{files.bak => }/files/var13.gno (100%) rename gnovm/tests/{files.bak => }/files/var14.gno (100%) rename gnovm/tests/{files.bak => }/files/var15.gno (100%) rename gnovm/tests/{files.bak => }/files/var16.gno (100%) rename gnovm/tests/{files.bak => }/files/var17.gno (100%) rename gnovm/tests/{files.bak => }/files/var2.gno (100%) rename gnovm/tests/{files.bak => }/files/var3.gno (100%) rename gnovm/tests/{files.bak => }/files/var4.gno (100%) rename gnovm/tests/{files.bak => }/files/var5.gno (100%) rename gnovm/tests/{files.bak => }/files/var6.gno (100%) rename gnovm/tests/{files.bak => }/files/var7.gno (100%) rename gnovm/tests/{files.bak => }/files/var9.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic0.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic1.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic2.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic3.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic4.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic5.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic6.gno (100%) rename gnovm/tests/{files.bak => }/files/variadic9.gno (100%) rename gnovm/tests/{files.bak => }/files/xfactor_long.gno (100%) rename gnovm/tests/{files.bak => }/files/xfib_long.gno (100%) rename gnovm/tests/{files.bak => }/files/zavltree.gno (100%) rename gnovm/tests/{files.bak => }/files/zavltree0.gno (100%) rename gnovm/tests/{files.bak => }/files/zavltree1.gno (100%) rename gnovm/tests/{files.bak/files/zpersist_valids.gno => files/zpersist_valids.gnoa} (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm0.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm1.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm10.gno (98%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm11.gno (98%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm12.gno (97%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm2.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm3.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm4.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm5.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm6.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm7.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm8.gno (98%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm9.gno (98%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_avl0.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_avl1.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_avl2.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_const.gno (85%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm0.gno (92%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm1.gno (93%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm10.gno (89%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm11.gno (98%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm12.gno (83%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm2.gno (94%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm3.gno (94%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm4.gno (94%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm5.gno (94%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm6.gno (93%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm7.gno (89%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm8.gno (89%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_crossrealm9.gno (89%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_example.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_map0.gno (93%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std0.gno (91%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std1.gno (97%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std2.gno (97%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std3.gno (93%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std4.gno (95%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std5.gno (95%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_std6.gno (93%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_tests0.gno (99%) rename gnovm/tests/{files.bak/files => files/zrealm}/zrealm_testutils0.gno (92%) rename gnovm/tests/{files.bak => }/files/zregexp_stdlibs.gno (100%) rename gnovm/tests/{files.bak => }/files/zsolitaire_long.gno (100%) diff --git a/gnovm/Makefile b/gnovm/Makefile index 34e94f88633..d0309702e03 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -55,6 +55,8 @@ _test.gnolang.native:; go test tests/*.go -test.short -run "TestFilesNativ _test.gnolang.stdlibs:; go test tests/*.go -test.short -run 'TestFiles$$/' $(GOTEST_FLAGS) _test.gnolang.native.sync:; go test tests/*.go -test.short -run "TestFilesNative/" --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.stdlibs.sync:; go test tests/*.go -test.short -run 'TestFiles$$/' --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallenges$$/' $(GOTEST_FLAGS) +_test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' --update-golden-tests $(GOTEST_FLAGS) ######################################## # Code gen diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index fe39c05d8be..84bf2578078 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -77,40 +77,38 @@ func (m *Machine) doOpEql() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - - fmt.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) - fmt.Printf("lv typeID: %v, kind: %v \n", lv.T.TypeID(), lv.T.Kind()) - fmt.Printf("rv typeID: %v, kind: %v \n", rv.T.TypeID(), rv.T.Kind()) - if debug { assertEqualityTypes(lv.T, rv.T) } - //if lv.T.Kind() == InterfaceKind && - // IsImplementedBy(lv.T, rv.T) { - // println("left is interface, rt conforms it") - //} else if rv.T.Kind() == InterfaceKind && - // IsImplementedBy(rv.T, lv.T) { - // println("right is interface, left conforms it") - //} else if lv.T.Kind() == InterfaceKind && rv.T.Kind() == InterfaceKind { - // println("both interface") - //} + fmt.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - // strict type match check - if lv.T.TypeID() != rv.T.TypeID() { - fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "EQL", rv.T.TypeID()) - res = false - } else { + //// strict type match check, after preprocess + //// TODO: fix databytetype + //if (lv.T != nil && rv.T != nil) && (lv.T.TypeID() != rv.T.TypeID()) { + // // TODO: in golang, this would not panic, but give a false as result + // fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "EQL", rv.T.TypeID()) + // res = false + //} else { + // res = isEql(m.Store, lv, rv) + //} + + if isSameTypes(lv.T, rv.T) { res = isEql(m.Store, lv, rv) + } else { + res = false } + lv.T = UntypedBoolType + lv.V = nil + lv.SetBool(res) - // set result in lv. lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) } func (m *Machine) doOpNeq() { + println("doOpNeq") m.PopExpr() // get right and left operands. @@ -119,17 +117,23 @@ func (m *Machine) doOpNeq() { if debug { assertEqualityTypes(lv.T, rv.T) } + fmt.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - // strict type match check - if lv.T.TypeID() != rv.T.TypeID() { - fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "NEQ", rv.T.TypeID()) - res = false + //// strict type match check, after preprocess + //if (lv.T != nil && rv.T != nil) && (lv.T.TypeID() != rv.T.TypeID()) { + // // TODO: in golang, this would not panic, but give a false as result + // fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "EQL", rv.T.TypeID()) + // res = true // not equal + //} else { + // res = !isEql(m.Store, lv, rv) + //} + + if isSameTypes(lv.T, rv.T) { + res = !isEql(m.Store, lv, rv) } else { - res = isEql(m.Store, lv, rv) + res = true } - - // set result in lv. lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -957,7 +961,7 @@ func remAssign(lv, rv *TypedValue) { lv.V = BigintValue{V: lb} default: panic(fmt.Sprintf( - "operators %% and %%= not defined for %s", + "operators rem and rem= not defined for %s", lv.T, )) } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index d64a60d9f50..557daa611bd 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -907,9 +907,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } //} else if rcx.T == nil { - } else { + } else if rcx.T == nil { + println("rcx.T == nil ") // convert n.Right to typed-nil type. checkOrConvertType(store, last, &n.Right, lt, n.Op, false) + } else if !isShift { + checkOrConvertType(store, last, &n.Right, lt, n.Op, false) } } else { fmt.Printf("both not const, lt: %v, rt:%v \n", lt, rt) @@ -1299,12 +1302,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *ArrayType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) + convertConstType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, ILLEGAL, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) + convertConstType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, ILLEGAL, false) } case *MapType: @@ -1667,17 +1670,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { println("len of LHS: ", len(n.Lhs)) println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) - rt := evalStaticTypeOf(store, last, n.Rhs[0]) + //rt := evalStaticTypeOf(store, last, n.Rhs[0]) // TODO: check other like sh* // only check when rt is typed - if !isUntyped(rt) { - if lt.TypeID() != rt.TypeID() { - panic("mismatch type for Assign") - } - } else { - checkOrConvertType(store, last, &n.Rhs[0], lt, n.Op, false) - } + //if !isUntyped(rt) { + // if lt.TypeID() != rt.TypeID() { + // panic("mismatch type for Assign") + // } + //} else { + checkOrConvertType(store, last, &n.Rhs[0], lt, n.Op, false) + //} } else { // all else, like BAND_ASSIGN, etc println("case: a, b = x, y") fmt.Printf("Op: %v \n", n.Op) @@ -1693,9 +1696,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Rhs[i], lt, n.Op, false) } else { println("rt not untyped, check strict") - if lt.TypeID() != rt.TypeID() { - panic("mismatch type for Assign, in case: a, b = x, y") - } + //if lt.TypeID() != rt.TypeID() { + // panic("mismatch type for Assign, in case: a, b = x, y") + //} + checkOrConvertType(store, last, &n.Rhs[i], lt, n.Op, false) } } } @@ -2389,15 +2393,28 @@ func cmpSpecificity(t1, t2 Type) int { } } +// for special case of index conversion +func convertConstType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { + fmt.Printf("convertConstType, x: %v, t:%v, \n", x, t) + if cx, ok := (*x).(*ConstExpr); ok { + convertConst(store, last, cx, t) + } +} + // 1. convert x to t if x is *ConstExpr. // 2. otherwise, assert that x can be coerced to t. // autoNative is usually false, but set to true // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() + +// TODO: NOTE, more about const, sometimes we convert it anyway, like uint8 -> int as index of an array +// TODO: but if it's bind to ops like +, type conversion should be checked +// TODO: this should be awareness at its origin func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { - fmt.Printf("checkOrConvertType, x: %v, t:%v, t.typeID: %v, t.kind:%v \n", x, t, t.TypeID(), t.Kind()) + fmt.Printf("checkOrConvertType, x: %v, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { + println("ConstExpr") // here we should check too, e.g. primitive to declared type is convertable checkType(cx.T, t, op, autoNative) fmt.Printf("convertConst, cx: %v \n", cx) @@ -2409,8 +2426,10 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, a } else if *x != nil { // XXX if x != nil && t != nil { println("else") xt := evalStaticTypeOf(store, last, *x) + var conversionNeeded bool if t != nil { - checkType(xt, t, op, autoNative) + //checkType(xt, t, op, autoNative) + conversionNeeded = checkType(xt, t, op, autoNative) } if isUntyped(xt) { if t == nil { @@ -2437,6 +2456,12 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, a cx = Preprocess(store, last, cx).(Expr) *x = cx } + // cover all declared type case + if conversionNeeded { + cx := Expr(Call(constType(nil, t), *x)) + cx = Preprocess(store, last, cx).(Expr) + *x = cx + } } } @@ -2469,269 +2494,428 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func checkType(xt Type, dt Type, op Word, autoNative bool) { +func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded bool) { + if xt == nil || dt == nil { + return + } fmt.Printf("checkType, xt: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, dt, dt.Kind(), op) // TODO: first check operands and Op // two steps of check: - // first, check is the dt type satisfy op, the switch + // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this - if op != ILLEGAL { // should check operand with op + // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt + if op != ILLEGAL { // should check operand with op, this would filter most of the op relate issues println("check matchable with op") switch op { case ADD: // dt is the dest type, what we need check - if !isTypedNumber(dt) && !isTypedString(dt) { + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { panic(fmt.Sprintf("+ should have operand number or string, while have: %v", dt)) } case SUB: - if !isTypedNumber(dt) { + if !isTypedNumber(dt) && dt != UntypedRuneType { panic(fmt.Sprintf("- should have operand number, while have: %v", dt)) } case MUL: - if !isTypedNumber(dt) { + if !isTypedNumber(dt) && dt != UntypedRuneType { panic(fmt.Sprintf("* should have operand number, while have: %v", dt)) } - case QUO, REM: - if !isTypedNumber(dt) { + case QUO: + if !isTypedNumber(dt) && dt != UntypedRuneType { panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) } + case REM: + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) + } + case BAND: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator & not defined on: %v", dt)) + } + case BAND_ASSIGN: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator &= not defined on: %v", dt)) + } + case BOR: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator | not defined on: %v", dt)) + } + case BOR_ASSIGN: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator |= not defined on: %v", dt)) + } + case XOR: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator ^ not defined on: %v", dt)) + } + case XOR_ASSIGN: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator ^= not defined on: %v", dt)) + } + case BAND_NOT: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator &^ not defined on: %v", dt)) + } + case BAND_NOT_ASSIGN: // not defined on float + if !isIntNumber(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator &^= not defined on: %v", dt)) + } + case LAND: // not defined on float + if dt != UntypedBoolType && dt != BoolType { + panic(fmt.Sprintf("operator && not defined on: %v", dt)) + } + case LOR: // not defined on float + if dt != UntypedBoolType && dt != BoolType { + panic(fmt.Sprintf("operator || not defined on: %v", dt)) + } + case ADD_ASSIGN: + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator += not defined on: %v", dt)) + } + case SUB_ASSIGN: + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator -= not defined on: %v", dt)) + } + case MUL_ASSIGN: + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator *= not defined on: %v", dt)) + } + case QUO_ASSIGN: + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator /= not defined on: %v", dt)) + } + case REM_ASSIGN: + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator %%= not defined on: %v", dt)) + } + + case EQL, NEQ: + // do nothing here, as a special case, EQL or NEQ is more relaxed than ADD, so convertable is checked as `equality` in logic below + // + case SHL, SHR: + // TODO: right should be numeric + case LSS: + if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + panic(fmt.Sprintf("operator < not defined on: %v", dt)) + } + default: // do nothing // TODO: should also check the divisor not zero - } } - if xt.TypeID() != dt.TypeID() { // check if convertable - // 1. convert with no op, e.g. elements in slice - // 2. convert with op, like int(1) + 0, will also need check convertable - println("check convertable") - // Special case if dt is interface kind: - if dt.Kind() == InterfaceKind { - if idt, ok := baseOf(dt).(*InterfaceType); ok { - if idt.IsEmptyInterface() { - // if dt is an empty Gno interface, any x ok. - return // ok - } else if idt.IsImplementedBy(xt) { - // if dt implements idt, ok. + // check convertable + // TODO: xt could be nil + //if xt.TypeID() != dt.TypeID() { + // 1. convert with no op, e.g. elements in slice + // 2. convert with op, like int(1) + 0, will also need check convertable + println("check convertable") + println("xt is nil?", xt == nil) + + var xtStr string + if xt != nil { + xtStr = xt.String() + } + // Special case if dt is interface kind: + if dt.Kind() == InterfaceKind { + println("dt is interface") + if idt, ok := baseOf(dt).(*InterfaceType); ok { + if idt.IsEmptyInterface() { + println("dt is empty interface") + // if dt is an empty Gno interface, any x ok. + return // ok + } else if idt.IsImplementedBy(xt) { + println("dt is implemented by xt") + // if dt implements idt, ok. + return // ok + } else { + panic(fmt.Sprintf( + "%s does not implement %s", + xtStr, + dt.String())) + } + } else if ndt, ok := baseOf(dt).(*NativeType); ok { + nidt := ndt.Type + if nidt.NumMethod() == 0 { + // if dt is an empty Go native interface, ditto. + return // ok + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nidt) { return // ok } else { panic(fmt.Sprintf( - "%s does not implement %s", - xt.String(), - dt.String())) + "cannot use %s as %s", + nxt.String(), + nidt.String())) } - } else if ndt, ok := baseOf(dt).(*NativeType); ok { - nidt := ndt.Type - if nidt.NumMethod() == 0 { - // if dt is an empty Go native interface, ditto. - return // ok - } else if nxt, ok := baseOf(xt).(*NativeType); ok { - // if xt has native base, do the naive native. - if nxt.Type.AssignableTo(nidt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nxt.String(), - nidt.String())) - } - } else if pxt, ok := baseOf(xt).(*PointerType); ok { - nxt, ok := pxt.Elt.(*NativeType) - if !ok { - panic(fmt.Sprintf( - "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", - pxt.String(), - nidt.String())) - } - // if xt has native base, do the naive native. - if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - pxt.String(), - nidt.String())) - } - } else { + } else if pxt, ok := baseOf(xt).(*PointerType); ok { + nxt, ok := pxt.Elt.(*NativeType) + if !ok { panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - xt.String(), - dt.String())) + "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", + pxt.String(), + nidt.String())) } - } else { - panic("should not happen") - } - } - // Special case if xt or dt is *PointerType to *NativeType, - // convert to *NativeType of pointer kind. - if pxt, ok := xt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - //nolint:misspell - if enxt, ok := pxt.Elt.(*NativeType); ok { - xt = &NativeType{ - Type: reflect.PtrTo(enxt.Type), - } - } - } - if pdt, ok := dt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - if endt, ok := pdt.Elt.(*NativeType); ok { - dt = &NativeType{ - Type: reflect.PtrTo(endt.Type), - } - } - } - // Special case of xt or dt is *DeclaredType, - // allow implicit conversion unless both are declared. - // TODO simplify with .IsNamedType(). - if dxt, ok := xt.(*DeclaredType); ok { - if ddt, ok := dt.(*DeclaredType); ok { - // types must match exactly. - if !dxt.sealed && !ddt.sealed && - dxt.PkgPath == ddt.PkgPath && - dxt.Name == ddt.Name { // not yet sealed - return // ok - } else if dxt.TypeID() == ddt.TypeID() { + // if xt has native base, do the naive native. + if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { return // ok } else { panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - ddt.String())) + "cannot use %s as %s", + pxt.String(), + nidt.String())) } } else { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := dt.(PrimitiveType); ok { - //panic(fmt.Sprintf( - // "cannot use %s as %s without explicit conversion", - // dxt.String(), - // dt.String())) - xt = dxt.Base - } else { - // carry on with baseOf(dxt) - xt = dxt.Base - } + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + xtStr, + dt.String())) } - } else if ddt, ok := dt.(*DeclaredType); ok { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := xt.(PrimitiveType); ok { - // type Error int, if Error(0) == 0 should be legal - // type Error string, if Error("hi") == 0 should be illegal - fmt.Printf("xt typeID: %v, default type of xt:%v, ddt.Base typeID: %v \n", xt.TypeID(), defaultTypeOf(xt), ddt.Base.TypeID()) - //if xt.TypeID() != ddt.Base.TypeID() { - //panic(fmt.Sprintf( - // "cannot use %s as %s without explicit conversion", - // xt.String(), - // ddt.String())) - //} - dt = ddt.Base + } else { + panic("should not happen") + } + } else if xt.Kind() == InterfaceKind { + println("xt is interface") + if ixt, ok := baseOf(xt).(*InterfaceType); ok { + if ixt.IsEmptyInterface() { + println("xt is empty interface") + // if dt is an empty Gno interface, any x ok. + return // ok + } else if ixt.IsImplementedBy(xt) { + println("xt is implemented by dt") + // if dt implements idt, ok. + return // ok } else { - // carry on with baseOf(ddt) - dt = ddt.Base + panic(fmt.Sprintf( + "%s does not implement %s", + dt.String(), xtStr)) } - } - // General cases. - switch cdt := dt.(type) { - case PrimitiveType: - // if xt is untyped, ensure dt is compatible. - switch xt { - case UntypedBoolType: - if dt.Kind() == BoolKind { + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + nixt := nxt.Type + if nixt.NumMethod() == 0 { + // if dt is an empty Go native interface, ditto. + return // ok + } else if ndt, ok := baseOf(dt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nixt) { return // ok } else { panic(fmt.Sprintf( - "cannot use untyped bool as %s", - dt.Kind())) + "cannot use %s as %s", + nixt.String(), ndt.String())) } - case UntypedStringType: - if dt.Kind() == StringKind { - return // ok - } else { + } else if pdt, ok := baseOf(dt).(*PointerType); ok { + nxt, ok := pdt.Elt.(*NativeType) + if !ok { panic(fmt.Sprintf( - "cannot use untyped string as %s", - dt.Kind())) + "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", + nixt.String(), pdt.String())) } - case UntypedRuneType, UntypedBigintType: - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind: + // if xt has native base, do the naive native. + if reflect.PtrTo(nxt.Type).AssignableTo(nixt) { return // ok - default: + } else { panic(fmt.Sprintf( - "cannot use untyped rune as %s", - dt.Kind())) - } - default: - if isUntyped(xt) { - panic("unexpected untyped type") - } - if xt.TypeID() == cdt.TypeID() { - return // ok + "cannot use %s as %s", + nixt.String(), pdt.String())) } + } else { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + xtStr, + dt.String())) } - case *PointerType: - if pt, ok := xt.(*PointerType); ok { - checkType(pt.Elt, cdt.Elt, ILLEGAL, false) - return // ok + } else { + panic("should not happen") + } + } + // Special case if xt or dt is *PointerType to *NativeType, + // convert to *NativeType of pointer kind. + if pxt, ok := xt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + //nolint:misspell + if enxt, ok := pxt.Elt.(*NativeType); ok { + xt = &NativeType{ + Type: reflect.PtrTo(enxt.Type), } - case *ArrayType: - if at, ok := xt.(*ArrayType); ok { - checkType(at.Elt, cdt.Elt, ILLEGAL, false) - return // ok + } + } + if pdt, ok := dt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + if endt, ok := pdt.Elt.(*NativeType); ok { + dt = &NativeType{ + Type: reflect.PtrTo(endt.Type), } - case *SliceType: - if st, ok := xt.(*SliceType); ok { - checkType(st.Elt, cdt.Elt, ILLEGAL, false) + } + } + // Special case of xt or dt is *DeclaredType, + // allow implicit conversion unless both are declared. + // TODO simplify with .IsNamedType(). + if dxt, ok := xt.(*DeclaredType); ok { + if ddt, ok := dt.(*DeclaredType); ok { + // types must match exactly. + if !dxt.sealed && !ddt.sealed && + dxt.PkgPath == ddt.PkgPath && + dxt.Name == ddt.Name { // not yet sealed return // ok + } else if dxt.TypeID() == ddt.TypeID() { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + ddt.String())) } - case *MapType: - if mt, ok := xt.(*MapType); ok { - checkType(mt.Key, cdt.Key, ILLEGAL, false) - checkType(mt.Value, cdt.Value, ILLEGAL, false) + } else { + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := dt.(PrimitiveType); ok { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + dt.String())) + //xt = dxt.Base + } else { + // carry on with baseOf(dxt) + xt = dxt.Base + conversionNeeded = true + } + } + } else if ddt, ok := dt.(*DeclaredType); ok { + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := xt.(PrimitiveType); ok { + println("xt is primitiveType") + // this is special when dt is the declared type of x + if !isUntyped(xt) { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + xt.String(), + ddt.String())) + } + + } else { + // carry on with baseOf(ddt) + dt = ddt.Base + conversionNeeded = true + } + } + // General cases. + switch cdt := dt.(type) { + case PrimitiveType: + println("primitive type") + // if xt is untyped, ensure dt is compatible. + switch xt { + case UntypedBoolType: + if dt.Kind() == BoolKind { return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped bool as %s", + dt.Kind())) } - case *FuncType: - if xt.TypeID() == cdt.TypeID() { + case UntypedStringType: + if dt.Kind() == StringKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped string as %s", + dt.Kind())) + } + case UntypedBigintType, UntypedBigdecType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped Bigint/Bigdec as %s", + dt.Kind())) + } + case UntypedRuneType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped rune as %s", + dt.Kind())) + } + + default: + if isUntyped(xt) { + panic("unexpected untyped type") } - case *InterfaceType: - panic("should not happen") - case *DeclaredType: - panic("should not happen") - case *StructType, *PackageType, *ChanType: if xt.TypeID() == cdt.TypeID() { return // ok } - case *TypeType: + } + case *PointerType: + if pt, ok := xt.(*PointerType); ok { + cdt := checkType(pt.Elt, cdt.Elt, ILLEGAL, false) + return cdt || conversionNeeded + } + case *ArrayType: + if at, ok := xt.(*ArrayType); ok { + cdt := checkType(at.Elt, cdt.Elt, ILLEGAL, false) + return cdt || conversionNeeded + } + case *SliceType: + if st, ok := xt.(*SliceType); ok { + cdt := checkType(st.Elt, cdt.Elt, ILLEGAL, false) + return cdt || conversionNeeded + } + case *MapType: + if mt, ok := xt.(*MapType); ok { + cn1 := checkType(mt.Key, cdt.Key, ILLEGAL, false) + cn2 := checkType(mt.Value, cdt.Value, ILLEGAL, false) + return cn1 || cn2 || conversionNeeded + } + case *FuncType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *InterfaceType: + panic("should not happen") + case *DeclaredType: + // do nothing, untyped to declared type + return + //panic("should not happen") + case *StructType, *PackageType, *ChanType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *TypeType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *NativeType: + if !autoNative { if xt.TypeID() == cdt.TypeID() { return // ok } - case *NativeType: - if !autoNative { - if xt.TypeID() == cdt.TypeID() { - return // ok - } - } else { - // autoNative, so check whether matches. - // xt: any type but a *DeclaredType; could be native. - // cdt: actual concrete native target type. - // ie, if cdt can match against xt. - if gno2GoTypeMatches(xt, cdt.Type) { - return // ok - } + } else { + // autoNative, so check whether matches. + // xt: any type but a *DeclaredType; could be native. + // cdt: actual concrete native target type. + // ie, if cdt can match against xt. + if gno2GoTypeMatches(xt, cdt.Type) { + return // ok } - default: - panic(fmt.Sprintf( - "unexpected type %s", - dt.String())) } + default: panic(fmt.Sprintf( - "cannot use %s as %s", - xt.String(), + "unexpected type %s", dt.String())) } + panic(fmt.Sprintf( + "cannot use %s as %s", + xt.String(), + dt.String())) + //} } // Returns any names not yet defined nor predefined in expr. These happen diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index cfa5b5fb83e..40a9946baf5 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1985,11 +1985,26 @@ const ( RefTypeKind // not in go. ) +// only for / and % /= %=, no support for float +func isIntNumber(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + switch t { + case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, UntypedBigintType, BigintType: + return true + default: + return false + } + default: + return false + } +} + func isTypedNumber(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: switch t { - case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, Float32Type, Float64Type, BigintType, BigdecType: + case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, Float32Type, Float64Type, UntypedBigintType, BigintType, UntypedBigdecType, BigdecType: return true default: return false @@ -2003,7 +2018,7 @@ func isTypedString(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: switch t { - case StringType: + case UntypedStringType, StringType: return true default: return false @@ -2126,6 +2141,53 @@ func assertSameTypes(lt, rt Type) { } } +func isSameTypes(lt, rt Type) bool { + fmt.Printf("isSameTypes, lt: %v, rt: %v \n", lt, rt) + println("is lt data byte: ", isDataByte(lt)) + println("is rt data byte: ", isDataByte(rt)) + + if lpt, ok := lt.(*PointerType); ok { + println("lt is pointer type, typeid: ", lpt.typeid) + if isDataByte(lpt.Elt) { + println("got data byte, left") + return true + } + } + + if rpt, ok := rt.(*PointerType); ok { + println("rt is pointer type, typeid: ", rpt.typeid) + if isDataByte(rpt.Elt) { + println("got data byte, right") + return true + } + } + + if isDataByte(lt) || isDataByte(rt) { + println("one is date byte") + return true + } + + if lt == nil && rt == nil { + // both are nil. + } else if lt == nil || rt == nil { + // one is nil. see function comment. + } else if lt.Kind() == rt.Kind() && + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + } else if lt.Kind() == rt.Kind() && + isDataByte(lt) { + // left is databyte of same kind, + // specifically for assignments. + // TODO: make another function + // and remove this case? + } else if lt.TypeID() == rt.TypeID() { + // non-nil types are identical. + } else { + return false + } + return true +} + // Like assertSameTypes(), but more relaxed, for == and !=. func assertEqualityTypes(lt, rt Type) { if lt == nil && rt == nil { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index cc7c0de9f09..3687b57caef 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -877,6 +877,7 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { + fmt.Printf("ConvertUntypedTo, tv:%v, t:%v \n", tv, t) if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( @@ -923,6 +924,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { // general case if t == nil { t = defaultTypeOf(tv.T) + fmt.Printf("give t its default type, to be:%v \n", t) } switch tv.T { case UntypedBoolType: @@ -1049,6 +1051,7 @@ func ConvertUntypedRuneTo(dst *TypedValue, t Type) { } func ConvertUntypedBigintTo(dst *TypedValue, bv BigintValue, t Type) { + fmt.Printf("ConvertUntypedBigintTo, dst: %v, bv:%v, t:%v \n", dst, bv, t) k := t.Kind() bi := bv.V var sv int64 = 0 // if signed. diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index f070546ab74..53b2d7cc960 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -37,6 +37,11 @@ func TestChallenges(t *testing.T) { runFileTests(t, baseDir, nil) } +func TestTypes(t *testing.T) { + baseDir := filepath.Join(".", "files/types") + runFileTests(t, baseDir, nil) +} + func filterFileTests(t *testing.T, files []fs.DirEntry, ignore []string) []fs.DirEntry { t.Helper() diff --git a/gnovm/tests/files.bak/files/a1.gno b/gnovm/tests/files/a1.gno similarity index 100% rename from gnovm/tests/files.bak/files/a1.gno rename to gnovm/tests/files/a1.gno diff --git a/gnovm/tests/files.bak/files/a10.gno b/gnovm/tests/files/a10.gno similarity index 100% rename from gnovm/tests/files.bak/files/a10.gno rename to gnovm/tests/files/a10.gno diff --git a/gnovm/tests/files.bak/files/a11.gno b/gnovm/tests/files/a11.gno similarity index 100% rename from gnovm/tests/files.bak/files/a11.gno rename to gnovm/tests/files/a11.gno diff --git a/gnovm/tests/files.bak/files/a12.gno b/gnovm/tests/files/a12.gno similarity index 100% rename from gnovm/tests/files.bak/files/a12.gno rename to gnovm/tests/files/a12.gno diff --git a/gnovm/tests/files.bak/files/a13.gno b/gnovm/tests/files/a13.gno similarity index 100% rename from gnovm/tests/files.bak/files/a13.gno rename to gnovm/tests/files/a13.gno diff --git a/gnovm/tests/files.bak/files/a14.gno b/gnovm/tests/files/a14.gno similarity index 100% rename from gnovm/tests/files.bak/files/a14.gno rename to gnovm/tests/files/a14.gno diff --git a/gnovm/tests/files.bak/files/a15.gno b/gnovm/tests/files/a15.gno similarity index 100% rename from gnovm/tests/files.bak/files/a15.gno rename to gnovm/tests/files/a15.gno diff --git a/gnovm/tests/files.bak/files/a16.gno b/gnovm/tests/files/a16.gno similarity index 100% rename from gnovm/tests/files.bak/files/a16.gno rename to gnovm/tests/files/a16.gno diff --git a/gnovm/tests/files.bak/files/a17.gno b/gnovm/tests/files/a17.gno similarity index 100% rename from gnovm/tests/files.bak/files/a17.gno rename to gnovm/tests/files/a17.gno diff --git a/gnovm/tests/files.bak/files/a18.gno b/gnovm/tests/files/a18.gno similarity index 100% rename from gnovm/tests/files.bak/files/a18.gno rename to gnovm/tests/files/a18.gno diff --git a/gnovm/tests/files.bak/files/a19.gno b/gnovm/tests/files/a19.gno similarity index 100% rename from gnovm/tests/files.bak/files/a19.gno rename to gnovm/tests/files/a19.gno diff --git a/gnovm/tests/files.bak/files/a2.gno b/gnovm/tests/files/a2.gno similarity index 100% rename from gnovm/tests/files.bak/files/a2.gno rename to gnovm/tests/files/a2.gno diff --git a/gnovm/tests/files.bak/files/a20.gno b/gnovm/tests/files/a20.gno similarity index 100% rename from gnovm/tests/files.bak/files/a20.gno rename to gnovm/tests/files/a20.gno diff --git a/gnovm/tests/files.bak/files/a21.gno b/gnovm/tests/files/a21.gno similarity index 100% rename from gnovm/tests/files.bak/files/a21.gno rename to gnovm/tests/files/a21.gno diff --git a/gnovm/tests/files.bak/files/a22.gno b/gnovm/tests/files/a22.gno similarity index 100% rename from gnovm/tests/files.bak/files/a22.gno rename to gnovm/tests/files/a22.gno diff --git a/gnovm/tests/files.bak/files/a23.gno b/gnovm/tests/files/a23.gno similarity index 100% rename from gnovm/tests/files.bak/files/a23.gno rename to gnovm/tests/files/a23.gno diff --git a/gnovm/tests/files.bak/files/a24.gno b/gnovm/tests/files/a24.gno similarity index 100% rename from gnovm/tests/files.bak/files/a24.gno rename to gnovm/tests/files/a24.gno diff --git a/gnovm/tests/files.bak/files/a25.gno b/gnovm/tests/files/a25.gno similarity index 100% rename from gnovm/tests/files.bak/files/a25.gno rename to gnovm/tests/files/a25.gno diff --git a/gnovm/tests/files.bak/files/a26.gno b/gnovm/tests/files/a26.gno similarity index 100% rename from gnovm/tests/files.bak/files/a26.gno rename to gnovm/tests/files/a26.gno diff --git a/gnovm/tests/files.bak/files/a27.gno b/gnovm/tests/files/a27.gno similarity index 100% rename from gnovm/tests/files.bak/files/a27.gno rename to gnovm/tests/files/a27.gno diff --git a/gnovm/tests/files.bak/files/a28.gno b/gnovm/tests/files/a28.gno similarity index 100% rename from gnovm/tests/files.bak/files/a28.gno rename to gnovm/tests/files/a28.gno diff --git a/gnovm/tests/files.bak/files/a29.gno b/gnovm/tests/files/a29.gno similarity index 100% rename from gnovm/tests/files.bak/files/a29.gno rename to gnovm/tests/files/a29.gno diff --git a/gnovm/tests/files.bak/files/a3.gno b/gnovm/tests/files/a3.gno similarity index 100% rename from gnovm/tests/files.bak/files/a3.gno rename to gnovm/tests/files/a3.gno diff --git a/gnovm/tests/files.bak/files/a30.gno b/gnovm/tests/files/a30.gno similarity index 100% rename from gnovm/tests/files.bak/files/a30.gno rename to gnovm/tests/files/a30.gno diff --git a/gnovm/tests/files.bak/files/a31.gno b/gnovm/tests/files/a31.gno similarity index 100% rename from gnovm/tests/files.bak/files/a31.gno rename to gnovm/tests/files/a31.gno diff --git a/gnovm/tests/files.bak/files/a32.gno b/gnovm/tests/files/a32.gno similarity index 100% rename from gnovm/tests/files.bak/files/a32.gno rename to gnovm/tests/files/a32.gno diff --git a/gnovm/tests/files.bak/files/a33.gno b/gnovm/tests/files/a33.gno similarity index 100% rename from gnovm/tests/files.bak/files/a33.gno rename to gnovm/tests/files/a33.gno diff --git a/gnovm/tests/files.bak/files/a34.gno b/gnovm/tests/files/a34.gno similarity index 100% rename from gnovm/tests/files.bak/files/a34.gno rename to gnovm/tests/files/a34.gno diff --git a/gnovm/tests/files.bak/files/a35.gno b/gnovm/tests/files/a35.gno similarity index 100% rename from gnovm/tests/files.bak/files/a35.gno rename to gnovm/tests/files/a35.gno diff --git a/gnovm/tests/files.bak/files/a36.gno b/gnovm/tests/files/a36.gno similarity index 100% rename from gnovm/tests/files.bak/files/a36.gno rename to gnovm/tests/files/a36.gno diff --git a/gnovm/tests/files.bak/files/a37.gno b/gnovm/tests/files/a37.gno similarity index 100% rename from gnovm/tests/files.bak/files/a37.gno rename to gnovm/tests/files/a37.gno diff --git a/gnovm/tests/files.bak/files/a38.gno b/gnovm/tests/files/a38.gno similarity index 100% rename from gnovm/tests/files.bak/files/a38.gno rename to gnovm/tests/files/a38.gno diff --git a/gnovm/tests/files.bak/files/a39.gno b/gnovm/tests/files/a39.gno similarity index 100% rename from gnovm/tests/files.bak/files/a39.gno rename to gnovm/tests/files/a39.gno diff --git a/gnovm/tests/files.bak/files/a4.gno b/gnovm/tests/files/a4.gno similarity index 100% rename from gnovm/tests/files.bak/files/a4.gno rename to gnovm/tests/files/a4.gno diff --git a/gnovm/tests/files.bak/files/a40.gno b/gnovm/tests/files/a40.gno similarity index 100% rename from gnovm/tests/files.bak/files/a40.gno rename to gnovm/tests/files/a40.gno diff --git a/gnovm/tests/files.bak/files/a41.gno b/gnovm/tests/files/a41.gno similarity index 100% rename from gnovm/tests/files.bak/files/a41.gno rename to gnovm/tests/files/a41.gno diff --git a/gnovm/tests/files.bak/files/a42.gno b/gnovm/tests/files/a42.gno similarity index 100% rename from gnovm/tests/files.bak/files/a42.gno rename to gnovm/tests/files/a42.gno diff --git a/gnovm/tests/files.bak/files/a43.gno b/gnovm/tests/files/a43.gno similarity index 100% rename from gnovm/tests/files.bak/files/a43.gno rename to gnovm/tests/files/a43.gno diff --git a/gnovm/tests/files.bak/files/a44.gno b/gnovm/tests/files/a44.gno similarity index 100% rename from gnovm/tests/files.bak/files/a44.gno rename to gnovm/tests/files/a44.gno diff --git a/gnovm/tests/files.bak/files/a45.gno b/gnovm/tests/files/a45.gno similarity index 100% rename from gnovm/tests/files.bak/files/a45.gno rename to gnovm/tests/files/a45.gno diff --git a/gnovm/tests/files.bak/files/a45a.gno b/gnovm/tests/files/a45a.gno similarity index 100% rename from gnovm/tests/files.bak/files/a45a.gno rename to gnovm/tests/files/a45a.gno diff --git a/gnovm/tests/files.bak/files/a46.gno b/gnovm/tests/files/a46.gno similarity index 100% rename from gnovm/tests/files.bak/files/a46.gno rename to gnovm/tests/files/a46.gno diff --git a/gnovm/tests/files.bak/files/a5.gno b/gnovm/tests/files/a5.gno similarity index 100% rename from gnovm/tests/files.bak/files/a5.gno rename to gnovm/tests/files/a5.gno diff --git a/gnovm/tests/files.bak/files/a6.gno b/gnovm/tests/files/a6.gno similarity index 100% rename from gnovm/tests/files.bak/files/a6.gno rename to gnovm/tests/files/a6.gno diff --git a/gnovm/tests/files.bak/files/a7.gno b/gnovm/tests/files/a7.gno similarity index 100% rename from gnovm/tests/files.bak/files/a7.gno rename to gnovm/tests/files/a7.gno diff --git a/gnovm/tests/files.bak/files/a8.gno b/gnovm/tests/files/a8.gno similarity index 100% rename from gnovm/tests/files.bak/files/a8.gno rename to gnovm/tests/files/a8.gno diff --git a/gnovm/tests/files.bak/files/a9.gno b/gnovm/tests/files/a9.gno similarity index 100% rename from gnovm/tests/files.bak/files/a9.gno rename to gnovm/tests/files/a9.gno diff --git a/gnovm/tests/files.bak/files/access0.gno b/gnovm/tests/files/access0.gno similarity index 100% rename from gnovm/tests/files.bak/files/access0.gno rename to gnovm/tests/files/access0.gno diff --git a/gnovm/tests/files.bak/files/access1.gno b/gnovm/tests/files/access1.gno similarity index 100% rename from gnovm/tests/files.bak/files/access1.gno rename to gnovm/tests/files/access1.gno diff --git a/gnovm/tests/files.bak/files/access2.gno b/gnovm/tests/files/access2.gnoa similarity index 91% rename from gnovm/tests/files.bak/files/access2.gno rename to gnovm/tests/files/access2.gnoa index 46b17136b54..4c9eb952914 100644 --- a/gnovm/tests/files.bak/files/access2.gno +++ b/gnovm/tests/files/access2.gnoa @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/access_test -package access_test +package main import ( "gno.land/p/demo/testutils" diff --git a/gnovm/tests/files.bak/files/access3.gno b/gnovm/tests/files/access3.gno similarity index 100% rename from gnovm/tests/files.bak/files/access3.gno rename to gnovm/tests/files/access3.gno diff --git a/gnovm/tests/files.bak/files/access4.gno b/gnovm/tests/files/access4.gno similarity index 100% rename from gnovm/tests/files.bak/files/access4.gno rename to gnovm/tests/files/access4.gno diff --git a/gnovm/tests/files.bak/files/access5.gno b/gnovm/tests/files/access5.gno similarity index 100% rename from gnovm/tests/files.bak/files/access5.gno rename to gnovm/tests/files/access5.gno diff --git a/gnovm/tests/files.bak/files/access6.gno b/gnovm/tests/files/access6.gno similarity index 100% rename from gnovm/tests/files.bak/files/access6.gno rename to gnovm/tests/files/access6.gno diff --git a/gnovm/tests/files.bak/files/access7.gno b/gnovm/tests/files/access7.gno similarity index 100% rename from gnovm/tests/files.bak/files/access7.gno rename to gnovm/tests/files/access7.gno diff --git a/gnovm/tests/files.bak/files/add0.gno b/gnovm/tests/files/add0.gno similarity index 100% rename from gnovm/tests/files.bak/files/add0.gno rename to gnovm/tests/files/add0.gno diff --git a/gnovm/tests/files.bak/files/add1.gno b/gnovm/tests/files/add1.gno similarity index 100% rename from gnovm/tests/files.bak/files/add1.gno rename to gnovm/tests/files/add1.gno diff --git a/gnovm/tests/files.bak/files/add2.gno b/gnovm/tests/files/add2.gno similarity index 100% rename from gnovm/tests/files.bak/files/add2.gno rename to gnovm/tests/files/add2.gno diff --git a/gnovm/tests/files.bak/files/addr0b_native.gno b/gnovm/tests/files/addr0b_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/addr0b_native.gno rename to gnovm/tests/files/addr0b_native.gno diff --git a/gnovm/tests/files.bak/files/addr0b_stdlibs.gno b/gnovm/tests/files/addr0b_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/addr0b_stdlibs.gno rename to gnovm/tests/files/addr0b_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/addr1.gno b/gnovm/tests/files/addr1.gno similarity index 100% rename from gnovm/tests/files.bak/files/addr1.gno rename to gnovm/tests/files/addr1.gno diff --git a/gnovm/tests/files.bak/files/addr2b.gno b/gnovm/tests/files/addr2b.gno similarity index 100% rename from gnovm/tests/files.bak/files/addr2b.gno rename to gnovm/tests/files/addr2b.gno diff --git a/gnovm/tests/files.bak/files/alias0.gno b/gnovm/tests/files/alias0.gno similarity index 100% rename from gnovm/tests/files.bak/files/alias0.gno rename to gnovm/tests/files/alias0.gno diff --git a/gnovm/tests/files.bak/files/alias1.gno b/gnovm/tests/files/alias1.gno similarity index 100% rename from gnovm/tests/files.bak/files/alias1.gno rename to gnovm/tests/files/alias1.gno diff --git a/gnovm/tests/files.bak/files/and.gno b/gnovm/tests/files/and.gno similarity index 100% rename from gnovm/tests/files.bak/files/and.gno rename to gnovm/tests/files/and.gno diff --git a/gnovm/tests/files.bak/files/and0.gno b/gnovm/tests/files/and0.gno similarity index 100% rename from gnovm/tests/files.bak/files/and0.gno rename to gnovm/tests/files/and0.gno diff --git a/gnovm/tests/files.bak/files/and1.gno b/gnovm/tests/files/and1.gno similarity index 100% rename from gnovm/tests/files.bak/files/and1.gno rename to gnovm/tests/files/and1.gno diff --git a/gnovm/tests/files.bak/files/and2.gno b/gnovm/tests/files/and2.gno similarity index 100% rename from gnovm/tests/files.bak/files/and2.gno rename to gnovm/tests/files/and2.gno diff --git a/gnovm/tests/files.bak/files/and3.gno b/gnovm/tests/files/and3.gno similarity index 100% rename from gnovm/tests/files.bak/files/and3.gno rename to gnovm/tests/files/and3.gno diff --git a/gnovm/tests/files.bak/files/append0.gno b/gnovm/tests/files/append0.gno similarity index 100% rename from gnovm/tests/files.bak/files/append0.gno rename to gnovm/tests/files/append0.gno diff --git a/gnovm/tests/files.bak/files/append1.gno b/gnovm/tests/files/append1.gno similarity index 100% rename from gnovm/tests/files.bak/files/append1.gno rename to gnovm/tests/files/append1.gno diff --git a/gnovm/tests/files.bak/files/append2.gno b/gnovm/tests/files/append2.gno similarity index 100% rename from gnovm/tests/files.bak/files/append2.gno rename to gnovm/tests/files/append2.gno diff --git a/gnovm/tests/files.bak/files/append3.gno b/gnovm/tests/files/append3.gno similarity index 100% rename from gnovm/tests/files.bak/files/append3.gno rename to gnovm/tests/files/append3.gno diff --git a/gnovm/tests/files.bak/files/append4.gno b/gnovm/tests/files/append4.gno similarity index 100% rename from gnovm/tests/files.bak/files/append4.gno rename to gnovm/tests/files/append4.gno diff --git a/gnovm/tests/files.bak/files/append5.gno b/gnovm/tests/files/append5.gno similarity index 100% rename from gnovm/tests/files.bak/files/append5.gno rename to gnovm/tests/files/append5.gno diff --git a/gnovm/tests/files.bak/files/array0.gno b/gnovm/tests/files/array0.gno similarity index 100% rename from gnovm/tests/files.bak/files/array0.gno rename to gnovm/tests/files/array0.gno diff --git a/gnovm/tests/files.bak/files/array1.gno b/gnovm/tests/files/array1.gno similarity index 100% rename from gnovm/tests/files.bak/files/array1.gno rename to gnovm/tests/files/array1.gno diff --git a/gnovm/tests/files.bak/files/array2.gno b/gnovm/tests/files/array2.gno similarity index 100% rename from gnovm/tests/files.bak/files/array2.gno rename to gnovm/tests/files/array2.gno diff --git a/gnovm/tests/files.bak/files/array3.gno b/gnovm/tests/files/array3.gno similarity index 100% rename from gnovm/tests/files.bak/files/array3.gno rename to gnovm/tests/files/array3.gno diff --git a/gnovm/tests/files.bak/files/array4.gno b/gnovm/tests/files/array4.gno similarity index 100% rename from gnovm/tests/files.bak/files/array4.gno rename to gnovm/tests/files/array4.gno diff --git a/gnovm/tests/files.bak/files/array5.gno b/gnovm/tests/files/array5.gno similarity index 100% rename from gnovm/tests/files.bak/files/array5.gno rename to gnovm/tests/files/array5.gno diff --git a/gnovm/tests/files.bak/files/assign.gno b/gnovm/tests/files/assign.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign.gno rename to gnovm/tests/files/assign.gno diff --git a/gnovm/tests/files.bak/files/assign0b_native.gno b/gnovm/tests/files/assign0b_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign0b_native.gno rename to gnovm/tests/files/assign0b_native.gno diff --git a/gnovm/tests/files.bak/files/assign0b_stdlibs.gno b/gnovm/tests/files/assign0b_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign0b_stdlibs.gno rename to gnovm/tests/files/assign0b_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/assign1.gno b/gnovm/tests/files/assign1.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign1.gno rename to gnovm/tests/files/assign1.gno diff --git a/gnovm/tests/files.bak/files/assign10.gno b/gnovm/tests/files/assign10.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign10.gno rename to gnovm/tests/files/assign10.gno diff --git a/gnovm/tests/files.bak/files/assign11.gno b/gnovm/tests/files/assign11.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign11.gno rename to gnovm/tests/files/assign11.gno diff --git a/gnovm/tests/files.bak/files/assign12.gno b/gnovm/tests/files/assign12.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign12.gno rename to gnovm/tests/files/assign12.gno diff --git a/gnovm/tests/files.bak/files/assign16.gno b/gnovm/tests/files/assign16.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign16.gno rename to gnovm/tests/files/assign16.gno diff --git a/gnovm/tests/files.bak/files/assign2.gno b/gnovm/tests/files/assign2.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign2.gno rename to gnovm/tests/files/assign2.gno diff --git a/gnovm/tests/files.bak/files/assign20.gno b/gnovm/tests/files/assign20.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign20.gno rename to gnovm/tests/files/assign20.gno diff --git a/gnovm/tests/files.bak/files/assign21.gno b/gnovm/tests/files/assign21.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign21.gno rename to gnovm/tests/files/assign21.gno diff --git a/gnovm/tests/files.bak/files/assign3.gno b/gnovm/tests/files/assign3.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign3.gno rename to gnovm/tests/files/assign3.gno diff --git a/gnovm/tests/files.bak/files/assign4.gno b/gnovm/tests/files/assign4.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign4.gno rename to gnovm/tests/files/assign4.gno diff --git a/gnovm/tests/files.bak/files/assign5.gno b/gnovm/tests/files/assign5.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign5.gno rename to gnovm/tests/files/assign5.gno diff --git a/gnovm/tests/files.bak/files/assign8.gno b/gnovm/tests/files/assign8.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign8.gno rename to gnovm/tests/files/assign8.gno diff --git a/gnovm/tests/files.bak/files/assign9.gno b/gnovm/tests/files/assign9.gno similarity index 100% rename from gnovm/tests/files.bak/files/assign9.gno rename to gnovm/tests/files/assign9.gno diff --git a/gnovm/tests/files.bak/files/avl0.gno b/gnovm/tests/files/avl0.gno similarity index 100% rename from gnovm/tests/files.bak/files/avl0.gno rename to gnovm/tests/files/avl0.gno diff --git a/gnovm/tests/files.bak/files/avl1.gno b/gnovm/tests/files/avl1.gno similarity index 100% rename from gnovm/tests/files.bak/files/avl1.gno rename to gnovm/tests/files/avl1.gno diff --git a/gnovm/tests/files.bak/files/bin.gno b/gnovm/tests/files/bin.gno similarity index 100% rename from gnovm/tests/files.bak/files/bin.gno rename to gnovm/tests/files/bin.gno diff --git a/gnovm/tests/files.bak/files/bin0.gno b/gnovm/tests/files/bin0.gno similarity index 100% rename from gnovm/tests/files.bak/files/bin0.gno rename to gnovm/tests/files/bin0.gno diff --git a/gnovm/tests/files.bak/files/bin1.gno b/gnovm/tests/files/bin1.gno similarity index 100% rename from gnovm/tests/files.bak/files/bin1.gno rename to gnovm/tests/files/bin1.gno diff --git a/gnovm/tests/files.bak/files/bin3.gno b/gnovm/tests/files/bin3.gno similarity index 100% rename from gnovm/tests/files.bak/files/bin3.gno rename to gnovm/tests/files/bin3.gno diff --git a/gnovm/tests/files.bak/files/bin4.gno b/gnovm/tests/files/bin4.gno similarity index 100% rename from gnovm/tests/files.bak/files/bin4.gno rename to gnovm/tests/files/bin4.gno diff --git a/gnovm/tests/files.bak/files/bin5.gno b/gnovm/tests/files/bin5.gno similarity index 100% rename from gnovm/tests/files.bak/files/bin5.gno rename to gnovm/tests/files/bin5.gno diff --git a/gnovm/tests/files.bak/files/binstruct_ptr_map0.gno b/gnovm/tests/files/binstruct_ptr_map0.gno similarity index 100% rename from gnovm/tests/files.bak/files/binstruct_ptr_map0.gno rename to gnovm/tests/files/binstruct_ptr_map0.gno diff --git a/gnovm/tests/files.bak/files/binstruct_ptr_slice0.gno b/gnovm/tests/files/binstruct_ptr_slice0.gno similarity index 100% rename from gnovm/tests/files.bak/files/binstruct_ptr_slice0.gno rename to gnovm/tests/files/binstruct_ptr_slice0.gno diff --git a/gnovm/tests/files.bak/files/binstruct_slice0.gno b/gnovm/tests/files/binstruct_slice0.gno similarity index 100% rename from gnovm/tests/files.bak/files/binstruct_slice0.gno rename to gnovm/tests/files/binstruct_slice0.gno diff --git a/gnovm/tests/files.bak/files/bltn.gno b/gnovm/tests/files/bltn.gno similarity index 100% rename from gnovm/tests/files.bak/files/bltn.gno rename to gnovm/tests/files/bltn.gno diff --git a/gnovm/tests/files.bak/files/bltn0.gno b/gnovm/tests/files/bltn0.gno similarity index 100% rename from gnovm/tests/files.bak/files/bltn0.gno rename to gnovm/tests/files/bltn0.gno diff --git a/gnovm/tests/files.bak/files/bool.gno b/gnovm/tests/files/bool.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool.gno rename to gnovm/tests/files/bool.gno diff --git a/gnovm/tests/files.bak/files/bool0.gno b/gnovm/tests/files/bool0.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool0.gno rename to gnovm/tests/files/bool0.gno diff --git a/gnovm/tests/files.bak/files/bool1.gno b/gnovm/tests/files/bool1.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool1.gno rename to gnovm/tests/files/bool1.gno diff --git a/gnovm/tests/files.bak/files/bool2.gno b/gnovm/tests/files/bool2.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool2.gno rename to gnovm/tests/files/bool2.gno diff --git a/gnovm/tests/files.bak/files/bool3.gno b/gnovm/tests/files/bool3.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool3.gno rename to gnovm/tests/files/bool3.gno diff --git a/gnovm/tests/files.bak/files/bool4.gno b/gnovm/tests/files/bool4.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool4.gno rename to gnovm/tests/files/bool4.gno diff --git a/gnovm/tests/files.bak/files/bool5.gno b/gnovm/tests/files/bool5.gno similarity index 100% rename from gnovm/tests/files.bak/files/bool5.gno rename to gnovm/tests/files/bool5.gno diff --git a/gnovm/tests/files.bak/files/build0.gno b/gnovm/tests/files/build0.gno similarity index 100% rename from gnovm/tests/files.bak/files/build0.gno rename to gnovm/tests/files/build0.gno diff --git a/gnovm/tests/files.bak/files/cap0.gno b/gnovm/tests/files/cap0.gno similarity index 100% rename from gnovm/tests/files.bak/files/cap0.gno rename to gnovm/tests/files/cap0.gno diff --git a/gnovm/tests/files.bak/files/closure0.gno b/gnovm/tests/files/closure0.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure0.gno rename to gnovm/tests/files/closure0.gno diff --git a/gnovm/tests/files.bak/files/closure1.gno b/gnovm/tests/files/closure1.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure1.gno rename to gnovm/tests/files/closure1.gno diff --git a/gnovm/tests/files.bak/files/closure2.gno b/gnovm/tests/files/closure2.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure2.gno rename to gnovm/tests/files/closure2.gno diff --git a/gnovm/tests/files.bak/files/closure3.gno b/gnovm/tests/files/closure3.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure3.gno rename to gnovm/tests/files/closure3.gno diff --git a/gnovm/tests/files.bak/files/closure4.gno b/gnovm/tests/files/closure4.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure4.gno rename to gnovm/tests/files/closure4.gno diff --git a/gnovm/tests/files.bak/files/closure5.gno b/gnovm/tests/files/closure5.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure5.gno rename to gnovm/tests/files/closure5.gno diff --git a/gnovm/tests/files.bak/files/closure6.gno b/gnovm/tests/files/closure6.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure6.gno rename to gnovm/tests/files/closure6.gno diff --git a/gnovm/tests/files.bak/files/closure7.gno b/gnovm/tests/files/closure7.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure7.gno rename to gnovm/tests/files/closure7.gno diff --git a/gnovm/tests/files.bak/files/closure8.gno b/gnovm/tests/files/closure8.gno similarity index 100% rename from gnovm/tests/files.bak/files/closure8.gno rename to gnovm/tests/files/closure8.gno diff --git a/gnovm/tests/files.bak/files/comp1.gno b/gnovm/tests/files/comp1.gno similarity index 100% rename from gnovm/tests/files.bak/files/comp1.gno rename to gnovm/tests/files/comp1.gno diff --git a/gnovm/tests/files.bak/files/comp2.gno b/gnovm/tests/files/comp2.gno similarity index 100% rename from gnovm/tests/files.bak/files/comp2.gno rename to gnovm/tests/files/comp2.gno diff --git a/gnovm/tests/files.bak/files/comp3.gno b/gnovm/tests/files/comp3.gno similarity index 100% rename from gnovm/tests/files.bak/files/comp3.gno rename to gnovm/tests/files/comp3.gno diff --git a/gnovm/tests/files.bak/files/composite0.gno b/gnovm/tests/files/composite0.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite0.gno rename to gnovm/tests/files/composite0.gno diff --git a/gnovm/tests/files.bak/files/composite1.gno b/gnovm/tests/files/composite1.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite1.gno rename to gnovm/tests/files/composite1.gno diff --git a/gnovm/tests/files.bak/files/composite10.gno b/gnovm/tests/files/composite10.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite10.gno rename to gnovm/tests/files/composite10.gno diff --git a/gnovm/tests/files.bak/files/composite11.gno b/gnovm/tests/files/composite11.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite11.gno rename to gnovm/tests/files/composite11.gno diff --git a/gnovm/tests/files.bak/files/composite12.gno b/gnovm/tests/files/composite12.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite12.gno rename to gnovm/tests/files/composite12.gno diff --git a/gnovm/tests/files.bak/files/composite13.gno b/gnovm/tests/files/composite13.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite13.gno rename to gnovm/tests/files/composite13.gno diff --git a/gnovm/tests/files.bak/files/composite14.gno b/gnovm/tests/files/composite14.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite14.gno rename to gnovm/tests/files/composite14.gno diff --git a/gnovm/tests/files.bak/files/composite15.gno b/gnovm/tests/files/composite15.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite15.gno rename to gnovm/tests/files/composite15.gno diff --git a/gnovm/tests/files.bak/files/composite16.gno b/gnovm/tests/files/composite16.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite16.gno rename to gnovm/tests/files/composite16.gno diff --git a/gnovm/tests/files.bak/files/composite17.gno b/gnovm/tests/files/composite17.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite17.gno rename to gnovm/tests/files/composite17.gno diff --git a/gnovm/tests/files.bak/files/composite2.gno b/gnovm/tests/files/composite2.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite2.gno rename to gnovm/tests/files/composite2.gno diff --git a/gnovm/tests/files.bak/files/composite3.gno b/gnovm/tests/files/composite3.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite3.gno rename to gnovm/tests/files/composite3.gno diff --git a/gnovm/tests/files.bak/files/composite4.gno b/gnovm/tests/files/composite4.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite4.gno rename to gnovm/tests/files/composite4.gno diff --git a/gnovm/tests/files.bak/files/composite5.gno b/gnovm/tests/files/composite5.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite5.gno rename to gnovm/tests/files/composite5.gno diff --git a/gnovm/tests/files.bak/files/composite6.gno b/gnovm/tests/files/composite6.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite6.gno rename to gnovm/tests/files/composite6.gno diff --git a/gnovm/tests/files.bak/files/composite7.gno b/gnovm/tests/files/composite7.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite7.gno rename to gnovm/tests/files/composite7.gno diff --git a/gnovm/tests/files.bak/files/composite8.gno b/gnovm/tests/files/composite8.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite8.gno rename to gnovm/tests/files/composite8.gno diff --git a/gnovm/tests/files.bak/files/composite8bis.gno b/gnovm/tests/files/composite8bis.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite8bis.gno rename to gnovm/tests/files/composite8bis.gno diff --git a/gnovm/tests/files.bak/files/composite9.gno b/gnovm/tests/files/composite9.gno similarity index 100% rename from gnovm/tests/files.bak/files/composite9.gno rename to gnovm/tests/files/composite9.gno diff --git a/gnovm/tests/files.bak/files/const0.gno b/gnovm/tests/files/const0.gno similarity index 100% rename from gnovm/tests/files.bak/files/const0.gno rename to gnovm/tests/files/const0.gno diff --git a/gnovm/tests/files.bak/files/const1.gno b/gnovm/tests/files/const1.gno similarity index 100% rename from gnovm/tests/files.bak/files/const1.gno rename to gnovm/tests/files/const1.gno diff --git a/gnovm/tests/files.bak/files/const10.gno b/gnovm/tests/files/const10.gno similarity index 100% rename from gnovm/tests/files.bak/files/const10.gno rename to gnovm/tests/files/const10.gno diff --git a/gnovm/tests/files.bak/files/const11.gno b/gnovm/tests/files/const11.gno similarity index 100% rename from gnovm/tests/files.bak/files/const11.gno rename to gnovm/tests/files/const11.gno diff --git a/gnovm/tests/files.bak/files/const12.gno b/gnovm/tests/files/const12.gno similarity index 100% rename from gnovm/tests/files.bak/files/const12.gno rename to gnovm/tests/files/const12.gno diff --git a/gnovm/tests/files.bak/files/const13.gno b/gnovm/tests/files/const13.gno similarity index 100% rename from gnovm/tests/files.bak/files/const13.gno rename to gnovm/tests/files/const13.gno diff --git a/gnovm/tests/files.bak/files/const14.gno b/gnovm/tests/files/const14.gno similarity index 100% rename from gnovm/tests/files.bak/files/const14.gno rename to gnovm/tests/files/const14.gno diff --git a/gnovm/tests/files.bak/files/const15.gno b/gnovm/tests/files/const15.gno similarity index 100% rename from gnovm/tests/files.bak/files/const15.gno rename to gnovm/tests/files/const15.gno diff --git a/gnovm/tests/files.bak/files/const16.gno b/gnovm/tests/files/const16.gno similarity index 100% rename from gnovm/tests/files.bak/files/const16.gno rename to gnovm/tests/files/const16.gno diff --git a/gnovm/tests/files.bak/files/const17.gno b/gnovm/tests/files/const17.gno similarity index 100% rename from gnovm/tests/files.bak/files/const17.gno rename to gnovm/tests/files/const17.gno diff --git a/gnovm/tests/files.bak/files/const18.gno b/gnovm/tests/files/const18.gno similarity index 100% rename from gnovm/tests/files.bak/files/const18.gno rename to gnovm/tests/files/const18.gno diff --git a/gnovm/tests/files.bak/files/const19.gno b/gnovm/tests/files/const19.gno similarity index 100% rename from gnovm/tests/files.bak/files/const19.gno rename to gnovm/tests/files/const19.gno diff --git a/gnovm/tests/files.bak/files/const2.gno b/gnovm/tests/files/const2.gno similarity index 100% rename from gnovm/tests/files.bak/files/const2.gno rename to gnovm/tests/files/const2.gno diff --git a/gnovm/tests/files.bak/files/const20.gno b/gnovm/tests/files/const20.gno similarity index 100% rename from gnovm/tests/files.bak/files/const20.gno rename to gnovm/tests/files/const20.gno diff --git a/gnovm/tests/files.bak/files/const21.gno b/gnovm/tests/files/const21.gno similarity index 100% rename from gnovm/tests/files.bak/files/const21.gno rename to gnovm/tests/files/const21.gno diff --git a/gnovm/tests/files.bak/files/const22.gno b/gnovm/tests/files/const22.gno similarity index 100% rename from gnovm/tests/files.bak/files/const22.gno rename to gnovm/tests/files/const22.gno diff --git a/gnovm/tests/files.bak/files/const3.gno b/gnovm/tests/files/const3.gno similarity index 100% rename from gnovm/tests/files.bak/files/const3.gno rename to gnovm/tests/files/const3.gno diff --git a/gnovm/tests/files.bak/files/const4.gno b/gnovm/tests/files/const4.gno similarity index 100% rename from gnovm/tests/files.bak/files/const4.gno rename to gnovm/tests/files/const4.gno diff --git a/gnovm/tests/files.bak/files/const5.gno b/gnovm/tests/files/const5.gno similarity index 100% rename from gnovm/tests/files.bak/files/const5.gno rename to gnovm/tests/files/const5.gno diff --git a/gnovm/tests/files.bak/files/const6.gno b/gnovm/tests/files/const6.gno similarity index 100% rename from gnovm/tests/files.bak/files/const6.gno rename to gnovm/tests/files/const6.gno diff --git a/gnovm/tests/files.bak/files/const7.gno b/gnovm/tests/files/const7.gno similarity index 100% rename from gnovm/tests/files.bak/files/const7.gno rename to gnovm/tests/files/const7.gno diff --git a/gnovm/tests/files.bak/files/const8.gno b/gnovm/tests/files/const8.gno similarity index 100% rename from gnovm/tests/files.bak/files/const8.gno rename to gnovm/tests/files/const8.gno diff --git a/gnovm/tests/files.bak/files/const9.gno b/gnovm/tests/files/const9.gno similarity index 100% rename from gnovm/tests/files.bak/files/const9.gno rename to gnovm/tests/files/const9.gno diff --git a/gnovm/tests/files.bak/files/cont.gno b/gnovm/tests/files/cont.gno similarity index 100% rename from gnovm/tests/files.bak/files/cont.gno rename to gnovm/tests/files/cont.gno diff --git a/gnovm/tests/files.bak/files/cont0.gno b/gnovm/tests/files/cont0.gno similarity index 100% rename from gnovm/tests/files.bak/files/cont0.gno rename to gnovm/tests/files/cont0.gno diff --git a/gnovm/tests/files.bak/files/cont1.gno b/gnovm/tests/files/cont1.gno similarity index 100% rename from gnovm/tests/files.bak/files/cont1.gno rename to gnovm/tests/files/cont1.gno diff --git a/gnovm/tests/files.bak/files/context.gno b/gnovm/tests/files/context.gno similarity index 100% rename from gnovm/tests/files.bak/files/context.gno rename to gnovm/tests/files/context.gno diff --git a/gnovm/tests/files.bak/files/context2.gno b/gnovm/tests/files/context2.gno similarity index 100% rename from gnovm/tests/files.bak/files/context2.gno rename to gnovm/tests/files/context2.gno diff --git a/gnovm/tests/files.bak/files/convert0.gno b/gnovm/tests/files/convert0.gno similarity index 100% rename from gnovm/tests/files.bak/files/convert0.gno rename to gnovm/tests/files/convert0.gno diff --git a/gnovm/tests/files.bak/files/convert1.gno b/gnovm/tests/files/convert1.gno similarity index 100% rename from gnovm/tests/files.bak/files/convert1.gno rename to gnovm/tests/files/convert1.gno diff --git a/gnovm/tests/files.bak/files/convert3.gno b/gnovm/tests/files/convert3.gno similarity index 100% rename from gnovm/tests/files.bak/files/convert3.gno rename to gnovm/tests/files/convert3.gno diff --git a/gnovm/tests/files.bak/files/copy0.gno b/gnovm/tests/files/copy0.gno similarity index 100% rename from gnovm/tests/files.bak/files/copy0.gno rename to gnovm/tests/files/copy0.gno diff --git a/gnovm/tests/files.bak/files/copy1.gno b/gnovm/tests/files/copy1.gno similarity index 100% rename from gnovm/tests/files.bak/files/copy1.gno rename to gnovm/tests/files/copy1.gno diff --git a/gnovm/tests/files.bak/files/copy2.gno b/gnovm/tests/files/copy2.gno similarity index 100% rename from gnovm/tests/files.bak/files/copy2.gno rename to gnovm/tests/files/copy2.gno diff --git a/gnovm/tests/files.bak/files/defer0.gno b/gnovm/tests/files/defer0.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer0.gno rename to gnovm/tests/files/defer0.gno diff --git a/gnovm/tests/files.bak/files/defer1.gno b/gnovm/tests/files/defer1.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer1.gno rename to gnovm/tests/files/defer1.gno diff --git a/gnovm/tests/files.bak/files/defer2.gno b/gnovm/tests/files/defer2.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer2.gno rename to gnovm/tests/files/defer2.gno diff --git a/gnovm/tests/files.bak/files/defer3.gno b/gnovm/tests/files/defer3.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer3.gno rename to gnovm/tests/files/defer3.gno diff --git a/gnovm/tests/files.bak/files/defer4.gno b/gnovm/tests/files/defer4.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer4.gno rename to gnovm/tests/files/defer4.gno diff --git a/gnovm/tests/files.bak/files/defer5.gno b/gnovm/tests/files/defer5.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer5.gno rename to gnovm/tests/files/defer5.gno diff --git a/gnovm/tests/files.bak/files/defer6.gno b/gnovm/tests/files/defer6.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer6.gno rename to gnovm/tests/files/defer6.gno diff --git a/gnovm/tests/files.bak/files/defer7.gno b/gnovm/tests/files/defer7.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer7.gno rename to gnovm/tests/files/defer7.gno diff --git a/gnovm/tests/files.bak/files/defer8.gno b/gnovm/tests/files/defer8.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer8.gno rename to gnovm/tests/files/defer8.gno diff --git a/gnovm/tests/files.bak/files/defer9.gno b/gnovm/tests/files/defer9.gno similarity index 100% rename from gnovm/tests/files.bak/files/defer9.gno rename to gnovm/tests/files/defer9.gno diff --git a/gnovm/tests/files.bak/files/define0.gno b/gnovm/tests/files/define0.gno similarity index 100% rename from gnovm/tests/files.bak/files/define0.gno rename to gnovm/tests/files/define0.gno diff --git a/gnovm/tests/files.bak/files/define1.gno b/gnovm/tests/files/define1.gno similarity index 100% rename from gnovm/tests/files.bak/files/define1.gno rename to gnovm/tests/files/define1.gno diff --git a/gnovm/tests/files.bak/files/define2.gno b/gnovm/tests/files/define2.gno similarity index 100% rename from gnovm/tests/files.bak/files/define2.gno rename to gnovm/tests/files/define2.gno diff --git a/gnovm/tests/files.bak/files/define3.gno b/gnovm/tests/files/define3.gno similarity index 100% rename from gnovm/tests/files.bak/files/define3.gno rename to gnovm/tests/files/define3.gno diff --git a/gnovm/tests/files.bak/files/define4.gno b/gnovm/tests/files/define4.gno similarity index 100% rename from gnovm/tests/files.bak/files/define4.gno rename to gnovm/tests/files/define4.gno diff --git a/gnovm/tests/files.bak/files/delete0.gno b/gnovm/tests/files/delete0.gno similarity index 100% rename from gnovm/tests/files.bak/files/delete0.gno rename to gnovm/tests/files/delete0.gno diff --git a/gnovm/tests/files.bak/files/errors.gno b/gnovm/tests/files/errors.gno similarity index 100% rename from gnovm/tests/files.bak/files/errors.gno rename to gnovm/tests/files/errors.gno diff --git a/gnovm/tests/files.bak/files/extern/b1/foo/foo.gno b/gnovm/tests/files/extern/b1/foo/foo.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/b1/foo/foo.gno rename to gnovm/tests/files/extern/b1/foo/foo.gno diff --git a/gnovm/tests/files.bak/files/extern/b2/foo/foo.gno b/gnovm/tests/files/extern/b2/foo/foo.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/b2/foo/foo.gno rename to gnovm/tests/files/extern/b2/foo/foo.gno diff --git a/gnovm/tests/files.bak/files/extern/bar/quux.gno b/gnovm/tests/files/extern/bar/quux.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/bar/quux.gno rename to gnovm/tests/files/extern/bar/quux.gno diff --git a/gnovm/tests/files.bak/files/extern/baz-bat/baz-bat.gno b/gnovm/tests/files/extern/baz-bat/baz-bat.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/baz-bat/baz-bat.gno rename to gnovm/tests/files/extern/baz-bat/baz-bat.gno diff --git a/gnovm/tests/files.bak/files/extern/baz/quux.gno b/gnovm/tests/files/extern/baz/quux.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/baz/quux.gno rename to gnovm/tests/files/extern/baz/quux.gno diff --git a/gnovm/tests/files.bak/files/extern/c1/c1.gno b/gnovm/tests/files/extern/c1/c1.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/c1/c1.gno rename to gnovm/tests/files/extern/c1/c1.gno diff --git a/gnovm/tests/files.bak/files/extern/c2/c2.gno b/gnovm/tests/files/extern/c2/c2.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/c2/c2.gno rename to gnovm/tests/files/extern/c2/c2.gno diff --git a/gnovm/tests/files.bak/files/extern/context/context.gno b/gnovm/tests/files/extern/context/context.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/context/context.gno rename to gnovm/tests/files/extern/context/context.gno diff --git a/gnovm/tests/files.bak/files/extern/ct/ct1.gno b/gnovm/tests/files/extern/ct/ct1.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/ct/ct1.gno rename to gnovm/tests/files/extern/ct/ct1.gno diff --git a/gnovm/tests/files.bak/files/extern/ct/ct2.gno b/gnovm/tests/files/extern/ct/ct2.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/ct/ct2.gno rename to gnovm/tests/files/extern/ct/ct2.gno diff --git a/gnovm/tests/files.bak/files/extern/ct/ct3.gno b/gnovm/tests/files/extern/ct/ct3.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/ct/ct3.gno rename to gnovm/tests/files/extern/ct/ct3.gno diff --git a/gnovm/tests/files.bak/files/extern/ct1/ct1.gno b/gnovm/tests/files/extern/ct1/ct1.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/ct1/ct1.gno rename to gnovm/tests/files/extern/ct1/ct1.gno diff --git a/gnovm/tests/files.bak/files/extern/foo-bar/foo-bar.gno b/gnovm/tests/files/extern/foo-bar/foo-bar.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/foo-bar/foo-bar.gno rename to gnovm/tests/files/extern/foo-bar/foo-bar.gno diff --git a/gnovm/tests/files.bak/files/extern/foo/bar.gno b/gnovm/tests/files/extern/foo/bar.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/foo/bar.gno rename to gnovm/tests/files/extern/foo/bar.gno diff --git a/gnovm/tests/files.bak/files/extern/foo/bir.gno b/gnovm/tests/files/extern/foo/bir.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/foo/bir.gno rename to gnovm/tests/files/extern/foo/bir.gno diff --git a/gnovm/tests/files.bak/files/extern/foo/boo/boo.gno b/gnovm/tests/files/extern/foo/boo/boo.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/foo/boo/boo.gno rename to gnovm/tests/files/extern/foo/boo/boo.gno diff --git a/gnovm/tests/files.bak/files/extern/m1/main.gno b/gnovm/tests/files/extern/m1/main.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/m1/main.gno rename to gnovm/tests/files/extern/m1/main.gno diff --git a/gnovm/tests/files.bak/files/extern/m1/main_test.gno b/gnovm/tests/files/extern/m1/main_test.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/m1/main_test.gno rename to gnovm/tests/files/extern/m1/main_test.gno diff --git a/gnovm/tests/files.bak/files/extern/m2/m2_test.gno b/gnovm/tests/files/extern/m2/m2_test.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/m2/m2_test.gno rename to gnovm/tests/files/extern/m2/m2_test.gno diff --git a/gnovm/tests/files.bak/files/extern/net/http/http.gno b/gnovm/tests/files/extern/net/http/http.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/net/http/http.gno rename to gnovm/tests/files/extern/net/http/http.gno diff --git a/gnovm/tests/files.bak/files/extern/net/http/httptest/httptest.gno b/gnovm/tests/files/extern/net/http/httptest/httptest.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/net/http/httptest/httptest.gno rename to gnovm/tests/files/extern/net/http/httptest/httptest.gno diff --git a/gnovm/tests/files.bak/files/extern/net/net.gno b/gnovm/tests/files/extern/net/net.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/net/net.gno rename to gnovm/tests/files/extern/net/net.gno diff --git a/gnovm/tests/files.bak/files/extern/net/url/url.gno b/gnovm/tests/files/extern/net/url/url.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/net/url/url.gno rename to gnovm/tests/files/extern/net/url/url.gno diff --git a/gnovm/tests/files.bak/files/extern/p1/s1.gno b/gnovm/tests/files/extern/p1/s1.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/p1/s1.gno rename to gnovm/tests/files/extern/p1/s1.gno diff --git a/gnovm/tests/files.bak/files/extern/p1/s2.gno b/gnovm/tests/files/extern/p1/s2.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/p1/s2.gno rename to gnovm/tests/files/extern/p1/s2.gno diff --git a/gnovm/tests/files.bak/files/extern/tata/tutu.gno b/gnovm/tests/files/extern/tata/tutu.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/tata/tutu.gno rename to gnovm/tests/files/extern/tata/tutu.gno diff --git a/gnovm/tests/files.bak/files/extern/time/time.gno b/gnovm/tests/files/extern/time/time.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/time/time.gno rename to gnovm/tests/files/extern/time/time.gno diff --git a/gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/avl/avltree.gno b/gnovm/tests/files/extern/timtadh/data-structures/tree/avl/avltree.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/avl/avltree.gno rename to gnovm/tests/files/extern/timtadh/data-structures/tree/avl/avltree.gno diff --git a/gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/utils.gno b/gnovm/tests/files/extern/timtadh/data-structures/tree/utils.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/timtadh/data-structures/tree/utils.gno rename to gnovm/tests/files/extern/timtadh/data-structures/tree/utils.gno diff --git a/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/map_entry.gno b/gnovm/tests/files/extern/timtadh/data-structures/types/map_entry.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/map_entry.gno rename to gnovm/tests/files/extern/timtadh/data-structures/types/map_entry.gno diff --git a/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/string.gno b/gnovm/tests/files/extern/timtadh/data-structures/types/string.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/string.gno rename to gnovm/tests/files/extern/timtadh/data-structures/types/string.gno diff --git a/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/types.gno b/gnovm/tests/files/extern/timtadh/data-structures/types/types.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/types.gno rename to gnovm/tests/files/extern/timtadh/data-structures/types/types.gno diff --git a/gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/util.gno b/gnovm/tests/files/extern/timtadh/data-structures/types/util.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/timtadh/data-structures/types/util.gno rename to gnovm/tests/files/extern/timtadh/data-structures/types/util.gno diff --git a/gnovm/tests/files.bak/files/extern/toto/titi.gno b/gnovm/tests/files/extern/toto/titi.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/toto/titi.gno rename to gnovm/tests/files/extern/toto/titi.gno diff --git a/gnovm/tests/files.bak/files/extern/vars/first.gno b/gnovm/tests/files/extern/vars/first.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/vars/first.gno rename to gnovm/tests/files/extern/vars/first.gno diff --git a/gnovm/tests/files.bak/files/extern/vars/second.gno b/gnovm/tests/files/extern/vars/second.gno similarity index 100% rename from gnovm/tests/files.bak/files/extern/vars/second.gno rename to gnovm/tests/files/extern/vars/second.gno diff --git a/gnovm/tests/files.bak/files/fib0.gno b/gnovm/tests/files/fib0.gno similarity index 100% rename from gnovm/tests/files.bak/files/fib0.gno rename to gnovm/tests/files/fib0.gno diff --git a/gnovm/tests/files.bak/files/float0.gno b/gnovm/tests/files/float0.gno similarity index 100% rename from gnovm/tests/files.bak/files/float0.gno rename to gnovm/tests/files/float0.gno diff --git a/gnovm/tests/files.bak/files/float1.gno b/gnovm/tests/files/float1.gno similarity index 100% rename from gnovm/tests/files.bak/files/float1.gno rename to gnovm/tests/files/float1.gno diff --git a/gnovm/tests/files.bak/files/float2.gno b/gnovm/tests/files/float2.gno similarity index 100% rename from gnovm/tests/files.bak/files/float2.gno rename to gnovm/tests/files/float2.gno diff --git a/gnovm/tests/files.bak/files/float3.gno b/gnovm/tests/files/float3.gno similarity index 100% rename from gnovm/tests/files.bak/files/float3.gno rename to gnovm/tests/files/float3.gno diff --git a/gnovm/tests/files.bak/files/float4.gno b/gnovm/tests/files/float4.gno similarity index 100% rename from gnovm/tests/files.bak/files/float4.gno rename to gnovm/tests/files/float4.gno diff --git a/gnovm/tests/files.bak/files/float5_native.gno b/gnovm/tests/files/float5_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/float5_native.gno rename to gnovm/tests/files/float5_native.gno diff --git a/gnovm/tests/files.bak/files/float5_stdlibs.gno b/gnovm/tests/files/float5_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/float5_stdlibs.gno rename to gnovm/tests/files/float5_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/float6.gno b/gnovm/tests/files/float6.gno similarity index 100% rename from gnovm/tests/files.bak/files/float6.gno rename to gnovm/tests/files/float6.gno diff --git a/gnovm/tests/files.bak/files/float7.gno b/gnovm/tests/files/float7.gno similarity index 100% rename from gnovm/tests/files.bak/files/float7.gno rename to gnovm/tests/files/float7.gno diff --git a/gnovm/tests/files.bak/files/for0.gno b/gnovm/tests/files/for0.gno similarity index 100% rename from gnovm/tests/files.bak/files/for0.gno rename to gnovm/tests/files/for0.gno diff --git a/gnovm/tests/files.bak/files/for1.gno b/gnovm/tests/files/for1.gno similarity index 100% rename from gnovm/tests/files.bak/files/for1.gno rename to gnovm/tests/files/for1.gno diff --git a/gnovm/tests/files.bak/files/for10.gno b/gnovm/tests/files/for10.gno similarity index 100% rename from gnovm/tests/files.bak/files/for10.gno rename to gnovm/tests/files/for10.gno diff --git a/gnovm/tests/files.bak/files/for11.gno b/gnovm/tests/files/for11.gno similarity index 100% rename from gnovm/tests/files.bak/files/for11.gno rename to gnovm/tests/files/for11.gno diff --git a/gnovm/tests/files.bak/files/for12.gno b/gnovm/tests/files/for12.gno similarity index 100% rename from gnovm/tests/files.bak/files/for12.gno rename to gnovm/tests/files/for12.gno diff --git a/gnovm/tests/files.bak/files/for13.gno b/gnovm/tests/files/for13.gno similarity index 100% rename from gnovm/tests/files.bak/files/for13.gno rename to gnovm/tests/files/for13.gno diff --git a/gnovm/tests/files.bak/files/for14.gno b/gnovm/tests/files/for14.gno similarity index 100% rename from gnovm/tests/files.bak/files/for14.gno rename to gnovm/tests/files/for14.gno diff --git a/gnovm/tests/files.bak/files/for15.gno b/gnovm/tests/files/for15.gno similarity index 100% rename from gnovm/tests/files.bak/files/for15.gno rename to gnovm/tests/files/for15.gno diff --git a/gnovm/tests/files.bak/files/for16.gno b/gnovm/tests/files/for16.gno similarity index 100% rename from gnovm/tests/files.bak/files/for16.gno rename to gnovm/tests/files/for16.gno diff --git a/gnovm/tests/files.bak/files/for17.gno b/gnovm/tests/files/for17.gno similarity index 100% rename from gnovm/tests/files.bak/files/for17.gno rename to gnovm/tests/files/for17.gno diff --git a/gnovm/tests/files.bak/files/for18.gno b/gnovm/tests/files/for18.gno similarity index 100% rename from gnovm/tests/files.bak/files/for18.gno rename to gnovm/tests/files/for18.gno diff --git a/gnovm/tests/files.bak/files/for2.gno b/gnovm/tests/files/for2.gno similarity index 100% rename from gnovm/tests/files.bak/files/for2.gno rename to gnovm/tests/files/for2.gno diff --git a/gnovm/tests/files.bak/files/for3.gno b/gnovm/tests/files/for3.gno similarity index 100% rename from gnovm/tests/files.bak/files/for3.gno rename to gnovm/tests/files/for3.gno diff --git a/gnovm/tests/files.bak/files/for4.gno b/gnovm/tests/files/for4.gno similarity index 100% rename from gnovm/tests/files.bak/files/for4.gno rename to gnovm/tests/files/for4.gno diff --git a/gnovm/tests/files.bak/files/for5.gno b/gnovm/tests/files/for5.gno similarity index 100% rename from gnovm/tests/files.bak/files/for5.gno rename to gnovm/tests/files/for5.gno diff --git a/gnovm/tests/files.bak/files/for6.gno b/gnovm/tests/files/for6.gno similarity index 100% rename from gnovm/tests/files.bak/files/for6.gno rename to gnovm/tests/files/for6.gno diff --git a/gnovm/tests/files.bak/files/for7.gno b/gnovm/tests/files/for7.gno similarity index 100% rename from gnovm/tests/files.bak/files/for7.gno rename to gnovm/tests/files/for7.gno diff --git a/gnovm/tests/files.bak/files/for8.gno b/gnovm/tests/files/for8.gno similarity index 100% rename from gnovm/tests/files.bak/files/for8.gno rename to gnovm/tests/files/for8.gno diff --git a/gnovm/tests/files.bak/files/for9.gno b/gnovm/tests/files/for9.gno similarity index 100% rename from gnovm/tests/files.bak/files/for9.gno rename to gnovm/tests/files/for9.gno diff --git a/gnovm/tests/files.bak/files/fun.gno b/gnovm/tests/files/fun.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun.gno rename to gnovm/tests/files/fun.gno diff --git a/gnovm/tests/files.bak/files/fun10.gno b/gnovm/tests/files/fun10.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun10.gno rename to gnovm/tests/files/fun10.gno diff --git a/gnovm/tests/files.bak/files/fun11.gno b/gnovm/tests/files/fun11.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun11.gno rename to gnovm/tests/files/fun11.gno diff --git a/gnovm/tests/files.bak/files/fun12.gno b/gnovm/tests/files/fun12.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun12.gno rename to gnovm/tests/files/fun12.gno diff --git a/gnovm/tests/files.bak/files/fun13.gno b/gnovm/tests/files/fun13.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun13.gno rename to gnovm/tests/files/fun13.gno diff --git a/gnovm/tests/files.bak/files/fun14.gno b/gnovm/tests/files/fun14.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun14.gno rename to gnovm/tests/files/fun14.gno diff --git a/gnovm/tests/files.bak/files/fun15.gno b/gnovm/tests/files/fun15.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun15.gno rename to gnovm/tests/files/fun15.gno diff --git a/gnovm/tests/files.bak/files/fun16.gno b/gnovm/tests/files/fun16.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun16.gno rename to gnovm/tests/files/fun16.gno diff --git a/gnovm/tests/files.bak/files/fun17.gno b/gnovm/tests/files/fun17.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun17.gno rename to gnovm/tests/files/fun17.gno diff --git a/gnovm/tests/files.bak/files/fun18.gno b/gnovm/tests/files/fun18.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun18.gno rename to gnovm/tests/files/fun18.gno diff --git a/gnovm/tests/files.bak/files/fun19b.gno b/gnovm/tests/files/fun19b.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun19b.gno rename to gnovm/tests/files/fun19b.gno diff --git a/gnovm/tests/files.bak/files/fun2.gno b/gnovm/tests/files/fun2.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun2.gno rename to gnovm/tests/files/fun2.gno diff --git a/gnovm/tests/files.bak/files/fun20b.gno b/gnovm/tests/files/fun20b.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun20b.gno rename to gnovm/tests/files/fun20b.gno diff --git a/gnovm/tests/files.bak/files/fun21.gno b/gnovm/tests/files/fun21.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun21.gno rename to gnovm/tests/files/fun21.gno diff --git a/gnovm/tests/files.bak/files/fun22.gno b/gnovm/tests/files/fun22.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun22.gno rename to gnovm/tests/files/fun22.gno diff --git a/gnovm/tests/files.bak/files/fun23.gno b/gnovm/tests/files/fun23.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun23.gno rename to gnovm/tests/files/fun23.gno diff --git a/gnovm/tests/files.bak/files/fun24.gno b/gnovm/tests/files/fun24.gno similarity index 61% rename from gnovm/tests/files.bak/files/fun24.gno rename to gnovm/tests/files/fun24.gno index 42468ff087e..100d3c26ded 100644 --- a/gnovm/tests/files.bak/files/fun24.gno +++ b/gnovm/tests/files/fun24.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/fun24.gno:3: cannot convert StringKind to IntKind +// main/files/fun24.gno:3: cannot use untyped string as IntKind diff --git a/gnovm/tests/files.bak/files/fun25.gno b/gnovm/tests/files/fun25.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun25.gno rename to gnovm/tests/files/fun25.gno diff --git a/gnovm/tests/files.bak/files/fun26.gno b/gnovm/tests/files/fun26.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun26.gno rename to gnovm/tests/files/fun26.gno diff --git a/gnovm/tests/files.bak/files/fun3.gno b/gnovm/tests/files/fun3.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun3.gno rename to gnovm/tests/files/fun3.gno diff --git a/gnovm/tests/files.bak/files/fun4.gno b/gnovm/tests/files/fun4.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun4.gno rename to gnovm/tests/files/fun4.gno diff --git a/gnovm/tests/files.bak/files/fun5.gno b/gnovm/tests/files/fun5.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun5.gno rename to gnovm/tests/files/fun5.gno diff --git a/gnovm/tests/files.bak/files/fun6.gno b/gnovm/tests/files/fun6.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun6.gno rename to gnovm/tests/files/fun6.gno diff --git a/gnovm/tests/files.bak/files/fun6b.gno b/gnovm/tests/files/fun6b.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun6b.gno rename to gnovm/tests/files/fun6b.gno diff --git a/gnovm/tests/files.bak/files/fun7.gno b/gnovm/tests/files/fun7.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun7.gno rename to gnovm/tests/files/fun7.gno diff --git a/gnovm/tests/files.bak/files/fun8.gno b/gnovm/tests/files/fun8.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun8.gno rename to gnovm/tests/files/fun8.gno diff --git a/gnovm/tests/files.bak/files/fun9.gno b/gnovm/tests/files/fun9.gno similarity index 100% rename from gnovm/tests/files.bak/files/fun9.gno rename to gnovm/tests/files/fun9.gno diff --git a/gnovm/tests/files.bak/files/goto0.gno b/gnovm/tests/files/goto0.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto0.gno rename to gnovm/tests/files/goto0.gno diff --git a/gnovm/tests/files.bak/files/goto1.gno b/gnovm/tests/files/goto1.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto1.gno rename to gnovm/tests/files/goto1.gno diff --git a/gnovm/tests/files.bak/files/goto2.gno b/gnovm/tests/files/goto2.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto2.gno rename to gnovm/tests/files/goto2.gno diff --git a/gnovm/tests/files.bak/files/goto3.gno b/gnovm/tests/files/goto3.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto3.gno rename to gnovm/tests/files/goto3.gno diff --git a/gnovm/tests/files.bak/files/goto3a.gno b/gnovm/tests/files/goto3a.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto3a.gno rename to gnovm/tests/files/goto3a.gno diff --git a/gnovm/tests/files.bak/files/goto4.gno b/gnovm/tests/files/goto4.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto4.gno rename to gnovm/tests/files/goto4.gno diff --git a/gnovm/tests/files.bak/files/goto5.gno b/gnovm/tests/files/goto5.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto5.gno rename to gnovm/tests/files/goto5.gno diff --git a/gnovm/tests/files.bak/files/goto6.gno b/gnovm/tests/files/goto6.gno similarity index 100% rename from gnovm/tests/files.bak/files/goto6.gno rename to gnovm/tests/files/goto6.gno diff --git a/gnovm/tests/files.bak/files/if.gno b/gnovm/tests/files/if.gno similarity index 100% rename from gnovm/tests/files.bak/files/if.gno rename to gnovm/tests/files/if.gno diff --git a/gnovm/tests/files.bak/files/if0.gno b/gnovm/tests/files/if0.gno similarity index 100% rename from gnovm/tests/files.bak/files/if0.gno rename to gnovm/tests/files/if0.gno diff --git a/gnovm/tests/files.bak/files/if1.gno b/gnovm/tests/files/if1.gno similarity index 100% rename from gnovm/tests/files.bak/files/if1.gno rename to gnovm/tests/files/if1.gno diff --git a/gnovm/tests/files.bak/files/if2.gno b/gnovm/tests/files/if2.gno similarity index 100% rename from gnovm/tests/files.bak/files/if2.gno rename to gnovm/tests/files/if2.gno diff --git a/gnovm/tests/files.bak/files/if3.gno b/gnovm/tests/files/if3.gno similarity index 100% rename from gnovm/tests/files.bak/files/if3.gno rename to gnovm/tests/files/if3.gno diff --git a/gnovm/tests/files.bak/files/if4.gno b/gnovm/tests/files/if4.gno similarity index 100% rename from gnovm/tests/files.bak/files/if4.gno rename to gnovm/tests/files/if4.gno diff --git a/gnovm/tests/files.bak/files/if5.gno b/gnovm/tests/files/if5.gno similarity index 100% rename from gnovm/tests/files.bak/files/if5.gno rename to gnovm/tests/files/if5.gno diff --git a/gnovm/tests/files.bak/files/if6.gno b/gnovm/tests/files/if6.gno similarity index 100% rename from gnovm/tests/files.bak/files/if6.gno rename to gnovm/tests/files/if6.gno diff --git a/gnovm/tests/files.bak/files/if7.gno b/gnovm/tests/files/if7.gno similarity index 100% rename from gnovm/tests/files.bak/files/if7.gno rename to gnovm/tests/files/if7.gno diff --git a/gnovm/tests/files.bak/files/import0.gno b/gnovm/tests/files/import0.gno similarity index 100% rename from gnovm/tests/files.bak/files/import0.gno rename to gnovm/tests/files/import0.gno diff --git a/gnovm/tests/files.bak/files/import1.gno b/gnovm/tests/files/import1.gno similarity index 100% rename from gnovm/tests/files.bak/files/import1.gno rename to gnovm/tests/files/import1.gno diff --git a/gnovm/tests/files.bak/files/import10.gno b/gnovm/tests/files/import10.gno similarity index 100% rename from gnovm/tests/files.bak/files/import10.gno rename to gnovm/tests/files/import10.gno diff --git a/gnovm/tests/files.bak/files/import3.gno b/gnovm/tests/files/import3.gno similarity index 100% rename from gnovm/tests/files.bak/files/import3.gno rename to gnovm/tests/files/import3.gno diff --git a/gnovm/tests/files.bak/files/import4.gno b/gnovm/tests/files/import4.gno similarity index 100% rename from gnovm/tests/files.bak/files/import4.gno rename to gnovm/tests/files/import4.gno diff --git a/gnovm/tests/files.bak/files/import5.gno b/gnovm/tests/files/import5.gno similarity index 100% rename from gnovm/tests/files.bak/files/import5.gno rename to gnovm/tests/files/import5.gno diff --git a/gnovm/tests/files.bak/files/import6.gno b/gnovm/tests/files/import6.gno similarity index 100% rename from gnovm/tests/files.bak/files/import6.gno rename to gnovm/tests/files/import6.gno diff --git a/gnovm/tests/files.bak/files/import7.gno b/gnovm/tests/files/import7.gno similarity index 100% rename from gnovm/tests/files.bak/files/import7.gno rename to gnovm/tests/files/import7.gno diff --git a/gnovm/tests/files.bak/files/import8.gno b/gnovm/tests/files/import8.gno similarity index 100% rename from gnovm/tests/files.bak/files/import8.gno rename to gnovm/tests/files/import8.gno diff --git a/gnovm/tests/files.bak/files/import9.gno b/gnovm/tests/files/import9.gno similarity index 100% rename from gnovm/tests/files.bak/files/import9.gno rename to gnovm/tests/files/import9.gno diff --git a/gnovm/tests/files.bak/files/inc.gno b/gnovm/tests/files/inc.gno similarity index 100% rename from gnovm/tests/files.bak/files/inc.gno rename to gnovm/tests/files/inc.gno diff --git a/gnovm/tests/files.bak/files/index0.gno b/gnovm/tests/files/index0.gno similarity index 100% rename from gnovm/tests/files.bak/files/index0.gno rename to gnovm/tests/files/index0.gno diff --git a/gnovm/tests/files.bak/files/init0.gno b/gnovm/tests/files/init0.gno similarity index 100% rename from gnovm/tests/files.bak/files/init0.gno rename to gnovm/tests/files/init0.gno diff --git a/gnovm/tests/files.bak/files/init1.gno b/gnovm/tests/files/init1.gno similarity index 100% rename from gnovm/tests/files.bak/files/init1.gno rename to gnovm/tests/files/init1.gno diff --git a/gnovm/tests/files.bak/files/interface0.gno b/gnovm/tests/files/interface0.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface0.gno rename to gnovm/tests/files/interface0.gno diff --git a/gnovm/tests/files.bak/files/interface1.gno b/gnovm/tests/files/interface1.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface1.gno rename to gnovm/tests/files/interface1.gno diff --git a/gnovm/tests/files.bak/files/interface10.gno b/gnovm/tests/files/interface10.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface10.gno rename to gnovm/tests/files/interface10.gno diff --git a/gnovm/tests/files.bak/files/interface11.gno b/gnovm/tests/files/interface11.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface11.gno rename to gnovm/tests/files/interface11.gno diff --git a/gnovm/tests/files.bak/files/interface12.gno b/gnovm/tests/files/interface12.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface12.gno rename to gnovm/tests/files/interface12.gno diff --git a/gnovm/tests/files.bak/files/interface13.gno b/gnovm/tests/files/interface13.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface13.gno rename to gnovm/tests/files/interface13.gno diff --git a/gnovm/tests/files.bak/files/interface14.gno b/gnovm/tests/files/interface14.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface14.gno rename to gnovm/tests/files/interface14.gno diff --git a/gnovm/tests/files.bak/files/interface15.gno b/gnovm/tests/files/interface15.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface15.gno rename to gnovm/tests/files/interface15.gno diff --git a/gnovm/tests/files.bak/files/interface16.gno b/gnovm/tests/files/interface16.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface16.gno rename to gnovm/tests/files/interface16.gno diff --git a/gnovm/tests/files.bak/files/interface17.gno b/gnovm/tests/files/interface17.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface17.gno rename to gnovm/tests/files/interface17.gno diff --git a/gnovm/tests/files.bak/files/interface18.gno b/gnovm/tests/files/interface18.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface18.gno rename to gnovm/tests/files/interface18.gno diff --git a/gnovm/tests/files.bak/files/interface19.gno b/gnovm/tests/files/interface19.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface19.gno rename to gnovm/tests/files/interface19.gno diff --git a/gnovm/tests/files.bak/files/interface2.gno b/gnovm/tests/files/interface2.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface2.gno rename to gnovm/tests/files/interface2.gno diff --git a/gnovm/tests/files.bak/files/interface20.gno b/gnovm/tests/files/interface20.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface20.gno rename to gnovm/tests/files/interface20.gno diff --git a/gnovm/tests/files.bak/files/interface21.gno b/gnovm/tests/files/interface21.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface21.gno rename to gnovm/tests/files/interface21.gno diff --git a/gnovm/tests/files.bak/files/interface22.gno b/gnovm/tests/files/interface22.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface22.gno rename to gnovm/tests/files/interface22.gno diff --git a/gnovm/tests/files.bak/files/interface23.gno b/gnovm/tests/files/interface23.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface23.gno rename to gnovm/tests/files/interface23.gno diff --git a/gnovm/tests/files.bak/files/interface24.gno b/gnovm/tests/files/interface24.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface24.gno rename to gnovm/tests/files/interface24.gno diff --git a/gnovm/tests/files.bak/files/interface25.gno b/gnovm/tests/files/interface25.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface25.gno rename to gnovm/tests/files/interface25.gno diff --git a/gnovm/tests/files.bak/files/interface26.gno b/gnovm/tests/files/interface26.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface26.gno rename to gnovm/tests/files/interface26.gno diff --git a/gnovm/tests/files.bak/files/interface27b.gno b/gnovm/tests/files/interface27b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface27b.gno rename to gnovm/tests/files/interface27b.gno diff --git a/gnovm/tests/files.bak/files/interface28b.gno b/gnovm/tests/files/interface28b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface28b.gno rename to gnovm/tests/files/interface28b.gno diff --git a/gnovm/tests/files.bak/files/interface29.gno b/gnovm/tests/files/interface29.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface29.gno rename to gnovm/tests/files/interface29.gno diff --git a/gnovm/tests/files.bak/files/interface3.gno b/gnovm/tests/files/interface3.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface3.gno rename to gnovm/tests/files/interface3.gno diff --git a/gnovm/tests/files.bak/files/interface30.gno b/gnovm/tests/files/interface30.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface30.gno rename to gnovm/tests/files/interface30.gno diff --git a/gnovm/tests/files.bak/files/interface31.gno b/gnovm/tests/files/interface31.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface31.gno rename to gnovm/tests/files/interface31.gno diff --git a/gnovm/tests/files.bak/files/interface32.gno b/gnovm/tests/files/interface32.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface32.gno rename to gnovm/tests/files/interface32.gno diff --git a/gnovm/tests/files.bak/files/interface33.gno b/gnovm/tests/files/interface33.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface33.gno rename to gnovm/tests/files/interface33.gno diff --git a/gnovm/tests/files.bak/files/interface34.gno b/gnovm/tests/files/interface34.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface34.gno rename to gnovm/tests/files/interface34.gno diff --git a/gnovm/tests/files.bak/files/interface35.gno b/gnovm/tests/files/interface35.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface35.gno rename to gnovm/tests/files/interface35.gno diff --git a/gnovm/tests/files.bak/files/interface36.gno b/gnovm/tests/files/interface36.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface36.gno rename to gnovm/tests/files/interface36.gno diff --git a/gnovm/tests/files.bak/files/interface37.gno b/gnovm/tests/files/interface37.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface37.gno rename to gnovm/tests/files/interface37.gno diff --git a/gnovm/tests/files.bak/files/interface38b.gno b/gnovm/tests/files/interface38b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface38b.gno rename to gnovm/tests/files/interface38b.gno diff --git a/gnovm/tests/files.bak/files/interface39b.gno b/gnovm/tests/files/interface39b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface39b.gno rename to gnovm/tests/files/interface39b.gno diff --git a/gnovm/tests/files.bak/files/interface4.gno b/gnovm/tests/files/interface4.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface4.gno rename to gnovm/tests/files/interface4.gno diff --git a/gnovm/tests/files.bak/files/interface40b.gno b/gnovm/tests/files/interface40b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface40b.gno rename to gnovm/tests/files/interface40b.gno diff --git a/gnovm/tests/files.bak/files/interface41b.gno b/gnovm/tests/files/interface41b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface41b.gno rename to gnovm/tests/files/interface41b.gno diff --git a/gnovm/tests/files.bak/files/interface42.gno b/gnovm/tests/files/interface42.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface42.gno rename to gnovm/tests/files/interface42.gno diff --git a/gnovm/tests/files.bak/files/interface43.gno b/gnovm/tests/files/interface43.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface43.gno rename to gnovm/tests/files/interface43.gno diff --git a/gnovm/tests/files.bak/files/interface44.gno b/gnovm/tests/files/interface44.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface44.gno rename to gnovm/tests/files/interface44.gno diff --git a/gnovm/tests/files.bak/files/interface45.gno b/gnovm/tests/files/interface45.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface45.gno rename to gnovm/tests/files/interface45.gno diff --git a/gnovm/tests/files.bak/files/interface46.gno b/gnovm/tests/files/interface46.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface46.gno rename to gnovm/tests/files/interface46.gno diff --git a/gnovm/tests/files.bak/files/interface5.gno b/gnovm/tests/files/interface5.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface5.gno rename to gnovm/tests/files/interface5.gno diff --git a/gnovm/tests/files.bak/files/interface6.gno b/gnovm/tests/files/interface6.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface6.gno rename to gnovm/tests/files/interface6.gno diff --git a/gnovm/tests/files.bak/files/interface7b.gno b/gnovm/tests/files/interface7b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface7b.gno rename to gnovm/tests/files/interface7b.gno diff --git a/gnovm/tests/files.bak/files/interface8.gno b/gnovm/tests/files/interface8.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface8.gno rename to gnovm/tests/files/interface8.gno diff --git a/gnovm/tests/files.bak/files/interface9b.gno b/gnovm/tests/files/interface9b.gno similarity index 100% rename from gnovm/tests/files.bak/files/interface9b.gno rename to gnovm/tests/files/interface9b.gno diff --git a/gnovm/tests/files.bak/files/interp.gi b/gnovm/tests/files/interp.gi similarity index 100% rename from gnovm/tests/files.bak/files/interp.gi rename to gnovm/tests/files/interp.gi diff --git a/gnovm/tests/files.bak/files/interp2.gi b/gnovm/tests/files/interp2.gi similarity index 100% rename from gnovm/tests/files.bak/files/interp2.gi rename to gnovm/tests/files/interp2.gi diff --git a/gnovm/tests/files.bak/files/io0_native.gno b/gnovm/tests/files/io0_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/io0_native.gno rename to gnovm/tests/files/io0_native.gno diff --git a/gnovm/tests/files.bak/files/io0_stdlibs.gno b/gnovm/tests/files/io0_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/io0_stdlibs.gno rename to gnovm/tests/files/io0_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/io1.gno b/gnovm/tests/files/io1.gno similarity index 100% rename from gnovm/tests/files.bak/files/io1.gno rename to gnovm/tests/files/io1.gno diff --git a/gnovm/tests/files.bak/files/io2.gno b/gnovm/tests/files/io2.gno similarity index 100% rename from gnovm/tests/files.bak/files/io2.gno rename to gnovm/tests/files/io2.gno diff --git a/gnovm/tests/files.bak/files/iota.gno b/gnovm/tests/files/iota.gno similarity index 100% rename from gnovm/tests/files.bak/files/iota.gno rename to gnovm/tests/files/iota.gno diff --git a/gnovm/tests/files.bak/files/iota0.gno b/gnovm/tests/files/iota0.gno similarity index 100% rename from gnovm/tests/files.bak/files/iota0.gno rename to gnovm/tests/files/iota0.gno diff --git a/gnovm/tests/files.bak/files/ipp_as_key.gno b/gnovm/tests/files/ipp_as_key.gno similarity index 100% rename from gnovm/tests/files.bak/files/ipp_as_key.gno rename to gnovm/tests/files/ipp_as_key.gno diff --git a/gnovm/tests/files.bak/files/issue-1096.gno b/gnovm/tests/files/issue-1096.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-1096.gno rename to gnovm/tests/files/issue-1096.gno diff --git a/gnovm/tests/files.bak/files/issue-558b.gno b/gnovm/tests/files/issue-558b.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-558b.gno rename to gnovm/tests/files/issue-558b.gno diff --git a/gnovm/tests/files.bak/files/issue-735.gno b/gnovm/tests/files/issue-735.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-735.gno rename to gnovm/tests/files/issue-735.gno diff --git a/gnovm/tests/files.bak/files/issue-776.gno b/gnovm/tests/files/issue-776.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-776.gno rename to gnovm/tests/files/issue-776.gno diff --git a/gnovm/tests/files.bak/files/issue-782.gno b/gnovm/tests/files/issue-782.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-782.gno rename to gnovm/tests/files/issue-782.gno diff --git a/gnovm/tests/files.bak/files/issue-784.gno b/gnovm/tests/files/issue-784.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-784.gno rename to gnovm/tests/files/issue-784.gno diff --git a/gnovm/tests/files.bak/files/issue-880.gno b/gnovm/tests/files/issue-880.gno similarity index 100% rename from gnovm/tests/files.bak/files/issue-880.gno rename to gnovm/tests/files/issue-880.gno diff --git a/gnovm/tests/files.bak/files/l2_long.gno b/gnovm/tests/files/l2_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/l2_long.gno rename to gnovm/tests/files/l2_long.gno diff --git a/gnovm/tests/files.bak/files/l3_long.gno b/gnovm/tests/files/l3_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/l3_long.gno rename to gnovm/tests/files/l3_long.gno diff --git a/gnovm/tests/files.bak/files/l4_long.gno b/gnovm/tests/files/l4_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/l4_long.gno rename to gnovm/tests/files/l4_long.gno diff --git a/gnovm/tests/files.bak/files/l5_long.gno b/gnovm/tests/files/l5_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/l5_long.gno rename to gnovm/tests/files/l5_long.gno diff --git a/gnovm/tests/files.bak/files/len0.gno b/gnovm/tests/files/len0.gno similarity index 100% rename from gnovm/tests/files.bak/files/len0.gno rename to gnovm/tests/files/len0.gno diff --git a/gnovm/tests/files.bak/files/make0.gno b/gnovm/tests/files/make0.gno similarity index 100% rename from gnovm/tests/files.bak/files/make0.gno rename to gnovm/tests/files/make0.gno diff --git a/gnovm/tests/files.bak/files/make1.gno b/gnovm/tests/files/make1.gno similarity index 100% rename from gnovm/tests/files.bak/files/make1.gno rename to gnovm/tests/files/make1.gno diff --git a/gnovm/tests/files.bak/files/make2.gno b/gnovm/tests/files/make2.gno similarity index 100% rename from gnovm/tests/files.bak/files/make2.gno rename to gnovm/tests/files/make2.gno diff --git a/gnovm/tests/files.bak/files/map.gno b/gnovm/tests/files/map.gno similarity index 100% rename from gnovm/tests/files.bak/files/map.gno rename to gnovm/tests/files/map.gno diff --git a/gnovm/tests/files.bak/files/map0.gno b/gnovm/tests/files/map0.gno similarity index 100% rename from gnovm/tests/files.bak/files/map0.gno rename to gnovm/tests/files/map0.gno diff --git a/gnovm/tests/files.bak/files/map1.gno b/gnovm/tests/files/map1.gno similarity index 100% rename from gnovm/tests/files.bak/files/map1.gno rename to gnovm/tests/files/map1.gno diff --git a/gnovm/tests/files.bak/files/map10.gno b/gnovm/tests/files/map10.gno similarity index 100% rename from gnovm/tests/files.bak/files/map10.gno rename to gnovm/tests/files/map10.gno diff --git a/gnovm/tests/files.bak/files/map11.gno b/gnovm/tests/files/map11.gno similarity index 100% rename from gnovm/tests/files.bak/files/map11.gno rename to gnovm/tests/files/map11.gno diff --git a/gnovm/tests/files.bak/files/map12.gno b/gnovm/tests/files/map12.gno similarity index 100% rename from gnovm/tests/files.bak/files/map12.gno rename to gnovm/tests/files/map12.gno diff --git a/gnovm/tests/files.bak/files/map13.gno b/gnovm/tests/files/map13.gno similarity index 100% rename from gnovm/tests/files.bak/files/map13.gno rename to gnovm/tests/files/map13.gno diff --git a/gnovm/tests/files.bak/files/map14b.gno b/gnovm/tests/files/map14b.gno similarity index 100% rename from gnovm/tests/files.bak/files/map14b.gno rename to gnovm/tests/files/map14b.gno diff --git a/gnovm/tests/files.bak/files/map15.gno b/gnovm/tests/files/map15.gno similarity index 100% rename from gnovm/tests/files.bak/files/map15.gno rename to gnovm/tests/files/map15.gno diff --git a/gnovm/tests/files.bak/files/map16.gno b/gnovm/tests/files/map16.gno similarity index 100% rename from gnovm/tests/files.bak/files/map16.gno rename to gnovm/tests/files/map16.gno diff --git a/gnovm/tests/files.bak/files/map17.gno b/gnovm/tests/files/map17.gno similarity index 100% rename from gnovm/tests/files.bak/files/map17.gno rename to gnovm/tests/files/map17.gno diff --git a/gnovm/tests/files.bak/files/map18.gno b/gnovm/tests/files/map18.gno similarity index 100% rename from gnovm/tests/files.bak/files/map18.gno rename to gnovm/tests/files/map18.gno diff --git a/gnovm/tests/files.bak/files/map19b.gno b/gnovm/tests/files/map19b.gno similarity index 100% rename from gnovm/tests/files.bak/files/map19b.gno rename to gnovm/tests/files/map19b.gno diff --git a/gnovm/tests/files.bak/files/map2.gno b/gnovm/tests/files/map2.gno similarity index 100% rename from gnovm/tests/files.bak/files/map2.gno rename to gnovm/tests/files/map2.gno diff --git a/gnovm/tests/files.bak/files/map20.gno b/gnovm/tests/files/map20.gno similarity index 100% rename from gnovm/tests/files.bak/files/map20.gno rename to gnovm/tests/files/map20.gno diff --git a/gnovm/tests/files.bak/files/map21.gno b/gnovm/tests/files/map21.gno similarity index 100% rename from gnovm/tests/files.bak/files/map21.gno rename to gnovm/tests/files/map21.gno diff --git a/gnovm/tests/files.bak/files/map22.gno b/gnovm/tests/files/map22.gno similarity index 100% rename from gnovm/tests/files.bak/files/map22.gno rename to gnovm/tests/files/map22.gno diff --git a/gnovm/tests/files.bak/files/map23.gno b/gnovm/tests/files/map23.gno similarity index 100% rename from gnovm/tests/files.bak/files/map23.gno rename to gnovm/tests/files/map23.gno diff --git a/gnovm/tests/files.bak/files/map24.gno b/gnovm/tests/files/map24.gno similarity index 100% rename from gnovm/tests/files.bak/files/map24.gno rename to gnovm/tests/files/map24.gno diff --git a/gnovm/tests/files.bak/files/map25.gno b/gnovm/tests/files/map25.gno similarity index 100% rename from gnovm/tests/files.bak/files/map25.gno rename to gnovm/tests/files/map25.gno diff --git a/gnovm/tests/files.bak/files/map26.gno b/gnovm/tests/files/map26.gno similarity index 100% rename from gnovm/tests/files.bak/files/map26.gno rename to gnovm/tests/files/map26.gno diff --git a/gnovm/tests/files.bak/files/map27.gno b/gnovm/tests/files/map27.gno similarity index 100% rename from gnovm/tests/files.bak/files/map27.gno rename to gnovm/tests/files/map27.gno diff --git a/gnovm/tests/files.bak/files/map28b.gno b/gnovm/tests/files/map28b.gno similarity index 100% rename from gnovm/tests/files.bak/files/map28b.gno rename to gnovm/tests/files/map28b.gno diff --git a/gnovm/tests/files.bak/files/map28c.gno b/gnovm/tests/files/map28c.gno similarity index 100% rename from gnovm/tests/files.bak/files/map28c.gno rename to gnovm/tests/files/map28c.gno diff --git a/gnovm/tests/files.bak/files/map29_native.gno b/gnovm/tests/files/map29_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/map29_native.gno rename to gnovm/tests/files/map29_native.gno diff --git a/gnovm/tests/files.bak/files/map29_stdlibs.gno b/gnovm/tests/files/map29_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/map29_stdlibs.gno rename to gnovm/tests/files/map29_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/map3.gno b/gnovm/tests/files/map3.gno similarity index 100% rename from gnovm/tests/files.bak/files/map3.gno rename to gnovm/tests/files/map3.gno diff --git a/gnovm/tests/files.bak/files/map4.gno b/gnovm/tests/files/map4.gno similarity index 100% rename from gnovm/tests/files.bak/files/map4.gno rename to gnovm/tests/files/map4.gno diff --git a/gnovm/tests/files.bak/files/map5.gno b/gnovm/tests/files/map5.gno similarity index 100% rename from gnovm/tests/files.bak/files/map5.gno rename to gnovm/tests/files/map5.gno diff --git a/gnovm/tests/files.bak/files/map6.gno b/gnovm/tests/files/map6.gno similarity index 100% rename from gnovm/tests/files.bak/files/map6.gno rename to gnovm/tests/files/map6.gno diff --git a/gnovm/tests/files.bak/files/map7.gno b/gnovm/tests/files/map7.gno similarity index 100% rename from gnovm/tests/files.bak/files/map7.gno rename to gnovm/tests/files/map7.gno diff --git a/gnovm/tests/files.bak/files/map8.gno b/gnovm/tests/files/map8.gno similarity index 100% rename from gnovm/tests/files.bak/files/map8.gno rename to gnovm/tests/files/map8.gno diff --git a/gnovm/tests/files.bak/files/map9.gno b/gnovm/tests/files/map9.gno similarity index 100% rename from gnovm/tests/files.bak/files/map9.gno rename to gnovm/tests/files/map9.gno diff --git a/gnovm/tests/files.bak/files/math0_native.gno b/gnovm/tests/files/math0_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/math0_native.gno rename to gnovm/tests/files/math0_native.gno diff --git a/gnovm/tests/files.bak/files/math0_stdlibs.gno b/gnovm/tests/files/math0_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/math0_stdlibs.gno rename to gnovm/tests/files/math0_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/math2.gno b/gnovm/tests/files/math2.gno similarity index 100% rename from gnovm/tests/files.bak/files/math2.gno rename to gnovm/tests/files/math2.gno diff --git a/gnovm/tests/files.bak/files/math3.gno b/gnovm/tests/files/math3.gno similarity index 100% rename from gnovm/tests/files.bak/files/math3.gno rename to gnovm/tests/files/math3.gno diff --git a/gnovm/tests/files.bak/files/maths_int16_long.gno b/gnovm/tests/files/maths_int16_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/maths_int16_long.gno rename to gnovm/tests/files/maths_int16_long.gno diff --git a/gnovm/tests/files.bak/files/maths_int8.gno b/gnovm/tests/files/maths_int8.gno similarity index 100% rename from gnovm/tests/files.bak/files/maths_int8.gno rename to gnovm/tests/files/maths_int8.gno diff --git a/gnovm/tests/files.bak/files/method.gno b/gnovm/tests/files/method.gno similarity index 100% rename from gnovm/tests/files.bak/files/method.gno rename to gnovm/tests/files/method.gno diff --git a/gnovm/tests/files.bak/files/method0.gno b/gnovm/tests/files/method0.gno similarity index 100% rename from gnovm/tests/files.bak/files/method0.gno rename to gnovm/tests/files/method0.gno diff --git a/gnovm/tests/files.bak/files/method1.gno b/gnovm/tests/files/method1.gno similarity index 100% rename from gnovm/tests/files.bak/files/method1.gno rename to gnovm/tests/files/method1.gno diff --git a/gnovm/tests/files.bak/files/method10.gno b/gnovm/tests/files/method10.gno similarity index 100% rename from gnovm/tests/files.bak/files/method10.gno rename to gnovm/tests/files/method10.gno diff --git a/gnovm/tests/files.bak/files/method11.gno b/gnovm/tests/files/method11.gno similarity index 100% rename from gnovm/tests/files.bak/files/method11.gno rename to gnovm/tests/files/method11.gno diff --git a/gnovm/tests/files.bak/files/method12.gno b/gnovm/tests/files/method12.gno similarity index 100% rename from gnovm/tests/files.bak/files/method12.gno rename to gnovm/tests/files/method12.gno diff --git a/gnovm/tests/files.bak/files/method13.gno b/gnovm/tests/files/method13.gno similarity index 100% rename from gnovm/tests/files.bak/files/method13.gno rename to gnovm/tests/files/method13.gno diff --git a/gnovm/tests/files.bak/files/method14.gno b/gnovm/tests/files/method14.gno similarity index 100% rename from gnovm/tests/files.bak/files/method14.gno rename to gnovm/tests/files/method14.gno diff --git a/gnovm/tests/files.bak/files/method15.gno b/gnovm/tests/files/method15.gno similarity index 100% rename from gnovm/tests/files.bak/files/method15.gno rename to gnovm/tests/files/method15.gno diff --git a/gnovm/tests/files.bak/files/method16b.gno b/gnovm/tests/files/method16b.gno similarity index 100% rename from gnovm/tests/files.bak/files/method16b.gno rename to gnovm/tests/files/method16b.gno diff --git a/gnovm/tests/files.bak/files/method17b.gno b/gnovm/tests/files/method17b.gno similarity index 100% rename from gnovm/tests/files.bak/files/method17b.gno rename to gnovm/tests/files/method17b.gno diff --git a/gnovm/tests/files.bak/files/method18.gno b/gnovm/tests/files/method18.gno similarity index 100% rename from gnovm/tests/files.bak/files/method18.gno rename to gnovm/tests/files/method18.gno diff --git a/gnovm/tests/files.bak/files/method19.gno b/gnovm/tests/files/method19.gno similarity index 100% rename from gnovm/tests/files.bak/files/method19.gno rename to gnovm/tests/files/method19.gno diff --git a/gnovm/tests/files.bak/files/method2.gno b/gnovm/tests/files/method2.gno similarity index 100% rename from gnovm/tests/files.bak/files/method2.gno rename to gnovm/tests/files/method2.gno diff --git a/gnovm/tests/files.bak/files/method20.gno b/gnovm/tests/files/method20.gno similarity index 100% rename from gnovm/tests/files.bak/files/method20.gno rename to gnovm/tests/files/method20.gno diff --git a/gnovm/tests/files.bak/files/method21.gno b/gnovm/tests/files/method21.gno similarity index 100% rename from gnovm/tests/files.bak/files/method21.gno rename to gnovm/tests/files/method21.gno diff --git a/gnovm/tests/files.bak/files/method22.gno b/gnovm/tests/files/method22.gno similarity index 100% rename from gnovm/tests/files.bak/files/method22.gno rename to gnovm/tests/files/method22.gno diff --git a/gnovm/tests/files.bak/files/method23.gno b/gnovm/tests/files/method23.gno similarity index 100% rename from gnovm/tests/files.bak/files/method23.gno rename to gnovm/tests/files/method23.gno diff --git a/gnovm/tests/files.bak/files/method24.gno b/gnovm/tests/files/method24.gno similarity index 100% rename from gnovm/tests/files.bak/files/method24.gno rename to gnovm/tests/files/method24.gno diff --git a/gnovm/tests/files.bak/files/method25.gno b/gnovm/tests/files/method25.gno similarity index 100% rename from gnovm/tests/files.bak/files/method25.gno rename to gnovm/tests/files/method25.gno diff --git a/gnovm/tests/files.bak/files/method26.gno b/gnovm/tests/files/method26.gno similarity index 100% rename from gnovm/tests/files.bak/files/method26.gno rename to gnovm/tests/files/method26.gno diff --git a/gnovm/tests/files.bak/files/method27.gno b/gnovm/tests/files/method27.gno similarity index 100% rename from gnovm/tests/files.bak/files/method27.gno rename to gnovm/tests/files/method27.gno diff --git a/gnovm/tests/files.bak/files/method28.gno b/gnovm/tests/files/method28.gno similarity index 100% rename from gnovm/tests/files.bak/files/method28.gno rename to gnovm/tests/files/method28.gno diff --git a/gnovm/tests/files.bak/files/method29b.gno b/gnovm/tests/files/method29b.gno similarity index 100% rename from gnovm/tests/files.bak/files/method29b.gno rename to gnovm/tests/files/method29b.gno diff --git a/gnovm/tests/files.bak/files/method3.gno b/gnovm/tests/files/method3.gno similarity index 100% rename from gnovm/tests/files.bak/files/method3.gno rename to gnovm/tests/files/method3.gno diff --git a/gnovm/tests/files.bak/files/method30.gno b/gnovm/tests/files/method30.gno similarity index 100% rename from gnovm/tests/files.bak/files/method30.gno rename to gnovm/tests/files/method30.gno diff --git a/gnovm/tests/files.bak/files/method31b.gno b/gnovm/tests/files/method31b.gno similarity index 100% rename from gnovm/tests/files.bak/files/method31b.gno rename to gnovm/tests/files/method31b.gno diff --git a/gnovm/tests/files.bak/files/method32.gno b/gnovm/tests/files/method32.gno similarity index 100% rename from gnovm/tests/files.bak/files/method32.gno rename to gnovm/tests/files/method32.gno diff --git a/gnovm/tests/files.bak/files/method33.gno b/gnovm/tests/files/method33.gno similarity index 100% rename from gnovm/tests/files.bak/files/method33.gno rename to gnovm/tests/files/method33.gno diff --git a/gnovm/tests/files.bak/files/method34.gno b/gnovm/tests/files/method34.gno similarity index 100% rename from gnovm/tests/files.bak/files/method34.gno rename to gnovm/tests/files/method34.gno diff --git a/gnovm/tests/files.bak/files/method35.gno b/gnovm/tests/files/method35.gno similarity index 100% rename from gnovm/tests/files.bak/files/method35.gno rename to gnovm/tests/files/method35.gno diff --git a/gnovm/tests/files.bak/files/method36.gno b/gnovm/tests/files/method36.gno similarity index 100% rename from gnovm/tests/files.bak/files/method36.gno rename to gnovm/tests/files/method36.gno diff --git a/gnovm/tests/files.bak/files/method37.gno b/gnovm/tests/files/method37.gno similarity index 100% rename from gnovm/tests/files.bak/files/method37.gno rename to gnovm/tests/files/method37.gno diff --git a/gnovm/tests/files.bak/files/method4.gno b/gnovm/tests/files/method4.gno similarity index 100% rename from gnovm/tests/files.bak/files/method4.gno rename to gnovm/tests/files/method4.gno diff --git a/gnovm/tests/files.bak/files/method5.gno b/gnovm/tests/files/method5.gno similarity index 100% rename from gnovm/tests/files.bak/files/method5.gno rename to gnovm/tests/files/method5.gno diff --git a/gnovm/tests/files.bak/files/method6.gno b/gnovm/tests/files/method6.gno similarity index 100% rename from gnovm/tests/files.bak/files/method6.gno rename to gnovm/tests/files/method6.gno diff --git a/gnovm/tests/files.bak/files/method7.gno b/gnovm/tests/files/method7.gno similarity index 100% rename from gnovm/tests/files.bak/files/method7.gno rename to gnovm/tests/files/method7.gno diff --git a/gnovm/tests/files.bak/files/method8.gno b/gnovm/tests/files/method8.gno similarity index 100% rename from gnovm/tests/files.bak/files/method8.gno rename to gnovm/tests/files/method8.gno diff --git a/gnovm/tests/files.bak/files/method9.gno b/gnovm/tests/files/method9.gno similarity index 100% rename from gnovm/tests/files.bak/files/method9.gno rename to gnovm/tests/files/method9.gno diff --git a/gnovm/tests/files.bak/files/neg0.gno b/gnovm/tests/files/neg0.gno similarity index 100% rename from gnovm/tests/files.bak/files/neg0.gno rename to gnovm/tests/files/neg0.gno diff --git a/gnovm/tests/files.bak/files/new0.gno b/gnovm/tests/files/new0.gno similarity index 100% rename from gnovm/tests/files.bak/files/new0.gno rename to gnovm/tests/files/new0.gno diff --git a/gnovm/tests/files.bak/files/new1.gno b/gnovm/tests/files/new1.gno similarity index 100% rename from gnovm/tests/files.bak/files/new1.gno rename to gnovm/tests/files/new1.gno diff --git a/gnovm/tests/files.bak/files/new2.gno b/gnovm/tests/files/new2.gno similarity index 100% rename from gnovm/tests/files.bak/files/new2.gno rename to gnovm/tests/files/new2.gno diff --git a/gnovm/tests/files.bak/files/new3.gno b/gnovm/tests/files/new3.gno similarity index 100% rename from gnovm/tests/files.bak/files/new3.gno rename to gnovm/tests/files/new3.gno diff --git a/gnovm/tests/files.bak/files/nil0.gno b/gnovm/tests/files/nil0.gno similarity index 100% rename from gnovm/tests/files.bak/files/nil0.gno rename to gnovm/tests/files/nil0.gno diff --git a/gnovm/tests/files.bak/files/nil1.gno b/gnovm/tests/files/nil1.gno similarity index 100% rename from gnovm/tests/files.bak/files/nil1.gno rename to gnovm/tests/files/nil1.gno diff --git a/gnovm/tests/files.bak/files/nil2.gno b/gnovm/tests/files/nil2.gno similarity index 100% rename from gnovm/tests/files.bak/files/nil2.gno rename to gnovm/tests/files/nil2.gno diff --git a/gnovm/tests/files.bak/files/nil3.gno b/gnovm/tests/files/nil3.gno similarity index 100% rename from gnovm/tests/files.bak/files/nil3.gno rename to gnovm/tests/files/nil3.gno diff --git a/gnovm/tests/files.bak/files/not0.gno b/gnovm/tests/files/not0.gno similarity index 100% rename from gnovm/tests/files.bak/files/not0.gno rename to gnovm/tests/files/not0.gno diff --git a/gnovm/tests/files.bak/files/not1.gno b/gnovm/tests/files/not1.gno similarity index 100% rename from gnovm/tests/files.bak/files/not1.gno rename to gnovm/tests/files/not1.gno diff --git a/gnovm/tests/files.bak/files/not2.gno b/gnovm/tests/files/not2.gno similarity index 100% rename from gnovm/tests/files.bak/files/not2.gno rename to gnovm/tests/files/not2.gno diff --git a/gnovm/tests/files.bak/files/op0.gno b/gnovm/tests/files/op0.gno similarity index 100% rename from gnovm/tests/files.bak/files/op0.gno rename to gnovm/tests/files/op0.gno diff --git a/gnovm/tests/files.bak/files/op2.gno b/gnovm/tests/files/op2.gno similarity index 100% rename from gnovm/tests/files.bak/files/op2.gno rename to gnovm/tests/files/op2.gno diff --git a/gnovm/tests/files.bak/files/op6.gno b/gnovm/tests/files/op6.gno similarity index 100% rename from gnovm/tests/files.bak/files/op6.gno rename to gnovm/tests/files/op6.gno diff --git a/gnovm/tests/files.bak/files/op7.gno b/gnovm/tests/files/op7.gno similarity index 60% rename from gnovm/tests/files.bak/files/op7.gno rename to gnovm/tests/files/op7.gno index c92a567110d..519b69299d5 100644 --- a/gnovm/tests/files.bak/files/op7.gno +++ b/gnovm/tests/files/op7.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/op7.gno:11: incompatible types in binary expression: err GTR invalidT +// comparison operator > not defined for InterfaceKind diff --git a/gnovm/tests/files.bak/files/op8.gno b/gnovm/tests/files/op8.gno similarity index 100% rename from gnovm/tests/files.bak/files/op8.gno rename to gnovm/tests/files/op8.gno diff --git a/gnovm/tests/files.bak/files/opint16.gno b/gnovm/tests/files/opint16.gno similarity index 100% rename from gnovm/tests/files.bak/files/opint16.gno rename to gnovm/tests/files/opint16.gno diff --git a/gnovm/tests/files.bak/files/opint32.gno b/gnovm/tests/files/opint32.gno similarity index 100% rename from gnovm/tests/files.bak/files/opint32.gno rename to gnovm/tests/files/opint32.gno diff --git a/gnovm/tests/files.bak/files/opint64.gno b/gnovm/tests/files/opint64.gno similarity index 100% rename from gnovm/tests/files.bak/files/opint64.gno rename to gnovm/tests/files/opint64.gno diff --git a/gnovm/tests/files.bak/files/opint8.gno b/gnovm/tests/files/opint8.gno similarity index 100% rename from gnovm/tests/files.bak/files/opint8.gno rename to gnovm/tests/files/opint8.gno diff --git a/gnovm/tests/files.bak/files/opstring.gno b/gnovm/tests/files/opstring.gno similarity index 100% rename from gnovm/tests/files.bak/files/opstring.gno rename to gnovm/tests/files/opstring.gno diff --git a/gnovm/tests/files.bak/files/opuint16.gno b/gnovm/tests/files/opuint16.gno similarity index 100% rename from gnovm/tests/files.bak/files/opuint16.gno rename to gnovm/tests/files/opuint16.gno diff --git a/gnovm/tests/files.bak/files/opuint32.gno b/gnovm/tests/files/opuint32.gno similarity index 100% rename from gnovm/tests/files.bak/files/opuint32.gno rename to gnovm/tests/files/opuint32.gno diff --git a/gnovm/tests/files.bak/files/opuint64.gno b/gnovm/tests/files/opuint64.gno similarity index 100% rename from gnovm/tests/files.bak/files/opuint64.gno rename to gnovm/tests/files/opuint64.gno diff --git a/gnovm/tests/files.bak/files/opuint8.gno b/gnovm/tests/files/opuint8.gno similarity index 100% rename from gnovm/tests/files.bak/files/opuint8.gno rename to gnovm/tests/files/opuint8.gno diff --git a/gnovm/tests/files.bak/files/or0.gno b/gnovm/tests/files/or0.gno similarity index 100% rename from gnovm/tests/files.bak/files/or0.gno rename to gnovm/tests/files/or0.gno diff --git a/gnovm/tests/files.bak/files/or1.gno b/gnovm/tests/files/or1.gno similarity index 100% rename from gnovm/tests/files.bak/files/or1.gno rename to gnovm/tests/files/or1.gno diff --git a/gnovm/tests/files.bak/files/or2.gno b/gnovm/tests/files/or2.gno similarity index 100% rename from gnovm/tests/files.bak/files/or2.gno rename to gnovm/tests/files/or2.gno diff --git a/gnovm/tests/files.bak/files/or3.gno b/gnovm/tests/files/or3.gno similarity index 100% rename from gnovm/tests/files.bak/files/or3.gno rename to gnovm/tests/files/or3.gno diff --git a/gnovm/tests/files.bak/files/or4.gno b/gnovm/tests/files/or4.gno similarity index 100% rename from gnovm/tests/files.bak/files/or4.gno rename to gnovm/tests/files/or4.gno diff --git a/gnovm/tests/files.bak/files/panic0.gno b/gnovm/tests/files/panic0.gno similarity index 100% rename from gnovm/tests/files.bak/files/panic0.gno rename to gnovm/tests/files/panic0.gno diff --git a/gnovm/tests/files.bak/files/panic0b.gno b/gnovm/tests/files/panic0b.gno similarity index 100% rename from gnovm/tests/files.bak/files/panic0b.gno rename to gnovm/tests/files/panic0b.gno diff --git a/gnovm/tests/files.bak/files/persist_map.gno b/gnovm/tests/files/persist_map.gno.a similarity index 96% rename from gnovm/tests/files.bak/files/persist_map.gno rename to gnovm/tests/files/persist_map.gno.a index 53a1ad80f77..f062bf877ee 100644 --- a/gnovm/tests/files.bak/files/persist_map.gno +++ b/gnovm/tests/files/persist_map.gno.a @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/demo/tests_test -package tests_test +package main var amap map[string]string = map[string]string{"a": "1"} diff --git a/gnovm/tests/files.bak/files/pkgname0.gno b/gnovm/tests/files/pkgname0.gno similarity index 100% rename from gnovm/tests/files.bak/files/pkgname0.gno rename to gnovm/tests/files/pkgname0.gno diff --git a/gnovm/tests/files.bak/files/pkgname1.gno b/gnovm/tests/files/pkgname1.gno similarity index 100% rename from gnovm/tests/files.bak/files/pkgname1.gno rename to gnovm/tests/files/pkgname1.gno diff --git a/gnovm/tests/files.bak/files/pkgname2.gno b/gnovm/tests/files/pkgname2.gno similarity index 100% rename from gnovm/tests/files.bak/files/pkgname2.gno rename to gnovm/tests/files/pkgname2.gno diff --git a/gnovm/tests/files.bak/files/primes.gno b/gnovm/tests/files/primes.gno similarity index 100% rename from gnovm/tests/files.bak/files/primes.gno rename to gnovm/tests/files/primes.gno diff --git a/gnovm/tests/files.bak/files/print0.gno b/gnovm/tests/files/print0.gno similarity index 100% rename from gnovm/tests/files.bak/files/print0.gno rename to gnovm/tests/files/print0.gno diff --git a/gnovm/tests/files.bak/files/ptr0.gno b/gnovm/tests/files/ptr0.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr0.gno rename to gnovm/tests/files/ptr0.gno diff --git a/gnovm/tests/files.bak/files/ptr1.gno b/gnovm/tests/files/ptr1.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr1.gno rename to gnovm/tests/files/ptr1.gno diff --git a/gnovm/tests/files.bak/files/ptr2.gno b/gnovm/tests/files/ptr2.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr2.gno rename to gnovm/tests/files/ptr2.gno diff --git a/gnovm/tests/files.bak/files/ptr3.gno b/gnovm/tests/files/ptr3.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr3.gno rename to gnovm/tests/files/ptr3.gno diff --git a/gnovm/tests/files.bak/files/ptr4.gno b/gnovm/tests/files/ptr4.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr4.gno rename to gnovm/tests/files/ptr4.gno diff --git a/gnovm/tests/files.bak/files/ptr5.gno b/gnovm/tests/files/ptr5.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr5.gno rename to gnovm/tests/files/ptr5.gno diff --git a/gnovm/tests/files.bak/files/ptr5a.gno b/gnovm/tests/files/ptr5a.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr5a.gno rename to gnovm/tests/files/ptr5a.gno diff --git a/gnovm/tests/files.bak/files/ptr6.gno b/gnovm/tests/files/ptr6.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr6.gno rename to gnovm/tests/files/ptr6.gno diff --git a/gnovm/tests/files.bak/files/ptr7.gno b/gnovm/tests/files/ptr7.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr7.gno rename to gnovm/tests/files/ptr7.gno diff --git a/gnovm/tests/files.bak/files/ptr8.gno b/gnovm/tests/files/ptr8.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr8.gno rename to gnovm/tests/files/ptr8.gno diff --git a/gnovm/tests/files.bak/files/ptr_array0.gno b/gnovm/tests/files/ptr_array0.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr_array0.gno rename to gnovm/tests/files/ptr_array0.gno diff --git a/gnovm/tests/files.bak/files/ptr_array1.gno b/gnovm/tests/files/ptr_array1.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr_array1.gno rename to gnovm/tests/files/ptr_array1.gno diff --git a/gnovm/tests/files.bak/files/ptr_array2.gno b/gnovm/tests/files/ptr_array2.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr_array2.gno rename to gnovm/tests/files/ptr_array2.gno diff --git a/gnovm/tests/files.bak/files/ptr_array3.gno b/gnovm/tests/files/ptr_array3.gno similarity index 100% rename from gnovm/tests/files.bak/files/ptr_array3.gno rename to gnovm/tests/files/ptr_array3.gno diff --git a/gnovm/tests/files.bak/files/range0.gno b/gnovm/tests/files/range0.gno similarity index 100% rename from gnovm/tests/files.bak/files/range0.gno rename to gnovm/tests/files/range0.gno diff --git a/gnovm/tests/files.bak/files/range1.gno b/gnovm/tests/files/range1.gno similarity index 100% rename from gnovm/tests/files.bak/files/range1.gno rename to gnovm/tests/files/range1.gno diff --git a/gnovm/tests/files.bak/files/range2.gno b/gnovm/tests/files/range2.gno similarity index 100% rename from gnovm/tests/files.bak/files/range2.gno rename to gnovm/tests/files/range2.gno diff --git a/gnovm/tests/files.bak/files/range3.gno b/gnovm/tests/files/range3.gno similarity index 100% rename from gnovm/tests/files.bak/files/range3.gno rename to gnovm/tests/files/range3.gno diff --git a/gnovm/tests/files.bak/files/range4.gno b/gnovm/tests/files/range4.gno similarity index 100% rename from gnovm/tests/files.bak/files/range4.gno rename to gnovm/tests/files/range4.gno diff --git a/gnovm/tests/files.bak/files/range5.gno b/gnovm/tests/files/range5.gno similarity index 100% rename from gnovm/tests/files.bak/files/range5.gno rename to gnovm/tests/files/range5.gno diff --git a/gnovm/tests/files.bak/files/range6.gno b/gnovm/tests/files/range6.gno similarity index 100% rename from gnovm/tests/files.bak/files/range6.gno rename to gnovm/tests/files/range6.gno diff --git a/gnovm/tests/files.bak/files/range7.gno b/gnovm/tests/files/range7.gno similarity index 100% rename from gnovm/tests/files.bak/files/range7.gno rename to gnovm/tests/files/range7.gno diff --git a/gnovm/tests/files.bak/files/recover0.gno b/gnovm/tests/files/recover0.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover0.gno rename to gnovm/tests/files/recover0.gno diff --git a/gnovm/tests/files.bak/files/recover1.gno b/gnovm/tests/files/recover1.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover1.gno rename to gnovm/tests/files/recover1.gno diff --git a/gnovm/tests/files.bak/files/recover1b.gno b/gnovm/tests/files/recover1b.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover1b.gno rename to gnovm/tests/files/recover1b.gno diff --git a/gnovm/tests/files.bak/files/recover2.gno b/gnovm/tests/files/recover2.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover2.gno rename to gnovm/tests/files/recover2.gno diff --git a/gnovm/tests/files.bak/files/recover3.gno b/gnovm/tests/files/recover3.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover3.gno rename to gnovm/tests/files/recover3.gno diff --git a/gnovm/tests/files.bak/files/recover4.gno b/gnovm/tests/files/recover4.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover4.gno rename to gnovm/tests/files/recover4.gno diff --git a/gnovm/tests/files.bak/files/recover5.gno b/gnovm/tests/files/recover5.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover5.gno rename to gnovm/tests/files/recover5.gno diff --git a/gnovm/tests/files.bak/files/recover6.gno b/gnovm/tests/files/recover6.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover6.gno rename to gnovm/tests/files/recover6.gno diff --git a/gnovm/tests/files.bak/files/recover7.gno b/gnovm/tests/files/recover7.gno similarity index 100% rename from gnovm/tests/files.bak/files/recover7.gno rename to gnovm/tests/files/recover7.gno diff --git a/gnovm/tests/files.bak/files/recurse0.gno b/gnovm/tests/files/recurse0.gno similarity index 100% rename from gnovm/tests/files.bak/files/recurse0.gno rename to gnovm/tests/files/recurse0.gno diff --git a/gnovm/tests/files.bak/files/redeclaration-global0.gno b/gnovm/tests/files/redeclaration-global0.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration-global0.gno rename to gnovm/tests/files/redeclaration-global0.gno diff --git a/gnovm/tests/files.bak/files/redeclaration-global1.gno b/gnovm/tests/files/redeclaration-global1.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration-global1.gno rename to gnovm/tests/files/redeclaration-global1.gno diff --git a/gnovm/tests/files.bak/files/redeclaration-global5.gno b/gnovm/tests/files/redeclaration-global5.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration-global5.gno rename to gnovm/tests/files/redeclaration-global5.gno diff --git a/gnovm/tests/files.bak/files/redeclaration0.gno b/gnovm/tests/files/redeclaration0.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration0.gno rename to gnovm/tests/files/redeclaration0.gno diff --git a/gnovm/tests/files.bak/files/redeclaration1.gno b/gnovm/tests/files/redeclaration1.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration1.gno rename to gnovm/tests/files/redeclaration1.gno diff --git a/gnovm/tests/files.bak/files/redeclaration2.gno b/gnovm/tests/files/redeclaration2.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration2.gno rename to gnovm/tests/files/redeclaration2.gno diff --git a/gnovm/tests/files.bak/files/redeclaration3.gno b/gnovm/tests/files/redeclaration3.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration3.gno rename to gnovm/tests/files/redeclaration3.gno diff --git a/gnovm/tests/files.bak/files/redeclaration4.gno b/gnovm/tests/files/redeclaration4.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration4.gno rename to gnovm/tests/files/redeclaration4.gno diff --git a/gnovm/tests/files.bak/files/redeclaration5.gno b/gnovm/tests/files/redeclaration5.gno similarity index 100% rename from gnovm/tests/files.bak/files/redeclaration5.gno rename to gnovm/tests/files/redeclaration5.gno diff --git a/gnovm/tests/files.bak/files/ret1.gno b/gnovm/tests/files/ret1.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret1.gno rename to gnovm/tests/files/ret1.gno diff --git a/gnovm/tests/files.bak/files/ret10.gno b/gnovm/tests/files/ret10.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret10.gno rename to gnovm/tests/files/ret10.gno diff --git a/gnovm/tests/files.bak/files/ret11.gno b/gnovm/tests/files/ret11.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret11.gno rename to gnovm/tests/files/ret11.gno diff --git a/gnovm/tests/files.bak/files/ret12.gno b/gnovm/tests/files/ret12.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret12.gno rename to gnovm/tests/files/ret12.gno diff --git a/gnovm/tests/files.bak/files/ret13.gno b/gnovm/tests/files/ret13.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret13.gno rename to gnovm/tests/files/ret13.gno diff --git a/gnovm/tests/files.bak/files/ret14.gno b/gnovm/tests/files/ret14.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret14.gno rename to gnovm/tests/files/ret14.gno diff --git a/gnovm/tests/files.bak/files/ret2.gno b/gnovm/tests/files/ret2.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret2.gno rename to gnovm/tests/files/ret2.gno diff --git a/gnovm/tests/files.bak/files/ret3.gno b/gnovm/tests/files/ret3.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret3.gno rename to gnovm/tests/files/ret3.gno diff --git a/gnovm/tests/files.bak/files/ret4.gno b/gnovm/tests/files/ret4.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret4.gno rename to gnovm/tests/files/ret4.gno diff --git a/gnovm/tests/files.bak/files/ret5.gno b/gnovm/tests/files/ret5.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret5.gno rename to gnovm/tests/files/ret5.gno diff --git a/gnovm/tests/files.bak/files/ret6.gno b/gnovm/tests/files/ret6.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret6.gno rename to gnovm/tests/files/ret6.gno diff --git a/gnovm/tests/files.bak/files/ret7.gno b/gnovm/tests/files/ret7.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret7.gno rename to gnovm/tests/files/ret7.gno diff --git a/gnovm/tests/files.bak/files/ret8.gno b/gnovm/tests/files/ret8.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret8.gno rename to gnovm/tests/files/ret8.gno diff --git a/gnovm/tests/files.bak/files/ret9.gno b/gnovm/tests/files/ret9.gno similarity index 100% rename from gnovm/tests/files.bak/files/ret9.gno rename to gnovm/tests/files/ret9.gno diff --git a/gnovm/tests/files.bak/files/run0.gno b/gnovm/tests/files/run0.gno similarity index 100% rename from gnovm/tests/files.bak/files/run0.gno rename to gnovm/tests/files/run0.gno diff --git a/gnovm/tests/files.bak/files/run1.gno b/gnovm/tests/files/run1.gno similarity index 100% rename from gnovm/tests/files.bak/files/run1.gno rename to gnovm/tests/files/run1.gno diff --git a/gnovm/tests/files.bak/files/run10.gno b/gnovm/tests/files/run10.gno similarity index 100% rename from gnovm/tests/files.bak/files/run10.gno rename to gnovm/tests/files/run10.gno diff --git a/gnovm/tests/files.bak/files/run11.gno b/gnovm/tests/files/run11.gno similarity index 100% rename from gnovm/tests/files.bak/files/run11.gno rename to gnovm/tests/files/run11.gno diff --git a/gnovm/tests/files.bak/files/run12.gno b/gnovm/tests/files/run12.gno similarity index 100% rename from gnovm/tests/files.bak/files/run12.gno rename to gnovm/tests/files/run12.gno diff --git a/gnovm/tests/files.bak/files/run13.gno b/gnovm/tests/files/run13.gno similarity index 100% rename from gnovm/tests/files.bak/files/run13.gno rename to gnovm/tests/files/run13.gno diff --git a/gnovm/tests/files.bak/files/run4.gno b/gnovm/tests/files/run4.gno similarity index 100% rename from gnovm/tests/files.bak/files/run4.gno rename to gnovm/tests/files/run4.gno diff --git a/gnovm/tests/files.bak/files/run5.gno b/gnovm/tests/files/run5.gno similarity index 100% rename from gnovm/tests/files.bak/files/run5.gno rename to gnovm/tests/files/run5.gno diff --git a/gnovm/tests/files.bak/files/run6.gno b/gnovm/tests/files/run6.gno similarity index 100% rename from gnovm/tests/files.bak/files/run6.gno rename to gnovm/tests/files/run6.gno diff --git a/gnovm/tests/files.bak/files/run7.gno b/gnovm/tests/files/run7.gno similarity index 100% rename from gnovm/tests/files.bak/files/run7.gno rename to gnovm/tests/files/run7.gno diff --git a/gnovm/tests/files.bak/files/run8.gno b/gnovm/tests/files/run8.gno similarity index 100% rename from gnovm/tests/files.bak/files/run8.gno rename to gnovm/tests/files/run8.gno diff --git a/gnovm/tests/files.bak/files/run9.gno b/gnovm/tests/files/run9.gno similarity index 100% rename from gnovm/tests/files.bak/files/run9.gno rename to gnovm/tests/files/run9.gno diff --git a/gnovm/tests/files.bak/files/rune0.gno b/gnovm/tests/files/rune0.gno similarity index 100% rename from gnovm/tests/files.bak/files/rune0.gno rename to gnovm/tests/files/rune0.gno diff --git a/gnovm/tests/files.bak/files/rune1.gno b/gnovm/tests/files/rune1.gno similarity index 100% rename from gnovm/tests/files.bak/files/rune1.gno rename to gnovm/tests/files/rune1.gno diff --git a/gnovm/tests/files.bak/files/rune2.gno b/gnovm/tests/files/rune2.gno similarity index 100% rename from gnovm/tests/files.bak/files/rune2.gno rename to gnovm/tests/files/rune2.gno diff --git a/gnovm/tests/files.bak/files/sample.plugin b/gnovm/tests/files/sample.plugin similarity index 100% rename from gnovm/tests/files.bak/files/sample.plugin rename to gnovm/tests/files/sample.plugin diff --git a/gnovm/tests/files.bak/files/scope0.gno b/gnovm/tests/files/scope0.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope0.gno rename to gnovm/tests/files/scope0.gno diff --git a/gnovm/tests/files.bak/files/scope1.gno b/gnovm/tests/files/scope1.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope1.gno rename to gnovm/tests/files/scope1.gno diff --git a/gnovm/tests/files.bak/files/scope2.gno b/gnovm/tests/files/scope2.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope2.gno rename to gnovm/tests/files/scope2.gno diff --git a/gnovm/tests/files.bak/files/scope3.gno b/gnovm/tests/files/scope3.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope3.gno rename to gnovm/tests/files/scope3.gno diff --git a/gnovm/tests/files.bak/files/scope4.gno b/gnovm/tests/files/scope4.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope4.gno rename to gnovm/tests/files/scope4.gno diff --git a/gnovm/tests/files.bak/files/scope5.gno b/gnovm/tests/files/scope5.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope5.gno rename to gnovm/tests/files/scope5.gno diff --git a/gnovm/tests/files.bak/files/scope6.gno b/gnovm/tests/files/scope6.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope6.gno rename to gnovm/tests/files/scope6.gno diff --git a/gnovm/tests/files.bak/files/scope7.gno b/gnovm/tests/files/scope7.gno similarity index 100% rename from gnovm/tests/files.bak/files/scope7.gno rename to gnovm/tests/files/scope7.gno diff --git a/gnovm/tests/files.bak/files/secure.gi b/gnovm/tests/files/secure.gi similarity index 100% rename from gnovm/tests/files.bak/files/secure.gi rename to gnovm/tests/files/secure.gi diff --git a/gnovm/tests/files.bak/files/shift0.gno b/gnovm/tests/files/shift0.gno similarity index 100% rename from gnovm/tests/files.bak/files/shift0.gno rename to gnovm/tests/files/shift0.gno diff --git a/gnovm/tests/files.bak/files/shift1.gno b/gnovm/tests/files/shift1.gno similarity index 100% rename from gnovm/tests/files.bak/files/shift1.gno rename to gnovm/tests/files/shift1.gno diff --git a/gnovm/tests/files.bak/files/shift2.gno b/gnovm/tests/files/shift2.gno similarity index 100% rename from gnovm/tests/files.bak/files/shift2.gno rename to gnovm/tests/files/shift2.gno diff --git a/gnovm/tests/files.bak/files/shift3.gno b/gnovm/tests/files/shift3.gno similarity index 100% rename from gnovm/tests/files.bak/files/shift3.gno rename to gnovm/tests/files/shift3.gno diff --git a/gnovm/tests/files.bak/files/shift4.gno b/gnovm/tests/files/shift4.gno similarity index 100% rename from gnovm/tests/files.bak/files/shift4.gno rename to gnovm/tests/files/shift4.gno diff --git a/gnovm/tests/files.bak/files/shift5.gno b/gnovm/tests/files/shift5.gno similarity index 100% rename from gnovm/tests/files.bak/files/shift5.gno rename to gnovm/tests/files/shift5.gno diff --git a/gnovm/tests/files.bak/files/slice0.gno b/gnovm/tests/files/slice0.gno similarity index 100% rename from gnovm/tests/files.bak/files/slice0.gno rename to gnovm/tests/files/slice0.gno diff --git a/gnovm/tests/files.bak/files/slice1.gno b/gnovm/tests/files/slice1.gno similarity index 100% rename from gnovm/tests/files.bak/files/slice1.gno rename to gnovm/tests/files/slice1.gno diff --git a/gnovm/tests/files.bak/files/slice2.gno b/gnovm/tests/files/slice2.gno similarity index 100% rename from gnovm/tests/files.bak/files/slice2.gno rename to gnovm/tests/files/slice2.gno diff --git a/gnovm/tests/files.bak/files/std0.gno b/gnovm/tests/files/std0.gno similarity index 100% rename from gnovm/tests/files.bak/files/std0.gno rename to gnovm/tests/files/std0.gno diff --git a/gnovm/tests/files.bak/files/std10.gno b/gnovm/tests/files/std10.gno similarity index 100% rename from gnovm/tests/files.bak/files/std10.gno rename to gnovm/tests/files/std10.gno diff --git a/gnovm/tests/files.bak/files/std11.gno b/gnovm/tests/files/std11.gno similarity index 100% rename from gnovm/tests/files.bak/files/std11.gno rename to gnovm/tests/files/std11.gno diff --git a/gnovm/tests/files.bak/files/std2.gno b/gnovm/tests/files/std2.gno similarity index 100% rename from gnovm/tests/files.bak/files/std2.gno rename to gnovm/tests/files/std2.gno diff --git a/gnovm/tests/files.bak/files/std3.gno b/gnovm/tests/files/std3.gno similarity index 100% rename from gnovm/tests/files.bak/files/std3.gno rename to gnovm/tests/files/std3.gno diff --git a/gnovm/tests/files.bak/files/std4.gno b/gnovm/tests/files/std4.gno similarity index 100% rename from gnovm/tests/files.bak/files/std4.gno rename to gnovm/tests/files/std4.gno diff --git a/gnovm/tests/files.bak/files/std5.gno b/gnovm/tests/files/std5.gno similarity index 100% rename from gnovm/tests/files.bak/files/std5.gno rename to gnovm/tests/files/std5.gno diff --git a/gnovm/tests/files.bak/files/std6.gno b/gnovm/tests/files/std6.gno similarity index 100% rename from gnovm/tests/files.bak/files/std6.gno rename to gnovm/tests/files/std6.gno diff --git a/gnovm/tests/files.bak/files/std7.gno b/gnovm/tests/files/std7.gno similarity index 100% rename from gnovm/tests/files.bak/files/std7.gno rename to gnovm/tests/files/std7.gno diff --git a/gnovm/tests/files.bak/files/std8.gno b/gnovm/tests/files/std8.gno similarity index 100% rename from gnovm/tests/files.bak/files/std8.gno rename to gnovm/tests/files/std8.gno diff --git a/gnovm/tests/files.bak/files/std9.gno b/gnovm/tests/files/std9.gno similarity index 100% rename from gnovm/tests/files.bak/files/std9.gno rename to gnovm/tests/files/std9.gno diff --git a/gnovm/tests/files.bak/files/stdlibs_native.gno b/gnovm/tests/files/stdlibs_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/stdlibs_native.gno rename to gnovm/tests/files/stdlibs_native.gno diff --git a/gnovm/tests/files.bak/files/stdlibs_stdlibs.gno b/gnovm/tests/files/stdlibs_stdlibs.gnoa similarity index 94% rename from gnovm/tests/files.bak/files/stdlibs_stdlibs.gno rename to gnovm/tests/files/stdlibs_stdlibs.gnoa index 261e7fbe78c..fbbfcd82845 100644 --- a/gnovm/tests/files.bak/files/stdlibs_stdlibs.gno +++ b/gnovm/tests/files/stdlibs_stdlibs.gnoa @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import "time" diff --git a/gnovm/tests/files.bak/files/str.gno b/gnovm/tests/files/str.gno similarity index 100% rename from gnovm/tests/files.bak/files/str.gno rename to gnovm/tests/files/str.gno diff --git a/gnovm/tests/files.bak/files/str0.gno b/gnovm/tests/files/str0.gno similarity index 100% rename from gnovm/tests/files.bak/files/str0.gno rename to gnovm/tests/files/str0.gno diff --git a/gnovm/tests/files.bak/files/str1.gno b/gnovm/tests/files/str1.gno similarity index 100% rename from gnovm/tests/files.bak/files/str1.gno rename to gnovm/tests/files/str1.gno diff --git a/gnovm/tests/files.bak/files/str2.gno b/gnovm/tests/files/str2.gno similarity index 100% rename from gnovm/tests/files.bak/files/str2.gno rename to gnovm/tests/files/str2.gno diff --git a/gnovm/tests/files.bak/files/str3.gno b/gnovm/tests/files/str3.gno similarity index 100% rename from gnovm/tests/files.bak/files/str3.gno rename to gnovm/tests/files/str3.gno diff --git a/gnovm/tests/files.bak/files/str4.gno b/gnovm/tests/files/str4.gno similarity index 100% rename from gnovm/tests/files.bak/files/str4.gno rename to gnovm/tests/files/str4.gno diff --git a/gnovm/tests/files.bak/files/struct.gno b/gnovm/tests/files/struct.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct.gno rename to gnovm/tests/files/struct.gno diff --git a/gnovm/tests/files.bak/files/struct0.gno b/gnovm/tests/files/struct0.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct0.gno rename to gnovm/tests/files/struct0.gno diff --git a/gnovm/tests/files.bak/files/struct0a.gno b/gnovm/tests/files/struct0a.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct0a.gno rename to gnovm/tests/files/struct0a.gno diff --git a/gnovm/tests/files.bak/files/struct1.gno b/gnovm/tests/files/struct1.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct1.gno rename to gnovm/tests/files/struct1.gno diff --git a/gnovm/tests/files.bak/files/struct10.gno b/gnovm/tests/files/struct10.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct10.gno rename to gnovm/tests/files/struct10.gno diff --git a/gnovm/tests/files.bak/files/struct11.gno b/gnovm/tests/files/struct11.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct11.gno rename to gnovm/tests/files/struct11.gno diff --git a/gnovm/tests/files.bak/files/struct11b.gno b/gnovm/tests/files/struct11b.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct11b.gno rename to gnovm/tests/files/struct11b.gno diff --git a/gnovm/tests/files.bak/files/struct12.gno b/gnovm/tests/files/struct12.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct12.gno rename to gnovm/tests/files/struct12.gno diff --git a/gnovm/tests/files.bak/files/struct13_native.gno b/gnovm/tests/files/struct13_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct13_native.gno rename to gnovm/tests/files/struct13_native.gno diff --git a/gnovm/tests/files.bak/files/struct13_stdlibs.gno b/gnovm/tests/files/struct13_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct13_stdlibs.gno rename to gnovm/tests/files/struct13_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/struct14.gno b/gnovm/tests/files/struct14.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct14.gno rename to gnovm/tests/files/struct14.gno diff --git a/gnovm/tests/files.bak/files/struct16.gno b/gnovm/tests/files/struct16.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct16.gno rename to gnovm/tests/files/struct16.gno diff --git a/gnovm/tests/files.bak/files/struct17.gno b/gnovm/tests/files/struct17.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct17.gno rename to gnovm/tests/files/struct17.gno diff --git a/gnovm/tests/files.bak/files/struct19.gno b/gnovm/tests/files/struct19.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct19.gno rename to gnovm/tests/files/struct19.gno diff --git a/gnovm/tests/files.bak/files/struct2.gno b/gnovm/tests/files/struct2.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct2.gno rename to gnovm/tests/files/struct2.gno diff --git a/gnovm/tests/files.bak/files/struct20.gno b/gnovm/tests/files/struct20.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct20.gno rename to gnovm/tests/files/struct20.gno diff --git a/gnovm/tests/files.bak/files/struct21.gno b/gnovm/tests/files/struct21.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct21.gno rename to gnovm/tests/files/struct21.gno diff --git a/gnovm/tests/files.bak/files/struct22.gno b/gnovm/tests/files/struct22.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct22.gno rename to gnovm/tests/files/struct22.gno diff --git a/gnovm/tests/files.bak/files/struct24.gno b/gnovm/tests/files/struct24.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct24.gno rename to gnovm/tests/files/struct24.gno diff --git a/gnovm/tests/files.bak/files/struct25.gno b/gnovm/tests/files/struct25.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct25.gno rename to gnovm/tests/files/struct25.gno diff --git a/gnovm/tests/files.bak/files/struct26.gno b/gnovm/tests/files/struct26.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct26.gno rename to gnovm/tests/files/struct26.gno diff --git a/gnovm/tests/files.bak/files/struct27.gno b/gnovm/tests/files/struct27.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct27.gno rename to gnovm/tests/files/struct27.gno diff --git a/gnovm/tests/files.bak/files/struct28b.gno b/gnovm/tests/files/struct28b.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct28b.gno rename to gnovm/tests/files/struct28b.gno diff --git a/gnovm/tests/files.bak/files/struct29.gno b/gnovm/tests/files/struct29.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct29.gno rename to gnovm/tests/files/struct29.gno diff --git a/gnovm/tests/files.bak/files/struct2b.gno b/gnovm/tests/files/struct2b.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct2b.gno rename to gnovm/tests/files/struct2b.gno diff --git a/gnovm/tests/files.bak/files/struct3.gno b/gnovm/tests/files/struct3.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct3.gno rename to gnovm/tests/files/struct3.gno diff --git a/gnovm/tests/files.bak/files/struct30.gno b/gnovm/tests/files/struct30.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct30.gno rename to gnovm/tests/files/struct30.gno diff --git a/gnovm/tests/files.bak/files/struct31.gno b/gnovm/tests/files/struct31.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct31.gno rename to gnovm/tests/files/struct31.gno diff --git a/gnovm/tests/files.bak/files/struct32.gno b/gnovm/tests/files/struct32.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct32.gno rename to gnovm/tests/files/struct32.gno diff --git a/gnovm/tests/files.bak/files/struct33.gno b/gnovm/tests/files/struct33.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct33.gno rename to gnovm/tests/files/struct33.gno diff --git a/gnovm/tests/files.bak/files/struct34.gno b/gnovm/tests/files/struct34.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct34.gno rename to gnovm/tests/files/struct34.gno diff --git a/gnovm/tests/files.bak/files/struct35.gno b/gnovm/tests/files/struct35.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct35.gno rename to gnovm/tests/files/struct35.gno diff --git a/gnovm/tests/files.bak/files/struct36.gno b/gnovm/tests/files/struct36.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct36.gno rename to gnovm/tests/files/struct36.gno diff --git a/gnovm/tests/files.bak/files/struct37.gno b/gnovm/tests/files/struct37.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct37.gno rename to gnovm/tests/files/struct37.gno diff --git a/gnovm/tests/files.bak/files/struct38.gno b/gnovm/tests/files/struct38.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct38.gno rename to gnovm/tests/files/struct38.gno diff --git a/gnovm/tests/files.bak/files/struct39.gno b/gnovm/tests/files/struct39.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct39.gno rename to gnovm/tests/files/struct39.gno diff --git a/gnovm/tests/files.bak/files/struct4.gno b/gnovm/tests/files/struct4.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct4.gno rename to gnovm/tests/files/struct4.gno diff --git a/gnovm/tests/files.bak/files/struct40.gno b/gnovm/tests/files/struct40.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct40.gno rename to gnovm/tests/files/struct40.gno diff --git a/gnovm/tests/files.bak/files/struct41.gno b/gnovm/tests/files/struct41.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct41.gno rename to gnovm/tests/files/struct41.gno diff --git a/gnovm/tests/files.bak/files/struct42.gno b/gnovm/tests/files/struct42.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct42.gno rename to gnovm/tests/files/struct42.gno diff --git a/gnovm/tests/files.bak/files/struct43.gno b/gnovm/tests/files/struct43.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct43.gno rename to gnovm/tests/files/struct43.gno diff --git a/gnovm/tests/files.bak/files/struct44.gno b/gnovm/tests/files/struct44.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct44.gno rename to gnovm/tests/files/struct44.gno diff --git a/gnovm/tests/files.bak/files/struct45.gno b/gnovm/tests/files/struct45.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct45.gno rename to gnovm/tests/files/struct45.gno diff --git a/gnovm/tests/files.bak/files/struct46.gno b/gnovm/tests/files/struct46.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct46.gno rename to gnovm/tests/files/struct46.gno diff --git a/gnovm/tests/files.bak/files/struct47.gno b/gnovm/tests/files/struct47.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct47.gno rename to gnovm/tests/files/struct47.gno diff --git a/gnovm/tests/files.bak/files/struct48.gno b/gnovm/tests/files/struct48.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct48.gno rename to gnovm/tests/files/struct48.gno diff --git a/gnovm/tests/files.bak/files/struct49.gno b/gnovm/tests/files/struct49.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct49.gno rename to gnovm/tests/files/struct49.gno diff --git a/gnovm/tests/files.bak/files/struct5.gno b/gnovm/tests/files/struct5.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct5.gno rename to gnovm/tests/files/struct5.gno diff --git a/gnovm/tests/files.bak/files/struct50b.gno b/gnovm/tests/files/struct50b.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct50b.gno rename to gnovm/tests/files/struct50b.gno diff --git a/gnovm/tests/files.bak/files/struct52b.gno b/gnovm/tests/files/struct52b.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct52b.gno rename to gnovm/tests/files/struct52b.gno diff --git a/gnovm/tests/files.bak/files/struct53b.gno b/gnovm/tests/files/struct53b.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct53b.gno rename to gnovm/tests/files/struct53b.gno diff --git a/gnovm/tests/files.bak/files/struct54.gno b/gnovm/tests/files/struct54.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct54.gno rename to gnovm/tests/files/struct54.gno diff --git a/gnovm/tests/files.bak/files/struct56.gno b/gnovm/tests/files/struct56.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct56.gno rename to gnovm/tests/files/struct56.gno diff --git a/gnovm/tests/files.bak/files/struct57.gno b/gnovm/tests/files/struct57.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct57.gno rename to gnovm/tests/files/struct57.gno diff --git a/gnovm/tests/files.bak/files/struct6.gno b/gnovm/tests/files/struct6.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct6.gno rename to gnovm/tests/files/struct6.gno diff --git a/gnovm/tests/files.bak/files/struct7.gno b/gnovm/tests/files/struct7.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct7.gno rename to gnovm/tests/files/struct7.gno diff --git a/gnovm/tests/files.bak/files/struct8.gno b/gnovm/tests/files/struct8.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct8.gno rename to gnovm/tests/files/struct8.gno diff --git a/gnovm/tests/files.bak/files/struct9.gno b/gnovm/tests/files/struct9.gno similarity index 100% rename from gnovm/tests/files.bak/files/struct9.gno rename to gnovm/tests/files/struct9.gno diff --git a/gnovm/tests/files.bak/files/switch.gno b/gnovm/tests/files/switch.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch.gno rename to gnovm/tests/files/switch.gno diff --git a/gnovm/tests/files.bak/files/switch0.gno b/gnovm/tests/files/switch0.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch0.gno rename to gnovm/tests/files/switch0.gno diff --git a/gnovm/tests/files.bak/files/switch1.gno b/gnovm/tests/files/switch1.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch1.gno rename to gnovm/tests/files/switch1.gno diff --git a/gnovm/tests/files.bak/files/switch10.gno b/gnovm/tests/files/switch10.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch10.gno rename to gnovm/tests/files/switch10.gno diff --git a/gnovm/tests/files.bak/files/switch11.gno b/gnovm/tests/files/switch11.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch11.gno rename to gnovm/tests/files/switch11.gno diff --git a/gnovm/tests/files.bak/files/switch12.gno b/gnovm/tests/files/switch12.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch12.gno rename to gnovm/tests/files/switch12.gno diff --git a/gnovm/tests/files.bak/files/switch13.gno b/gnovm/tests/files/switch13.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch13.gno rename to gnovm/tests/files/switch13.gno diff --git a/gnovm/tests/files.bak/files/switch14.gno b/gnovm/tests/files/switch14.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch14.gno rename to gnovm/tests/files/switch14.gno diff --git a/gnovm/tests/files.bak/files/switch15.gno b/gnovm/tests/files/switch15.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch15.gno rename to gnovm/tests/files/switch15.gno diff --git a/gnovm/tests/files.bak/files/switch16.gno b/gnovm/tests/files/switch16.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch16.gno rename to gnovm/tests/files/switch16.gno diff --git a/gnovm/tests/files.bak/files/switch17.gno b/gnovm/tests/files/switch17.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch17.gno rename to gnovm/tests/files/switch17.gno diff --git a/gnovm/tests/files.bak/files/switch18.gno b/gnovm/tests/files/switch18.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch18.gno rename to gnovm/tests/files/switch18.gno diff --git a/gnovm/tests/files.bak/files/switch19.gno b/gnovm/tests/files/switch19.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch19.gno rename to gnovm/tests/files/switch19.gno diff --git a/gnovm/tests/files.bak/files/switch2.gno b/gnovm/tests/files/switch2.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch2.gno rename to gnovm/tests/files/switch2.gno diff --git a/gnovm/tests/files.bak/files/switch20.gno b/gnovm/tests/files/switch20.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch20.gno rename to gnovm/tests/files/switch20.gno diff --git a/gnovm/tests/files.bak/files/switch21.gno b/gnovm/tests/files/switch21.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch21.gno rename to gnovm/tests/files/switch21.gno diff --git a/gnovm/tests/files.bak/files/switch22.gno b/gnovm/tests/files/switch22.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch22.gno rename to gnovm/tests/files/switch22.gno diff --git a/gnovm/tests/files.bak/files/switch23.gno b/gnovm/tests/files/switch23.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch23.gno rename to gnovm/tests/files/switch23.gno diff --git a/gnovm/tests/files.bak/files/switch24.gno b/gnovm/tests/files/switch24.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch24.gno rename to gnovm/tests/files/switch24.gno diff --git a/gnovm/tests/files.bak/files/switch25.gno b/gnovm/tests/files/switch25.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch25.gno rename to gnovm/tests/files/switch25.gno diff --git a/gnovm/tests/files.bak/files/switch26.gno b/gnovm/tests/files/switch26.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch26.gno rename to gnovm/tests/files/switch26.gno diff --git a/gnovm/tests/files.bak/files/switch27.gno b/gnovm/tests/files/switch27.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch27.gno rename to gnovm/tests/files/switch27.gno diff --git a/gnovm/tests/files.bak/files/switch28.gno b/gnovm/tests/files/switch28.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch28.gno rename to gnovm/tests/files/switch28.gno diff --git a/gnovm/tests/files.bak/files/switch29.gno b/gnovm/tests/files/switch29.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch29.gno rename to gnovm/tests/files/switch29.gno diff --git a/gnovm/tests/files.bak/files/switch3.gno b/gnovm/tests/files/switch3.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch3.gno rename to gnovm/tests/files/switch3.gno diff --git a/gnovm/tests/files.bak/files/switch30.gno b/gnovm/tests/files/switch30.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch30.gno rename to gnovm/tests/files/switch30.gno diff --git a/gnovm/tests/files.bak/files/switch31.gno b/gnovm/tests/files/switch31.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch31.gno rename to gnovm/tests/files/switch31.gno diff --git a/gnovm/tests/files.bak/files/switch32.gno b/gnovm/tests/files/switch32.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch32.gno rename to gnovm/tests/files/switch32.gno diff --git a/gnovm/tests/files.bak/files/switch33.gno b/gnovm/tests/files/switch33.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch33.gno rename to gnovm/tests/files/switch33.gno diff --git a/gnovm/tests/files.bak/files/switch34.gno b/gnovm/tests/files/switch34.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch34.gno rename to gnovm/tests/files/switch34.gno diff --git a/gnovm/tests/files.bak/files/switch35.gno b/gnovm/tests/files/switch35.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch35.gno rename to gnovm/tests/files/switch35.gno diff --git a/gnovm/tests/files.bak/files/switch36.gno b/gnovm/tests/files/switch36.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch36.gno rename to gnovm/tests/files/switch36.gno diff --git a/gnovm/tests/files.bak/files/switch37.gno b/gnovm/tests/files/switch37.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch37.gno rename to gnovm/tests/files/switch37.gno diff --git a/gnovm/tests/files.bak/files/switch38.gno b/gnovm/tests/files/switch38.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch38.gno rename to gnovm/tests/files/switch38.gno diff --git a/gnovm/tests/files.bak/files/switch39.gno b/gnovm/tests/files/switch39.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch39.gno rename to gnovm/tests/files/switch39.gno diff --git a/gnovm/tests/files.bak/files/switch4.gno b/gnovm/tests/files/switch4.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch4.gno rename to gnovm/tests/files/switch4.gno diff --git a/gnovm/tests/files.bak/files/switch40.gno b/gnovm/tests/files/switch40.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch40.gno rename to gnovm/tests/files/switch40.gno diff --git a/gnovm/tests/files.bak/files/switch41.gno b/gnovm/tests/files/switch41.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch41.gno rename to gnovm/tests/files/switch41.gno diff --git a/gnovm/tests/files.bak/files/switch5.gno b/gnovm/tests/files/switch5.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch5.gno rename to gnovm/tests/files/switch5.gno diff --git a/gnovm/tests/files.bak/files/switch6.gno b/gnovm/tests/files/switch6.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch6.gno rename to gnovm/tests/files/switch6.gno diff --git a/gnovm/tests/files.bak/files/switch6b.gno b/gnovm/tests/files/switch6b.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch6b.gno rename to gnovm/tests/files/switch6b.gno diff --git a/gnovm/tests/files.bak/files/switch6c.gno b/gnovm/tests/files/switch6c.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch6c.gno rename to gnovm/tests/files/switch6c.gno diff --git a/gnovm/tests/files.bak/files/switch7.gno b/gnovm/tests/files/switch7.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch7.gno rename to gnovm/tests/files/switch7.gno diff --git a/gnovm/tests/files.bak/files/switch8.gno b/gnovm/tests/files/switch8.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch8.gno rename to gnovm/tests/files/switch8.gno diff --git a/gnovm/tests/files.bak/files/switch8b.gno b/gnovm/tests/files/switch8b.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch8b.gno rename to gnovm/tests/files/switch8b.gno diff --git a/gnovm/tests/files.bak/files/switch8c.gno b/gnovm/tests/files/switch8c.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch8c.gno rename to gnovm/tests/files/switch8c.gno diff --git a/gnovm/tests/files.bak/files/switch9.gno b/gnovm/tests/files/switch9.gno similarity index 100% rename from gnovm/tests/files.bak/files/switch9.gno rename to gnovm/tests/files/switch9.gno diff --git a/gnovm/tests/files.bak/files/time0_native.gno b/gnovm/tests/files/time0_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time0_native.gno rename to gnovm/tests/files/time0_native.gno diff --git a/gnovm/tests/files.bak/files/time0_stdlibs.gno b/gnovm/tests/files/time0_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time0_stdlibs.gno rename to gnovm/tests/files/time0_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time11_native.gno b/gnovm/tests/files/time11_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time11_native.gno rename to gnovm/tests/files/time11_native.gno diff --git a/gnovm/tests/files.bak/files/time11_stdlibs.gno b/gnovm/tests/files/time11_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time11_stdlibs.gno rename to gnovm/tests/files/time11_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time12_native.gno b/gnovm/tests/files/time12_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time12_native.gno rename to gnovm/tests/files/time12_native.gno diff --git a/gnovm/tests/files.bak/files/time12_stdlibs.gno b/gnovm/tests/files/time12_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time12_stdlibs.gno rename to gnovm/tests/files/time12_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time13_native.gno b/gnovm/tests/files/time13_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time13_native.gno rename to gnovm/tests/files/time13_native.gno diff --git a/gnovm/tests/files.bak/files/time13_stdlibs.gno b/gnovm/tests/files/time13_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time13_stdlibs.gno rename to gnovm/tests/files/time13_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time14_native.gno b/gnovm/tests/files/time14_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time14_native.gno rename to gnovm/tests/files/time14_native.gno diff --git a/gnovm/tests/files.bak/files/time14_stdlibs.gno b/gnovm/tests/files/time14_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time14_stdlibs.gno rename to gnovm/tests/files/time14_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time15.gno b/gnovm/tests/files/time15.gno similarity index 100% rename from gnovm/tests/files.bak/files/time15.gno rename to gnovm/tests/files/time15.gno diff --git a/gnovm/tests/files.bak/files/time1_native.gno b/gnovm/tests/files/time1_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time1_native.gno rename to gnovm/tests/files/time1_native.gno diff --git a/gnovm/tests/files.bak/files/time1_stdlibs.gno b/gnovm/tests/files/time1_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time1_stdlibs.gno rename to gnovm/tests/files/time1_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time2_native.gno b/gnovm/tests/files/time2_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time2_native.gno rename to gnovm/tests/files/time2_native.gno diff --git a/gnovm/tests/files.bak/files/time2_stdlibs.gno b/gnovm/tests/files/time2_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time2_stdlibs.gno rename to gnovm/tests/files/time2_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time3_native.gno b/gnovm/tests/files/time3_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time3_native.gno rename to gnovm/tests/files/time3_native.gno diff --git a/gnovm/tests/files.bak/files/time3_stdlibs.gno b/gnovm/tests/files/time3_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time3_stdlibs.gno rename to gnovm/tests/files/time3_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time4_native.gno b/gnovm/tests/files/time4_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time4_native.gno rename to gnovm/tests/files/time4_native.gno diff --git a/gnovm/tests/files.bak/files/time4_stdlibs.gno b/gnovm/tests/files/time4_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time4_stdlibs.gno rename to gnovm/tests/files/time4_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time6_native.gno b/gnovm/tests/files/time6_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time6_native.gno rename to gnovm/tests/files/time6_native.gno diff --git a/gnovm/tests/files.bak/files/time6_stdlibs.gno b/gnovm/tests/files/time6_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time6_stdlibs.gno rename to gnovm/tests/files/time6_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time7_native.gno b/gnovm/tests/files/time7_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time7_native.gno rename to gnovm/tests/files/time7_native.gno diff --git a/gnovm/tests/files.bak/files/time7_stdlibs.gno b/gnovm/tests/files/time7_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time7_stdlibs.gno rename to gnovm/tests/files/time7_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/time8.gno b/gnovm/tests/files/time8.gno similarity index 100% rename from gnovm/tests/files.bak/files/time8.gno rename to gnovm/tests/files/time8.gno diff --git a/gnovm/tests/files.bak/files/time9_native.gno b/gnovm/tests/files/time9_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/time9_native.gno rename to gnovm/tests/files/time9_native.gno diff --git a/gnovm/tests/files.bak/files/time9_stdlibs.gno b/gnovm/tests/files/time9_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/time9_stdlibs.gno rename to gnovm/tests/files/time9_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/type0.gno b/gnovm/tests/files/type0.gno similarity index 100% rename from gnovm/tests/files.bak/files/type0.gno rename to gnovm/tests/files/type0.gno diff --git a/gnovm/tests/files.bak/files/type1.gno b/gnovm/tests/files/type1.gno similarity index 100% rename from gnovm/tests/files.bak/files/type1.gno rename to gnovm/tests/files/type1.gno diff --git a/gnovm/tests/files.bak/files/type11.gno b/gnovm/tests/files/type11.gno similarity index 100% rename from gnovm/tests/files.bak/files/type11.gno rename to gnovm/tests/files/type11.gno diff --git a/gnovm/tests/files.bak/files/type12.gno b/gnovm/tests/files/type12.gno similarity index 100% rename from gnovm/tests/files.bak/files/type12.gno rename to gnovm/tests/files/type12.gno diff --git a/gnovm/tests/files.bak/files/type13.gno b/gnovm/tests/files/type13.gno similarity index 100% rename from gnovm/tests/files.bak/files/type13.gno rename to gnovm/tests/files/type13.gno diff --git a/gnovm/tests/files.bak/files/type14.gno b/gnovm/tests/files/type14.gno similarity index 100% rename from gnovm/tests/files.bak/files/type14.gno rename to gnovm/tests/files/type14.gno diff --git a/gnovm/tests/files.bak/files/type15.gno b/gnovm/tests/files/type15.gno similarity index 100% rename from gnovm/tests/files.bak/files/type15.gno rename to gnovm/tests/files/type15.gno diff --git a/gnovm/tests/files.bak/files/type16.gno b/gnovm/tests/files/type16.gno similarity index 100% rename from gnovm/tests/files.bak/files/type16.gno rename to gnovm/tests/files/type16.gno diff --git a/gnovm/tests/files.bak/files/type17.gno b/gnovm/tests/files/type17.gno similarity index 100% rename from gnovm/tests/files.bak/files/type17.gno rename to gnovm/tests/files/type17.gno diff --git a/gnovm/tests/files.bak/files/type18.gno b/gnovm/tests/files/type18.gno similarity index 100% rename from gnovm/tests/files.bak/files/type18.gno rename to gnovm/tests/files/type18.gno diff --git a/gnovm/tests/files.bak/files/type19.gno b/gnovm/tests/files/type19.gno similarity index 100% rename from gnovm/tests/files.bak/files/type19.gno rename to gnovm/tests/files/type19.gno diff --git a/gnovm/tests/files.bak/files/type20.gno b/gnovm/tests/files/type20.gno similarity index 100% rename from gnovm/tests/files.bak/files/type20.gno rename to gnovm/tests/files/type20.gno diff --git a/gnovm/tests/files.bak/files/type22.gno b/gnovm/tests/files/type22.gno similarity index 100% rename from gnovm/tests/files.bak/files/type22.gno rename to gnovm/tests/files/type22.gno diff --git a/gnovm/tests/files.bak/files/type23b.gno b/gnovm/tests/files/type23b.gno similarity index 100% rename from gnovm/tests/files.bak/files/type23b.gno rename to gnovm/tests/files/type23b.gno diff --git a/gnovm/tests/files.bak/files/type24b.gno b/gnovm/tests/files/type24b.gno similarity index 100% rename from gnovm/tests/files.bak/files/type24b.gno rename to gnovm/tests/files/type24b.gno diff --git a/gnovm/tests/files.bak/files/type2_native.gno b/gnovm/tests/files/type2_native.gno similarity index 100% rename from gnovm/tests/files.bak/files/type2_native.gno rename to gnovm/tests/files/type2_native.gno diff --git a/gnovm/tests/files.bak/files/type2_stdlibs.gno b/gnovm/tests/files/type2_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/type2_stdlibs.gno rename to gnovm/tests/files/type2_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/type3.gno b/gnovm/tests/files/type3.gno similarity index 100% rename from gnovm/tests/files.bak/files/type3.gno rename to gnovm/tests/files/type3.gno diff --git a/gnovm/tests/files.bak/files/type30.gno b/gnovm/tests/files/type30.gno similarity index 100% rename from gnovm/tests/files.bak/files/type30.gno rename to gnovm/tests/files/type30.gno diff --git a/gnovm/tests/files.bak/files/type31.gno b/gnovm/tests/files/type31.gno similarity index 50% rename from gnovm/tests/files.bak/files/type31.gno rename to gnovm/tests/files/type31.gno index a80d07d70f2..1c8b91b02fd 100644 --- a/gnovm/tests/files.bak/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/type31.gno:8: incompatible types in binary expression: x ADD y +// main/files/type31.gno:8: cannot use string as main.String without explicit conversion diff --git a/gnovm/tests/files.bak/files/type32.gno b/gnovm/tests/files/type32.gno similarity index 51% rename from gnovm/tests/files.bak/files/type32.gno rename to gnovm/tests/files/type32.gno index b679543cf9f..58a19f606ae 100644 --- a/gnovm/tests/files.bak/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/type32.gno:9#1: incompatible types in binary expression: a + (const (":" string)) ADD b +// main/files/type32.gno:9#1: cannot use string as main.S without explicit conversion diff --git a/gnovm/tests/files.bak/files/type7.gno b/gnovm/tests/files/type7.gno similarity index 100% rename from gnovm/tests/files.bak/files/type7.gno rename to gnovm/tests/files/type7.gno diff --git a/gnovm/tests/files.bak/files/type8.gno b/gnovm/tests/files/type8.gno similarity index 100% rename from gnovm/tests/files.bak/files/type8.gno rename to gnovm/tests/files/type8.gno diff --git a/gnovm/tests/files/types/0b2_filetest.gno b/gnovm/tests/files/types/0b2_filetest.gno new file mode 100644 index 00000000000..95544ef88ba --- /dev/null +++ b/gnovm/tests/files/types/0b2_filetest.gno @@ -0,0 +1,22 @@ +package main + +type Error string + +func (e Error) Error() string { + return "error: " + string(e) +} + +// left is untyped const, right is typed const +// untyped value can be converted to its correspondence value when: +// a) it's (untyped) const +// b) it's declared type of value, like type Error int8, 0 will be able to converted to Error +func main() { + if 1 == Error(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0b2_filetest.gno:14: cannot convert untyped bigint type to StringKind diff --git a/gnovm/tests/files/types/10a0_filetest.gno b/gnovm/tests/files/types/10a0_filetest.gno new file mode 100644 index 00000000000..a31e7bd8f82 --- /dev/null +++ b/gnovm/tests/files/types/10a0_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both typed(different) const +func main() { + println(int(1) << int(1)) + println(int(1) >> int(1)) +} + +// Output: +// 2 +// 0 diff --git a/gnovm/tests/files/types/10a1_filetest.gno b/gnovm/tests/files/types/10a1_filetest.gno new file mode 100644 index 00000000000..ba92bf0f7d2 --- /dev/null +++ b/gnovm/tests/files/types/10a1_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both typed(different) const +func main() { + println(int(1) << int8(1)) + println(int(1) >> int8(1)) +} + +// Output: +// 2 +// 0 diff --git a/gnovm/tests/files/types/10a2_filetest.gno b/gnovm/tests/files/types/10a2_filetest.gno new file mode 100644 index 00000000000..91072929306 --- /dev/null +++ b/gnovm/tests/files/types/10a2_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both typed(different) const +func main() { + println(1 << int(1)) + println(1 >> int(1)) +} + +// Output: +// 2 +// 0 diff --git a/gnovm/tests/files/types/10a3_filetest.gno b/gnovm/tests/files/types/10a3_filetest.gno new file mode 100644 index 00000000000..6bb19f9db27 --- /dev/null +++ b/gnovm/tests/files/types/10a3_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both typed(different) const +func main() { + println(1 << 'a') + println(1 >> 'a') +} + +// Error: +// main/files/types/10a3_filetest.gno:5: bigint overflows target kind diff --git a/gnovm/tests/files/types/10a4_filetest.gno b/gnovm/tests/files/types/10a4_filetest.gno new file mode 100644 index 00000000000..3561929b672 --- /dev/null +++ b/gnovm/tests/files/types/10a4_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both typed(different) const +func main() { + println(1 << 1.0) + println(1 >> 1.0) +} + +// Output: +// 2 +// 0 diff --git a/gnovm/tests/files/types/10a5_filetest.gno b/gnovm/tests/files/types/10a5_filetest.gno new file mode 100644 index 00000000000..5c54ead8c8d --- /dev/null +++ b/gnovm/tests/files/types/10a5_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both typed(different) const +func main() { + //println(1.0 << 1) + //println(1.0 >> 1) +} + +// TODO: no support for this for now +// Output: diff --git a/gnovm/tests/files/types/11a0_filetest.gno b/gnovm/tests/files/types/11a0_filetest.gno new file mode 100644 index 00000000000..7315ac56c7c --- /dev/null +++ b/gnovm/tests/files/types/11a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) && int(1)) +} + +// Error: +// main/files/types/11a0_filetest.gno:5: operator && not defined on: int \ No newline at end of file diff --git a/gnovm/tests/files/types/11a1_filetest.gno b/gnovm/tests/files/types/11a1_filetest.gno new file mode 100644 index 00000000000..30a21fbb8e6 --- /dev/null +++ b/gnovm/tests/files/types/11a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(1 && 1) +} + +// Error: +// main/files/types/11a1_filetest.gno:5: operator && not defined on: bigint diff --git a/gnovm/tests/files/types/11a2_filetest.gno b/gnovm/tests/files/types/11a2_filetest.gno new file mode 100644 index 00000000000..fc8b1401304 --- /dev/null +++ b/gnovm/tests/files/types/11a2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(true && 1) +} + +// Error: +// main/files/types/11a2_filetest.gno:5: operator && not defined on: bigint \ No newline at end of file diff --git a/gnovm/tests/files/types/11a3_filetest.gno b/gnovm/tests/files/types/11a3_filetest.gno new file mode 100644 index 00000000000..c6f03efb164 --- /dev/null +++ b/gnovm/tests/files/types/11a3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both typed(different) const +func main() { + println(true && true) + println(true && false) + println(1 == 1 && true) + println(1 == 1 && false) +} + +// Output: +// true +// false +// true +// false diff --git a/gnovm/tests/files/types/12a0_filetest.gno b/gnovm/tests/files/types/12a0_filetest.gno new file mode 100644 index 00000000000..8db29851474 --- /dev/null +++ b/gnovm/tests/files/types/12a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) || int(1)) +} + +// Error: +// main/files/types/12a0_filetest.gno:5: operator || not defined on: int diff --git a/gnovm/tests/files/types/12a1_filetest.gno b/gnovm/tests/files/types/12a1_filetest.gno new file mode 100644 index 00000000000..745ce998d57 --- /dev/null +++ b/gnovm/tests/files/types/12a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(1 || 1) +} + +// Error: +// main/files/types/12a1_filetest.gno:5: operator || not defined on: bigint diff --git a/gnovm/tests/files/types/12a2_filetest.gno b/gnovm/tests/files/types/12a2_filetest.gno new file mode 100644 index 00000000000..328758cf3fe --- /dev/null +++ b/gnovm/tests/files/types/12a2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(true || 1) +} + +// Error: +// main/files/types/12a2_filetest.gno:5: operator || not defined on: bigint diff --git a/gnovm/tests/files/types/12a3_filetest.gno b/gnovm/tests/files/types/12a3_filetest.gno new file mode 100644 index 00000000000..7bd3d97b019 --- /dev/null +++ b/gnovm/tests/files/types/12a3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both typed(different) const +func main() { + println(true || true) + println(true || false) + println(1 == 1 || true) + println(1 == 1 || false) +} + +// Output: +// true +// true +// true +// true diff --git a/gnovm/tests/files/types/13a0_filetest.gno b/gnovm/tests/files/types/13a0_filetest.gno new file mode 100644 index 00000000000..c5c9fb7d34c --- /dev/null +++ b/gnovm/tests/files/types/13a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + int(0) += int8(1) +} + +// Error: +// main/files/types/13a0_filetest.gno:5: cannot use int8 as int diff --git a/gnovm/tests/files/types/13a1_filetest.gno b/gnovm/tests/files/types/13a1_filetest.gno new file mode 100644 index 00000000000..37bf8c07bad --- /dev/null +++ b/gnovm/tests/files/types/13a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + Error1(0) += Error2(0) +} + +// Error: +// main/files/types/13a1_filetest.gno:21: cannot use main.Error2 as main.Error1 without explicit conversion diff --git a/gnovm/tests/files/types/13b0_filetest.gno b/gnovm/tests/files/types/13b0_filetest.gno new file mode 100644 index 00000000000..44138c412b6 --- /dev/null +++ b/gnovm/tests/files/types/13b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + r := 1 + r += Error(1) + println(r) +} + +// Error: +// main/files/types/13b0_filetest.gno:8: cannot use main.Error as int without explicit conversion diff --git a/gnovm/tests/files/types/13b1_filetest.gno b/gnovm/tests/files/types/13b1_filetest.gno new file mode 100644 index 00000000000..2e702256f29 --- /dev/null +++ b/gnovm/tests/files/types/13b1_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + r := Error(1) + r += 1 + println(r) +} + +// Output: +// (2 main.Error) diff --git a/gnovm/tests/files/types/13b2_filetest.gno b/gnovm/tests/files/types/13b2_filetest.gno new file mode 100644 index 00000000000..87b09754046 --- /dev/null +++ b/gnovm/tests/files/types/13b2_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := 1 + r += 'a' + println(r) +} + +// Output: +// 98 diff --git a/gnovm/tests/files/types/13d0_filetest.gno b/gnovm/tests/files/types/13d0_filetest.gno new file mode 100644 index 00000000000..f3da2497a84 --- /dev/null +++ b/gnovm/tests/files/types/13d0_filetest.gno @@ -0,0 +1,12 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + r := 1.0 + r += 1 + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/13e0_filetest.gno b/gnovm/tests/files/types/13e0_filetest.gno new file mode 100644 index 00000000000..37530394129 --- /dev/null +++ b/gnovm/tests/files/types/13e0_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + e1 += e2 + println(e1) +} + +// Error: +// main/files/types/13e0_filetest.gno:23: cannot use main.Error2 as main.Error1 without explicit conversion diff --git a/gnovm/tests/files/types/13f0_filetest.gno b/gnovm/tests/files/types/13f0_filetest.gno new file mode 100644 index 00000000000..60c28c3c3f2 --- /dev/null +++ b/gnovm/tests/files/types/13f0_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + r := 1 + r += errCmp + println(r) +} + +// Error: +// main/files/types/13f0_filetest.gno:20: cannot use .uverse.error as int without explicit conversion diff --git a/gnovm/tests/files/types/13f1_filetest.gno b/gnovm/tests/files/types/13f1_filetest.gno new file mode 100644 index 00000000000..9a9f34d5669 --- /dev/null +++ b/gnovm/tests/files/types/13f1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + r := Error(0) + r += errCmp + println(r) +} + +// Error: +// main/files/types/13f1_filetest.gno:20: cannot use .uverse.error as main.Error without explicit conversion \ No newline at end of file diff --git a/gnovm/tests/files/types/13f2_filetest.gno b/gnovm/tests/files/types/13f2_filetest.gno new file mode 100644 index 00000000000..0386fafa53f --- /dev/null +++ b/gnovm/tests/files/types/13f2_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + r := Error(0) + errCmp += r + println(errCmp) +} + +// Error: +// main/files/types/13f2_filetest.gno:20: operator += not defined on: .uverse.error diff --git a/gnovm/tests/files/types/13f3_filetest.gno b/gnovm/tests/files/types/13f3_filetest.gno new file mode 100644 index 00000000000..3b015e74b5d --- /dev/null +++ b/gnovm/tests/files/types/13f3_filetest.gno @@ -0,0 +1,32 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + e1 += e2 + println(e1) +} + +// Error: +// main/files/types/13f3_filetest.gno:27: operator += not defined on: main.E diff --git a/gnovm/tests/files/types/18a0_filetest.gno b/gnovm/tests/files/types/18a0_filetest.gno new file mode 100644 index 00000000000..31d88639bd8 --- /dev/null +++ b/gnovm/tests/files/types/18a0_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := int(1) + r &= int(1) + println(r) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/18a1_filetest.gno b/gnovm/tests/files/types/18a1_filetest.gno new file mode 100644 index 00000000000..c3b080cabf1 --- /dev/null +++ b/gnovm/tests/files/types/18a1_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := int(1) + r &= 1 + println(r) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/18a2_filetest.gno b/gnovm/tests/files/types/18a2_filetest.gno new file mode 100644 index 00000000000..ef5970417c9 --- /dev/null +++ b/gnovm/tests/files/types/18a2_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := int(1) + r &= int8(1) + println(r) +} + +// Error: +// main/files/types/18a2_filetest.gno:5: cannot use int8 as int diff --git a/gnovm/tests/files/types/18a3_filetest.gno b/gnovm/tests/files/types/18a3_filetest.gno new file mode 100644 index 00000000000..aa3de3b8944 --- /dev/null +++ b/gnovm/tests/files/types/18a3_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := int(1) + r &= 'a' + println(r) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/19a0_filetest.gno b/gnovm/tests/files/types/19a0_filetest.gno new file mode 100644 index 00000000000..03ad4c0bcea --- /dev/null +++ b/gnovm/tests/files/types/19a0_filetest.gno @@ -0,0 +1,14 @@ +package main + +func main() { + r := int(1) + println(r << 5) + println(r) + r <<= 5 + println(r) +} + +// Output: +// 32 +// 1 +// 32 diff --git a/gnovm/tests/files/types/19a1_filetest.gno b/gnovm/tests/files/types/19a1_filetest.gno new file mode 100644 index 00000000000..0cfee424bf2 --- /dev/null +++ b/gnovm/tests/files/types/19a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := int(1) + println(r << "a") +} + +// Error: +// main/files/types/19a1_filetest.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types/20a0_filetest.gno b/gnovm/tests/files/types/20a0_filetest.gno new file mode 100644 index 00000000000..fe43114da90 --- /dev/null +++ b/gnovm/tests/files/types/20a0_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(1) < int8(2)) +} + +// Error: +// main/files/types/20a0_filetest.gno:4: cannot use int as int8 diff --git a/gnovm/tests/files/types/20a1_filetest.gno b/gnovm/tests/files/types/20a1_filetest.gno new file mode 100644 index 00000000000..770bbc61d12 --- /dev/null +++ b/gnovm/tests/files/types/20a1_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(1) < 2) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/20a2_filetest.gno b/gnovm/tests/files/types/20a2_filetest.gno new file mode 100644 index 00000000000..887f23c13e0 --- /dev/null +++ b/gnovm/tests/files/types/20a2_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(1) < 'a') +} + +// Output: +// true diff --git a/gnovm/tests/files/types/20a3_filetest.gno b/gnovm/tests/files/types/20a3_filetest.gno new file mode 100644 index 00000000000..8afe6a84a5f --- /dev/null +++ b/gnovm/tests/files/types/20a3_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(1) < "a") +} + +// Error: +// main/files/types/20a3_filetest.gno:4: cannot use untyped string as IntKind diff --git a/gnovm/tests/files/types/20a4_filetest.gno b/gnovm/tests/files/types/20a4_filetest.gno new file mode 100644 index 00000000000..7339ac40893 --- /dev/null +++ b/gnovm/tests/files/types/20a4_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(true < 1) +} + +// Error: +// main/files/types/20a4_filetest.gno:4: cannot use untyped bool as BigintKind diff --git a/gnovm/tests/files/types/20a5_filetest.gno b/gnovm/tests/files/types/20a5_filetest.gno new file mode 100644 index 00000000000..f89ed14eddb --- /dev/null +++ b/gnovm/tests/files/types/20a5_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println("a" < "b") +} + +// Output: +// true diff --git a/gnovm/tests/files/types/21a0_filetest.gno b/gnovm/tests/files/types/21a0_filetest.gno new file mode 100644 index 00000000000..0a661854805 --- /dev/null +++ b/gnovm/tests/files/types/21a0_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var a int + a = int8(1) + println(a) +} + +// Error: +// main/files/types/21a0_filetest.gno:5: cannot use int8 as int diff --git a/gnovm/tests/files/types/21a1_filetest.gno b/gnovm/tests/files/types/21a1_filetest.gno new file mode 100644 index 00000000000..12486ff0ded --- /dev/null +++ b/gnovm/tests/files/types/21a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := int8(1) + println(a) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/22a0_filetest.gno b/gnovm/tests/files/types/22a0_filetest.gno new file mode 100644 index 00000000000..1904b59edb6 --- /dev/null +++ b/gnovm/tests/files/types/22a0_filetest.gno @@ -0,0 +1,18 @@ +package main + +type Int int8 + +func (i Int) Inc() { + i++ +} + +// right is typed const, can not use as its correspondence declared type +func main() { + var a Int + a = int8(0) + a.Inc() + println(a) +} + +// Error: +// main/files/types/22a0_filetest.gno:12: cannot use int8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/22a10_filetest.gno b/gnovm/tests/files/types/22a10_filetest.gno new file mode 100644 index 00000000000..cf1bf1c1759 --- /dev/null +++ b/gnovm/tests/files/types/22a10_filetest.gno @@ -0,0 +1,21 @@ +package main + +type word uint +type nat []word + +func (n nat) add(x, y nat) bool { + return true +} + +// parameter +func main() { + var abs nat + abs = []word{0} + x := []word{1} + y := []word{2} + + println(abs.add(x, y)) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a11_filetest.gno b/gnovm/tests/files/types/22a11_filetest.gno new file mode 100644 index 00000000000..e99eb493d7e --- /dev/null +++ b/gnovm/tests/files/types/22a11_filetest.gno @@ -0,0 +1,22 @@ +package main + +type BasicFunc func(int, int) int +type MyFunc BasicFunc + +func (f MyFunc) Apply(a, b int) int { + return f(a, b) +} + +func main() { + basicAdd := func(a, b int) int { + return a + b + } + var myAdd MyFunc + myAdd = basicAdd + + result := myAdd.Apply(2, 3) + println(result) +} + +// Output: +// 5 diff --git a/gnovm/tests/files/types/22a11a_filetest.gno b/gnovm/tests/files/types/22a11a_filetest.gno new file mode 100644 index 00000000000..fd79fa9fc47 --- /dev/null +++ b/gnovm/tests/files/types/22a11a_filetest.gno @@ -0,0 +1,21 @@ +package main + +type MyFunc func(int, int) int + +func (f MyFunc) Apply(a, b int) int { + return f(a, b) +} + +func main() { + basicAdd := func(a, b int) int { + return a + b + } + var myAdd MyFunc + myAdd = basicAdd + + result := myAdd.Apply(2, 3) + println(result) +} + +// Output: +// 5 diff --git a/gnovm/tests/files/types/22a12_filetest.gno b/gnovm/tests/files/types/22a12_filetest.gno new file mode 100644 index 00000000000..6173afd0c01 --- /dev/null +++ b/gnovm/tests/files/types/22a12_filetest.gno @@ -0,0 +1,20 @@ +package main + +type c uint +type word c +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + + abs = []c{0} + + println(abs.add()) +} + +// Error: +// main/files/types/22a12_filetest.gno:14: cannot use main.c as main.word without explicit conversion diff --git a/gnovm/tests/files/types/22a13_filetest.gno b/gnovm/tests/files/types/22a13_filetest.gno new file mode 100644 index 00000000000..8c143338cee --- /dev/null +++ b/gnovm/tests/files/types/22a13_filetest.gno @@ -0,0 +1,20 @@ +package main + +type c uint +type word c +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + + abs = []uint{0} + + println(abs.add()) +} + +// Error: +// main/files/types/22a13_filetest.gno:14: cannot use uint as main.word without explicit conversion diff --git a/gnovm/tests/files/types/22a14_filetest.gno b/gnovm/tests/files/types/22a14_filetest.gno new file mode 100644 index 00000000000..2385623808b --- /dev/null +++ b/gnovm/tests/files/types/22a14_filetest.gno @@ -0,0 +1,21 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// parameter +// TODO: should fix in another place, this should not work +func main() { + des := make([]nat, 2) + src := make([][]word, 2) + + src[0] = []word{0} + + copy(des, src) +} + +// Error: diff --git a/gnovm/tests/files/types/22a15_filetest.gno b/gnovm/tests/files/types/22a15_filetest.gno new file mode 100644 index 00000000000..bf307296caa --- /dev/null +++ b/gnovm/tests/files/types/22a15_filetest.gno @@ -0,0 +1,18 @@ +package main + +type word uint +type nat map[string]word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + abs = map[string]word{"test": word(0)} // unname-Composit to named DeclaredTypes + + println(abs.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a16_filetest.gno b/gnovm/tests/files/types/22a16_filetest.gno new file mode 100644 index 00000000000..b6a3088bd86 --- /dev/null +++ b/gnovm/tests/files/types/22a16_filetest.gno @@ -0,0 +1,25 @@ +package main + +type nat []int + +func main() { + + var a nat + a = []int{0} + b := []int{1} + + println(a) + println(b) + + a = nat{0} + b = a + + println(a) + println(b) +} + +// Output: +// (slice[(0 int)] main.nat) +// slice[(1 int)] +// (slice[(0 int)] main.nat) +// slice[(0 int)] diff --git a/gnovm/tests/files/types/22a17_filetest.gno b/gnovm/tests/files/types/22a17_filetest.gno new file mode 100644 index 00000000000..d47b1c83f8d --- /dev/null +++ b/gnovm/tests/files/types/22a17_filetest.gno @@ -0,0 +1,15 @@ +package main + +type Int int8 + +func Add(a, b Int) Int { + return a + b +} + +func main() { + r := Add(0, 1) + println(r) +} + +// Output: +// (1 main.Int) diff --git a/gnovm/tests/files/types/22a17a_filetest.gno b/gnovm/tests/files/types/22a17a_filetest.gno new file mode 100644 index 00000000000..e145dd61251 --- /dev/null +++ b/gnovm/tests/files/types/22a17a_filetest.gno @@ -0,0 +1,15 @@ +package main + +type Int int8 + +func Add(a, b Int) Int { + return a + b +} + +func main() { + r := Add(0, int8(1)) + println(r) +} + +// Error: +// main/files/types/22a17a_filetest.gno:10: cannot use int8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/22a17b_filetest.gno b/gnovm/tests/files/types/22a17b_filetest.gno new file mode 100644 index 00000000000..d9724e67ad6 --- /dev/null +++ b/gnovm/tests/files/types/22a17b_filetest.gno @@ -0,0 +1,16 @@ +package main + +type i8 int8 +type Int i8 + +func Add(a, b Int) Int { + return a + b +} + +func main() { + r := Add(0, i8(1)) + println(r) +} + +// Error: +// main/files/types/22a17b_filetest.gno:11: cannot use main.i8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/22a17c_filetest.gno b/gnovm/tests/files/types/22a17c_filetest.gno new file mode 100644 index 00000000000..7231e33f9b6 --- /dev/null +++ b/gnovm/tests/files/types/22a17c_filetest.gno @@ -0,0 +1,20 @@ +package main + +type word uint +type nat []word + +func Add(n1, n2 nat) bool { + return true +} + +// mapLit +func main() { + n0 := []word{0} + n1 := []word{1} + + r := Add(n0, n1) + println(r) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a17d_filetest.gno b/gnovm/tests/files/types/22a17d_filetest.gno new file mode 100644 index 00000000000..ffd8e4c3c27 --- /dev/null +++ b/gnovm/tests/files/types/22a17d_filetest.gno @@ -0,0 +1,20 @@ +package main + +type word uint +type nat []word + +func Add(n1, n2 nat) int { + return len(n1) + len(n2) +} + +// mapLit +func main() { + n0 := []word{0} + n1 := []word{1} + + r := Add(n0, n1) + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/22a17e_filetest.gno b/gnovm/tests/files/types/22a17e_filetest.gno new file mode 100644 index 00000000000..bd46a6f9d7a --- /dev/null +++ b/gnovm/tests/files/types/22a17e_filetest.gno @@ -0,0 +1,23 @@ +package main + +type word uint +type nat []word + +// receiver +func (n nat) add() bool { + return true +} + +func Gen() nat { + n := []word{0} + return n +} + +// mapLit +func main() { + r := Gen() + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a17f_filetest.gno b/gnovm/tests/files/types/22a17f_filetest.gno new file mode 100644 index 00000000000..bf82d9fea0d --- /dev/null +++ b/gnovm/tests/files/types/22a17f_filetest.gno @@ -0,0 +1,26 @@ +package main + +type word uint +type nat []word + +// receiver +func (n nat) add() bool { + return true +} + +func Gen2() (nat, nat) { + n0 := []word{0} + n1 := []word{1} + return n0, n1 +} + +// mapLit +func main() { + r1, r2 := Gen2() + println(r1.add()) + println(r2.add()) +} + +// Output: +// true +// true diff --git a/gnovm/tests/files/types/22a17g_filetest.gno b/gnovm/tests/files/types/22a17g_filetest.gno new file mode 100644 index 00000000000..7676395b252 --- /dev/null +++ b/gnovm/tests/files/types/22a17g_filetest.gno @@ -0,0 +1,36 @@ +package main + +import "fmt" + +type word uint +type nat []word + +// receiver +func (n nat) add() bool { + return true +} + +func Gen() interface{} { + n := []word{0} + return n +} + +// mapLit +func main() { + r := Gen() + + fmt.Printf("%T \n", r) + + switch r.(type) { + case nat: + println("nat") + case []word: + println("[]word") + default: + panic("should not happen") + } +} + +// Output: +// []uint +// []word diff --git a/gnovm/tests/files/types/22a17h_filetest.gno b/gnovm/tests/files/types/22a17h_filetest.gno new file mode 100644 index 00000000000..6acba35183c --- /dev/null +++ b/gnovm/tests/files/types/22a17h_filetest.gno @@ -0,0 +1,31 @@ +package main + +type word uint +type nat []word + +// receiver +func (n nat) add() bool { + return true +} + +func Gen() nat { + n := []word{0} + return n +} + +// mapLit +func main() { + r := Gen() + switch r.(type) { + case nat: + println("nat") + println(r.add()) + default: + println("should not happen") + + } +} + +// Output: +// nat +// true diff --git a/gnovm/tests/files/types/22a1_filetest.gno b/gnovm/tests/files/types/22a1_filetest.gno new file mode 100644 index 00000000000..52250bc4393 --- /dev/null +++ b/gnovm/tests/files/types/22a1_filetest.gno @@ -0,0 +1,17 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + abs = []word{0} // unname-Composit to named DeclaredTypes + println(abs.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a1a_filetest.gno b/gnovm/tests/files/types/22a1a_filetest.gno new file mode 100644 index 00000000000..3c9bc4d1e03 --- /dev/null +++ b/gnovm/tests/files/types/22a1a_filetest.gno @@ -0,0 +1,29 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + abs = []word{0} // unname-Composit to named DeclaredTypes + println(abs.add()) + + var w []word + w = abs + println(w) + switch w.(type) { + case []word: + println("[]word") + case nat: + println("should not happen") + } +} + +// Output: +// true +// slice[(0 main.word)] +// []word diff --git a/gnovm/tests/files/types/22a2_filetest.gno b/gnovm/tests/files/types/22a2_filetest.gno new file mode 100644 index 00000000000..62a38acbe20 --- /dev/null +++ b/gnovm/tests/files/types/22a2_filetest.gno @@ -0,0 +1,25 @@ +package main + +type word uint +type nat []word + +// structLit +type Int struct { + neg bool + abs nat +} + +func (n nat) add() bool { + return true +} + +func main() { + z := &Int{ + neg: true, + abs: []word{0}, + } + println(z.abs.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a3_filetest.gno b/gnovm/tests/files/types/22a3_filetest.gno new file mode 100644 index 00000000000..5b49241ae8b --- /dev/null +++ b/gnovm/tests/files/types/22a3_filetest.gno @@ -0,0 +1,25 @@ +package main + +type word uint +type nat []word + +type Int struct { + neg bool + abs nat +} + +func (n nat) add() bool { + return true +} + +func main() { + z := &Int{ + neg: true, + } + + z.abs = []word{0} + println(z.abs.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a4_filetest.gno b/gnovm/tests/files/types/22a4_filetest.gno new file mode 100644 index 00000000000..f66dcfe2ace --- /dev/null +++ b/gnovm/tests/files/types/22a4_filetest.gno @@ -0,0 +1,25 @@ +package main + +type word uint +type nat []word + +// receiver +func (n nat) add() bool { + return true +} + +// map +func main() { + items := map[string]nat{} + + n := []word{0} + + items["test"] = n + + r := items["test"] + + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a5_filetest.gno b/gnovm/tests/files/types/22a5_filetest.gno new file mode 100644 index 00000000000..3352f38083d --- /dev/null +++ b/gnovm/tests/files/types/22a5_filetest.gno @@ -0,0 +1,24 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// mapLit +func main() { + n := []word{0} + + items := map[string]nat{ + "test": n, + } + + r := items["test"] + + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a6_filetest.gno b/gnovm/tests/files/types/22a6_filetest.gno new file mode 100644 index 00000000000..f5beceec159 --- /dev/null +++ b/gnovm/tests/files/types/22a6_filetest.gno @@ -0,0 +1,20 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// sliceLit +func main() { + items := []nat{[]word{0}, []word{1}} + + r := items[0] + + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a7_filetest.gno b/gnovm/tests/files/types/22a7_filetest.gno new file mode 100644 index 00000000000..5b91ac72cc3 --- /dev/null +++ b/gnovm/tests/files/types/22a7_filetest.gno @@ -0,0 +1,20 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// sliceLit2 +func main() { + items := []nat{1: []word{0}, 2: []word{1}} + + r := items[1] + + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a8_filetest.gno b/gnovm/tests/files/types/22a8_filetest.gno new file mode 100644 index 00000000000..a6bc0f251a5 --- /dev/null +++ b/gnovm/tests/files/types/22a8_filetest.gno @@ -0,0 +1,24 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// slice append +func main() { + var items []nat + + n := []word{0} + + items = append(items, n) + + r := items[0] + + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/22a9_filetest.gno b/gnovm/tests/files/types/22a9_filetest.gno new file mode 100644 index 00000000000..b10c2f9ab8a --- /dev/null +++ b/gnovm/tests/files/types/22a9_filetest.gno @@ -0,0 +1,20 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// ArrayLit +func main() { + items := [3]nat{[]word{0}, []word{1}} + + r := items[0] + + println(r.add()) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/9a0_filetest.gno b/gnovm/tests/files/types/9a0_filetest.gno new file mode 100644 index 00000000000..2abfadea84d --- /dev/null +++ b/gnovm/tests/files/types/9a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(0) &^ int8(1)) +} + +// Error: +// main/files/types/9a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/9a1_filetest.gno b/gnovm/tests/files/types/9a1_filetest.gno new file mode 100644 index 00000000000..2a426d60e53 --- /dev/null +++ b/gnovm/tests/files/types/9a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) &^ Error2(0)) +} + +// Error: +// main/files/types/9a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/9b0_filetest.gno b/gnovm/tests/files/types/9b0_filetest.gno new file mode 100644 index 00000000000..835aae4de9a --- /dev/null +++ b/gnovm/tests/files/types/9b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + println(1 &^ Error(1)) + println(Error(1) &^ 1) +} + +// Output: +// (0 main.Error) +// (0 main.Error) diff --git a/gnovm/tests/files/types/9b1_filetest.gno b/gnovm/tests/files/types/9b1_filetest.gno new file mode 100644 index 00000000000..caabd382658 --- /dev/null +++ b/gnovm/tests/files/types/9b1_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// one untyped const, one typed const +func main() { + println(1 &^ Error(1)) + println(Error(1) &^ 1) +} + +// Output: +// error: 0 +// error: 0 diff --git a/gnovm/tests/files/types/9b2_filetest.gno b/gnovm/tests/files/types/9b2_filetest.gno new file mode 100644 index 00000000000..2fb7afdf91e --- /dev/null +++ b/gnovm/tests/files/types/9b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 &^ "a") +} + +// Error: +// main/files/types/9b2_filetest.gno:5: operator &^ not defined on: string diff --git a/gnovm/tests/files/types/9b3_filetest.gno b/gnovm/tests/files/types/9b3_filetest.gno new file mode 100644 index 00000000000..b0fe7e24d60 --- /dev/null +++ b/gnovm/tests/files/types/9b3_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" &^ "a") +} + +// Error: +// main/files/types/9b3_filetest.gno:5: operator &^ not defined on: string diff --git a/gnovm/tests/files/types/9b4_filetest.gno b/gnovm/tests/files/types/9b4_filetest.gno new file mode 100644 index 00000000000..10d4b05e7ab --- /dev/null +++ b/gnovm/tests/files/types/9b4_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 &^ 'a') +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/9d0_filetest.gno b/gnovm/tests/files/types/9d0_filetest.gno new file mode 100644 index 00000000000..8499acea7e9 --- /dev/null +++ b/gnovm/tests/files/types/9d0_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 &^ 1) +} + +// Error: +// main/files/types/9d0_filetest.gno:6: operator &^ not defined on: bigdec diff --git a/gnovm/tests/files/types/9d1_filetest.gno b/gnovm/tests/files/types/9d1_filetest.gno new file mode 100644 index 00000000000..cebcd08fb73 --- /dev/null +++ b/gnovm/tests/files/types/9d1_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println('a' &^ 'b') +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/9d2_filetest.gno b/gnovm/tests/files/types/9d2_filetest.gno new file mode 100644 index 00000000000..fc38bfcf907 --- /dev/null +++ b/gnovm/tests/files/types/9d2_filetest.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// TODO: dec value representation +var r rune + +func main() { + r = 'a' + println(r &^ 'b') +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/9d3_filetest.gno b/gnovm/tests/files/types/9d3_filetest.gno new file mode 100644 index 00000000000..64f0efc651a --- /dev/null +++ b/gnovm/tests/files/types/9d3_filetest.gno @@ -0,0 +1,15 @@ +package main + +// both untyped const +// TODO: dec value representation +var r1 rune +var r2 rune + +func main() { + r1 = 'a' + r2 = 'b' + println(r1 &^ r2) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/9d4_filetest.gno b/gnovm/tests/files/types/9d4_filetest.gno new file mode 100644 index 00000000000..f44ece6fb12 --- /dev/null +++ b/gnovm/tests/files/types/9d4_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 &^ 0) +} + +// Error: +// main/files/types/9d4_filetest.gno:6: operator &^ not defined on: bigdec diff --git a/gnovm/tests/files/types/9e0_filetest.gno b/gnovm/tests/files/types/9e0_filetest.gno new file mode 100644 index 00000000000..7f8d83a5f4e --- /dev/null +++ b/gnovm/tests/files/types/9e0_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + println(e1 &^ e2) +} + +// Error: +// main/files/types/9e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/9f0_filetest.gno b/gnovm/tests/files/types/9f0_filetest.gno new file mode 100644 index 00000000000..bd169eb32e0 --- /dev/null +++ b/gnovm/tests/files/types/9f0_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(1 &^ errCmp) +} + +// Error: +// main/files/types/9f0_filetest.gno:19: operator &^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/9f1_filetest.gno b/gnovm/tests/files/types/9f1_filetest.gno new file mode 100644 index 00000000000..ecb77efbe74 --- /dev/null +++ b/gnovm/tests/files/types/9f1_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + println(Error(0) &^ errCmp) +} + +// Error: +// main/files/types/9f1_filetest.gno:19: operator &^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/9f2_filetest.gno b/gnovm/tests/files/types/9f2_filetest.gno new file mode 100644 index 00000000000..81092b6b3ff --- /dev/null +++ b/gnovm/tests/files/types/9f2_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 &^ e2) +} + +// Error: +// main/files/types/9f2_filetest.gno:27: operator &^ not defined on: main.E diff --git a/gnovm/tests/files.bak/files/unary.gno b/gnovm/tests/files/unary.gno similarity index 100% rename from gnovm/tests/files.bak/files/unary.gno rename to gnovm/tests/files/unary.gno diff --git a/gnovm/tests/files.bak/files/unary1.gno b/gnovm/tests/files/unary1.gno similarity index 100% rename from gnovm/tests/files.bak/files/unary1.gno rename to gnovm/tests/files/unary1.gno diff --git a/gnovm/tests/files.bak/files/untyped0.gno b/gnovm/tests/files/untyped0.gno similarity index 100% rename from gnovm/tests/files.bak/files/untyped0.gno rename to gnovm/tests/files/untyped0.gno diff --git a/gnovm/tests/files.bak/files/untyped1.gno b/gnovm/tests/files/untyped1.gno similarity index 100% rename from gnovm/tests/files.bak/files/untyped1.gno rename to gnovm/tests/files/untyped1.gno diff --git a/gnovm/tests/files.bak/files/var.gno b/gnovm/tests/files/var.gno similarity index 100% rename from gnovm/tests/files.bak/files/var.gno rename to gnovm/tests/files/var.gno diff --git a/gnovm/tests/files.bak/files/var10.gno b/gnovm/tests/files/var10.gno similarity index 100% rename from gnovm/tests/files.bak/files/var10.gno rename to gnovm/tests/files/var10.gno diff --git a/gnovm/tests/files.bak/files/var11.gno b/gnovm/tests/files/var11.gno similarity index 100% rename from gnovm/tests/files.bak/files/var11.gno rename to gnovm/tests/files/var11.gno diff --git a/gnovm/tests/files.bak/files/var12.gno b/gnovm/tests/files/var12.gno similarity index 100% rename from gnovm/tests/files.bak/files/var12.gno rename to gnovm/tests/files/var12.gno diff --git a/gnovm/tests/files.bak/files/var13.gno b/gnovm/tests/files/var13.gno similarity index 100% rename from gnovm/tests/files.bak/files/var13.gno rename to gnovm/tests/files/var13.gno diff --git a/gnovm/tests/files.bak/files/var14.gno b/gnovm/tests/files/var14.gno similarity index 100% rename from gnovm/tests/files.bak/files/var14.gno rename to gnovm/tests/files/var14.gno diff --git a/gnovm/tests/files.bak/files/var15.gno b/gnovm/tests/files/var15.gno similarity index 100% rename from gnovm/tests/files.bak/files/var15.gno rename to gnovm/tests/files/var15.gno diff --git a/gnovm/tests/files.bak/files/var16.gno b/gnovm/tests/files/var16.gno similarity index 100% rename from gnovm/tests/files.bak/files/var16.gno rename to gnovm/tests/files/var16.gno diff --git a/gnovm/tests/files.bak/files/var17.gno b/gnovm/tests/files/var17.gno similarity index 100% rename from gnovm/tests/files.bak/files/var17.gno rename to gnovm/tests/files/var17.gno diff --git a/gnovm/tests/files.bak/files/var2.gno b/gnovm/tests/files/var2.gno similarity index 100% rename from gnovm/tests/files.bak/files/var2.gno rename to gnovm/tests/files/var2.gno diff --git a/gnovm/tests/files.bak/files/var3.gno b/gnovm/tests/files/var3.gno similarity index 100% rename from gnovm/tests/files.bak/files/var3.gno rename to gnovm/tests/files/var3.gno diff --git a/gnovm/tests/files.bak/files/var4.gno b/gnovm/tests/files/var4.gno similarity index 100% rename from gnovm/tests/files.bak/files/var4.gno rename to gnovm/tests/files/var4.gno diff --git a/gnovm/tests/files.bak/files/var5.gno b/gnovm/tests/files/var5.gno similarity index 100% rename from gnovm/tests/files.bak/files/var5.gno rename to gnovm/tests/files/var5.gno diff --git a/gnovm/tests/files.bak/files/var6.gno b/gnovm/tests/files/var6.gno similarity index 100% rename from gnovm/tests/files.bak/files/var6.gno rename to gnovm/tests/files/var6.gno diff --git a/gnovm/tests/files.bak/files/var7.gno b/gnovm/tests/files/var7.gno similarity index 100% rename from gnovm/tests/files.bak/files/var7.gno rename to gnovm/tests/files/var7.gno diff --git a/gnovm/tests/files.bak/files/var9.gno b/gnovm/tests/files/var9.gno similarity index 100% rename from gnovm/tests/files.bak/files/var9.gno rename to gnovm/tests/files/var9.gno diff --git a/gnovm/tests/files.bak/files/variadic.gno b/gnovm/tests/files/variadic.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic.gno rename to gnovm/tests/files/variadic.gno diff --git a/gnovm/tests/files.bak/files/variadic0.gno b/gnovm/tests/files/variadic0.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic0.gno rename to gnovm/tests/files/variadic0.gno diff --git a/gnovm/tests/files.bak/files/variadic1.gno b/gnovm/tests/files/variadic1.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic1.gno rename to gnovm/tests/files/variadic1.gno diff --git a/gnovm/tests/files.bak/files/variadic2.gno b/gnovm/tests/files/variadic2.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic2.gno rename to gnovm/tests/files/variadic2.gno diff --git a/gnovm/tests/files.bak/files/variadic3.gno b/gnovm/tests/files/variadic3.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic3.gno rename to gnovm/tests/files/variadic3.gno diff --git a/gnovm/tests/files.bak/files/variadic4.gno b/gnovm/tests/files/variadic4.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic4.gno rename to gnovm/tests/files/variadic4.gno diff --git a/gnovm/tests/files.bak/files/variadic5.gno b/gnovm/tests/files/variadic5.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic5.gno rename to gnovm/tests/files/variadic5.gno diff --git a/gnovm/tests/files.bak/files/variadic6.gno b/gnovm/tests/files/variadic6.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic6.gno rename to gnovm/tests/files/variadic6.gno diff --git a/gnovm/tests/files.bak/files/variadic9.gno b/gnovm/tests/files/variadic9.gno similarity index 100% rename from gnovm/tests/files.bak/files/variadic9.gno rename to gnovm/tests/files/variadic9.gno diff --git a/gnovm/tests/files.bak/files/xfactor_long.gno b/gnovm/tests/files/xfactor_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/xfactor_long.gno rename to gnovm/tests/files/xfactor_long.gno diff --git a/gnovm/tests/files.bak/files/xfib_long.gno b/gnovm/tests/files/xfib_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/xfib_long.gno rename to gnovm/tests/files/xfib_long.gno diff --git a/gnovm/tests/files.bak/files/zavltree.gno b/gnovm/tests/files/zavltree.gno similarity index 100% rename from gnovm/tests/files.bak/files/zavltree.gno rename to gnovm/tests/files/zavltree.gno diff --git a/gnovm/tests/files.bak/files/zavltree0.gno b/gnovm/tests/files/zavltree0.gno similarity index 100% rename from gnovm/tests/files.bak/files/zavltree0.gno rename to gnovm/tests/files/zavltree0.gno diff --git a/gnovm/tests/files.bak/files/zavltree1.gno b/gnovm/tests/files/zavltree1.gno similarity index 100% rename from gnovm/tests/files.bak/files/zavltree1.gno rename to gnovm/tests/files/zavltree1.gno diff --git a/gnovm/tests/files.bak/files/zpersist_valids.gno b/gnovm/tests/files/zpersist_valids.gnoa similarity index 99% rename from gnovm/tests/files.bak/files/zpersist_valids.gno rename to gnovm/tests/files/zpersist_valids.gnoa index 2709a243adf..1095b1ae02b 100644 --- a/gnovm/tests/files.bak/files/zpersist_valids.gno +++ b/gnovm/tests/files/zpersist_valids.gnoa @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/demo/tests_test -package tests_test +package main type myStruct struct { A int diff --git a/gnovm/tests/files.bak/files/zrealm0.gno b/gnovm/tests/files/zrealm/zrealm0.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm0.gno rename to gnovm/tests/files/zrealm/zrealm0.gno index 1b8f37540b3..f29360d666c 100644 --- a/gnovm/tests/files.bak/files/zrealm0.gno +++ b/gnovm/tests/files/zrealm/zrealm0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main var root interface{} diff --git a/gnovm/tests/files.bak/files/zrealm1.gno b/gnovm/tests/files/zrealm/zrealm1.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm1.gno rename to gnovm/tests/files/zrealm/zrealm1.gno index 1dea983a49d..b75a0666a22 100644 --- a/gnovm/tests/files.bak/files/zrealm1.gno +++ b/gnovm/tests/files/zrealm/zrealm1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main var root Node diff --git a/gnovm/tests/files.bak/files/zrealm10.gno b/gnovm/tests/files/zrealm/zrealm10.gno similarity index 98% rename from gnovm/tests/files.bak/files/zrealm10.gno rename to gnovm/tests/files/zrealm/zrealm10.gno index 97bb9d439e2..af4ab478416 100644 --- a/gnovm/tests/files.bak/files/zrealm10.gno +++ b/gnovm/tests/files/zrealm/zrealm10.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main type MyStruct struct { Field int diff --git a/gnovm/tests/files.bak/files/zrealm11.gno b/gnovm/tests/files/zrealm/zrealm11.gno similarity index 98% rename from gnovm/tests/files.bak/files/zrealm11.gno rename to gnovm/tests/files/zrealm/zrealm11.gno index 0f4d26a44c0..6372a69d777 100644 --- a/gnovm/tests/files.bak/files/zrealm11.gno +++ b/gnovm/tests/files/zrealm/zrealm11.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main type MyStruct struct { Field int diff --git a/gnovm/tests/files.bak/files/zrealm12.gno b/gnovm/tests/files/zrealm/zrealm12.gno similarity index 97% rename from gnovm/tests/files.bak/files/zrealm12.gno rename to gnovm/tests/files/zrealm/zrealm12.gno index 0049cba6073..f67e7d81068 100644 --- a/gnovm/tests/files.bak/files/zrealm12.gno +++ b/gnovm/tests/files/zrealm/zrealm12.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "std" diff --git a/gnovm/tests/files.bak/files/zrealm2.gno b/gnovm/tests/files/zrealm/zrealm2.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm2.gno rename to gnovm/tests/files/zrealm/zrealm2.gno index bf321c42d31..60031e31d1e 100644 --- a/gnovm/tests/files.bak/files/zrealm2.gno +++ b/gnovm/tests/files/zrealm/zrealm2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main var root Node diff --git a/gnovm/tests/files.bak/files/zrealm3.gno b/gnovm/tests/files/zrealm/zrealm3.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm3.gno rename to gnovm/tests/files/zrealm/zrealm3.gno index 4ff8dd1a531..58f9fadbd80 100644 --- a/gnovm/tests/files.bak/files/zrealm3.gno +++ b/gnovm/tests/files/zrealm/zrealm3.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main var root *Node diff --git a/gnovm/tests/files.bak/files/zrealm4.gno b/gnovm/tests/files/zrealm/zrealm4.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm4.gno rename to gnovm/tests/files/zrealm/zrealm4.gno index 2e2fa4e8d09..fca8cacae81 100644 --- a/gnovm/tests/files.bak/files/zrealm4.gno +++ b/gnovm/tests/files/zrealm/zrealm4.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files.bak/files/zrealm5.gno b/gnovm/tests/files/zrealm/zrealm5.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm5.gno rename to gnovm/tests/files/zrealm/zrealm5.gno index 8ad3e7400b3..77a7140b54d 100644 --- a/gnovm/tests/files.bak/files/zrealm5.gno +++ b/gnovm/tests/files/zrealm/zrealm5.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files.bak/files/zrealm6.gno b/gnovm/tests/files/zrealm/zrealm6.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm6.gno rename to gnovm/tests/files/zrealm/zrealm6.gno index fbe320ad962..54649fc7096 100644 --- a/gnovm/tests/files.bak/files/zrealm6.gno +++ b/gnovm/tests/files/zrealm/zrealm6.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files.bak/files/zrealm7.gno b/gnovm/tests/files/zrealm/zrealm7.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm7.gno rename to gnovm/tests/files/zrealm/zrealm7.gno index 689d55d3916..e46cdb3409e 100644 --- a/gnovm/tests/files.bak/files/zrealm7.gno +++ b/gnovm/tests/files/zrealm/zrealm7.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files.bak/files/zrealm8.gno b/gnovm/tests/files/zrealm/zrealm8.gno similarity index 98% rename from gnovm/tests/files.bak/files/zrealm8.gno rename to gnovm/tests/files/zrealm/zrealm8.gno index 1452301dac6..5c271a95a59 100644 --- a/gnovm/tests/files.bak/files/zrealm8.gno +++ b/gnovm/tests/files/zrealm/zrealm8.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main type MyStruct struct { Field int diff --git a/gnovm/tests/files.bak/files/zrealm9.gno b/gnovm/tests/files/zrealm/zrealm9.gno similarity index 98% rename from gnovm/tests/files.bak/files/zrealm9.gno rename to gnovm/tests/files/zrealm/zrealm9.gno index 306ca02a92a..5aa5c0a6cb2 100644 --- a/gnovm/tests/files.bak/files/zrealm9.gno +++ b/gnovm/tests/files/zrealm/zrealm9.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main type MyStruct struct { Field int diff --git a/gnovm/tests/files.bak/files/zrealm_avl0.gno b/gnovm/tests/files/zrealm/zrealm_avl0.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm_avl0.gno rename to gnovm/tests/files/zrealm/zrealm_avl0.gno index 814e19d6d49..4360aca0ad9 100644 --- a/gnovm/tests/files.bak/files/zrealm_avl0.gno +++ b/gnovm/tests/files/zrealm/zrealm_avl0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "gno.land/p/demo/avl" diff --git a/gnovm/tests/files.bak/files/zrealm_avl1.gno b/gnovm/tests/files/zrealm/zrealm_avl1.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm_avl1.gno rename to gnovm/tests/files/zrealm/zrealm_avl1.gno index 410e9e93601..49034d2ce9b 100644 --- a/gnovm/tests/files.bak/files/zrealm_avl1.gno +++ b/gnovm/tests/files/zrealm/zrealm_avl1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "gno.land/p/demo/avl" diff --git a/gnovm/tests/files.bak/files/zrealm_avl2.gno b/gnovm/tests/files/zrealm/zrealm_avl2.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm_avl2.gno rename to gnovm/tests/files/zrealm/zrealm_avl2.gno index 8ecf6ba52bc..cbd31bd2ead 100644 --- a/gnovm/tests/files.bak/files/zrealm_avl2.gno +++ b/gnovm/tests/files/zrealm/zrealm_avl2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "gno.land/p/demo/avl" diff --git a/gnovm/tests/files.bak/files/zrealm_const.gno b/gnovm/tests/files/zrealm/zrealm_const.gno similarity index 85% rename from gnovm/tests/files.bak/files/zrealm_const.gno rename to gnovm/tests/files/zrealm/zrealm_const.gno index 210ceff3373..163adfdd014 100644 --- a/gnovm/tests/files.bak/files/zrealm_const.gno +++ b/gnovm/tests/files/zrealm/zrealm_const.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/const_test -package const_test +package main import "std" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm0.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm0.gno similarity index 92% rename from gnovm/tests/files.bak/files/zrealm_crossrealm0.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm0.gno index 5bf34c2c852..cd19eb6b5fb 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm0.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm1.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm1.gno similarity index 93% rename from gnovm/tests/files.bak/files/zrealm_crossrealm1.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm1.gno index 686468b40c7..20c0be864a4 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm1.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm10.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm10.gno similarity index 89% rename from gnovm/tests/files.bak/files/zrealm_crossrealm10.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm10.gno index 73ad3ea74d7..7e6e0127f2c 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm10.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm10.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm11.gno similarity index 98% rename from gnovm/tests/files.bak/files/zrealm_crossrealm11.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm11.gno index b250b07bbac..7194d86d016 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm11.gno @@ -1,14 +1,11 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( - "std" - "strings" - ptests "gno.land/p/demo/tests" "gno.land/p/demo/ufmt" rtests "gno.land/r/demo/tests" - testfoo "gno.land/r/demo/tests_foo" + "std" ) func getPrevRealm() std.Realm { diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm12.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm12.gno similarity index 83% rename from gnovm/tests/files.bak/files/zrealm_crossrealm12.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm12.gno index ef8ea141ac5..c7ec80e084a 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm12.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm12.gno @@ -1,23 +1,23 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( - "std" "fmt" + "std" psubtests "gno.land/p/demo/tests/subtests" rsubtests "gno.land/r/demo/tests/subtests" ) func main() { - tests := []struct{ + tests := []struct { fn func() std.Realm }{ - { std.CurrentRealm }, - { psubtests.GetCurrentRealm }, - { rsubtests.GetCurrentRealm }, + {std.CurrentRealm}, + {psubtests.GetCurrentRealm}, + {rsubtests.GetCurrentRealm}, } - + for _, test := range tests { r := test.fn() diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm2.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm2.gno similarity index 94% rename from gnovm/tests/files.bak/files/zrealm_crossrealm2.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm2.gno index cfcd4e6898c..5c1b3060461 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm2.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm3.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm3.gno similarity index 94% rename from gnovm/tests/files.bak/files/zrealm_crossrealm3.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm3.gno index 6aa9c5247d8..5b01fafecaf 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm3.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm3.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm4.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm4.gno similarity index 94% rename from gnovm/tests/files.bak/files/zrealm_crossrealm4.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm4.gno index 6aa9c5247d8..5b01fafecaf 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm4.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm4.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm5.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm5.gno similarity index 94% rename from gnovm/tests/files.bak/files/zrealm_crossrealm5.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm5.gno index 6aa9c5247d8..5b01fafecaf 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm5.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm5.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm6.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm6.gno similarity index 93% rename from gnovm/tests/files.bak/files/zrealm_crossrealm6.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm6.gno index d2e7a4b096a..3ba03fc5b30 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm6.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm6.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm7.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm7.gno similarity index 89% rename from gnovm/tests/files.bak/files/zrealm_crossrealm7.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm7.gno index 5a4dc3002cc..4cdbbfc2030 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm7.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm7.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm8.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm8.gno similarity index 89% rename from gnovm/tests/files.bak/files/zrealm_crossrealm8.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm8.gno index f03085ff4c7..2bbb7a323ad 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm8.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm8.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_crossrealm9.gno b/gnovm/tests/files/zrealm/zrealm_crossrealm9.gno similarity index 89% rename from gnovm/tests/files.bak/files/zrealm_crossrealm9.gno rename to gnovm/tests/files/zrealm/zrealm_crossrealm9.gno index 96a7a3484d7..98eb7556286 100644 --- a/gnovm/tests/files.bak/files/zrealm_crossrealm9.gno +++ b/gnovm/tests/files/zrealm/zrealm_crossrealm9.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test +package main import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_example.gno b/gnovm/tests/files/zrealm/zrealm_example.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm_example.gno rename to gnovm/tests/files/zrealm/zrealm_example.gno index 1ce70c04390..cd1c6a301af 100644 --- a/gnovm/tests/files.bak/files/zrealm_example.gno +++ b/gnovm/tests/files/zrealm/zrealm_example.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/example -package example +package main import ( "gno.land/p/demo/dom" diff --git a/gnovm/tests/files.bak/files/zrealm_map0.gno b/gnovm/tests/files/zrealm/zrealm_map0.gno similarity index 93% rename from gnovm/tests/files.bak/files/zrealm_map0.gno rename to gnovm/tests/files/zrealm/zrealm_map0.gno index 1dd2deff755..bb5ba9f6d06 100644 --- a/gnovm/tests/files.bak/files/zrealm_map0.gno +++ b/gnovm/tests/files/zrealm/zrealm_map0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main var m map[string]int diff --git a/gnovm/tests/files.bak/files/zrealm_std0.gno b/gnovm/tests/files/zrealm/zrealm_std0.gno similarity index 91% rename from gnovm/tests/files.bak/files/zrealm_std0.gno rename to gnovm/tests/files/zrealm/zrealm_std0.gno index 3f6bdae2537..fe2c1db0e11 100644 --- a/gnovm/tests/files.bak/files/zrealm_std0.gno +++ b/gnovm/tests/files/zrealm/zrealm_std0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package std_test +package main import ( "std" diff --git a/gnovm/tests/files.bak/files/zrealm_std1.gno b/gnovm/tests/files/zrealm/zrealm_std1.gno similarity index 97% rename from gnovm/tests/files.bak/files/zrealm_std1.gno rename to gnovm/tests/files/zrealm/zrealm_std1.gno index 87f75bcb871..2308520b29b 100644 --- a/gnovm/tests/files.bak/files/zrealm_std1.gno +++ b/gnovm/tests/files/zrealm/zrealm_std1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package std_test +package main import ( "std" diff --git a/gnovm/tests/files.bak/files/zrealm_std2.gno b/gnovm/tests/files/zrealm/zrealm_std2.gno similarity index 97% rename from gnovm/tests/files.bak/files/zrealm_std2.gno rename to gnovm/tests/files/zrealm/zrealm_std2.gno index 1ae1fb4a881..25c879b5573 100644 --- a/gnovm/tests/files.bak/files/zrealm_std2.gno +++ b/gnovm/tests/files/zrealm/zrealm_std2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package std_test +package main import ( "std" diff --git a/gnovm/tests/files.bak/files/zrealm_std3.gno b/gnovm/tests/files/zrealm/zrealm_std3.gno similarity index 93% rename from gnovm/tests/files.bak/files/zrealm_std3.gno rename to gnovm/tests/files/zrealm/zrealm_std3.gno index c13feffa42c..f1925a860bd 100644 --- a/gnovm/tests/files.bak/files/zrealm_std3.gno +++ b/gnovm/tests/files/zrealm/zrealm_std3.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package std_test +package main import ( "std" diff --git a/gnovm/tests/files.bak/files/zrealm_std4.gno b/gnovm/tests/files/zrealm/zrealm_std4.gno similarity index 95% rename from gnovm/tests/files.bak/files/zrealm_std4.gno rename to gnovm/tests/files/zrealm/zrealm_std4.gno index 4b8a1d6dfb3..d1b5dba9b7f 100644 --- a/gnovm/tests/files.bak/files/zrealm_std4.gno +++ b/gnovm/tests/files/zrealm/zrealm_std4.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package std_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_std5.gno b/gnovm/tests/files/zrealm/zrealm_std5.gno similarity index 95% rename from gnovm/tests/files.bak/files/zrealm_std5.gno rename to gnovm/tests/files/zrealm/zrealm_std5.gno index 86d26eef368..37a61dea6c8 100644 --- a/gnovm/tests/files.bak/files/zrealm_std5.gno +++ b/gnovm/tests/files/zrealm/zrealm_std5.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package std_test +package main import ( "gno.land/p/demo/tests" // NOTE: not a realm path. diff --git a/gnovm/tests/files.bak/files/zrealm_std6.gno b/gnovm/tests/files/zrealm/zrealm_std6.gno similarity index 93% rename from gnovm/tests/files.bak/files/zrealm_std6.gno rename to gnovm/tests/files/zrealm/zrealm_std6.gno index fb9e0f825a2..7280d12345b 100644 --- a/gnovm/tests/files.bak/files/zrealm_std6.gno +++ b/gnovm/tests/files/zrealm/zrealm_std6.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package test +package main import ( "std" diff --git a/gnovm/tests/files.bak/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm/zrealm_tests0.gno similarity index 99% rename from gnovm/tests/files.bak/files/zrealm_tests0.gno rename to gnovm/tests/files/zrealm/zrealm_tests0.gno index cfb1f08c6f4..f26be980ab8 100644 --- a/gnovm/tests/files.bak/files/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm/zrealm_tests0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/demo/tests_test -package tests_test +package main import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files.bak/files/zrealm_testutils0.gno b/gnovm/tests/files/zrealm/zrealm_testutils0.gno similarity index 92% rename from gnovm/tests/files.bak/files/zrealm_testutils0.gno rename to gnovm/tests/files/zrealm/zrealm_testutils0.gno index 33322f76719..3a8f48c0f0b 100644 --- a/gnovm/tests/files.bak/files/zrealm_testutils0.gno +++ b/gnovm/tests/files/zrealm/zrealm_testutils0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/testutils_test -package testutils_test +package main import ( "gno.land/p/demo/testutils" diff --git a/gnovm/tests/files.bak/files/zregexp_stdlibs.gno b/gnovm/tests/files/zregexp_stdlibs.gno similarity index 100% rename from gnovm/tests/files.bak/files/zregexp_stdlibs.gno rename to gnovm/tests/files/zregexp_stdlibs.gno diff --git a/gnovm/tests/files.bak/files/zsolitaire_long.gno b/gnovm/tests/files/zsolitaire_long.gno similarity index 100% rename from gnovm/tests/files.bak/files/zsolitaire_long.gno rename to gnovm/tests/files/zsolitaire_long.gno From 814354b1fe1ab0b4facb7ad9f990f603daad73d7 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 1 Dec 2023 07:57:37 +0800 Subject: [PATCH 008/193] make test work --- gnovm/pkg/gnolang/debug.go | 15 ++ gnovm/pkg/gnolang/op_binary.go | 18 +-- gnovm/pkg/gnolang/preprocess.go | 134 ++++++++++-------- gnovm/pkg/gnolang/types.go | 28 ++-- gnovm/pkg/gnolang/values_conversions.go | 6 +- gnovm/tests/files/{zrealm => }/zrealm0.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm1.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm10.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm11.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm12.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm2.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm3.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm4.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm5.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm6.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm7.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm8.gno | 2 +- gnovm/tests/files/{zrealm => }/zrealm9.gno | 2 +- .../tests/files/{zrealm => }/zrealm_avl0.gno | 2 +- .../tests/files/{zrealm => }/zrealm_avl1.gno | 2 +- .../tests/files/{zrealm => }/zrealm_avl2.gno | 2 +- .../tests/files/{zrealm => }/zrealm_const.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm0.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm1.gno | 2 +- .../{zrealm => }/zrealm_crossrealm10.gno | 2 +- .../{zrealm => }/zrealm_crossrealm11.gno | 2 +- .../{zrealm => }/zrealm_crossrealm12.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm2.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm3.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm4.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm5.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm6.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm7.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm8.gno | 2 +- .../files/{zrealm => }/zrealm_crossrealm9.gno | 2 +- .../files/{zrealm => }/zrealm_example.gno | 2 +- .../tests/files/{zrealm => }/zrealm_map0.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std0.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std1.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std2.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std3.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std4.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std5.gno | 2 +- .../tests/files/{zrealm => }/zrealm_std6.gno | 6 +- .../files/{zrealm => }/zrealm_tests0.gno | 2 +- .../files/{zrealm => }/zrealm_testutils0.gno | 2 +- 46 files changed, 161 insertions(+), 126 deletions(-) rename gnovm/tests/files/{zrealm => }/zrealm0.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm1.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm10.gno (98%) rename gnovm/tests/files/{zrealm => }/zrealm11.gno (98%) rename gnovm/tests/files/{zrealm => }/zrealm12.gno (97%) rename gnovm/tests/files/{zrealm => }/zrealm2.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm3.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm4.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm5.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm6.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm7.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm8.gno (98%) rename gnovm/tests/files/{zrealm => }/zrealm9.gno (98%) rename gnovm/tests/files/{zrealm => }/zrealm_avl0.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm_avl1.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm_avl2.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm_const.gno (85%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm0.gno (92%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm1.gno (93%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm10.gno (89%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm11.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm12.gno (97%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm2.gno (94%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm3.gno (94%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm4.gno (94%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm5.gno (94%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm6.gno (93%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm7.gno (89%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm8.gno (89%) rename gnovm/tests/files/{zrealm => }/zrealm_crossrealm9.gno (89%) rename gnovm/tests/files/{zrealm => }/zrealm_example.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm_map0.gno (93%) rename gnovm/tests/files/{zrealm => }/zrealm_std0.gno (91%) rename gnovm/tests/files/{zrealm => }/zrealm_std1.gno (97%) rename gnovm/tests/files/{zrealm => }/zrealm_std2.gno (97%) rename gnovm/tests/files/{zrealm => }/zrealm_std3.gno (93%) rename gnovm/tests/files/{zrealm => }/zrealm_std4.gno (95%) rename gnovm/tests/files/{zrealm => }/zrealm_std5.gno (95%) rename gnovm/tests/files/{zrealm => }/zrealm_std6.gno (56%) rename gnovm/tests/files/{zrealm => }/zrealm_tests0.gno (99%) rename gnovm/tests/files/{zrealm => }/zrealm_testutils0.gno (92%) diff --git a/gnovm/pkg/gnolang/debug.go b/gnovm/pkg/gnolang/debug.go index cb21da12ef2..6714116fd41 100644 --- a/gnovm/pkg/gnolang/debug.go +++ b/gnovm/pkg/gnolang/debug.go @@ -19,13 +19,16 @@ import ( // before calling debug.Println or debug.Printf. type debugging bool +type debugPreprocess bool // using a const is probably faster. // const debug debugging = true // or flip var debug debugging = false +var depp debugPreprocess = false func init() { debug = os.Getenv("DEBUG") == "1" + depp = os.Getenv("DEPP") == "1" if debug { go func() { // e.g. @@ -63,6 +66,18 @@ func (d debugging) Printf(format string, args ...interface{}) { } } +func (d debugPreprocess) Println(args ...interface{}) { + if d { + fmt.Println(append([]interface{}{"DEBUG:"}, args...)...) + } +} + +func (d debugPreprocess) Printf(format string, args ...interface{}) { + if d { + fmt.Printf("DEBUG: "+format, args...) + } +} + var derrors []string = nil // Instead of actually panic'ing, which messes with tests, errors are sometimes diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 84bf2578078..fe6ae768983 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -71,7 +71,7 @@ func (m *Machine) doOpLand() { } func (m *Machine) doOpEql() { - println("doOpEql") + depp.Println("doOpEql") m.PopExpr() // get right and left operands. @@ -80,7 +80,7 @@ func (m *Machine) doOpEql() { if debug { assertEqualityTypes(lv.T, rv.T) } - fmt.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + depp.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool //// strict type match check, after preprocess @@ -108,7 +108,7 @@ func (m *Machine) doOpEql() { } func (m *Machine) doOpNeq() { - println("doOpNeq") + depp.Println("doOpNeq") m.PopExpr() // get right and left operands. @@ -117,7 +117,7 @@ func (m *Machine) doOpNeq() { if debug { assertEqualityTypes(lv.T, rv.T) } - fmt.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + depp.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool //// strict type match check, after preprocess @@ -407,11 +407,11 @@ func isEql(store Store, lv, rv *TypedValue) bool { case Int32Kind: return (lv.GetInt32() == rv.GetInt32()) case Int64Kind: - println("int64 kind") - println("lv kind: ", lv.T.Kind()) - println("rv kind: ", rv.T.Kind()) - println("lv int64", lv.GetInt64()) - println("rv int64", rv.GetInt64()) + depp.Println("int64 kind") + depp.Println("lv kind: ", lv.T.Kind()) + depp.Println("rv kind: ", rv.T.Kind()) + depp.Println("lv int64", lv.GetInt64()) + depp.Println("rv int64", rv.GetInt64()) return (lv.GetInt64() == rv.GetInt64()) case UintKind: return (lv.GetUint() == rv.GetUint()) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 557daa611bd..9e537957b3c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,10 +2,9 @@ package gnolang import ( "fmt" + "github.com/gnolang/gno/tm2/pkg/errors" "math/big" "reflect" - - "github.com/gnolang/gno/tm2/pkg/errors" ) // In the case of a *FileSet, some declaration steps have to happen @@ -739,8 +738,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: - println("---binary expr---") - fmt.Printf("OP: %v \n", n.Op) + depp.Printf("--binary expr---, OP: %v \n", n.Op) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. @@ -762,14 +760,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) if lic { - println("left is const") + depp.Println("left is const") if ric { - println("right is const") + depp.Println("right is const") // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. if !isShift { - println("not shift") + depp.Println("not shift") //// is this implied implicitly? rest of the binary operators after SHL and SHR is excluded //// Note: this check happens only when left and right are both typed, if not, the checkOrConvert logic will be run if cmp not 0 //// TODO: checkOrConvertType, same way around @@ -787,11 +785,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // at least one of left or right is untyped cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // this always implies untyped>? - println("cmp < 0, ->") + depp.Println("cmp < 0, ->") // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rcx.T, n.Op, false) } else if cmp == 0 { - println("cmp == 0") + depp.Println("cmp == 0") // NOTE: the following doesn't work. // TODO: make it work. // convert n.Left to right type, @@ -800,7 +798,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // also need to check checkOrConvertType(store, last, &n.Left, rcx.T, n.Op, false) } else { // this always implies untyped>? - println("cmp > 0, <-") + depp.Println("cmp > 0, <-") // convert n.Right to left type. checkOrConvertType(store, last, &n.Right, lcx.T, n.Op, false) } @@ -809,10 +807,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { - println("left is untyped const, right not const") + depp.Println("left is untyped const, right not const") // Left untyped const, Right not ---------------- if rnt, ok := rt.(*NativeType); ok { - println("right native type") + depp.Println("right native type") if isShift { panic("should not happen") } @@ -836,22 +834,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - println("right not native") + depp.Println("right not native") if isShift { // nothing to do, right type is (already) uint type. // we don't yet know what this type should be, // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). } else { - println("not shift, convert") - fmt.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) - fmt.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) + depp.Println("not shift, convert") + depp.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) + depp.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const - println("left is typed const, right is not const, should check type too") + depp.Println("left is typed const, right is not const, should check type too") // NOTE: only in case == or !=, should using assert to make sure left and right equality // in case of add, etc. should use checkOrConvert // TODO: expand? @@ -863,15 +861,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } else if lcx.T == nil { - println("lcx.T is nil") + depp.Println("lcx.T is nil") // convert n.Left to typed-nil type. checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } - + // TODO: 912 line? } else if ric { - println("left not const, right is const") + depp.Println("left not const, right is const") if isUntyped(rcx.T) { - println("right untyped") + depp.Println("right untyped") // Left not, Right untyped const ---------------- if isShift { if baseOf(rt) != UintType { @@ -908,14 +906,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } //} else if rcx.T == nil { } else if rcx.T == nil { - println("rcx.T == nil ") + depp.Println("rcx.T == nil ") // convert n.Right to typed-nil type. checkOrConvertType(store, last, &n.Right, lt, n.Op, false) } else if !isShift { checkOrConvertType(store, last, &n.Right, lt, n.Op, false) } } else { - fmt.Printf("both not const, lt: %v, rt:%v \n", lt, rt) + depp.Printf("both not const, lt: %v, rt:%v \n", lt, rt) if n.Op == SHL || n.Op == SHR { // shift operator, nothing yet to do. code like this will work //package main @@ -965,11 +963,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // computed in gno, never with // reflect. } else { - println("no-shift, non-const, need all go through check") + depp.Println("no-shift, non-const, need all go through check") // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) - println("liu", liu) - println("rie", riu) + depp.Println("liu", liu) + depp.Println("rie", riu) if liu { if riu { if lt.TypeID() != rt.TypeID() { @@ -978,7 +976,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Left, n.Op, n.Right)) } } else { - println("left untyped, right is typed") + depp.Println("left untyped, right is typed") checkOrConvertType(store, last, &n.Left, rt, n.Op, false) } } else if riu { @@ -1548,7 +1546,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: - fmt.Printf("---AssignStmt, Op: %v \n", n.Op) + depp.Printf("---AssignStmt, Op: %v \n", n.Op) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { // Rhs consts become default *ConstExprs. @@ -1623,7 +1621,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { // ASSIGN. - println("assign") + depp.Println("assign") // NOTE: Keep in sync with DEFINE above. if len(n.Lhs) > len(n.Rhs) { // TODO dry code w/ above. @@ -1664,11 +1662,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Special case if shift assign <<= or >>=. checkOrConvertType(store, last, &n.Rhs[0], UintType, n.Op, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { - fmt.Printf("op is %v \n", n.Op) + depp.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, // TODO: assert length - println("len of LHS: ", len(n.Lhs)) - println("len of RHS: ", len(n.Rhs)) + depp.Println("len of LHS: ", len(n.Lhs)) + depp.Println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) //rt := evalStaticTypeOf(store, last, n.Rhs[0]) @@ -1682,20 +1680,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Rhs[0], lt, n.Op, false) //} } else { // all else, like BAND_ASSIGN, etc - println("case: a, b = x, y") - fmt.Printf("Op: %v \n", n.Op) + depp.Println("case: a, b = x, y") + depp.Printf("Op: %v \n", n.Op) // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) // is x or y is untyped, convert, else check type rt := evalStaticTypeOf(store, last, n.Rhs[i]) if isUntyped(rt) { - println("rt is untyped, convert") + depp.Println("rt is untyped, convert") // is untyped // converts if rx is "nil". checkOrConvertType(store, last, &n.Rhs[i], lt, n.Op, false) } else { - println("rt not untyped, check strict") + depp.Println("rt not untyped, check strict") //if lt.TypeID() != rt.TypeID() { // panic("mismatch type for Assign, in case: a, b = x, y") //} @@ -2372,17 +2370,17 @@ func isConstType(x Expr) bool { } func cmpSpecificity(t1, t2 Type) int { - fmt.Printf("cmpSpecificity, t1:%v, t2:%v \n", t1, t2) + depp.Printf("cmpSpecificity, t1:%v, t2:%v \n", t1, t2) t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { - println("t1 i prime type") + depp.Println("t1 i prime type") t1s = t1p.Specificity() } if t2p, ok := t2.(PrimitiveType); ok { - println("t2 i prime type") + depp.Println("t2 i prime type") t2s = t2p.Specificity() } - println("t1s, t2s: ", t1s, t2s) + depp.Println("t1s, t2s: ", t1s, t2s) if t1s < t2s { // NOTE: higher specificity has lower value, so backwards. return 1 @@ -2395,7 +2393,7 @@ func cmpSpecificity(t1, t2 Type) int { // for special case of index conversion func convertConstType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { - fmt.Printf("convertConstType, x: %v, t:%v, \n", x, t) + depp.Printf("convertConstType, x: %v, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { convertConst(store, last, cx, t) } @@ -2412,19 +2410,21 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, op Word, aut // TODO: but if it's bind to ops like +, type conversion should be checked // TODO: this should be awareness at its origin func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { - fmt.Printf("checkOrConvertType, x: %v, t:%v, \n", x, t) + depp.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { - println("ConstExpr") // here we should check too, e.g. primitive to declared type is convertable - checkType(cx.T, t, op, autoNative) - fmt.Printf("convertConst, cx: %v \n", cx) + if _, ok := t.(*NativeType); !ok { // not native type + depp.Println("ConstExpr is not nativeType, go check") + checkType(cx.T, t, op, autoNative) + } + depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - println("SHL or SHR") + depp.Println("SHL or SHR") // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, op, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { - println("else") + depp.Println("else, xt not nil") xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { @@ -2473,15 +2473,15 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - fmt.Printf("convertConst, cx:%v, t:%v \n", cx, t) + depp.Printf("convertConst, cx:%v, t:%v \n", cx, t) // TODO: some constraint, panic if not convertable // TODO: thought it should only be permmited to converted to default types, not convertable to interface not satisfied if t != nil && t.Kind() == InterfaceKind { - println("set t to nil, if its kind is interface") + depp.Println("set t to nil, if its kind is interface") t = nil // signifies to convert to default type. } if isUntyped(cx.T) { - println("untyped") + depp.Println("untyped") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) } else if t != nil { @@ -2498,14 +2498,14 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo if xt == nil || dt == nil { return } - fmt.Printf("checkType, xt: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, dt, dt.Kind(), op) + depp.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) // TODO: first check operands and Op // two steps of check: // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt if op != ILLEGAL { // should check operand with op, this would filter most of the op relate issues - println("check matchable with op") + depp.Printf("check matchable with op: %v \n", op) switch op { case ADD: // dt is the dest type, what we need check if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { @@ -2608,8 +2608,7 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo //if xt.TypeID() != dt.TypeID() { // 1. convert with no op, e.g. elements in slice // 2. convert with op, like int(1) + 0, will also need check convertable - println("check convertable") - println("xt is nil?", xt == nil) + depp.Println("ops checks pass, check convertable on operand") var xtStr string if xt != nil { @@ -2617,16 +2616,21 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo } // Special case if dt is interface kind: if dt.Kind() == InterfaceKind { - println("dt is interface") + depp.Println("dt is interface") if idt, ok := baseOf(dt).(*InterfaceType); ok { if idt.IsEmptyInterface() { - println("dt is empty interface") + depp.Println("dt is empty interface") // if dt is an empty Gno interface, any x ok. return // ok } else if idt.IsImplementedBy(xt) { - println("dt is implemented by xt") + depp.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok + } else if iot, ok := xt.(*InterfaceType); ok { + depp.Println("xt is empty interface") + if iot.IsEmptyInterface() { + return // ok + } } else { panic(fmt.Sprintf( "%s does not implement %s", @@ -2675,16 +2679,20 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo panic("should not happen") } } else if xt.Kind() == InterfaceKind { - println("xt is interface") + depp.Println("xt is interface") if ixt, ok := baseOf(xt).(*InterfaceType); ok { if ixt.IsEmptyInterface() { - println("xt is empty interface") + depp.Println("xt is empty interface") // if dt is an empty Gno interface, any x ok. return // ok - } else if ixt.IsImplementedBy(xt) { - println("xt is implemented by dt") + } else if ixt.IsImplementedBy(dt) { + depp.Println("xt is implemented by dt") // if dt implements idt, ok. return // ok + } else if idt, ok := dt.(*InterfaceType); ok { + if idt.IsEmptyInterface() { + return + } } else { panic(fmt.Sprintf( "%s does not implement %s", @@ -2785,7 +2793,7 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo // special case if implicitly named primitive type. // TODO simplify with .IsNamedType(). if _, ok := xt.(PrimitiveType); ok { - println("xt is primitiveType") + depp.Println("xt is primitiveType") // this is special when dt is the declared type of x if !isUntyped(xt) { panic(fmt.Sprintf( @@ -2803,7 +2811,7 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo // General cases. switch cdt := dt.(type) { case PrimitiveType: - println("primitive type") + depp.Println("primitive type") // if xt is untyped, ensure dt is compatible. switch xt { case UntypedBoolType: diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 40a9946baf5..e865e2b1775 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -977,11 +977,20 @@ func (it *InterfaceType) FindEmbeddedFieldType(callerPath string, n Name, m map[ // For run-time type assertion. // TODO: optimize somehow. func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { + depp.Printf("isImplementedBy, it %v, ot:%v \n", it, ot) + // empty interface{} + //if iot, ok := baseOf(ot).(*InterfaceType); ok { + // if iot.IsEmptyInterface() { + // return true + // } + //} + for _, im := range it.Methods { if im.Type.Kind() == InterfaceKind { // field is embedded interface... im2 := baseOf(im.Type).(*InterfaceType) if !im2.IsImplementedBy(ot) { + depp.Println("first false") return false } else { continue @@ -990,6 +999,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // find method in field. tr, hp, rt, ft, _ := findEmbeddedFieldType(it.PkgPath, ot, im.Name, nil) if tr == nil { // not found. + depp.Println("second false") return false } if nft, ok := ft.(*NativeType); ok { @@ -1000,6 +1010,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // ie, if each of ft's arg types can match // against the desired arg types in im.Types. if !gno2GoTypeMatches(im.Type, nft.Type) { + depp.Println("third false") return false } } else if mt, ok := ft.(*FuncType); ok { @@ -1011,6 +1022,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { dmtid := mt.TypeID() imtid := im.Type.TypeID() if dmtid != imtid { + depp.Println("fourth false") return false } } @@ -2142,28 +2154,28 @@ func assertSameTypes(lt, rt Type) { } func isSameTypes(lt, rt Type) bool { - fmt.Printf("isSameTypes, lt: %v, rt: %v \n", lt, rt) - println("is lt data byte: ", isDataByte(lt)) - println("is rt data byte: ", isDataByte(rt)) + depp.Printf("isSameTypes, lt: %v, rt: %v \n", lt, rt) + depp.Println("is lt data byte: ", isDataByte(lt)) + depp.Println("is rt data byte: ", isDataByte(rt)) if lpt, ok := lt.(*PointerType); ok { - println("lt is pointer type, typeid: ", lpt.typeid) + depp.Println("lt is pointer type, typeid: ", lpt.typeid) if isDataByte(lpt.Elt) { - println("got data byte, left") + depp.Println("got data byte, left") return true } } if rpt, ok := rt.(*PointerType); ok { - println("rt is pointer type, typeid: ", rpt.typeid) + depp.Println("rt is pointer type, typeid: ", rpt.typeid) if isDataByte(rpt.Elt) { - println("got data byte, right") + depp.Println("got data byte, right") return true } } if isDataByte(lt) || isDataByte(rt) { - println("one is date byte") + depp.Println("one is date byte") return true } diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 3687b57caef..33966846e55 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -877,7 +877,7 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { - fmt.Printf("ConvertUntypedTo, tv:%v, t:%v \n", tv, t) + depp.Printf("ConvertUntypedTo, tv:%v, t:%v \n", tv, t) if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( @@ -924,7 +924,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { // general case if t == nil { t = defaultTypeOf(tv.T) - fmt.Printf("give t its default type, to be:%v \n", t) + depp.Printf("give t its default type, to be:%v \n", t) } switch tv.T { case UntypedBoolType: @@ -1051,7 +1051,7 @@ func ConvertUntypedRuneTo(dst *TypedValue, t Type) { } func ConvertUntypedBigintTo(dst *TypedValue, bv BigintValue, t Type) { - fmt.Printf("ConvertUntypedBigintTo, dst: %v, bv:%v, t:%v \n", dst, bv, t) + depp.Printf("ConvertUntypedBigintTo, dst: %v, bv:%v, t:%v \n", dst, bv, t) k := t.Kind() bi := bv.V var sv int64 = 0 // if signed. diff --git a/gnovm/tests/files/zrealm/zrealm0.gno b/gnovm/tests/files/zrealm0.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm0.gno rename to gnovm/tests/files/zrealm0.gno index f29360d666c..1b8f37540b3 100644 --- a/gnovm/tests/files/zrealm/zrealm0.gno +++ b/gnovm/tests/files/zrealm0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test var root interface{} diff --git a/gnovm/tests/files/zrealm/zrealm1.gno b/gnovm/tests/files/zrealm1.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm1.gno rename to gnovm/tests/files/zrealm1.gno index b75a0666a22..1dea983a49d 100644 --- a/gnovm/tests/files/zrealm/zrealm1.gno +++ b/gnovm/tests/files/zrealm1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test var root Node diff --git a/gnovm/tests/files/zrealm/zrealm10.gno b/gnovm/tests/files/zrealm10.gno similarity index 98% rename from gnovm/tests/files/zrealm/zrealm10.gno rename to gnovm/tests/files/zrealm10.gno index af4ab478416..97bb9d439e2 100644 --- a/gnovm/tests/files/zrealm/zrealm10.gno +++ b/gnovm/tests/files/zrealm10.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test type MyStruct struct { Field int diff --git a/gnovm/tests/files/zrealm/zrealm11.gno b/gnovm/tests/files/zrealm11.gno similarity index 98% rename from gnovm/tests/files/zrealm/zrealm11.gno rename to gnovm/tests/files/zrealm11.gno index 6372a69d777..0f4d26a44c0 100644 --- a/gnovm/tests/files/zrealm/zrealm11.gno +++ b/gnovm/tests/files/zrealm11.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test type MyStruct struct { Field int diff --git a/gnovm/tests/files/zrealm/zrealm12.gno b/gnovm/tests/files/zrealm12.gno similarity index 97% rename from gnovm/tests/files/zrealm/zrealm12.gno rename to gnovm/tests/files/zrealm12.gno index f67e7d81068..0049cba6073 100644 --- a/gnovm/tests/files/zrealm/zrealm12.gno +++ b/gnovm/tests/files/zrealm12.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "std" diff --git a/gnovm/tests/files/zrealm/zrealm2.gno b/gnovm/tests/files/zrealm2.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm2.gno rename to gnovm/tests/files/zrealm2.gno index 60031e31d1e..bf321c42d31 100644 --- a/gnovm/tests/files/zrealm/zrealm2.gno +++ b/gnovm/tests/files/zrealm2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test var root Node diff --git a/gnovm/tests/files/zrealm/zrealm3.gno b/gnovm/tests/files/zrealm3.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm3.gno rename to gnovm/tests/files/zrealm3.gno index 58f9fadbd80..4ff8dd1a531 100644 --- a/gnovm/tests/files/zrealm/zrealm3.gno +++ b/gnovm/tests/files/zrealm3.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test var root *Node diff --git a/gnovm/tests/files/zrealm/zrealm4.gno b/gnovm/tests/files/zrealm4.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm4.gno rename to gnovm/tests/files/zrealm4.gno index fca8cacae81..2e2fa4e8d09 100644 --- a/gnovm/tests/files/zrealm/zrealm4.gno +++ b/gnovm/tests/files/zrealm4.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files/zrealm/zrealm5.gno b/gnovm/tests/files/zrealm5.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm5.gno rename to gnovm/tests/files/zrealm5.gno index 77a7140b54d..8ad3e7400b3 100644 --- a/gnovm/tests/files/zrealm/zrealm5.gno +++ b/gnovm/tests/files/zrealm5.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files/zrealm/zrealm6.gno b/gnovm/tests/files/zrealm6.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm6.gno rename to gnovm/tests/files/zrealm6.gno index 54649fc7096..fbe320ad962 100644 --- a/gnovm/tests/files/zrealm/zrealm6.gno +++ b/gnovm/tests/files/zrealm6.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files/zrealm/zrealm7.gno b/gnovm/tests/files/zrealm7.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm7.gno rename to gnovm/tests/files/zrealm7.gno index e46cdb3409e..689d55d3916 100644 --- a/gnovm/tests/files/zrealm/zrealm7.gno +++ b/gnovm/tests/files/zrealm7.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "github.com/gnolang/gno/_test/timtadh/data-structures/tree/avl" diff --git a/gnovm/tests/files/zrealm/zrealm8.gno b/gnovm/tests/files/zrealm8.gno similarity index 98% rename from gnovm/tests/files/zrealm/zrealm8.gno rename to gnovm/tests/files/zrealm8.gno index 5c271a95a59..1452301dac6 100644 --- a/gnovm/tests/files/zrealm/zrealm8.gno +++ b/gnovm/tests/files/zrealm8.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test type MyStruct struct { Field int diff --git a/gnovm/tests/files/zrealm/zrealm9.gno b/gnovm/tests/files/zrealm9.gno similarity index 98% rename from gnovm/tests/files/zrealm/zrealm9.gno rename to gnovm/tests/files/zrealm9.gno index 5aa5c0a6cb2..306ca02a92a 100644 --- a/gnovm/tests/files/zrealm/zrealm9.gno +++ b/gnovm/tests/files/zrealm9.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test type MyStruct struct { Field int diff --git a/gnovm/tests/files/zrealm/zrealm_avl0.gno b/gnovm/tests/files/zrealm_avl0.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm_avl0.gno rename to gnovm/tests/files/zrealm_avl0.gno index 4360aca0ad9..814e19d6d49 100644 --- a/gnovm/tests/files/zrealm/zrealm_avl0.gno +++ b/gnovm/tests/files/zrealm_avl0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "gno.land/p/demo/avl" diff --git a/gnovm/tests/files/zrealm/zrealm_avl1.gno b/gnovm/tests/files/zrealm_avl1.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm_avl1.gno rename to gnovm/tests/files/zrealm_avl1.gno index 49034d2ce9b..410e9e93601 100644 --- a/gnovm/tests/files/zrealm/zrealm_avl1.gno +++ b/gnovm/tests/files/zrealm_avl1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "gno.land/p/demo/avl" diff --git a/gnovm/tests/files/zrealm/zrealm_avl2.gno b/gnovm/tests/files/zrealm_avl2.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm_avl2.gno rename to gnovm/tests/files/zrealm_avl2.gno index cbd31bd2ead..8ecf6ba52bc 100644 --- a/gnovm/tests/files/zrealm/zrealm_avl2.gno +++ b/gnovm/tests/files/zrealm_avl2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import ( "gno.land/p/demo/avl" diff --git a/gnovm/tests/files/zrealm/zrealm_const.gno b/gnovm/tests/files/zrealm_const.gno similarity index 85% rename from gnovm/tests/files/zrealm/zrealm_const.gno rename to gnovm/tests/files/zrealm_const.gno index 163adfdd014..210ceff3373 100644 --- a/gnovm/tests/files/zrealm/zrealm_const.gno +++ b/gnovm/tests/files/zrealm_const.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/const_test -package main +package const_test import "std" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm0.gno b/gnovm/tests/files/zrealm_crossrealm0.gno similarity index 92% rename from gnovm/tests/files/zrealm/zrealm_crossrealm0.gno rename to gnovm/tests/files/zrealm_crossrealm0.gno index cd19eb6b5fb..5bf34c2c852 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm0.gno +++ b/gnovm/tests/files/zrealm_crossrealm0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm1.gno b/gnovm/tests/files/zrealm_crossrealm1.gno similarity index 93% rename from gnovm/tests/files/zrealm/zrealm_crossrealm1.gno rename to gnovm/tests/files/zrealm_crossrealm1.gno index 20c0be864a4..686468b40c7 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm1.gno +++ b/gnovm/tests/files/zrealm_crossrealm1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm10.gno b/gnovm/tests/files/zrealm_crossrealm10.gno similarity index 89% rename from gnovm/tests/files/zrealm/zrealm_crossrealm10.gno rename to gnovm/tests/files/zrealm_crossrealm10.gno index 7e6e0127f2c..73ad3ea74d7 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm10.gno +++ b/gnovm/tests/files/zrealm_crossrealm10.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm_crossrealm11.gno rename to gnovm/tests/files/zrealm_crossrealm11.gno index 7194d86d016..e6f33c50654 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( ptests "gno.land/p/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm12.gno b/gnovm/tests/files/zrealm_crossrealm12.gno similarity index 97% rename from gnovm/tests/files/zrealm/zrealm_crossrealm12.gno rename to gnovm/tests/files/zrealm_crossrealm12.gno index c7ec80e084a..f2f229cd5de 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm12.gno +++ b/gnovm/tests/files/zrealm_crossrealm12.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "fmt" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm2.gno b/gnovm/tests/files/zrealm_crossrealm2.gno similarity index 94% rename from gnovm/tests/files/zrealm/zrealm_crossrealm2.gno rename to gnovm/tests/files/zrealm_crossrealm2.gno index 5c1b3060461..cfcd4e6898c 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm2.gno +++ b/gnovm/tests/files/zrealm_crossrealm2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm3.gno b/gnovm/tests/files/zrealm_crossrealm3.gno similarity index 94% rename from gnovm/tests/files/zrealm/zrealm_crossrealm3.gno rename to gnovm/tests/files/zrealm_crossrealm3.gno index 5b01fafecaf..6aa9c5247d8 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm3.gno +++ b/gnovm/tests/files/zrealm_crossrealm3.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm4.gno b/gnovm/tests/files/zrealm_crossrealm4.gno similarity index 94% rename from gnovm/tests/files/zrealm/zrealm_crossrealm4.gno rename to gnovm/tests/files/zrealm_crossrealm4.gno index 5b01fafecaf..6aa9c5247d8 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm4.gno +++ b/gnovm/tests/files/zrealm_crossrealm4.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm5.gno b/gnovm/tests/files/zrealm_crossrealm5.gno similarity index 94% rename from gnovm/tests/files/zrealm/zrealm_crossrealm5.gno rename to gnovm/tests/files/zrealm_crossrealm5.gno index 5b01fafecaf..6aa9c5247d8 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm5.gno +++ b/gnovm/tests/files/zrealm_crossrealm5.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm6.gno b/gnovm/tests/files/zrealm_crossrealm6.gno similarity index 93% rename from gnovm/tests/files/zrealm/zrealm_crossrealm6.gno rename to gnovm/tests/files/zrealm_crossrealm6.gno index 3ba03fc5b30..d2e7a4b096a 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm6.gno +++ b/gnovm/tests/files/zrealm_crossrealm6.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm7.gno b/gnovm/tests/files/zrealm_crossrealm7.gno similarity index 89% rename from gnovm/tests/files/zrealm/zrealm_crossrealm7.gno rename to gnovm/tests/files/zrealm_crossrealm7.gno index 4cdbbfc2030..5a4dc3002cc 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm7.gno +++ b/gnovm/tests/files/zrealm_crossrealm7.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm8.gno b/gnovm/tests/files/zrealm_crossrealm8.gno similarity index 89% rename from gnovm/tests/files/zrealm/zrealm_crossrealm8.gno rename to gnovm/tests/files/zrealm_crossrealm8.gno index 2bbb7a323ad..f03085ff4c7 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm8.gno +++ b/gnovm/tests/files/zrealm_crossrealm8.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_crossrealm9.gno b/gnovm/tests/files/zrealm_crossrealm9.gno similarity index 89% rename from gnovm/tests/files/zrealm/zrealm_crossrealm9.gno rename to gnovm/tests/files/zrealm_crossrealm9.gno index 98eb7556286..96a7a3484d7 100644 --- a/gnovm/tests/files/zrealm/zrealm_crossrealm9.gno +++ b/gnovm/tests/files/zrealm_crossrealm9.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/crossrealm_test -package main +package crossrealm_test import ( "gno.land/p/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_example.gno b/gnovm/tests/files/zrealm_example.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm_example.gno rename to gnovm/tests/files/zrealm_example.gno index cd1c6a301af..1ce70c04390 100644 --- a/gnovm/tests/files/zrealm/zrealm_example.gno +++ b/gnovm/tests/files/zrealm_example.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/example -package main +package example import ( "gno.land/p/demo/dom" diff --git a/gnovm/tests/files/zrealm/zrealm_map0.gno b/gnovm/tests/files/zrealm_map0.gno similarity index 93% rename from gnovm/tests/files/zrealm/zrealm_map0.gno rename to gnovm/tests/files/zrealm_map0.gno index bb5ba9f6d06..1dd2deff755 100644 --- a/gnovm/tests/files/zrealm/zrealm_map0.gno +++ b/gnovm/tests/files/zrealm_map0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test var m map[string]int diff --git a/gnovm/tests/files/zrealm/zrealm_std0.gno b/gnovm/tests/files/zrealm_std0.gno similarity index 91% rename from gnovm/tests/files/zrealm/zrealm_std0.gno rename to gnovm/tests/files/zrealm_std0.gno index fe2c1db0e11..3f6bdae2537 100644 --- a/gnovm/tests/files/zrealm/zrealm_std0.gno +++ b/gnovm/tests/files/zrealm_std0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package main +package std_test import ( "std" diff --git a/gnovm/tests/files/zrealm/zrealm_std1.gno b/gnovm/tests/files/zrealm_std1.gno similarity index 97% rename from gnovm/tests/files/zrealm/zrealm_std1.gno rename to gnovm/tests/files/zrealm_std1.gno index 2308520b29b..87f75bcb871 100644 --- a/gnovm/tests/files/zrealm/zrealm_std1.gno +++ b/gnovm/tests/files/zrealm_std1.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package main +package std_test import ( "std" diff --git a/gnovm/tests/files/zrealm/zrealm_std2.gno b/gnovm/tests/files/zrealm_std2.gno similarity index 97% rename from gnovm/tests/files/zrealm/zrealm_std2.gno rename to gnovm/tests/files/zrealm_std2.gno index 25c879b5573..1ae1fb4a881 100644 --- a/gnovm/tests/files/zrealm/zrealm_std2.gno +++ b/gnovm/tests/files/zrealm_std2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package main +package std_test import ( "std" diff --git a/gnovm/tests/files/zrealm/zrealm_std3.gno b/gnovm/tests/files/zrealm_std3.gno similarity index 93% rename from gnovm/tests/files/zrealm/zrealm_std3.gno rename to gnovm/tests/files/zrealm_std3.gno index f1925a860bd..c13feffa42c 100644 --- a/gnovm/tests/files/zrealm/zrealm_std3.gno +++ b/gnovm/tests/files/zrealm_std3.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package main +package std_test import ( "std" diff --git a/gnovm/tests/files/zrealm/zrealm_std4.gno b/gnovm/tests/files/zrealm_std4.gno similarity index 95% rename from gnovm/tests/files/zrealm/zrealm_std4.gno rename to gnovm/tests/files/zrealm_std4.gno index d1b5dba9b7f..4b8a1d6dfb3 100644 --- a/gnovm/tests/files/zrealm/zrealm_std4.gno +++ b/gnovm/tests/files/zrealm_std4.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package main +package std_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_std5.gno b/gnovm/tests/files/zrealm_std5.gno similarity index 95% rename from gnovm/tests/files/zrealm/zrealm_std5.gno rename to gnovm/tests/files/zrealm_std5.gno index 37a61dea6c8..86d26eef368 100644 --- a/gnovm/tests/files/zrealm/zrealm_std5.gno +++ b/gnovm/tests/files/zrealm_std5.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/std_test -package main +package std_test import ( "gno.land/p/demo/tests" // NOTE: not a realm path. diff --git a/gnovm/tests/files/zrealm/zrealm_std6.gno b/gnovm/tests/files/zrealm_std6.gno similarity index 56% rename from gnovm/tests/files/zrealm/zrealm_std6.gno rename to gnovm/tests/files/zrealm_std6.gno index 7280d12345b..17a79c1d43b 100644 --- a/gnovm/tests/files/zrealm/zrealm_std6.gno +++ b/gnovm/tests/files/zrealm_std6.gno @@ -1,5 +1,5 @@ -// PKGPATH: gno.land/r/test -package main +// PKGPATH: gno.land/r/std_test +package std_test import ( "std" @@ -14,4 +14,4 @@ func main() { } // Output: -// g148esskg7wzxxw6axwv4j5nkgjzdp6v4zmy3pwc +// g157y5v3k529jyzhjjz4fn49tzzhf4gess6v39xg diff --git a/gnovm/tests/files/zrealm/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno similarity index 99% rename from gnovm/tests/files/zrealm/zrealm_tests0.gno rename to gnovm/tests/files/zrealm_tests0.gno index f26be980ab8..cfb1f08c6f4 100644 --- a/gnovm/tests/files/zrealm/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm_tests0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/demo/tests_test -package main +package tests_test import ( "gno.land/r/demo/tests" diff --git a/gnovm/tests/files/zrealm/zrealm_testutils0.gno b/gnovm/tests/files/zrealm_testutils0.gno similarity index 92% rename from gnovm/tests/files/zrealm/zrealm_testutils0.gno rename to gnovm/tests/files/zrealm_testutils0.gno index 3a8f48c0f0b..33322f76719 100644 --- a/gnovm/tests/files/zrealm/zrealm_testutils0.gno +++ b/gnovm/tests/files/zrealm_testutils0.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/testutils_test -package main +package testutils_test import ( "gno.land/p/demo/testutils" From 0f5312102c7dfc43956d1086b62d7059ddbf78d2 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 1 Dec 2023 16:54:17 +0800 Subject: [PATCH 009/193] fixup --- gnovm/pkg/gnolang/op_binary.go | 27 +++++++++++++++++++++++ gnovm/tests/files/types/0f11_filetest.gno | 24 ++++++++++++++++++++ gnovm/tests/files/types/0f4_filetest.gno | 2 +- gnovm/tests/files/types/0f5_filetest.gno | 2 +- gnovm/tests/files/types/13f0_filetest.gno | 2 +- gnovm/tests/files/types/13f1_filetest.gno | 7 +++--- gnovm/tests/files/types/13f2_filetest.gno | 22 +++++++++++++++++- gnovm/tests/files/types/others/README.md | 2 ++ 8 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 gnovm/tests/files/types/0f11_filetest.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index fe6ae768983..c5850988663 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -93,6 +93,8 @@ func (m *Machine) doOpEql() { // res = isEql(m.Store, lv, rv) //} + // TODO: this should be in preprocess too + // TODO: only assert here if isSameTypes(lv.T, rv.T) { res = isEql(m.Store, lv, rv) } else { @@ -706,6 +708,10 @@ func isGeq(lv, rv *TypedValue) bool { // for doOpAdd and doOpAddAssign. func addAssign(alloc *Allocator, lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } + // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -764,6 +770,9 @@ func addAssign(alloc *Allocator, lv, rv *TypedValue) { // for doOpSub and doOpSubAssign. func subAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -820,6 +829,9 @@ func subAssign(lv, rv *TypedValue) { // for doOpMul and doOpMulAssign. func mulAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -874,6 +886,9 @@ func mulAssign(lv, rv *TypedValue) { // for doOpQuo and doOpQuoAssign. func quoAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -930,6 +945,9 @@ func quoAssign(lv, rv *TypedValue) { // for doOpRem and doOpRemAssign. func remAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -969,6 +987,9 @@ func remAssign(lv, rv *TypedValue) { // for doOpBand and doOpBandAssign. func bandAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -1008,6 +1029,9 @@ func bandAssign(lv, rv *TypedValue) { // for doOpBandn and doOpBandnAssign. func bandnAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -1047,6 +1071,9 @@ func bandnAssign(lv, rv *TypedValue) { // for doOpBor and doOpBorAssign. func borAssign(lv, rv *TypedValue) { + if !isSameTypes(lv.T, rv.T) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { diff --git a/gnovm/tests/files/types/0f11_filetest.gno b/gnovm/tests/files/types/0f11_filetest.gno new file mode 100644 index 00000000000..a4ae0463291 --- /dev/null +++ b/gnovm/tests/files/types/0f11_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var l interface{} + if l == Error(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/0f4_filetest.gno b/gnovm/tests/files/types/0f4_filetest.gno index e213b50e8de..d765b9640f1 100644 --- a/gnovm/tests/files/types/0f4_filetest.gno +++ b/gnovm/tests/files/types/0f4_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Output: -// something else +// what the firetruck? diff --git a/gnovm/tests/files/types/0f5_filetest.gno b/gnovm/tests/files/types/0f5_filetest.gno index 7ab387f38c4..75f022c240a 100644 --- a/gnovm/tests/files/types/0f5_filetest.gno +++ b/gnovm/tests/files/types/0f5_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Output: -// something else +// what the firetruck? diff --git a/gnovm/tests/files/types/13f0_filetest.gno b/gnovm/tests/files/types/13f0_filetest.gno index 60c28c3c3f2..08b7ba35704 100644 --- a/gnovm/tests/files/types/13f0_filetest.gno +++ b/gnovm/tests/files/types/13f0_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/13f0_filetest.gno:20: cannot use .uverse.error as int without explicit conversion +// main/files/types/13f0_filetest.gno:20: int does not implement .uverse.error diff --git a/gnovm/tests/files/types/13f1_filetest.gno b/gnovm/tests/files/types/13f1_filetest.gno index 9a9f34d5669..52bc9e586f1 100644 --- a/gnovm/tests/files/types/13f1_filetest.gno +++ b/gnovm/tests/files/types/13f1_filetest.gno @@ -13,8 +13,9 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: -// one is interface +// special case: +// 1. base type of left is int64, op is legal; +// 2. while RHS is interface kind, and can be converted to left func main() { r := Error(0) r += errCmp @@ -22,4 +23,4 @@ func main() { } // Error: -// main/files/types/13f1_filetest.gno:20: cannot use .uverse.error as main.Error without explicit conversion \ No newline at end of file +// invalid operation: mismatched types main.Error and *errors.errorString diff --git a/gnovm/tests/files/types/13f2_filetest.gno b/gnovm/tests/files/types/13f2_filetest.gno index 0386fafa53f..c323d24ed95 100644 --- a/gnovm/tests/files/types/13f2_filetest.gno +++ b/gnovm/tests/files/types/13f2_filetest.gno @@ -13,6 +13,26 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") +// NOTE: in golang, this won't compile by type mismatch +// code like this : won't compile by : "invalid operation: operator + not defined on err1 (variable of type error)" +// which indicates that golang will check type match first, and operand legality secondly +// that is, for op =+, first check type match, second check operand +// in our condition, should check convert first, after that, check operand? + +//package main +// +//import ( +//"errors" +//) +// +//var err1 = errors.New("XXXX") +//var err2 = errors.New("XXXX") +// +//func main() { +// err1 += err2 +// println(err1) +//} + // specil case: // one is interface func main() { @@ -22,4 +42,4 @@ func main() { } // Error: -// main/files/types/13f2_filetest.gno:20: operator += not defined on: .uverse.error +// main/files/types/13f2_filetest.gno:40: operator += not defined on: .uverse.error diff --git a/gnovm/tests/files/types/others/README.md b/gnovm/tests/files/types/others/README.md index a2a9bd4d5f5..9c53dd3f92c 100644 --- a/gnovm/tests/files/types/others/README.md +++ b/gnovm/tests/files/types/others/README.md @@ -113,3 +113,5 @@ thoughts: TODOs: // TODO: dec value representation + // TODO: Current flow : check op operand, check type convertable, and convert, and check type match again, means, this kind of check should still in preprocess + // TODO: preCheck->Convert->postCheck, all in `checkOrConvertType` From ddd2c7147723f7deae8f17cec09fcabb2f1ed038 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 3 Dec 2023 22:38:05 +0800 Subject: [PATCH 010/193] refactor --- gnovm/Makefile | 2 +- gnovm/pkg/gnolang/nodes_string.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 6 +- gnovm/pkg/gnolang/preprocess.go | 343 ++++++++++++++-------- gnovm/pkg/gnolang/types.go | 210 ++++++++++--- gnovm/tests/files/types/13a0_filetest.gno | 2 +- gnovm/tests/files/types/13a1_filetest.gno | 2 +- gnovm/tests/files/types/13b0_filetest.gno | 2 +- gnovm/tests/files/types/13e0_filetest.gno | 2 +- gnovm/tests/files/types/13e1_filetest.gno | 20 ++ gnovm/tests/files/types/13e_filetest.gno | 21 ++ gnovm/tests/files/types/13f0_filetest.gno | 2 +- gnovm/tests/files/types/13f1_filetest.gno | 8 +- gnovm/tests/files/types/1d0_filetest.gno | 1 + gnovm/tests/files/types/1f0_filetest.gno | 2 +- gnovm/tests/files/types/1f1_filetest.gno | 2 +- gnovm/tests/files/types/1f2_filetest.gno | 2 +- gnovm/tests/files/types/2b2_filetest.gno | 2 +- gnovm/tests/files/types/2b3_filetest.gno | 2 +- gnovm/tests/files/types/2f0_filetest.gno | 2 +- gnovm/tests/files/types/2f1_filetest.gno | 2 +- gnovm/tests/files/types/2f2_filetest.gno | 2 +- gnovm/tests/files/types/3b2_filetest.gno | 2 +- gnovm/tests/files/types/3b3_filetest.gno | 2 +- gnovm/tests/files/types/3f0_filetest.gno | 2 +- gnovm/tests/files/types/3f1_filetest.gno | 2 +- gnovm/tests/files/types/3f2_filetest.gno | 2 +- gnovm/tests/files/types/4b2_filetest.gno | 2 +- gnovm/tests/files/types/4b3_filetest.gno | 2 +- gnovm/tests/files/types/4f0_filetest.gno | 2 +- gnovm/tests/files/types/4f1_filetest.gno | 2 +- gnovm/tests/files/types/4f2_filetest.gno | 2 +- gnovm/tests/files/types/5b2_filetest.gno | 2 +- gnovm/tests/files/types/5b3_filetest.gno | 2 +- gnovm/tests/files/types/5d0_filetest.gno | 2 +- gnovm/tests/files/types/5d4_filetest.gno | 2 +- gnovm/tests/files/types/5f0_filetest.gno | 2 +- gnovm/tests/files/types/5f1_filetest.gno | 2 +- gnovm/tests/files/types/5f2_filetest.gno | 2 +- gnovm/tests/files/types/others/README.md | 14 + 40 files changed, 483 insertions(+), 204 deletions(-) create mode 100644 gnovm/tests/files/types/13e1_filetest.gno create mode 100644 gnovm/tests/files/types/13e_filetest.gno diff --git a/gnovm/Makefile b/gnovm/Makefile index d0309702e03..3f6eb98be90 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -45,7 +45,7 @@ _test.pkg: go test ./pkg/... $(GOTEST_FLAGS) .PHONY: _test.gnolang -_test.gnolang: _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other +_test.gnolang: _test.gnolang.types _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other _test.gnolang.other:; go test tests/*.go -run "(TestFileStr|TestSelectors)" $(GOTEST_FLAGS) _test.gnolang.realm:; go test tests/*.go -run "TestFiles/^zrealm" $(GOTEST_FLAGS) _test.gnolang.pkg0:; go test tests/*.go -run "TestPackages/(bufio|crypto|encoding|errors|internal|io|math|sort|std|stdshim|strconv|strings|testing|unicode)" $(GOTEST_FLAGS) diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index 547ad83294d..17849057f38 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -13,7 +13,7 @@ var wordTokenStrings = map[Word]string{ SUB: "-", MUL: "*", QUO: "/", - REM: "%", + REM: "%%", BAND: "&", BOR: "|", XOR: "^", diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index c5850988663..d1490678414 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -708,9 +708,9 @@ func isGeq(lv, rv *TypedValue) bool { // for doOpAdd and doOpAddAssign. func addAssign(alloc *Allocator, lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } + //if !isSameTypes(lv.T, rv.T) { + // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) + //} // set the result in lv. // NOTE this block is replicated in op_assign.go diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9e537957b3c..34b330d6911 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -449,7 +449,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, cx := range n.Cases { cx = Preprocess( store, last, cx).(Expr) - checkOrConvertType(store, last, &cx, tt, ILLEGAL, false) // #nosec G601 + checkOrConvertType(store, last, &cx, tt, false) // #nosec G601 n.Cases[i] = cx } } @@ -787,7 +787,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cmp < 0 { // this always implies untyped>? depp.Println("cmp < 0, ->") // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rcx.T, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rcx.T, n.Op, false) } else if cmp == 0 { depp.Println("cmp == 0") // NOTE: the following doesn't work. @@ -796,11 +796,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // or check for compatibility. // (the other way around would work too) // also need to check - checkOrConvertType(store, last, &n.Left, rcx.T, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rcx.T, n.Op, false) } else { // this always implies untyped>? depp.Println("cmp > 0, <-") // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lcx.T, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, lcx.T, n.Op, false) } } // Then, evaluate the expression. @@ -817,7 +817,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, pt, n.Op, false) // convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. @@ -845,7 +845,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { depp.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) depp.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const @@ -858,12 +858,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { //} else { // checkOrConvertType(store, last, &n.Left, rt, n.Op, false) //} - checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) } else if lcx.T == nil { depp.Println("lcx.T is nil") // convert n.Left to typed-nil type. - checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) } // TODO: 912 line? } else if ric { @@ -874,7 +874,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { if baseOf(rt) != UintType { // convert n.Right to (gno) uint type. - checkOrConvertType(store, last, &n.Right, UintType, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, UintType, n.Op, false) } else { // leave n.Left as is and baseOf(n.Right) as UintType. } @@ -885,7 +885,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOrConvertType(store, last, &n.Right, pt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, pt, n.Op, false) // and convert result back. tx := constType(n, lnt) // reset/create n2 to preprocess left child. @@ -901,16 +901,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) } } //} else if rcx.T == nil { } else if rcx.T == nil { depp.Println("rcx.T == nil ") // convert n.Right to typed-nil type. - checkOrConvertType(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) } else if !isShift { - checkOrConvertType(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) } } else { depp.Printf("both not const, lt: %v, rt:%v \n", lt, rt) @@ -977,12 +977,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { depp.Println("left untyped, right is typed") - checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) } } else if riu { - checkOrConvertType(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) } else { - checkOrConvertType(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) //// left is untyped, right is not. //if lt.TypeID() != rt.TypeID() { // panic(fmt.Sprintf( @@ -1193,16 +1193,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if len(spts) <= i { panic("expected final vargs slice but got many") } - checkOrConvertType(store, last, &n.Args[i], spts[i].Type, ILLEGAL, true) + checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } else { checkOrConvertType(store, last, &n.Args[i], - spts[len(spts)-1].Type.Elem(), ILLEGAL, true) + spts[len(spts)-1].Type.Elem(), true) } } else { - checkOrConvertType(store, last, &n.Args[i], spts[i].Type, ILLEGAL, true) + checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } else { - checkOrConvertType(store, last, &n.Args[i], spts[i].Type, ILLEGAL, true) + checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } } @@ -1226,7 +1226,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertIntegerType(store, last, n.Index) case MapKind: mt := baseOf(gnoTypeOf(store, dt)).(*MapType) - checkOrConvertType(store, last, &n.Index, mt.Key, ILLEGAL, false) + checkOrConvertType(store, last, &n.Index, mt.Key, false) default: panic(fmt.Sprintf( "unexpected index base kind for type %s", @@ -1290,28 +1290,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { key := n.Elts[i].Key.(*NameExpr).Name path := cclt.GetPathForName(key) ft := cclt.GetStaticTypeOfAt(path) - checkOrConvertType(store, last, &n.Elts[i].Value, ft, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) } } else { for i := 0; i < len(n.Elts); i++ { ft := cclt.Fields[i].Type - checkOrConvertType(store, last, &n.Elts[i].Value, ft, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) } } case *ArrayType: for i := 0; i < len(n.Elts); i++ { convertConstType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) - checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { convertConstType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) - checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *MapType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, cclt.Key, ILLEGAL, false) - checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Value, ILLEGAL, false) + checkOrConvertType(store, last, &n.Elts[i].Key, cclt.Key, false) + checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Value, false) } case *NativeType: clt = cclt.GnoType(store) @@ -1660,7 +1660,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } // Special case if shift assign <<= or >>=. - checkOrConvertType(store, last, &n.Rhs[0], UintType, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[0], UintType, n.Op, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { depp.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, @@ -1677,7 +1677,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // panic("mismatch type for Assign") // } //} else { - checkOrConvertType(store, last, &n.Rhs[0], lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[0], lt, n.Op, false) //} } else { // all else, like BAND_ASSIGN, etc depp.Println("case: a, b = x, y") @@ -1691,13 +1691,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { depp.Println("rt is untyped, convert") // is untyped // converts if rx is "nil". - checkOrConvertType(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[i], lt, n.Op, false) } else { depp.Println("rt not untyped, check strict") //if lt.TypeID() != rt.TypeID() { // panic("mismatch type for Assign, in case: a, b = x, y") //} - checkOrConvertType(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[i], lt, n.Op, false) } } } @@ -1733,12 +1733,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ForStmt: // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, ILLEGAL, false) + checkOrConvertType(store, last, &n.Cond, BoolType, false) // TRANS_LEAVE ----------------------- case *IfStmt: // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, ILLEGAL, false) + checkOrConvertType(store, last, &n.Cond, BoolType, false) // TRANS_LEAVE ----------------------- case *RangeStmt: @@ -1793,7 +1793,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // XXX how to deal? panic("not yet implemented") } else { - checkOrConvertType(store, last, &n.Results[i], rt, ILLEGAL, false) + checkOrConvertType(store, last, &n.Results[i], rt, false) } } } @@ -1801,7 +1801,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SendStmt: // Value consts become default *ConstExprs. - checkOrConvertType(store, last, &n.Value, nil, ILLEGAL, false) + checkOrConvertType(store, last, &n.Value, nil, false) // TRANS_LEAVE ----------------------- case *SelectCaseStmt: @@ -1889,7 +1889,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // convert if const to nt. for i := range n.Values { - checkOrConvertType(store, last, &n.Values[i], nt, ILLEGAL, false) + checkOrConvertType(store, last, &n.Values[i], nt, false) } } else if n.Const { // derive static type from values. @@ -2409,7 +2409,8 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, op Word, aut // TODO: NOTE, more about const, sometimes we convert it anyway, like uint8 -> int as index of an array // TODO: but if it's bind to ops like +, type conversion should be checked // TODO: this should be awareness at its origin -func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { +func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { + op := ILLEGAL depp.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { // here we should check too, e.g. primitive to declared type is convertable @@ -2422,7 +2423,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, a } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { depp.Println("SHL or SHR") // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, op, autoNative) + checkOrConvertType(store, last, &bx.Left, t, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { depp.Println("else, xt not nil") xt := evalStaticTypeOf(store, last, *x) @@ -2441,12 +2442,68 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, op Word, a case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: // push t into bx.Left and bx.Right - checkOrConvertType(store, last, &bx.Left, t, op, autoNative) - checkOrConvertType(store, last, &bx.Right, t, op, autoNative) + checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Right, t, autoNative) return case SHL, SHR: // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, op, autoNative) + checkOrConvertType(store, last, &bx.Left, t, autoNative) + return + // case EQL, LSS, GTR, NEQ, LEQ, GEQ: + // default: + } + } + cx := Expr(Call(constType(nil, t), *x)) + cx = Preprocess(store, last, cx).(Expr) + *x = cx + } + // cover all declared type case + if conversionNeeded { + cx := Expr(Call(constType(nil, t), *x)) + cx = Preprocess(store, last, cx).(Expr) + *x = cx + } + } +} + +func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { + depp.Printf("checkOrConvertTypeWithOp, x: %v:, t:%v, op: %v \n", x, t, op) + if cx, ok := (*x).(*ConstExpr); ok { + // here we should check too, e.g. primitive to declared type is convertable + if _, ok := t.(*NativeType); !ok { // not native type + depp.Println("ConstExpr is not nativeType, go check") + checkType(cx.T, t, op, autoNative) + } + depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) + convertConst(store, last, cx, t) + } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + depp.Println("SHL or SHR") + // "push" expected type into shift binary's left operand. + checkOrConvertTypeWithOp(store, last, &bx.Left, t, op, autoNative) + } else if *x != nil { // XXX if x != nil && t != nil { + depp.Println("else, xt not nil") + xt := evalStaticTypeOf(store, last, *x) + var conversionNeeded bool + if t != nil { + //checkType(xt, t, op, autoNative) + conversionNeeded = checkType(xt, t, op, autoNative) + } + if isUntyped(xt) { + if t == nil { + t = defaultTypeOf(xt) + } + // Push type into expr if qualifying binary expr. + if bx, ok := (*x).(*BinaryExpr); ok { + switch bx.Op { + case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, + BAND_NOT, LAND, LOR: + // push t into bx.Left and bx.Right + checkOrConvertTypeWithOp(store, last, &bx.Left, t, op, autoNative) + checkOrConvertTypeWithOp(store, last, &bx.Right, t, op, autoNative) + return + case SHL, SHR: + // push t into bx.Left + checkOrConvertTypeWithOp(store, last, &bx.Left, t, op, autoNative) return // case EQL, LSS, GTR, NEQ, LEQ, GEQ: // default: @@ -2491,6 +2548,35 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { } } +type f func(t Type) bool + +var predicates map[Word]f + +func init() { + predicates = make(map[Word]f) + predicates[ADD] = isNumericOrString + predicates[ADD_ASSIGN] = isNumericOrString + predicates[SUB] = isNumeric + predicates[SUB_ASSIGN] = isNumeric + predicates[MUL] = isNumeric + predicates[MUL_ASSIGN] = isNumeric + predicates[QUO] = isNumeric + predicates[QUO_ASSIGN] = isNumeric + predicates[REM] = isIntNum + predicates[REM_ASSIGN] = isIntNum + + predicates[BAND] = isIntNum + predicates[BAND_ASSIGN] = isIntNum + predicates[XOR] = isIntNum + predicates[XOR_ASSIGN] = isIntNum + predicates[BOR] = isIntNum + predicates[BOR_ASSIGN] = isIntNum + predicates[BAND_NOT] = isIntNum + predicates[BAND_NOT_ASSIGN] = isIntNum + predicates[LAND] = isBoolean + predicates[LOR] = isBoolean +} + // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. @@ -2506,95 +2592,108 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt if op != ILLEGAL { // should check operand with op, this would filter most of the op relate issues depp.Printf("check matchable with op: %v \n", op) - switch op { - case ADD: // dt is the dest type, what we need check - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("+ should have operand number or string, while have: %v", dt)) - } - case SUB: - if !isTypedNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("- should have operand number, while have: %v", dt)) - } - case MUL: - if !isTypedNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("* should have operand number, while have: %v", dt)) - } - case QUO: - if !isTypedNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) - } - case REM: - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) - } - case BAND: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator & not defined on: %v", dt)) - } - case BAND_ASSIGN: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator &= not defined on: %v", dt)) - } - case BOR: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator | not defined on: %v", dt)) - } - case BOR_ASSIGN: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator |= not defined on: %v", dt)) - } - case XOR: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator ^ not defined on: %v", dt)) - } - case XOR_ASSIGN: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator ^= not defined on: %v", dt)) - } - case BAND_NOT: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator &^ not defined on: %v", dt)) - } - case BAND_NOT_ASSIGN: // not defined on float - if !isIntNumber(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator &^= not defined on: %v", dt)) - } - case LAND: // not defined on float - if dt != UntypedBoolType && dt != BoolType { - panic(fmt.Sprintf("operator && not defined on: %v", dt)) - } - case LOR: // not defined on float - if dt != UntypedBoolType && dt != BoolType { - panic(fmt.Sprintf("operator || not defined on: %v", dt)) + if pred, ok := predicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } + } + switch op { + //case ADD: // dt is the dest type, what we need check + //if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { + //panic(fmt.Sprintf("+ should have operand number or string, while have: %v", dt)) + //} + + //case SUB: + // if !isNumeric(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("- should have operand number, while have: %v", dt)) + // } + //case MUL: + // if !isNumeric(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("* should have operand number, while have: %v", dt)) + // } + //case QUO: + // if !isNumeric(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) + // } + //case REM: + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) + // } + //case BAND: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator & not defined on: %v", dt)) + // } + //case BAND_ASSIGN: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator &= not defined on: %v", dt)) + // } + //case BOR: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator | not defined on: %v", dt)) + // } + //case BOR_ASSIGN: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator |= not defined on: %v", dt)) + // } + //case XOR: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator ^ not defined on: %v", dt)) + // } + //case XOR_ASSIGN: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator ^= not defined on: %v", dt)) + // } + //case BAND_NOT: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator &^ not defined on: %v", dt)) + // } + //case BAND_NOT_ASSIGN: // not defined on float + // if !isIntNumber(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator &^= not defined on: %v", dt)) + // } + //case LAND: // not defined on float + // if dt != UntypedBoolType && dt != BoolType { + // panic(fmt.Sprintf("operator && not defined on: %v", dt)) + // } + //case LOR: // not defined on float + // if dt != UntypedBoolType && dt != BoolType { + // panic(fmt.Sprintf("operator || not defined on: %v", dt)) + // } case ADD_ASSIGN: - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator += not defined on: %v", dt)) - } - case SUB_ASSIGN: - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator -= not defined on: %v", dt)) - } - case MUL_ASSIGN: - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator *= not defined on: %v", dt)) - } - case QUO_ASSIGN: - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator /= not defined on: %v", dt)) - } - case REM_ASSIGN: - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator %%= not defined on: %v", dt)) - } + //if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator += not defined on: %v", dt)) + //} + // TODO: check matchable here, not in runtime + // special case + if !isUntyped(xt) { + if !isSameTypes(xt, dt) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + } + } + //case SUB_ASSIGN: + // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator -= not defined on: %v", dt)) + // } + //case MUL_ASSIGN: + // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator *= not defined on: %v", dt)) + // } + //case QUO_ASSIGN: + // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator /= not defined on: %v", dt)) + // } + //case REM_ASSIGN: + // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { + // panic(fmt.Sprintf("operator %%= not defined on: %v", dt)) + // } case EQL, NEQ: // do nothing here, as a special case, EQL or NEQ is more relaxed than ADD, so convertable is checked as `equality` in logic below // case SHL, SHR: // TODO: right should be numeric - case LSS: - if !isTypedNumber(dt) && !isTypedString(dt) && dt != UntypedRuneType { + case LSS: // TODO: comparable, assignable + if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { panic(fmt.Sprintf("operator < not defined on: %v", dt)) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index e865e2b1775..a09e9e6046c 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -257,6 +257,171 @@ func (pt PrimitiveType) TypeID() TypeID { } } +type predicate int + +const ( + IsInvalid = 0 + IsBoolean predicate = 1 << iota + IsInteger + IsUnsigned + IsFloat + IsComplex + IsString + IsUntyped + IsBigInt + IsBigDec + IsRune + + IsOrdered = IsInteger | IsFloat | IsString + IsNumeric = IsInteger | IsFloat | IsComplex | IsBigInt | IsBigDec + IsConstType = IsBoolean | IsNumeric | IsString +) + +func (pt PrimitiveType) Predicate() predicate { + switch pt { + case InvalidType: + return IsInvalid + case UntypedBoolType: + return IsBoolean + case BoolType: + return IsBoolean + case UntypedStringType: + return IsString + case StringType: + return IsString + case IntType: + return IsInteger + case Int8Type: + return IsInteger + case Int16Type: + return IsInteger + case UntypedRuneType: + return IsRune + case Int32Type: + return IsInteger + case Int64Type: + return IsInteger + case UintType: + return IsUnsigned + case Uint8Type: + return IsUnsigned + case DataByteType: + return IsUnsigned + case Uint16Type: + return IsUnsigned + case Uint32Type: + return IsUnsigned + case Uint64Type: + return IsUnsigned + case Float32Type: + return IsFloat + case Float64Type: + return IsFloat + case UntypedBigintType: + return IsBigInt + case BigintType: + return IsBigInt + case UntypedBigdecType: + return IsBigDec + case BigdecType: + return IsBigDec + default: + panic(fmt.Sprintf("unexpected primitive type %d", pt)) + } +} + +func isBoolean(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.Predicate() != IsInvalid && t.Predicate()&IsBoolean != 0 { + return true + } + return false + default: + return false + } +} + +// rune can be numeric and string +func isNumeric(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +func isIntNum(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsBigInt != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +func isNumericOrString(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsString != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +//func isNumeric(t Type) bool { +// switch t := baseOf(t).(type) { +// case PrimitiveType: +// switch t { +// case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, Float32Type, Float64Type, UntypedBigintType, BigintType, UntypedBigdecType, BigdecType: +// return true +// default: +// return false +// } +// default: +// return false +// } +//} + +//// only for / and % /= %=, no support for float +//func isIntNumber(t Type) bool { +// switch t := baseOf(t).(type) { +// case PrimitiveType: +// switch t { +// case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, UntypedBigintType, BigintType: +// return true +// default: +// return false +// } +// default: +// return false +// } +//} + +func isTypedString(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + switch t { + case UntypedStringType, StringType: + return true + default: + return false + } + default: + return false + } +} + func (pt PrimitiveType) String() string { switch pt { case InvalidType: @@ -1997,49 +2162,6 @@ const ( RefTypeKind // not in go. ) -// only for / and % /= %=, no support for float -func isIntNumber(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - switch t { - case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, UntypedBigintType, BigintType: - return true - default: - return false - } - default: - return false - } -} - -func isTypedNumber(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - switch t { - case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, Float32Type, Float64Type, UntypedBigintType, BigintType, UntypedBigdecType, BigdecType: - return true - default: - return false - } - default: - return false - } -} - -func isTypedString(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - switch t { - case UntypedStringType, StringType: - return true - default: - return false - } - default: - return false - } -} - // This is generally slower than switching on baseOf(t). func KindOf(t Type) Kind { switch t := baseOf(t).(type) { @@ -2154,7 +2276,7 @@ func assertSameTypes(lt, rt Type) { } func isSameTypes(lt, rt Type) bool { - depp.Printf("isSameTypes, lt: %v, rt: %v \n", lt, rt) + depp.Printf("check isSameTypes, lt: %v, rt: %v \n", lt, rt) depp.Println("is lt data byte: ", isDataByte(lt)) depp.Println("is rt data byte: ", isDataByte(rt)) diff --git a/gnovm/tests/files/types/13a0_filetest.gno b/gnovm/tests/files/types/13a0_filetest.gno index c5c9fb7d34c..e31be679bf8 100644 --- a/gnovm/tests/files/types/13a0_filetest.gno +++ b/gnovm/tests/files/types/13a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/13a0_filetest.gno:5: cannot use int8 as int +// main/files/types/13a0_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/13a1_filetest.gno b/gnovm/tests/files/types/13a1_filetest.gno index 37bf8c07bad..f46769cfe55 100644 --- a/gnovm/tests/files/types/13a1_filetest.gno +++ b/gnovm/tests/files/types/13a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/13a1_filetest.gno:21: cannot use main.Error2 as main.Error1 without explicit conversion +// main/files/types/13a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/13b0_filetest.gno b/gnovm/tests/files/types/13b0_filetest.gno index 44138c412b6..0d63c8007be 100644 --- a/gnovm/tests/files/types/13b0_filetest.gno +++ b/gnovm/tests/files/types/13b0_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types/13b0_filetest.gno:8: cannot use main.Error as int without explicit conversion +// main/files/types/13b0_filetest.gno:8: invalid operation: mismatched types int and main.Error diff --git a/gnovm/tests/files/types/13e0_filetest.gno b/gnovm/tests/files/types/13e0_filetest.gno index 37530394129..0484f2e612e 100644 --- a/gnovm/tests/files/types/13e0_filetest.gno +++ b/gnovm/tests/files/types/13e0_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/13e0_filetest.gno:23: cannot use main.Error2 as main.Error1 without explicit conversion +// main/files/types/13e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/13e1_filetest.gno b/gnovm/tests/files/types/13e1_filetest.gno new file mode 100644 index 00000000000..3657cf2872d --- /dev/null +++ b/gnovm/tests/files/types/13e1_filetest.gno @@ -0,0 +1,20 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 = Error1(0) + e1 += 1 + println(e1) +} + +// Output: +// error: 1 diff --git a/gnovm/tests/files/types/13e_filetest.gno b/gnovm/tests/files/types/13e_filetest.gno new file mode 100644 index 00000000000..3a72f9711be --- /dev/null +++ b/gnovm/tests/files/types/13e_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 = Error1(0) + var e2 int64 = 1 + e1 += Error1(e2) + println(e1) +} + +// Output: +// error: 1 diff --git a/gnovm/tests/files/types/13f0_filetest.gno b/gnovm/tests/files/types/13f0_filetest.gno index 08b7ba35704..c27fa805169 100644 --- a/gnovm/tests/files/types/13f0_filetest.gno +++ b/gnovm/tests/files/types/13f0_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/13f0_filetest.gno:20: int does not implement .uverse.error +// main/files/types/13f0_filetest.gno:20: invalid operation: mismatched types int and .uverse.error diff --git a/gnovm/tests/files/types/13f1_filetest.gno b/gnovm/tests/files/types/13f1_filetest.gno index 52bc9e586f1..817f2b6dac2 100644 --- a/gnovm/tests/files/types/13f1_filetest.gno +++ b/gnovm/tests/files/types/13f1_filetest.gno @@ -18,9 +18,11 @@ var errCmp = errors.New("XXXX") // 2. while RHS is interface kind, and can be converted to left func main() { r := Error(0) - r += errCmp - println(r) + r += errCmp // in case of this, should panic mismatch on operand, except RHS is untyped + //println(r) + // println(Error(0) == errCmp) // Note: this is different with += + } // Error: -// invalid operation: mismatched types main.Error and *errors.errorString +// main/files/types/13f1_filetest.gno:21: invalid operation: mismatched types main.Error and .uverse.error diff --git a/gnovm/tests/files/types/1d0_filetest.gno b/gnovm/tests/files/types/1d0_filetest.gno index 9899a65a098..3f0d9548fff 100644 --- a/gnovm/tests/files/types/1d0_filetest.gno +++ b/gnovm/tests/files/types/1d0_filetest.gno @@ -1,6 +1,7 @@ package main // both untyped const +// untyped bigint to untyped bigdec // TODO: dec value representation func main() { println(1.0 + 1) diff --git a/gnovm/tests/files/types/1f0_filetest.gno b/gnovm/tests/files/types/1f0_filetest.gno index 5353313abc8..a673615effe 100644 --- a/gnovm/tests/files/types/1f0_filetest.gno +++ b/gnovm/tests/files/types/1f0_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/1f0_filetest.gno:19: + should have operand number or string, while have: .uverse.error +// main/files/types/1f0_filetest.gno:19: operator + not defined on: .uverse.error diff --git a/gnovm/tests/files/types/1f1_filetest.gno b/gnovm/tests/files/types/1f1_filetest.gno index 503a138c1ae..4f66992c8cb 100644 --- a/gnovm/tests/files/types/1f1_filetest.gno +++ b/gnovm/tests/files/types/1f1_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/1f1_filetest.gno:19: + should have operand number or string, while have: .uverse.error +// main/files/types/1f1_filetest.gno:19: operator + not defined on: .uverse.error diff --git a/gnovm/tests/files/types/1f2_filetest.gno b/gnovm/tests/files/types/1f2_filetest.gno index 1f31ff81350..6b54b409245 100644 --- a/gnovm/tests/files/types/1f2_filetest.gno +++ b/gnovm/tests/files/types/1f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/1f2_filetest.gno:27: + should have operand number or string, while have: main.E +// main/files/types/1f2_filetest.gno:27: operator + not defined on: main.E diff --git a/gnovm/tests/files/types/2b2_filetest.gno b/gnovm/tests/files/types/2b2_filetest.gno index 58634bcf674..a56d48a64b2 100644 --- a/gnovm/tests/files/types/2b2_filetest.gno +++ b/gnovm/tests/files/types/2b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2b2_filetest.gno:5: - should have operand number, while have: string +// main/files/types/2b2_filetest.gno:5: operator - not defined on: string diff --git a/gnovm/tests/files/types/2b3_filetest.gno b/gnovm/tests/files/types/2b3_filetest.gno index 2859fcf168d..092a8cfc067 100644 --- a/gnovm/tests/files/types/2b3_filetest.gno +++ b/gnovm/tests/files/types/2b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2b3_filetest.gno:5: - should have operand number, while have: string +// main/files/types/2b3_filetest.gno:5: operator - not defined on: string diff --git a/gnovm/tests/files/types/2f0_filetest.gno b/gnovm/tests/files/types/2f0_filetest.gno index fe76480b1ff..a665ce179b6 100644 --- a/gnovm/tests/files/types/2f0_filetest.gno +++ b/gnovm/tests/files/types/2f0_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/2f0_filetest.gno:19: - should have operand number, while have: .uverse.error +// main/files/types/2f0_filetest.gno:19: operator - not defined on: .uverse.error diff --git a/gnovm/tests/files/types/2f1_filetest.gno b/gnovm/tests/files/types/2f1_filetest.gno index 86f5c3a2bbc..16eede87661 100644 --- a/gnovm/tests/files/types/2f1_filetest.gno +++ b/gnovm/tests/files/types/2f1_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/2f1_filetest.gno:19: - should have operand number, while have: .uverse.error +// main/files/types/2f1_filetest.gno:19: operator - not defined on: .uverse.error diff --git a/gnovm/tests/files/types/2f2_filetest.gno b/gnovm/tests/files/types/2f2_filetest.gno index f0c7382f16c..a204e2be86d 100644 --- a/gnovm/tests/files/types/2f2_filetest.gno +++ b/gnovm/tests/files/types/2f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/2f2_filetest.gno:27: - should have operand number, while have: main.E +// main/files/types/2f2_filetest.gno:27: operator - not defined on: main.E diff --git a/gnovm/tests/files/types/3b2_filetest.gno b/gnovm/tests/files/types/3b2_filetest.gno index b31aca67a77..7799f2e791e 100644 --- a/gnovm/tests/files/types/3b2_filetest.gno +++ b/gnovm/tests/files/types/3b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3b2_filetest.gno:5: * should have operand number, while have: string +// main/files/types/3b2_filetest.gno:5: operator * not defined on: string diff --git a/gnovm/tests/files/types/3b3_filetest.gno b/gnovm/tests/files/types/3b3_filetest.gno index a2c4186be7a..839879870ff 100644 --- a/gnovm/tests/files/types/3b3_filetest.gno +++ b/gnovm/tests/files/types/3b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3b3_filetest.gno:5: * should have operand number, while have: string +// main/files/types/3b3_filetest.gno:5: operator * not defined on: string diff --git a/gnovm/tests/files/types/3f0_filetest.gno b/gnovm/tests/files/types/3f0_filetest.gno index 7cfe92453c9..8d9d1817029 100644 --- a/gnovm/tests/files/types/3f0_filetest.gno +++ b/gnovm/tests/files/types/3f0_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/3f0_filetest.gno:19: * should have operand number, while have: .uverse.error +// main/files/types/3f0_filetest.gno:19: operator * not defined on: .uverse.error diff --git a/gnovm/tests/files/types/3f1_filetest.gno b/gnovm/tests/files/types/3f1_filetest.gno index d23cb28675f..8edc5cc2e98 100644 --- a/gnovm/tests/files/types/3f1_filetest.gno +++ b/gnovm/tests/files/types/3f1_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/3f1_filetest.gno:19: * should have operand number, while have: .uverse.error +// main/files/types/3f1_filetest.gno:19: operator * not defined on: .uverse.error diff --git a/gnovm/tests/files/types/3f2_filetest.gno b/gnovm/tests/files/types/3f2_filetest.gno index 097e3e8ba1d..a90d64a0328 100644 --- a/gnovm/tests/files/types/3f2_filetest.gno +++ b/gnovm/tests/files/types/3f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/3f2_filetest.gno:27: * should have operand number, while have: main.E +// main/files/types/3f2_filetest.gno:27: operator * not defined on: main.E diff --git a/gnovm/tests/files/types/4b2_filetest.gno b/gnovm/tests/files/types/4b2_filetest.gno index 7279af2df62..c0a7c118f0d 100644 --- a/gnovm/tests/files/types/4b2_filetest.gno +++ b/gnovm/tests/files/types/4b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4b2_filetest.gno:5: QUO or REM should have operand number, while have: string +// main/files/types/4b2_filetest.gno:5: operator / not defined on: string diff --git a/gnovm/tests/files/types/4b3_filetest.gno b/gnovm/tests/files/types/4b3_filetest.gno index b82ea58c37e..e8143b1ee10 100644 --- a/gnovm/tests/files/types/4b3_filetest.gno +++ b/gnovm/tests/files/types/4b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4b3_filetest.gno:5: QUO or REM should have operand number, while have: string +// main/files/types/4b3_filetest.gno:5: operator / not defined on: string diff --git a/gnovm/tests/files/types/4f0_filetest.gno b/gnovm/tests/files/types/4f0_filetest.gno index d7072b105c8..5b1f5df3430 100644 --- a/gnovm/tests/files/types/4f0_filetest.gno +++ b/gnovm/tests/files/types/4f0_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/4f0_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error +// main/files/types/4f0_filetest.gno:19: operator / not defined on: .uverse.error diff --git a/gnovm/tests/files/types/4f1_filetest.gno b/gnovm/tests/files/types/4f1_filetest.gno index 5677b827abd..52e1d7612a2 100644 --- a/gnovm/tests/files/types/4f1_filetest.gno +++ b/gnovm/tests/files/types/4f1_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/4f1_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error +// main/files/types/4f1_filetest.gno:19: operator / not defined on: .uverse.error diff --git a/gnovm/tests/files/types/4f2_filetest.gno b/gnovm/tests/files/types/4f2_filetest.gno index b9c345097a9..95b09f068fc 100644 --- a/gnovm/tests/files/types/4f2_filetest.gno +++ b/gnovm/tests/files/types/4f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/4f2_filetest.gno:27: QUO or REM should have operand number, while have: main.E +// main/files/types/4f2_filetest.gno:27: operator / not defined on: main.E diff --git a/gnovm/tests/files/types/5b2_filetest.gno b/gnovm/tests/files/types/5b2_filetest.gno index 9ecb05da049..4679f005cc0 100644 --- a/gnovm/tests/files/types/5b2_filetest.gno +++ b/gnovm/tests/files/types/5b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5b2_filetest.gno:5: QUO or REM should have operand number, while have: string +// main/files/types/5b2_filetest.gno:5: operator % not defined on: string diff --git a/gnovm/tests/files/types/5b3_filetest.gno b/gnovm/tests/files/types/5b3_filetest.gno index b10138ae562..ef990873c49 100644 --- a/gnovm/tests/files/types/5b3_filetest.gno +++ b/gnovm/tests/files/types/5b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5b3_filetest.gno:5: QUO or REM should have operand number, while have: string +// main/files/types/5b3_filetest.gno:5: operator % not defined on: string diff --git a/gnovm/tests/files/types/5d0_filetest.gno b/gnovm/tests/files/types/5d0_filetest.gno index 3d9e8857b74..1f6ed065974 100644 --- a/gnovm/tests/files/types/5d0_filetest.gno +++ b/gnovm/tests/files/types/5d0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/5d0_filetest.gno:6: QUO or REM should have operand number, while have: bigdec +// main/files/types/5d0_filetest.gno:6: operator % not defined on: bigdec diff --git a/gnovm/tests/files/types/5d4_filetest.gno b/gnovm/tests/files/types/5d4_filetest.gno index 2c277911bfe..703fc0aa8bf 100644 --- a/gnovm/tests/files/types/5d4_filetest.gno +++ b/gnovm/tests/files/types/5d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/5d4_filetest.gno:6: QUO or REM should have operand number, while have: bigdec +// main/files/types/5d4_filetest.gno:6: operator % not defined on: bigdec diff --git a/gnovm/tests/files/types/5f0_filetest.gno b/gnovm/tests/files/types/5f0_filetest.gno index 00d2cb3acdc..52bb636e087 100644 --- a/gnovm/tests/files/types/5f0_filetest.gno +++ b/gnovm/tests/files/types/5f0_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/5f0_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error +// main/files/types/5f0_filetest.gno:19: operator % not defined on: .uverse.error diff --git a/gnovm/tests/files/types/5f1_filetest.gno b/gnovm/tests/files/types/5f1_filetest.gno index 1a2db718ce8..7c5d88e3c3c 100644 --- a/gnovm/tests/files/types/5f1_filetest.gno +++ b/gnovm/tests/files/types/5f1_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/5f1_filetest.gno:19: QUO or REM should have operand number, while have: .uverse.error +// main/files/types/5f1_filetest.gno:19: operator % not defined on: .uverse.error diff --git a/gnovm/tests/files/types/5f2_filetest.gno b/gnovm/tests/files/types/5f2_filetest.gno index 22f34d6df6e..b8a5793d4ae 100644 --- a/gnovm/tests/files/types/5f2_filetest.gno +++ b/gnovm/tests/files/types/5f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/5f2_filetest.gno:27: QUO or REM should have operand number, while have: main.E +// main/files/types/5f2_filetest.gno:27: operator % not defined on: main.E diff --git a/gnovm/tests/files/types/others/README.md b/gnovm/tests/files/types/others/README.md index 9c53dd3f92c..c1ca831a209 100644 --- a/gnovm/tests/files/types/others/README.md +++ b/gnovm/tests/files/types/others/README.md @@ -115,3 +115,17 @@ TODOs: // TODO: dec value representation // TODO: Current flow : check op operand, check type convertable, and convert, and check type match again, means, this kind of check should still in preprocess // TODO: preCheck->Convert->postCheck, all in `checkOrConvertType` + + +NOTE: + + // in 13f1, indicates that, in preCheck, + // if dt is not match with op + // else if LHS,RHS is typed and mismatched, panic + // else, check untyped(const), unnamed(composite) cases + *** is straight forward, if we have right and left types, use it. how about interface and declared types? if LHS and RHS in one of this? so not only untyped passthrough, these latter two needs passthrouh from preCheck too. *** + + // wired that == accepts LHS impl RHS or visa versa, while += not accpet this + + + // only change for binary unary ,assign ,etc, op related, using another func like checkOperand, else checkOrConvert remains \ No newline at end of file From 7acaec6e1a14a2c034898e761293f4bea3044332 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 4 Dec 2023 11:25:12 +0800 Subject: [PATCH 011/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 208 +++++++++-------------- gnovm/pkg/gnolang/types.go | 9 +- gnovm/pkg/gnolang/values.go | 128 ++++++++++++++ gnovm/tests/files/type31.gno | 2 +- gnovm/tests/files/type32.gno | 2 +- gnovm/tests/files/types/1a0_filetest.gno | 2 +- gnovm/tests/files/types/1a1_filetest.gno | 2 +- gnovm/tests/files/types/1e0_filetest.gno | 2 +- gnovm/tests/files/types/2a0_filetest.gno | 2 +- gnovm/tests/files/types/2a1_filetest.gno | 2 +- gnovm/tests/files/types/2e0_filetest.gno | 2 +- gnovm/tests/files/types/3a0_filetest.gno | 2 +- gnovm/tests/files/types/3a1_filetest.gno | 2 +- gnovm/tests/files/types/3e0_filetest.gno | 2 +- gnovm/tests/files/types/4a0_filetest.gno | 2 +- gnovm/tests/files/types/4a1_filetest.gno | 2 +- gnovm/tests/files/types/4d4_filetest.gno | 2 +- gnovm/tests/files/types/4d5_filetest.gno | 11 ++ gnovm/tests/files/types/4d6_filetest.gno | 11 ++ gnovm/tests/files/types/4e0_filetest.gno | 2 +- gnovm/tests/files/types/5a0_filetest.gno | 2 +- gnovm/tests/files/types/5a1_filetest.gno | 2 +- gnovm/tests/files/types/5e0_filetest.gno | 2 +- 23 files changed, 252 insertions(+), 151 deletions(-) create mode 100644 gnovm/tests/files/types/4d5_filetest.gno create mode 100644 gnovm/tests/files/types/4d6_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 34b330d6911..cd2604799a0 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -763,6 +763,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { depp.Println("left is const") if ric { depp.Println("right is const") + // special case, check zero divisor + // should check in after type check + //checkOperand(rcx, n.Op) // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. @@ -787,7 +790,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cmp < 0 { // this always implies untyped>? depp.Println("cmp < 0, ->") // convert n.Left to right type. - checkOrConvertTypeWithOp(store, last, &n.Left, rcx.T, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rcx.T, n.Op, false) } else if cmp == 0 { depp.Println("cmp == 0") // NOTE: the following doesn't work. @@ -796,11 +799,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // or check for compatibility. // (the other way around would work too) // also need to check - checkOrConvertTypeWithOp(store, last, &n.Left, rcx.T, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rcx.T, n.Op, false) } else { // this always implies untyped>? depp.Println("cmp > 0, <-") // convert n.Right to left type. - checkOrConvertTypeWithOp(store, last, &n.Right, lcx.T, n.Op, false) + // TODO: this looks wired + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lcx.T, n.Op, false) } } // Then, evaluate the expression. @@ -817,7 +821,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOrConvertTypeWithOp(store, last, &n.Left, pt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, pt, n.Op, false) // convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. @@ -845,7 +849,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { depp.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) depp.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. - checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const @@ -858,12 +862,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { //} else { // checkOrConvertType(store, last, &n.Left, rt, n.Op, false) //} - checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } else if lcx.T == nil { depp.Println("lcx.T is nil") // convert n.Left to typed-nil type. - checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } // TODO: 912 line? } else if ric { @@ -874,7 +878,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { if baseOf(rt) != UintType { // convert n.Right to (gno) uint type. - checkOrConvertTypeWithOp(store, last, &n.Right, UintType, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, UintType, n.Op, false) } else { // leave n.Left as is and baseOf(n.Right) as UintType. } @@ -885,7 +889,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOrConvertTypeWithOp(store, last, &n.Right, pt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, pt, n.Op, false) // and convert result back. tx := constType(n, lnt) // reset/create n2 to preprocess left child. @@ -901,16 +905,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) } } //} else if rcx.T == nil { } else if rcx.T == nil { depp.Println("rcx.T == nil ") // convert n.Right to typed-nil type. - checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) } else if !isShift { - checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) } } else { depp.Printf("both not const, lt: %v, rt:%v \n", lt, rt) @@ -977,12 +981,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { depp.Println("left untyped, right is typed") - checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } } else if riu { - checkOrConvertTypeWithOp(store, last, &n.Right, lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) } else { - checkOrConvertTypeWithOp(store, last, &n.Left, rt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) //// left is untyped, right is not. //if lt.TypeID() != rt.TypeID() { // panic(fmt.Sprintf( @@ -1300,12 +1304,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *ArrayType: for i := 0; i < len(n.Elts); i++ { - convertConstType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) + convertConstType(store, last, &n.Elts[i].Key, IntType, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { - convertConstType(store, last, &n.Elts[i].Key, IntType, ILLEGAL, false) + convertConstType(store, last, &n.Elts[i].Key, IntType, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *MapType: @@ -1660,7 +1664,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } // Special case if shift assign <<= or >>=. - checkOrConvertTypeWithOp(store, last, &n.Rhs[0], UintType, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], UintType, n.Op, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { depp.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, @@ -1677,7 +1681,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // panic("mismatch type for Assign") // } //} else { - checkOrConvertTypeWithOp(store, last, &n.Rhs[0], lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], lt, n.Op, false) //} } else { // all else, like BAND_ASSIGN, etc depp.Println("case: a, b = x, y") @@ -1691,13 +1695,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { depp.Println("rt is untyped, convert") // is untyped // converts if rx is "nil". - checkOrConvertTypeWithOp(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) } else { depp.Println("rt not untyped, check strict") //if lt.TypeID() != rt.TypeID() { // panic("mismatch type for Assign, in case: a, b = x, y") //} - checkOrConvertTypeWithOp(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) } } } @@ -2392,7 +2396,7 @@ func cmpSpecificity(t1, t2 Type) int { } // for special case of index conversion -func convertConstType(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { +func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { depp.Printf("convertConstType, x: %v, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { convertConst(store, last, cx, t) @@ -2466,26 +2470,33 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } -func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, t Type, op Word, autoNative bool) { +// add operands here +// NOTE: y is used to check operand, e.g. zero divisor: a/0, any other cases? +// additionally, if something like, int(1)/int8(0), should first check is type matches, prior to check zero divisor +// TODO: simplify args, to be, n, dir, -1 right to left, 1 left to right +func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t Type, op Word, autoNative bool) { depp.Printf("checkOrConvertTypeWithOp, x: %v:, t:%v, op: %v \n", x, t, op) if cx, ok := (*x).(*ConstExpr); ok { // here we should check too, e.g. primitive to declared type is convertable if _, ok := t.(*NativeType); !ok { // not native type depp.Println("ConstExpr is not nativeType, go check") checkType(cx.T, t, op, autoNative) + // check operand + if cy, ok := (*y).(*ConstExpr); ok { + checkOperand(cy, op) + } } depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { depp.Println("SHL or SHR") // "push" expected type into shift binary's left operand. - checkOrConvertTypeWithOp(store, last, &bx.Left, t, op, autoNative) + checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { depp.Println("else, xt not nil") xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { - //checkType(xt, t, op, autoNative) conversionNeeded = checkType(xt, t, op, autoNative) } if isUntyped(xt) { @@ -2498,12 +2509,12 @@ func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, t Type, op W case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: // push t into bx.Left and bx.Right - checkOrConvertTypeWithOp(store, last, &bx.Left, t, op, autoNative) - checkOrConvertTypeWithOp(store, last, &bx.Right, t, op, autoNative) + checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) + checkOrConvertTypeWithOp(store, last, &bx.Right, y, t, op, autoNative) return case SHL, SHR: // push t into bx.Left - checkOrConvertTypeWithOp(store, last, &bx.Left, t, op, autoNative) + checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) return // case EQL, LSS, GTR, NEQ, LEQ, GEQ: // default: @@ -2577,115 +2588,45 @@ func init() { predicates[LOR] = isBoolean } -// Assert that xt can be assigned as dt (dest type). -// If autoNative is true, a broad range of xt can match against -// a target native dt type, if and only if dt is a native type. -func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded bool) { - if xt == nil || dt == nil { - return +// post check after conversion +// TODO: this not right, since xt is not divisor +func checkOperand(cx *ConstExpr, op Word) { + switch op { + case QUO, QUO_ASSIGN, REM, REM_ASSIGN: + // TODO, check zero divisor + // is there a sign method for numeric + if cx.TypedValue.T != nil { + depp.Println("check operand, kind is: ", cx.TypedValue.T.Kind()) + } + if cx.TypedValue.Sign() == 0 { + panic("invalid operation: division by zero") + } else { + depp.Println("sign is: ", cx.TypedValue.Sign()) + } } - depp.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) - // TODO: first check operands and Op +} + +func checkOp(xt Type, dt Type, op Word) { // two steps of check: // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt - if op != ILLEGAL { // should check operand with op, this would filter most of the op relate issues - depp.Printf("check matchable with op: %v \n", op) - if pred, ok := predicates[op]; ok { - if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) - } + depp.Printf("check matchable with op: %v \n", op) + if pred, ok := predicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } + } + if op != ILLEGAL { switch op { - //case ADD: // dt is the dest type, what we need check - //if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - //panic(fmt.Sprintf("+ should have operand number or string, while have: %v", dt)) - //} - - //case SUB: - // if !isNumeric(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("- should have operand number, while have: %v", dt)) - // } - //case MUL: - // if !isNumeric(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("* should have operand number, while have: %v", dt)) - // } - //case QUO: - // if !isNumeric(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) - // } - //case REM: - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("QUO or REM should have operand number, while have: %v", dt)) - // } - //case BAND: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator & not defined on: %v", dt)) - // } - //case BAND_ASSIGN: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator &= not defined on: %v", dt)) - // } - //case BOR: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator | not defined on: %v", dt)) - // } - //case BOR_ASSIGN: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator |= not defined on: %v", dt)) - // } - //case XOR: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator ^ not defined on: %v", dt)) - // } - //case XOR_ASSIGN: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator ^= not defined on: %v", dt)) - // } - //case BAND_NOT: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator &^ not defined on: %v", dt)) - // } - //case BAND_NOT_ASSIGN: // not defined on float - // if !isIntNumber(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator &^= not defined on: %v", dt)) - // } - //case LAND: // not defined on float - // if dt != UntypedBoolType && dt != BoolType { - // panic(fmt.Sprintf("operator && not defined on: %v", dt)) - // } - //case LOR: // not defined on float - // if dt != UntypedBoolType && dt != BoolType { - // panic(fmt.Sprintf("operator || not defined on: %v", dt)) - // } - case ADD_ASSIGN: - //if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator += not defined on: %v", dt)) - //} + case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: // TODO: check matchable here, not in runtime // special case - if !isUntyped(xt) { + if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped if !isSameTypes(xt, dt) { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } - //case SUB_ASSIGN: - // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator -= not defined on: %v", dt)) - // } - //case MUL_ASSIGN: - // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator *= not defined on: %v", dt)) - // } - //case QUO_ASSIGN: - // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator /= not defined on: %v", dt)) - // } - //case REM_ASSIGN: - // if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - // panic(fmt.Sprintf("operator %%= not defined on: %v", dt)) - // } case EQL, NEQ: // do nothing here, as a special case, EQL or NEQ is more relaxed than ADD, so convertable is checked as `equality` in logic below @@ -2696,12 +2637,24 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { panic(fmt.Sprintf("operator < not defined on: %v", dt)) } - default: // do nothing // TODO: should also check the divisor not zero } } +} + +// Assert that xt can be assigned as dt (dest type). +// If autoNative is true, a broad range of xt can match against +// a target native dt type, if and only if dt is a native type. +func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded bool) { + if xt == nil || dt == nil { + return + } + depp.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) + // TODO: first check operands and Op + + checkOp(xt, dt, op) // check convertable // TODO: xt could be nil //if xt.TypeID() != dt.TypeID() { @@ -2709,10 +2662,7 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo // 2. convert with op, like int(1) + 0, will also need check convertable depp.Println("ops checks pass, check convertable on operand") - var xtStr string - if xt != nil { - xtStr = xt.String() - } + xtStr := xt.String() // Special case if dt is interface kind: if dt.Kind() == InterfaceKind { depp.Println("dt is interface") diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index a09e9e6046c..8db17f009ec 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -273,7 +273,7 @@ const ( IsRune IsOrdered = IsInteger | IsFloat | IsString - IsNumeric = IsInteger | IsFloat | IsComplex | IsBigInt | IsBigDec + IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec IsConstType = IsBoolean | IsNumeric | IsString ) @@ -346,7 +346,7 @@ func isBoolean(t Type) bool { func isNumeric(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsRune != 0 { + if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate()&IsRune != 0 { return true } return false @@ -355,10 +355,11 @@ func isNumeric(t Type) bool { } } +// signed or unsigned int func isIntNum(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsBigInt != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsRune != 0 { + if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate()&IsUnsigned != 0 || t.Predicate()&IsBigInt != 0 || t.Predicate()&IsRune != 0 { return true } return false @@ -370,7 +371,7 @@ func isIntNum(t Type) bool { func isNumericOrString(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsString != 0 || t.Predicate() != IsInvalid && t.Predicate()&IsRune != 0 { + if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate()&IsString != 0 || t.Predicate()&IsRune != 0 { return true } return false diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 3bdd3332e08..0275e0155b8 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -1453,6 +1453,134 @@ func (tv *TypedValue) GetBigDec() *apd.Decimal { return tv.V.(BigdecValue).V } +// Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0; +// x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0, +// otherwise it is != 0. If x is Unknown, the result is 1. +func (tv *TypedValue) Sign() int { + if tv.T == nil { + panic("type should not be nil") + } + switch tv.T.Kind() { + case IntKind: + v := tv.GetInt() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Int8Kind: + v := tv.GetInt8() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Int16Kind: + v := tv.GetInt16() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Int32Kind: + v := tv.GetInt32() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Int64Kind: + v := tv.GetInt64() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case UintKind: + v := tv.GetInt() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Uint8Kind: + v := tv.GetInt8() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Uint16Kind: + v := tv.GetInt16() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Uint32Kind: + v := tv.GetInt32() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Uint64Kind: + v := tv.GetInt64() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Float32Kind: + v := tv.GetFloat32() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case Float64Kind: + v := tv.GetFloat64() + if v < 0 { + return -1 + } else if v == 0 { + return 0 + } else { + return 1 + } + case BigintKind: + v := tv.GetBigInt() + return v.Sign() + case BigdecKind: + v := tv.GetBigDec() + //fmt.Printf("bigdec, v %v: \n", v) + return v.Sign() + default: + panic("not numeric") + } +} + func (tv *TypedValue) ComputeMapKey(store Store, omitType bool) MapKey { // Special case when nil: has no separator. if tv.T == nil { diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index 1c8b91b02fd..7087561f33e 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/type31.gno:8: cannot use string as main.String without explicit conversion +// main/files/type31.gno:8: invalid operation: mismatched types main.String and string diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index 58a19f606ae..1a087ec1140 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/type32.gno:9#1: cannot use string as main.S without explicit conversion +// main/files/type32.gno:9#1: invalid operation: mismatched types main.S and string diff --git a/gnovm/tests/files/types/1a0_filetest.gno b/gnovm/tests/files/types/1a0_filetest.gno index 874c9a3d288..65b4cef3ae4 100644 --- a/gnovm/tests/files/types/1a0_filetest.gno +++ b/gnovm/tests/files/types/1a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/1a0_filetest.gno:5: cannot use int as int8 +// main/files/types/1a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/1a1_filetest.gno b/gnovm/tests/files/types/1a1_filetest.gno index ff236a28012..68cb813fef9 100644 --- a/gnovm/tests/files/types/1a1_filetest.gno +++ b/gnovm/tests/files/types/1a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/1a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/1a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/1e0_filetest.gno b/gnovm/tests/files/types/1e0_filetest.gno index 61c999ce0af..4e31870425c 100644 --- a/gnovm/tests/files/types/1e0_filetest.gno +++ b/gnovm/tests/files/types/1e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/1e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/1e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/2a0_filetest.gno b/gnovm/tests/files/types/2a0_filetest.gno index 4f3770c39c4..156fe844751 100644 --- a/gnovm/tests/files/types/2a0_filetest.gno +++ b/gnovm/tests/files/types/2a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2a0_filetest.gno:5: cannot use int as int8 +// main/files/types/2a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/2a1_filetest.gno b/gnovm/tests/files/types/2a1_filetest.gno index 53ef6bf03db..3b4e28d066b 100644 --- a/gnovm/tests/files/types/2a1_filetest.gno +++ b/gnovm/tests/files/types/2a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/2a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/2a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/2e0_filetest.gno b/gnovm/tests/files/types/2e0_filetest.gno index 42d9b638e12..33430eb7bf1 100644 --- a/gnovm/tests/files/types/2e0_filetest.gno +++ b/gnovm/tests/files/types/2e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/2e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/2e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/3a0_filetest.gno b/gnovm/tests/files/types/3a0_filetest.gno index 53e130ddce7..42fc593c685 100644 --- a/gnovm/tests/files/types/3a0_filetest.gno +++ b/gnovm/tests/files/types/3a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3a0_filetest.gno:5: cannot use int as int8 +// main/files/types/3a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/3a1_filetest.gno b/gnovm/tests/files/types/3a1_filetest.gno index 0244780e786..a472459d4a9 100644 --- a/gnovm/tests/files/types/3a1_filetest.gno +++ b/gnovm/tests/files/types/3a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/3a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/3a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/3e0_filetest.gno b/gnovm/tests/files/types/3e0_filetest.gno index 0916d0acede..f4a85ac3ca9 100644 --- a/gnovm/tests/files/types/3e0_filetest.gno +++ b/gnovm/tests/files/types/3e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/3e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/3e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/4a0_filetest.gno b/gnovm/tests/files/types/4a0_filetest.gno index 6b9909c16d1..e357bf749fc 100644 --- a/gnovm/tests/files/types/4a0_filetest.gno +++ b/gnovm/tests/files/types/4a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4a0_filetest.gno:5: cannot use int as int8 +// main/files/types/4a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/4a1_filetest.gno b/gnovm/tests/files/types/4a1_filetest.gno index 9142b04f57f..018e51bfdcd 100644 --- a/gnovm/tests/files/types/4a1_filetest.gno +++ b/gnovm/tests/files/types/4a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/4a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/4a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/4d4_filetest.gno b/gnovm/tests/files/types/4d4_filetest.gno index df023f067bd..b01f3fb24ce 100644 --- a/gnovm/tests/files/types/4d4_filetest.gno +++ b/gnovm/tests/files/types/4d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/4d4_filetest.gno:6: bigdec division error: division by zero +// main/files/types/4d4_filetest.gno:6: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4d5_filetest.gno b/gnovm/tests/files/types/4d5_filetest.gno new file mode 100644 index 00000000000..ef2140a7abd --- /dev/null +++ b/gnovm/tests/files/types/4d5_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + a := 1 / 0 + println(a) +} + +// Error: +// main/files/types/4d5_filetest.gno:6: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4d6_filetest.gno b/gnovm/tests/files/types/4d6_filetest.gno new file mode 100644 index 00000000000..a6c020b17eb --- /dev/null +++ b/gnovm/tests/files/types/4d6_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + a := 1 / 0.0 + println(a) +} + +// Error: +// main/files/types/4d6_filetest.gno:6: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4e0_filetest.gno b/gnovm/tests/files/types/4e0_filetest.gno index 6bc2276af1e..2787bfe292e 100644 --- a/gnovm/tests/files/types/4e0_filetest.gno +++ b/gnovm/tests/files/types/4e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/4e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/4e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/5a0_filetest.gno b/gnovm/tests/files/types/5a0_filetest.gno index eda3ca19569..6fa8e3dcbda 100644 --- a/gnovm/tests/files/types/5a0_filetest.gno +++ b/gnovm/tests/files/types/5a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5a0_filetest.gno:5: cannot use int as int8 +// main/files/types/5a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/5a1_filetest.gno b/gnovm/tests/files/types/5a1_filetest.gno index 6c7134acbc9..c9d4eea47b4 100644 --- a/gnovm/tests/files/types/5a1_filetest.gno +++ b/gnovm/tests/files/types/5a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/5a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/5a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/5e0_filetest.gno b/gnovm/tests/files/types/5e0_filetest.gno index 3dc5ebc4dd8..7cb4a1adf48 100644 --- a/gnovm/tests/files/types/5e0_filetest.gno +++ b/gnovm/tests/files/types/5e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/5e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/5e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 From e291e562f912bb837285e36b915bb38559ba10c9 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 5 Dec 2023 18:40:26 +0800 Subject: [PATCH 012/193] comparable --- gnovm/pkg/gnolang/op_binary.go | 17 +- gnovm/pkg/gnolang/preprocess.go | 357 ++------------------- gnovm/pkg/gnolang/types.go | 374 +++++++++++++++++++++- gnovm/pkg/gnolang/values.go | 3 - gnovm/tests/files/types/0f12_filetest.gno | 13 + gnovm/tests/files/types/0f13_filetest.gno | 15 + gnovm/tests/files/types/0f14_filetest.gno | 14 + gnovm/tests/files/types/0f15_filetest.gno | 18 ++ gnovm/tests/files/types/0f16_filetest.gno | 20 ++ gnovm/tests/files/types/0f17_filetest.gno | 13 + gnovm/tests/files/types/0f18_filetest.gno | 12 + gnovm/tests/files/types/0f19_filetest.gno | 12 + gnovm/tests/files/types/0f20_filetest.gno | 14 + gnovm/tests/files/types/0f21_filetest.gno | 14 + gnovm/tests/files/types/1d4_filetest.gno | 11 + gnovm/tests/files/types/1f3_filetest.gno | 34 ++ gnovm/tests/files/types/1f4_filetest.gno | 35 ++ gnovm/tests/files/types/1f5_filetest.gno | 39 +++ gnovm/tests/files/types/1f6_filetest.gno | 31 ++ gnovm/tests/files/types/1f7_filetest.gno | 28 ++ gnovm/tests/files/types/1f8_filetest.gno | 41 +++ gnovm/tests/files/types/1f9_filetest.gno | 35 ++ gnovm/tests/files/types/others/README.md | 31 ++ 23 files changed, 832 insertions(+), 349 deletions(-) create mode 100644 gnovm/tests/files/types/0f12_filetest.gno create mode 100644 gnovm/tests/files/types/0f13_filetest.gno create mode 100644 gnovm/tests/files/types/0f14_filetest.gno create mode 100644 gnovm/tests/files/types/0f15_filetest.gno create mode 100644 gnovm/tests/files/types/0f16_filetest.gno create mode 100644 gnovm/tests/files/types/0f17_filetest.gno create mode 100644 gnovm/tests/files/types/0f18_filetest.gno create mode 100644 gnovm/tests/files/types/0f19_filetest.gno create mode 100644 gnovm/tests/files/types/0f20_filetest.gno create mode 100644 gnovm/tests/files/types/0f21_filetest.gno create mode 100644 gnovm/tests/files/types/1d4_filetest.gno create mode 100644 gnovm/tests/files/types/1f3_filetest.gno create mode 100644 gnovm/tests/files/types/1f4_filetest.gno create mode 100644 gnovm/tests/files/types/1f5_filetest.gno create mode 100644 gnovm/tests/files/types/1f6_filetest.gno create mode 100644 gnovm/tests/files/types/1f7_filetest.gno create mode 100644 gnovm/tests/files/types/1f8_filetest.gno create mode 100644 gnovm/tests/files/types/1f9_filetest.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index d1490678414..735ec73f3e3 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -382,9 +382,9 @@ func isEql(store Store, lv, rv *TypedValue) bool { return false } if lnt, ok := lv.T.(*NativeType); ok { - println("left is native type") + depp.Println("left is native type") if rnt, ok := rv.T.(*NativeType); ok { - println("right is native type") + depp.Println("right is native type") if lnt.Type != rnt.Type { return false } @@ -409,11 +409,6 @@ func isEql(store Store, lv, rv *TypedValue) bool { case Int32Kind: return (lv.GetInt32() == rv.GetInt32()) case Int64Kind: - depp.Println("int64 kind") - depp.Println("lv kind: ", lv.T.Kind()) - depp.Println("rv kind: ", rv.T.Kind()) - depp.Println("lv int64", lv.GetInt64()) - depp.Println("rv int64", rv.GetInt64()) return (lv.GetInt64() == rv.GetInt64()) case UintKind: return (lv.GetUint() == rv.GetUint()) @@ -495,11 +490,11 @@ func isEql(store Store, lv, rv *TypedValue) bool { } return lv.V == rv.V case FuncKind: - if debug { - if lv.V != nil && rv.V != nil { - panic("function can only be compared with `nil`") - } + //if debug { + if lv.V != nil && rv.V != nil { + panic("function can only be compared with `nil`") } + //} if _, ok := lv.V.(*BoundMethodValue); ok { // BoundMethodValues are objects so just compare. return lv.V == rv.V diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cd2604799a0..4aab3197f28 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1052,7 +1052,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Handle special cases. // NOTE: these appear to be actually special cases in go. - // In general, a string is not assignable to []bytes + // In general, a string is not convertable to []bytes // without conversion. if cx, ok := n.Func.(*ConstExpr); ok { fv := cx.GetFunc() @@ -2473,7 +2473,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // add operands here // NOTE: y is used to check operand, e.g. zero divisor: a/0, any other cases? // additionally, if something like, int(1)/int8(0), should first check is type matches, prior to check zero divisor -// TODO: simplify args, to be, n, dir, -1 right to left, 1 left to right func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t Type, op Word, autoNative bool) { depp.Printf("checkOrConvertTypeWithOp, x: %v:, t:%v, op: %v \n", x, t, op) if cx, ok := (*x).(*ConstExpr); ok { @@ -2488,6 +2487,7 @@ func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t T } depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) + // TODO: } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { depp.Println("SHL or SHR") // "push" expected type into shift binary's left operand. @@ -2542,7 +2542,6 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { depp.Printf("convertConst, cx:%v, t:%v \n", cx, t) - // TODO: some constraint, panic if not convertable // TODO: thought it should only be permmited to converted to default types, not convertable to interface not satisfied if t != nil && t.Kind() == InterfaceKind { depp.Println("set t to nil, if its kind is interface") @@ -2606,7 +2605,31 @@ func checkOperand(cx *ConstExpr, op Word) { } } +func isComparison(op Word) bool { + switch op { + case EQL, NEQ, LSS, LEQ, GTR, GEQ: + return true + default: + return false + } +} + func checkOp(xt Type, dt Type, op Word) { + depp.Printf("checkOp, xt: %v, dt: %v, op: %v \n", xt, dt, op) + // first check comparison + if isComparison(op) { + switch op { + case EQL, NEQ: // check comparable + // 1. first, check specific types can be compared, like predicates for ADD, etc + // 2. comparable requires one is convertable to another + // 3. handle nil + if ok, code := comparable(dt); !ok { + depp.Printf("not comparable of dt :%v \n", dt) + panic(code) + } + case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString + } + } // two steps of check: // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this @@ -2621,22 +2644,17 @@ func checkOp(xt Type, dt Type, op Word) { switch op { case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: // TODO: check matchable here, not in runtime - // special case + // if both typed if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped if !isSameTypes(xt, dt) { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } - case EQL, NEQ: // do nothing here, as a special case, EQL or NEQ is more relaxed than ADD, so convertable is checked as `equality` in logic below // case SHL, SHR: // TODO: right should be numeric - case LSS: // TODO: comparable, assignable - if !isNumeric(dt) && !isTypedString(dt) && dt != UntypedRuneType { - panic(fmt.Sprintf("operator < not defined on: %v", dt)) - } default: // do nothing // TODO: should also check the divisor not zero @@ -2649,330 +2667,13 @@ func checkOp(xt Type, dt Type, op Word) { // a target native dt type, if and only if dt is a native type. func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded bool) { if xt == nil || dt == nil { + depp.Println("xt or dt is nil") return } depp.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) - // TODO: first check operands and Op - checkOp(xt, dt, op) - // check convertable - // TODO: xt could be nil - //if xt.TypeID() != dt.TypeID() { - // 1. convert with no op, e.g. elements in slice - // 2. convert with op, like int(1) + 0, will also need check convertable depp.Println("ops checks pass, check convertable on operand") - - xtStr := xt.String() - // Special case if dt is interface kind: - if dt.Kind() == InterfaceKind { - depp.Println("dt is interface") - if idt, ok := baseOf(dt).(*InterfaceType); ok { - if idt.IsEmptyInterface() { - depp.Println("dt is empty interface") - // if dt is an empty Gno interface, any x ok. - return // ok - } else if idt.IsImplementedBy(xt) { - depp.Println("dt is implemented by xt") - // if dt implements idt, ok. - return // ok - } else if iot, ok := xt.(*InterfaceType); ok { - depp.Println("xt is empty interface") - if iot.IsEmptyInterface() { - return // ok - } - } else { - panic(fmt.Sprintf( - "%s does not implement %s", - xtStr, - dt.String())) - } - } else if ndt, ok := baseOf(dt).(*NativeType); ok { - nidt := ndt.Type - if nidt.NumMethod() == 0 { - // if dt is an empty Go native interface, ditto. - return // ok - } else if nxt, ok := baseOf(xt).(*NativeType); ok { - // if xt has native base, do the naive native. - if nxt.Type.AssignableTo(nidt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nxt.String(), - nidt.String())) - } - } else if pxt, ok := baseOf(xt).(*PointerType); ok { - nxt, ok := pxt.Elt.(*NativeType) - if !ok { - panic(fmt.Sprintf( - "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", - pxt.String(), - nidt.String())) - } - // if xt has native base, do the naive native. - if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - pxt.String(), - nidt.String())) - } - } else { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - xtStr, - dt.String())) - } - } else { - panic("should not happen") - } - } else if xt.Kind() == InterfaceKind { - depp.Println("xt is interface") - if ixt, ok := baseOf(xt).(*InterfaceType); ok { - if ixt.IsEmptyInterface() { - depp.Println("xt is empty interface") - // if dt is an empty Gno interface, any x ok. - return // ok - } else if ixt.IsImplementedBy(dt) { - depp.Println("xt is implemented by dt") - // if dt implements idt, ok. - return // ok - } else if idt, ok := dt.(*InterfaceType); ok { - if idt.IsEmptyInterface() { - return - } - } else { - panic(fmt.Sprintf( - "%s does not implement %s", - dt.String(), xtStr)) - } - } else if nxt, ok := baseOf(xt).(*NativeType); ok { - nixt := nxt.Type - if nixt.NumMethod() == 0 { - // if dt is an empty Go native interface, ditto. - return // ok - } else if ndt, ok := baseOf(dt).(*NativeType); ok { - // if xt has native base, do the naive native. - if nxt.Type.AssignableTo(nixt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nixt.String(), ndt.String())) - } - } else if pdt, ok := baseOf(dt).(*PointerType); ok { - nxt, ok := pdt.Elt.(*NativeType) - if !ok { - panic(fmt.Sprintf( - "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", - nixt.String(), pdt.String())) - } - // if xt has native base, do the naive native. - if reflect.PtrTo(nxt.Type).AssignableTo(nixt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nixt.String(), pdt.String())) - } - } else { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - xtStr, - dt.String())) - } - } else { - panic("should not happen") - } - } - // Special case if xt or dt is *PointerType to *NativeType, - // convert to *NativeType of pointer kind. - if pxt, ok := xt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - //nolint:misspell - if enxt, ok := pxt.Elt.(*NativeType); ok { - xt = &NativeType{ - Type: reflect.PtrTo(enxt.Type), - } - } - } - if pdt, ok := dt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - if endt, ok := pdt.Elt.(*NativeType); ok { - dt = &NativeType{ - Type: reflect.PtrTo(endt.Type), - } - } - } - // Special case of xt or dt is *DeclaredType, - // allow implicit conversion unless both are declared. - // TODO simplify with .IsNamedType(). - if dxt, ok := xt.(*DeclaredType); ok { - if ddt, ok := dt.(*DeclaredType); ok { - // types must match exactly. - if !dxt.sealed && !ddt.sealed && - dxt.PkgPath == ddt.PkgPath && - dxt.Name == ddt.Name { // not yet sealed - return // ok - } else if dxt.TypeID() == ddt.TypeID() { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - ddt.String())) - } - } else { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := dt.(PrimitiveType); ok { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - dt.String())) - //xt = dxt.Base - } else { - // carry on with baseOf(dxt) - xt = dxt.Base - conversionNeeded = true - } - } - } else if ddt, ok := dt.(*DeclaredType); ok { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := xt.(PrimitiveType); ok { - depp.Println("xt is primitiveType") - // this is special when dt is the declared type of x - if !isUntyped(xt) { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - xt.String(), - ddt.String())) - } - - } else { - // carry on with baseOf(ddt) - dt = ddt.Base - conversionNeeded = true - } - } - // General cases. - switch cdt := dt.(type) { - case PrimitiveType: - depp.Println("primitive type") - // if xt is untyped, ensure dt is compatible. - switch xt { - case UntypedBoolType: - if dt.Kind() == BoolKind { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use untyped bool as %s", - dt.Kind())) - } - case UntypedStringType: - if dt.Kind() == StringKind { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use untyped string as %s", - dt.Kind())) - } - case UntypedBigintType, UntypedBigdecType: - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: - return // ok - default: - panic(fmt.Sprintf( - "cannot use untyped Bigint/Bigdec as %s", - dt.Kind())) - } - case UntypedRuneType: - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: - return // ok - default: - panic(fmt.Sprintf( - "cannot use untyped rune as %s", - dt.Kind())) - } - - default: - if isUntyped(xt) { - panic("unexpected untyped type") - } - if xt.TypeID() == cdt.TypeID() { - return // ok - } - } - case *PointerType: - if pt, ok := xt.(*PointerType); ok { - cdt := checkType(pt.Elt, cdt.Elt, ILLEGAL, false) - return cdt || conversionNeeded - } - case *ArrayType: - if at, ok := xt.(*ArrayType); ok { - cdt := checkType(at.Elt, cdt.Elt, ILLEGAL, false) - return cdt || conversionNeeded - } - case *SliceType: - if st, ok := xt.(*SliceType); ok { - cdt := checkType(st.Elt, cdt.Elt, ILLEGAL, false) - return cdt || conversionNeeded - } - case *MapType: - if mt, ok := xt.(*MapType); ok { - cn1 := checkType(mt.Key, cdt.Key, ILLEGAL, false) - cn2 := checkType(mt.Value, cdt.Value, ILLEGAL, false) - return cn1 || cn2 || conversionNeeded - } - case *FuncType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *InterfaceType: - panic("should not happen") - case *DeclaredType: - // do nothing, untyped to declared type - return - //panic("should not happen") - case *StructType, *PackageType, *ChanType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *TypeType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *NativeType: - if !autoNative { - if xt.TypeID() == cdt.TypeID() { - return // ok - } - } else { - // autoNative, so check whether matches. - // xt: any type but a *DeclaredType; could be native. - // cdt: actual concrete native target type. - // ie, if cdt can match against xt. - if gno2GoTypeMatches(xt, cdt.Type) { - return // ok - } - } - default: - panic(fmt.Sprintf( - "unexpected type %s", - dt.String())) - } - panic(fmt.Sprintf( - "cannot use %s as %s", - xt.String(), - dt.String())) - //} + return convertable(xt, dt, autoNative) } // Returns any names not yet defined nor predefined in expr. These happen diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 8db17f009ec..08cc85c310e 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2326,29 +2326,22 @@ func isSameTypes(lt, rt Type) bool { // Like assertSameTypes(), but more relaxed, for == and !=. func assertEqualityTypes(lt, rt Type) { if lt == nil && rt == nil { - println("1") // both are nil. } else if lt == nil || rt == nil { - println("2") // one is nil. see function comment. } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { - println("3") // one is untyped of same kind. } else if lt.Kind() == InterfaceKind && IsImplementedBy(lt, rt) { - println("4") // one is untyped of same kind. // rt implements lt (and lt is nil interface). } else if rt.Kind() == InterfaceKind && IsImplementedBy(rt, lt) { - println("5") // lt implements rt (and rt is nil interface). } else if lt.TypeID() == rt.TypeID() { - println("6") // non-nil types are identical. } else { - println("7") //panic("7, incompatible operands") debug.Errorf( "incompatible operands in binary (eql/neq) expression: %s and %s", @@ -2358,6 +2351,373 @@ func assertEqualityTypes(lt, rt Type) { } } +// t is the target type in convert process, check it firstly, then check if convertable +func comparable(t Type) (bool, string) { + depp.Printf("check comparable, t is %v \n", t) + // primitive is comparable + switch ct := baseOf(t).(type) { + case PrimitiveType: + depp.Println("primitive type, return true") + return true, "" + case *ArrayType: // NOTE: no recursive allowed + switch baseOf(ct.Elem()).(type) { + case PrimitiveType, *PointerType, *InterfaceType: // TODO: + return true, "" + default: + return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) + } + case *StructType: + for _, f := range ct.Fields { + switch baseOf(f.Type).(type) { + case PrimitiveType, *PointerType, *InterfaceType: + return true, "" + default: + return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) + } + } + return true, "" + case *PointerType: + return true, "" + case *InterfaceType: + return true, "" + case *SliceType, *FuncType: + // only comparable with nil, runtime check + return true, "" + case *NativeType: + if ct.Type.Comparable() { + return true, "" + } + return false, fmt.Sprintf("%v is not comparable \n", t) + default: + return false, fmt.Sprintf("%v is not comparable \n", t) + } +} + +// check if xt can be converted to dt, conversionNeeded indicate need convert from unnamed -> named +// case 1. untyped const to typed const with same kind +// case 2. unnamed to named +// case 3. dt is interface, xt satisfied dt +// case 4. general convert, for composite types check +func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { + // case3 + // if xt or dt is empty interface, convertable + // if no empty interface, then check if xt satisfied dt + if dt.Kind() == InterfaceKind { + depp.Println("dt is interface") + if idt, ok := baseOf(dt).(*InterfaceType); ok { + if idt.IsEmptyInterface() { + depp.Println("dt is empty interface") + // if dt is an empty Gno interface, any x ok. + return // ok + } else if idt.IsImplementedBy(xt) { + depp.Println("dt is implemented by xt") + // if dt implements idt, ok. + return // ok + } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6 + depp.Println("xt is empty interface: ", iot) + if iot.IsEmptyInterface() { + return // ok + } + } else { + panic(fmt.Sprintf( + "%s does not implement %s", + xt.String(), + dt.String())) + } + } else if ndt, ok := baseOf(dt).(*NativeType); ok { + nidt := ndt.Type + if nidt.NumMethod() == 0 { + // if dt is an empty Go native interface, ditto. + return // ok + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nidt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + nxt.String(), + nidt.String())) + } + } else if pxt, ok := baseOf(xt).(*PointerType); ok { + nxt, ok := pxt.Elt.(*NativeType) + if !ok { + panic(fmt.Sprintf( + "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", + pxt.String(), + nidt.String())) + } + // if xt has native base, do the naive native. + if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + pxt.String(), + nidt.String())) + } + } else { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + xt.String(), + dt.String())) + } + } else { + panic("should not happen") + } + } else if xt.Kind() == InterfaceKind { + depp.Println("xt is interface") + if ixt, ok := baseOf(xt).(*InterfaceType); ok { + if ixt.IsEmptyInterface() { + depp.Println("xt is empty interface") + // if dt is an empty Gno interface, any x ok. + return // ok + } else if ixt.IsImplementedBy(dt) { + depp.Println("xt is implemented by dt") + // if dt implements idt, ok. + return // ok + } else if idt, ok := dt.(*InterfaceType); ok { + if idt.IsEmptyInterface() { + return + } + } else { + panic(fmt.Sprintf( + "%s does not implement %s", + dt.String(), xt.String())) + } + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + nixt := nxt.Type + if nixt.NumMethod() == 0 { + // if dt is an empty Go native interface, ditto. + return // ok + } else if ndt, ok := baseOf(dt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nixt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + nixt.String(), ndt.String())) + } + } else if pdt, ok := baseOf(dt).(*PointerType); ok { + nxt, ok := pdt.Elt.(*NativeType) + if !ok { + panic(fmt.Sprintf( + "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", + nixt.String(), pdt.String())) + } + // if xt has native base, do the naive native. + if reflect.PtrTo(nxt.Type).AssignableTo(nixt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + nixt.String(), pdt.String())) + } + } else { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + xt.String(), + dt.String())) + } + } else { + panic("should not happen") + } + } + + // case2 + // Special case if xt or dt is *PointerType to *NativeType, + // convert to *NativeType of pointer kind. + if pxt, ok := xt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + //nolint:misspell + if enxt, ok := pxt.Elt.(*NativeType); ok { + xt = &NativeType{ + Type: reflect.PtrTo(enxt.Type), + } + } + } + if pdt, ok := dt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + if endt, ok := pdt.Elt.(*NativeType); ok { + dt = &NativeType{ + Type: reflect.PtrTo(endt.Type), + } + } + } + + // Special case of xt or dt is *DeclaredType, + // allow implicit conversion unless both are declared. + // TODO simplify with .IsNamedType(). + if dxt, ok := xt.(*DeclaredType); ok { + if ddt, ok := dt.(*DeclaredType); ok { + // types must match exactly. + if !dxt.sealed && !ddt.sealed && + dxt.PkgPath == ddt.PkgPath && + dxt.Name == ddt.Name { // not yet sealed + return // ok + } else if dxt.TypeID() == ddt.TypeID() { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + ddt.String())) + } + } else { + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := dt.(PrimitiveType); ok { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + dt.String())) + //xt = dxt.Base + } else { + // carry on with baseOf(dxt) + xt = dxt.Base + conversionNeeded = true + } + } + } else if ddt, ok := dt.(*DeclaredType); ok { + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := xt.(PrimitiveType); ok { + depp.Println("xt is primitiveType") + // this is special when dt is the declared type of x + if !isUntyped(xt) { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + xt.String(), + ddt.String())) + } + + } else { + // carry on with baseOf(ddt) + dt = ddt.Base + conversionNeeded = true + } + } + + // case 1 plus composite part + // General cases. + switch cdt := dt.(type) { + case PrimitiveType: // case 1 + depp.Println("primitive type") + // if xt is untyped, ensure dt is compatible. + switch xt { + case UntypedBoolType: + if dt.Kind() == BoolKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped bool as %s", + dt.Kind())) + } + case UntypedStringType: + if dt.Kind() == StringKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped string as %s", + dt.Kind())) + } + case UntypedBigintType, UntypedBigdecType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped Bigint/Bigdec as %s", + dt.Kind())) + } + case UntypedRuneType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped rune as %s", + dt.Kind())) + } + + default: + if isUntyped(xt) { + panic("unexpected untyped type") + } + if xt.TypeID() == cdt.TypeID() { + return // ok + } + } + case *PointerType: // case 4 from here on + if pt, ok := xt.(*PointerType); ok { + cdt := checkType(pt.Elt, cdt.Elt, ILLEGAL, false) + return cdt || conversionNeeded + } + case *ArrayType: + if at, ok := xt.(*ArrayType); ok { + cdt := checkType(at.Elt, cdt.Elt, ILLEGAL, false) + return cdt || conversionNeeded + } + case *SliceType: + if st, ok := xt.(*SliceType); ok { + cdt := checkType(st.Elt, cdt.Elt, ILLEGAL, false) + return cdt || conversionNeeded + } + case *MapType: + if mt, ok := xt.(*MapType); ok { + cn1 := checkType(mt.Key, cdt.Key, ILLEGAL, false) + cn2 := checkType(mt.Value, cdt.Value, ILLEGAL, false) + return cn1 || cn2 || conversionNeeded + } + case *FuncType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *InterfaceType: + panic("should not happen") + case *DeclaredType: + // do nothing, untyped to declared type + return + //panic("should not happen") + case *StructType, *PackageType, *ChanType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *TypeType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *NativeType: + if !autoNative { + if xt.TypeID() == cdt.TypeID() { + return // ok + } + } else { + // autoNative, so check whether matches. + // xt: any type but a *DeclaredType; could be native. + // cdt: actual concrete native target type. + // ie, if cdt can match against xt. + if gno2GoTypeMatches(xt, cdt.Type) { + return // ok + } + } + default: + panic(fmt.Sprintf( + "unexpected type %s", + dt.String())) + } + panic(fmt.Sprintf( + "cannot use %s as %s", + xt.String(), + dt.String())) + //} +} + // type-check rules: // 1. this happens in binary expressions, assign stmt, call to a func(args and return values) // 2. cases: (typed/untyped)const op not const, not const op (typed/untyped)const, not const/not const diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 0275e0155b8..2aaf960a11d 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -1454,8 +1454,6 @@ func (tv *TypedValue) GetBigDec() *apd.Decimal { } // Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0; -// x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0, -// otherwise it is != 0. If x is Unknown, the result is 1. func (tv *TypedValue) Sign() int { if tv.T == nil { panic("type should not be nil") @@ -1574,7 +1572,6 @@ func (tv *TypedValue) Sign() int { return v.Sign() case BigdecKind: v := tv.GetBigDec() - //fmt.Printf("bigdec, v %v: \n", v) return v.Sign() default: panic("not numeric") diff --git a/gnovm/tests/files/types/0f12_filetest.gno b/gnovm/tests/files/types/0f12_filetest.gno new file mode 100644 index 00000000000..751852d0b70 --- /dev/null +++ b/gnovm/tests/files/types/0f12_filetest.gno @@ -0,0 +1,13 @@ +package main + +var a [2]string +var b [2]string + +func main() { + a = [2]string{"hello", "world"} + b = [2]string{"hello", "world"} + println(a == b) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f13_filetest.gno b/gnovm/tests/files/types/0f13_filetest.gno new file mode 100644 index 00000000000..0ae088c05b0 --- /dev/null +++ b/gnovm/tests/files/types/0f13_filetest.gno @@ -0,0 +1,15 @@ +package main + +var a [2]string +var b [2]string +var c [2]int + +func main() { + + a = [2]string{"hello", "world"} + b = [2]string{"hello", "world"} + println(a == b) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f14_filetest.gno b/gnovm/tests/files/types/0f14_filetest.gno new file mode 100644 index 00000000000..92037364f85 --- /dev/null +++ b/gnovm/tests/files/types/0f14_filetest.gno @@ -0,0 +1,14 @@ +package main + +var a [2]string +var c [2]int + +// TODO: should stop at comparable check +func main() { + a = [2]string{"hello", "world"} + c = [2]int{1, 2} + println(a == c) +} + +// Error: +// main/files/types/0f14_filetest.gno:10: cannot use string as int diff --git a/gnovm/tests/files/types/0f15_filetest.gno b/gnovm/tests/files/types/0f15_filetest.gno new file mode 100644 index 00000000000..d8089d198c9 --- /dev/null +++ b/gnovm/tests/files/types/0f15_filetest.gno @@ -0,0 +1,18 @@ +package main + +var a [2]interface{} +var c [2]interface{} + +func gen() interface{} { + return 1 +} + +// TODO: should stop at comparable check +func main() { + a = [2]interface{}{gen(), gen()} + c = [2]interface{}{gen(), gen()} + println(a == c) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f16_filetest.gno b/gnovm/tests/files/types/0f16_filetest.gno new file mode 100644 index 00000000000..19d64c69387 --- /dev/null +++ b/gnovm/tests/files/types/0f16_filetest.gno @@ -0,0 +1,20 @@ +package main + +type word []int + +var a [2]word +var c [2]word + +func gen() word { + return []int{1} +} + +// TODO: should stop at comparable check +func main() { + a = [2]word{gen(), gen()} + c = [2]word{gen(), gen()} + println(a == c) +} + +// Error: +// main/files/types/0f16_filetest.gno:16: main.word cannot be compared diff --git a/gnovm/tests/files/types/0f17_filetest.gno b/gnovm/tests/files/types/0f17_filetest.gno new file mode 100644 index 00000000000..6665a44014b --- /dev/null +++ b/gnovm/tests/files/types/0f17_filetest.gno @@ -0,0 +1,13 @@ +package main + +type f func() bool + +var a f = func() bool { return true } +var b f = func() bool { return false } + +func main() { + println(a == b) +} + +// Error: +// function can only be compared with `nil` diff --git a/gnovm/tests/files/types/0f18_filetest.gno b/gnovm/tests/files/types/0f18_filetest.gno new file mode 100644 index 00000000000..ad534066fd1 --- /dev/null +++ b/gnovm/tests/files/types/0f18_filetest.gno @@ -0,0 +1,12 @@ +package main + +type f func() bool + +var a f = func() bool { return true } + +func main() { + println(a == nil) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/0f19_filetest.gno b/gnovm/tests/files/types/0f19_filetest.gno new file mode 100644 index 00000000000..8b08d616a06 --- /dev/null +++ b/gnovm/tests/files/types/0f19_filetest.gno @@ -0,0 +1,12 @@ +package main + +type f func() bool + +var a f + +func main() { + println(a == nil) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno new file mode 100644 index 00000000000..edc43a21dda --- /dev/null +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -0,0 +1,14 @@ +package main + +type f func() bool + +var a [2]f +var b [2]f + +// TODO: review where it happens +func main() { + println(a == nil) +} + +// Error: +// interface conversion: gnolang.Value is nil, not *gnolang.ArrayValue diff --git a/gnovm/tests/files/types/0f21_filetest.gno b/gnovm/tests/files/types/0f21_filetest.gno new file mode 100644 index 00000000000..163be3da4d4 --- /dev/null +++ b/gnovm/tests/files/types/0f21_filetest.gno @@ -0,0 +1,14 @@ +package main + +type f func() bool + +var a [2]f +var b [2]f + +// TODO: review where it happens +func main() { + println(a == b) +} + +// Error: +// main/files/types/0f21_filetest.gno:10: main.f cannot be compared diff --git a/gnovm/tests/files/types/1d4_filetest.gno b/gnovm/tests/files/types/1d4_filetest.gno new file mode 100644 index 00000000000..2ecaabe8424 --- /dev/null +++ b/gnovm/tests/files/types/1d4_filetest.gno @@ -0,0 +1,11 @@ +package main + +var a int +var b interface{} + +func main() { + println(b + a) +} + +// Error: +// main/files/types/1d4_filetest.gno:7: invalid operation: mismatched types int and interface{} diff --git a/gnovm/tests/files/types/1f3_filetest.gno b/gnovm/tests/files/types/1f3_filetest.gno new file mode 100644 index 00000000000..c57d3e9d375 --- /dev/null +++ b/gnovm/tests/files/types/1f3_filetest.gno @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "strconv" +) + +type Error0 int64 + +func (e Error0) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + defer func() { + if r := recover(); r != nil { + if r == Error1(0) { + fmt.Println("Recovered. Error:\n", r) + } + } + }() + + panic(Error1(0)) +} + +// Output: +// Recovered. Error: +// 0 diff --git a/gnovm/tests/files/types/1f4_filetest.gno b/gnovm/tests/files/types/1f4_filetest.gno new file mode 100644 index 00000000000..bddb57b7ec5 --- /dev/null +++ b/gnovm/tests/files/types/1f4_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "strconv" +) + +type Error0 int64 + +func (e Error0) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + defer func() { + if r := recover(); r != nil { + if r == Error0(0) { + fmt.Println("recover Error0") + } else { + fmt.Println("recover Error1") + } + } + }() + + panic(Error1(0)) +} + +// Output: +// recover Error1 diff --git a/gnovm/tests/files/types/1f5_filetest.gno b/gnovm/tests/files/types/1f5_filetest.gno new file mode 100644 index 00000000000..7fb051961ee --- /dev/null +++ b/gnovm/tests/files/types/1f5_filetest.gno @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "strconv" +) + +type Error0 int64 + +func (e Error0) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func get() interface{} { + return Error1(0) +} + +func main() { + defer func() { + if r := recover(); r != nil { + if r == get() { + fmt.Println("recover Error1") + } else { + fmt.Println("recover Error0") + } + } + }() + + panic(Error1(0)) +} + +// Output: +// recover Error1 diff --git a/gnovm/tests/files/types/1f6_filetest.gno b/gnovm/tests/files/types/1f6_filetest.gno new file mode 100644 index 00000000000..fcba5dad752 --- /dev/null +++ b/gnovm/tests/files/types/1f6_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("errCmp") + +func main() { + defer func() { + if r := recover(); r != nil { + if r == errCmp { + println("same error") + } else { + println("different error") + } + } + }() + + panic(Error1(0)) +} + +// Output: +// different error diff --git a/gnovm/tests/files/types/1f7_filetest.gno b/gnovm/tests/files/types/1f7_filetest.gno new file mode 100644 index 00000000000..d8831f7f9a4 --- /dev/null +++ b/gnovm/tests/files/types/1f7_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" +) + +func get() interface{} { + return "hello" +} + +var errCmp = errors.New("errCmp") + +func main() { + defer func() { + if r := recover(); r != nil { + if r == errCmp { + println("same error") + } else { + println("different error") + } + } + }() + + panic(get()) +} + +// Output: +// different error diff --git a/gnovm/tests/files/types/1f8_filetest.gno b/gnovm/tests/files/types/1f8_filetest.gno new file mode 100644 index 00000000000..d826bdbd155 --- /dev/null +++ b/gnovm/tests/files/types/1f8_filetest.gno @@ -0,0 +1,41 @@ +package main + +import ( + "errors" +) + +type animal interface { + eat() +} + +type dog struct { +} + +func (d *dog) eat() { + println("dog eating") +} + +func get() animal { + d := &dog{} + return d +} + +var errCmp = errors.New("errCmp") + +// no empty interface, different interface(with different methods) +func main() { + defer func() { + if r := recover(); r != nil { + if r == errCmp { + println("same error") + } else { + println("different error") + } + } + }() + + panic(get()) +} + +// Output: +// different error diff --git a/gnovm/tests/files/types/1f9_filetest.gno b/gnovm/tests/files/types/1f9_filetest.gno new file mode 100644 index 00000000000..146f8d09492 --- /dev/null +++ b/gnovm/tests/files/types/1f9_filetest.gno @@ -0,0 +1,35 @@ +package main + +import ( + "errors" +) + +type animal interface { + eat() +} + +type dog struct { +} + +func (d *dog) eat() { + println("dog eating") +} + +func get() animal { + d := &dog{} + return d +} + +var errCmp = errors.New("errCmp") + +// no empty interface, different interface(with different methods) +func main() { + if get() == errCmp { + println("same error") + } else { + println("different error") + } +} + +// Error: +// main/files/types/1f9_filetest.gno:27: main.animal does not implement .uverse.error diff --git a/gnovm/tests/files/types/others/README.md b/gnovm/tests/files/types/others/README.md index c1ca831a209..5550932e85e 100644 --- a/gnovm/tests/files/types/others/README.md +++ b/gnovm/tests/files/types/others/README.md @@ -1,3 +1,34 @@ + +binaryExpression + check comparison: + + assignableTo(type), LHS or RHS is assignable to the other + isIdentical + primitive, struct, map, ... + untyped -> typed + unnamed -> named + type(Impl) -> interface + + EQU NEQ + LHS, RHS both comparable + + LSS, GTR,,, + LHS, RHS ordered + + NOTE: above no requre for match type, e,g. Main.Error and error to compare + + // else ops + first check (if typed) LHS, RHS, panic mismatch directly + check predicates + check special case like zero divisor + check implicit convertable, same logic assignableTo(Type) + + + + + + + Scenarios: binary expression: left expression [Op] right expression From ad871277e311901429c82d79097b7b73d3c3fefa Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 6 Dec 2023 06:47:33 +0800 Subject: [PATCH 013/193] compare --- gnovm/pkg/gnolang/preprocess.go | 19 +++++++++++++- gnovm/pkg/gnolang/types.go | 20 ++++++++++++--- gnovm/tests/files/types/0f22_filetest.gno | 12 +++++++++ gnovm/tests/files/types/0f23_filetest.gno | 13 ++++++++++ gnovm/tests/files/types/0f24_filetest.gno | 13 ++++++++++ gnovm/tests/files/types/0f25_filetest.gno | 19 ++++++++++++++ gnovm/tests/files/types/0f26_filetest.gno | 27 ++++++++++++++++++++ gnovm/tests/files/types/0f27_filetest.gno | 21 +++++++++++++++ gnovm/tests/files/types/0f28_filetest.gno | 31 +++++++++++++++++++++++ gnovm/tests/files/types/0f29_filetest.gno | 24 ++++++++++++++++++ 10 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 gnovm/tests/files/types/0f22_filetest.gno create mode 100644 gnovm/tests/files/types/0f23_filetest.gno create mode 100644 gnovm/tests/files/types/0f24_filetest.gno create mode 100644 gnovm/tests/files/types/0f25_filetest.gno create mode 100644 gnovm/tests/files/types/0f26_filetest.gno create mode 100644 gnovm/tests/files/types/0f27_filetest.gno create mode 100644 gnovm/tests/files/types/0f28_filetest.gno create mode 100644 gnovm/tests/files/types/0f29_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 4aab3197f28..c6551cc0399 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2487,7 +2487,7 @@ func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t T } depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) - // TODO: + // TODO: check Op here? } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { depp.Println("SHL or SHR") // "push" expected type into shift binary's left operand. @@ -2523,12 +2523,14 @@ func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t T cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx + // TODO: check op here } // cover all declared type case if conversionNeeded { cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx + // TODO: check op here } } } @@ -2564,6 +2566,7 @@ var predicates map[Word]f func init() { predicates = make(map[Word]f) + // add,sub,mul,quo,rem with assgin predicates[ADD] = isNumericOrString predicates[ADD_ASSIGN] = isNumericOrString predicates[SUB] = isNumeric @@ -2575,6 +2578,7 @@ func init() { predicates[REM] = isIntNum predicates[REM_ASSIGN] = isIntNum + // bit op predicates[BAND] = isIntNum predicates[BAND_ASSIGN] = isIntNum predicates[XOR] = isIntNum @@ -2583,8 +2587,15 @@ func init() { predicates[BOR_ASSIGN] = isIntNum predicates[BAND_NOT] = isIntNum predicates[BAND_NOT_ASSIGN] = isIntNum + // logic op predicates[LAND] = isBoolean predicates[LOR] = isBoolean + + // compare + predicates[LSS] = isOrdered + predicates[LEQ] = isOrdered + predicates[GTR] = isOrdered + predicates[GEQ] = isOrdered } // post check after conversion @@ -2628,6 +2639,12 @@ func checkOp(xt Type, dt Type, op Word) { panic(code) } case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString + depp.Printf("L, G: %v \n", op) + if pred, ok := predicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } + } } } // two steps of check: diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 08cc85c310e..c34585e6096 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -272,7 +272,7 @@ const ( IsBigDec IsRune - IsOrdered = IsInteger | IsFloat | IsString + IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec IsConstType = IsBoolean | IsNumeric | IsString ) @@ -330,6 +330,18 @@ func (pt PrimitiveType) Predicate() predicate { } } +func isOrdered(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.Predicate() != IsInvalid && t.Predicate()&IsOrdered != 0 || t.Predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + func isBoolean(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: @@ -2276,6 +2288,7 @@ func assertSameTypes(lt, rt Type) { } } +// TODO: change to only check typed func isSameTypes(lt, rt Type) bool { depp.Printf("check isSameTypes, lt: %v, rt: %v \n", lt, rt) depp.Println("is lt data byte: ", isDataByte(lt)) @@ -2360,8 +2373,9 @@ func comparable(t Type) (bool, string) { depp.Println("primitive type, return true") return true, "" case *ArrayType: // NOTE: no recursive allowed + // TODO: check length? but that needs check after convert, indicates checkOp after convert? make more sense seems switch baseOf(ct.Elem()).(type) { - case PrimitiveType, *PointerType, *InterfaceType: // TODO: + case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // TODO: return true, "" default: return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) @@ -2369,7 +2383,7 @@ func comparable(t Type) (bool, string) { case *StructType: for _, f := range ct.Fields { switch baseOf(f.Type).(type) { - case PrimitiveType, *PointerType, *InterfaceType: + case PrimitiveType, *PointerType, *InterfaceType, *NativeType: return true, "" default: return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) diff --git a/gnovm/tests/files/types/0f22_filetest.gno b/gnovm/tests/files/types/0f22_filetest.gno new file mode 100644 index 00000000000..02d78481b57 --- /dev/null +++ b/gnovm/tests/files/types/0f22_filetest.gno @@ -0,0 +1,12 @@ +package main + +var a int = 0 +var b int = 1 + +// TODO: review where it happens +func main() { + println(&a == &b) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/0f23_filetest.gno b/gnovm/tests/files/types/0f23_filetest.gno new file mode 100644 index 00000000000..55f2ab5189d --- /dev/null +++ b/gnovm/tests/files/types/0f23_filetest.gno @@ -0,0 +1,13 @@ +package main + +var a int = 0 +var b int = 1 + +func main() { + c := &a + d := &b + println(*c == *d) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/0f24_filetest.gno b/gnovm/tests/files/types/0f24_filetest.gno new file mode 100644 index 00000000000..d01a9d4a14a --- /dev/null +++ b/gnovm/tests/files/types/0f24_filetest.gno @@ -0,0 +1,13 @@ +package main + +var a int = 0 +var b int = 0 + +func main() { + c := &a + d := &b + println(*c == *d) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f25_filetest.gno b/gnovm/tests/files/types/0f25_filetest.gno new file mode 100644 index 00000000000..8a3343146b0 --- /dev/null +++ b/gnovm/tests/files/types/0f25_filetest.gno @@ -0,0 +1,19 @@ +package main + +var a int = 0 +var b int = 0 + +func main() { + c := &a + d := &b + println(*c > *d) + println(*c >= *d) + println(*c < *d) + println(*c <= *d) +} + +// Output: +// false +// true +// false +// true diff --git a/gnovm/tests/files/types/0f26_filetest.gno b/gnovm/tests/files/types/0f26_filetest.gno new file mode 100644 index 00000000000..a05d236f661 --- /dev/null +++ b/gnovm/tests/files/types/0f26_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if 1 > errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f26_filetest.gno:19: operator > not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f27_filetest.gno b/gnovm/tests/files/types/0f27_filetest.gno new file mode 100644 index 00000000000..0731f838d5c --- /dev/null +++ b/gnovm/tests/files/types/0f27_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "errors" +) + +var errCmp1 = errors.New("XXXX") +var errCmp2 = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if errCmp1 > errCmp2 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f27_filetest.gno:13: operator > not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f28_filetest.gno b/gnovm/tests/files/types/0f28_filetest.gno new file mode 100644 index 00000000000..907153db280 --- /dev/null +++ b/gnovm/tests/files/types/0f28_filetest.gno @@ -0,0 +1,31 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + println(e1 > e2) +} + +// Error: +// main/files/types/0f28_filetest.gno:27: operator > not defined on: main.E diff --git a/gnovm/tests/files/types/0f29_filetest.gno b/gnovm/tests/files/types/0f29_filetest.gno new file mode 100644 index 00000000000..ec30b1f3901 --- /dev/null +++ b/gnovm/tests/files/types/0f29_filetest.gno @@ -0,0 +1,24 @@ +package main + +import ( + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var l interface{} + if l > Error(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f29_filetest.gno:16: operator > not defined on: interface{} From 7d21ff8d25fb6098a1bea1b2debd79f6ab9029b3 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 6 Dec 2023 07:38:21 +0800 Subject: [PATCH 014/193] unary --- gnovm/pkg/gnolang/preprocess.go | 105 ++++++++++++--------- gnovm/tests/files/types/23a0_filetest.gno | 12 +++ gnovm/tests/files/types/23a0a_filetest.gno | 12 +++ gnovm/tests/files/types/23a0b_filetest.gno | 12 +++ gnovm/tests/files/types/23a0c_filetest.gno | 12 +++ gnovm/tests/files/types/23a1_filetest.gno | 13 +++ gnovm/tests/files/types/23a2_filetest.gno | 13 +++ gnovm/tests/files/types/23a2a_filetest.gno | 13 +++ gnovm/tests/files/types/23a3_filetest.gno | 12 +++ gnovm/tests/files/types/23a4_filetest.gno | 12 +++ gnovm/tests/files/types/23a5_filetest.gno | 12 +++ gnovm/tests/files/types/23a6_filetest.gno | 12 +++ 12 files changed, 194 insertions(+), 46 deletions(-) create mode 100644 gnovm/tests/files/types/23a0_filetest.gno create mode 100644 gnovm/tests/files/types/23a0a_filetest.gno create mode 100644 gnovm/tests/files/types/23a0b_filetest.gno create mode 100644 gnovm/tests/files/types/23a0c_filetest.gno create mode 100644 gnovm/tests/files/types/23a1_filetest.gno create mode 100644 gnovm/tests/files/types/23a2_filetest.gno create mode 100644 gnovm/tests/files/types/23a2a_filetest.gno create mode 100644 gnovm/tests/files/types/23a3_filetest.gno create mode 100644 gnovm/tests/files/types/23a4_filetest.gno create mode 100644 gnovm/tests/files/types/23a5_filetest.gno create mode 100644 gnovm/tests/files/types/23a6_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c6551cc0399..51794e0f381 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1256,8 +1256,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: + depp.Printf("---unaryExpr, op: %v \n", n.Op) xt := evalStaticTypeOf(store, last, n.X) if xnt, ok := xt.(*NativeType); ok { + depp.Println("nativeType") // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) // convert n.X to gno type, @@ -1276,10 +1278,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // always computed in gno, never with reflect. } // Replace with *ConstExpr if const X. - if isConst(n.X) { + // checkOp, like +a, while a should be numeric + if cx, ok := n.X.(*ConstExpr); ok { + depp.Println("not native, ConstExpr") + // checkOp, e.g. +a while a is numeric + checkOp(nil, cx.T, n.Op, false) cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } + depp.Println("else") + checkOp(nil, xt, n.Op, false) // TRANS_LEAVE ----------------------- case *CompositeLitExpr: @@ -1664,6 +1672,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } // Special case if shift assign <<= or >>=. + // TODO: use the other one, like map key checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], UintType, n.Op, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { depp.Printf("op is %v \n", n.Op) @@ -1672,17 +1681,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { depp.Println("len of LHS: ", len(n.Lhs)) depp.Println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) - //rt := evalStaticTypeOf(store, last, n.Rhs[0]) - - // TODO: check other like sh* - // only check when rt is typed - //if !isUntyped(rt) { - // if lt.TypeID() != rt.TypeID() { - // panic("mismatch type for Assign") - // } - //} else { + // a += b, requires b -> a conversion checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], lt, n.Op, false) - //} } else { // all else, like BAND_ASSIGN, etc depp.Println("case: a, b = x, y") depp.Printf("Op: %v \n", n.Op) @@ -1698,9 +1698,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) } else { depp.Println("rt not untyped, check strict") - //if lt.TypeID() != rt.TypeID() { - // panic("mismatch type for Assign, in case: a, b = x, y") - //} checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) } } @@ -2562,40 +2559,48 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { type f func(t Type) bool -var predicates map[Word]f +var binaryPredicates map[Word]f +var unaryPredicates map[Word]f func init() { - predicates = make(map[Word]f) + binaryPredicates = make(map[Word]f) + unaryPredicates = make(map[Word]f) // add,sub,mul,quo,rem with assgin - predicates[ADD] = isNumericOrString - predicates[ADD_ASSIGN] = isNumericOrString - predicates[SUB] = isNumeric - predicates[SUB_ASSIGN] = isNumeric - predicates[MUL] = isNumeric - predicates[MUL_ASSIGN] = isNumeric - predicates[QUO] = isNumeric - predicates[QUO_ASSIGN] = isNumeric - predicates[REM] = isIntNum - predicates[REM_ASSIGN] = isIntNum + binaryPredicates[ADD] = isNumericOrString + binaryPredicates[ADD_ASSIGN] = isNumericOrString + binaryPredicates[SUB] = isNumeric + binaryPredicates[SUB_ASSIGN] = isNumeric + binaryPredicates[MUL] = isNumeric + binaryPredicates[MUL_ASSIGN] = isNumeric + binaryPredicates[QUO] = isNumeric + binaryPredicates[QUO_ASSIGN] = isNumeric + binaryPredicates[REM] = isIntNum + binaryPredicates[REM_ASSIGN] = isIntNum // bit op - predicates[BAND] = isIntNum - predicates[BAND_ASSIGN] = isIntNum - predicates[XOR] = isIntNum - predicates[XOR_ASSIGN] = isIntNum - predicates[BOR] = isIntNum - predicates[BOR_ASSIGN] = isIntNum - predicates[BAND_NOT] = isIntNum - predicates[BAND_NOT_ASSIGN] = isIntNum + binaryPredicates[BAND] = isIntNum + binaryPredicates[BAND_ASSIGN] = isIntNum + binaryPredicates[XOR] = isIntNum + binaryPredicates[XOR_ASSIGN] = isIntNum + binaryPredicates[BOR] = isIntNum + binaryPredicates[BOR_ASSIGN] = isIntNum + binaryPredicates[BAND_NOT] = isIntNum + binaryPredicates[BAND_NOT_ASSIGN] = isIntNum // logic op - predicates[LAND] = isBoolean - predicates[LOR] = isBoolean + binaryPredicates[LAND] = isBoolean + binaryPredicates[LOR] = isBoolean // compare - predicates[LSS] = isOrdered - predicates[LEQ] = isOrdered - predicates[GTR] = isOrdered - predicates[GEQ] = isOrdered + binaryPredicates[LSS] = isOrdered + binaryPredicates[LEQ] = isOrdered + binaryPredicates[GTR] = isOrdered + binaryPredicates[GEQ] = isOrdered + + // unary + unaryPredicates[ADD] = isNumeric + unaryPredicates[SUB] = isNumeric + unaryPredicates[XOR] = isIntNum + unaryPredicates[NOT] = isBoolean } // post check after conversion @@ -2625,13 +2630,21 @@ func isComparison(op Word) bool { } } -func checkOp(xt Type, dt Type, op Word) { - depp.Printf("checkOp, xt: %v, dt: %v, op: %v \n", xt, dt, op) +func checkOp(xt Type, dt Type, op Word, binary bool) { + depp.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binary) + if !binary { + if pred, ok := unaryPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } + } + } + // first check comparison if isComparison(op) { switch op { case EQL, NEQ: // check comparable - // 1. first, check specific types can be compared, like predicates for ADD, etc + // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc // 2. comparable requires one is convertable to another // 3. handle nil if ok, code := comparable(dt); !ok { @@ -2640,7 +2653,7 @@ func checkOp(xt Type, dt Type, op Word) { } case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString depp.Printf("L, G: %v \n", op) - if pred, ok := predicates[op]; ok { + if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } @@ -2652,7 +2665,7 @@ func checkOp(xt Type, dt Type, op Word) { // second, xt can be converted to dt, this is done below this // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt depp.Printf("check matchable with op: %v \n", op) - if pred, ok := predicates[op]; ok { + if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } @@ -2688,7 +2701,7 @@ func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded boo return } depp.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) - checkOp(xt, dt, op) + checkOp(xt, dt, op, true) depp.Println("ops checks pass, check convertable on operand") return convertable(xt, dt, autoNative) } diff --git a/gnovm/tests/files/types/23a0_filetest.gno b/gnovm/tests/files/types/23a0_filetest.gno new file mode 100644 index 00000000000..2e5a1d289c9 --- /dev/null +++ b/gnovm/tests/files/types/23a0_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := 5 + y := +x + fmt.Println(y) // Output: 5 +} + +// Output: +// 5 diff --git a/gnovm/tests/files/types/23a0a_filetest.gno b/gnovm/tests/files/types/23a0a_filetest.gno new file mode 100644 index 00000000000..3556bcf2bf6 --- /dev/null +++ b/gnovm/tests/files/types/23a0a_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := 1.0 + y := +x + fmt.Println(y) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/23a0b_filetest.gno b/gnovm/tests/files/types/23a0b_filetest.gno new file mode 100644 index 00000000000..ff4e863e10e --- /dev/null +++ b/gnovm/tests/files/types/23a0b_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := int(1) + y := +x + fmt.Println(y) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/23a0c_filetest.gno b/gnovm/tests/files/types/23a0c_filetest.gno new file mode 100644 index 00000000000..e6ead4453b0 --- /dev/null +++ b/gnovm/tests/files/types/23a0c_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := "hello" + y := +x + fmt.Println(y) +} + +// Error: +// main/files/types/23a0c_filetest.gno:7: operator + not defined on: string diff --git a/gnovm/tests/files/types/23a1_filetest.gno b/gnovm/tests/files/types/23a1_filetest.gno new file mode 100644 index 00000000000..c3c96d6724e --- /dev/null +++ b/gnovm/tests/files/types/23a1_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 5 + y := -x + fmt.Println(y) // Output: -5 + +} + +// Output: +// -5 diff --git a/gnovm/tests/files/types/23a2_filetest.gno b/gnovm/tests/files/types/23a2_filetest.gno new file mode 100644 index 00000000000..1b9edf1b712 --- /dev/null +++ b/gnovm/tests/files/types/23a2_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + a := true + b := !a + fmt.Println(b) // Output: false + +} + +// Output: +// false diff --git a/gnovm/tests/files/types/23a2a_filetest.gno b/gnovm/tests/files/types/23a2a_filetest.gno new file mode 100644 index 00000000000..4aa51db913d --- /dev/null +++ b/gnovm/tests/files/types/23a2a_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + a := 1 + b := !a + fmt.Println(b) // Output: false + +} + +// Error: +// main/files/types/23a2a_filetest.gno:7: operator ! not defined on: int diff --git a/gnovm/tests/files/types/23a3_filetest.gno b/gnovm/tests/files/types/23a3_filetest.gno new file mode 100644 index 00000000000..3f216ccb1c1 --- /dev/null +++ b/gnovm/tests/files/types/23a3_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := 10 + p := &x + fmt.Println(*p) // Output: 10 +} + +// Output: +// 10 diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno new file mode 100644 index 00000000000..c8a311b4a2a --- /dev/null +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + v := 42 + p := &v + fmt.Println(p) // Output: memory address of v +} + +// Output: +// 0x1400003b970 diff --git a/gnovm/tests/files/types/23a5_filetest.gno b/gnovm/tests/files/types/23a5_filetest.gno new file mode 100644 index 00000000000..bb956f85673 --- /dev/null +++ b/gnovm/tests/files/types/23a5_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := 1 + y := ^x + fmt.Println(y) // Output will be the bitwise complement of 1 +} + +// Output: +// -2 diff --git a/gnovm/tests/files/types/23a6_filetest.gno b/gnovm/tests/files/types/23a6_filetest.gno new file mode 100644 index 00000000000..455d7355a36 --- /dev/null +++ b/gnovm/tests/files/types/23a6_filetest.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := 1.0 + y := ^x + fmt.Println(y) // Output will be the bitwise complement of 1 +} + +// Error: +// main/files/types/23a6_filetest.gno:7: operator ^ not defined on: float64 From 9b0ace9a8b44cdb68fe0e20e5ea6c9fa96ca3022 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 6 Dec 2023 17:36:22 +0800 Subject: [PATCH 015/193] fixup --- gnovm/pkg/gnolang/debug.go | 4 +- gnovm/pkg/gnolang/op_binary.go | 56 +----- gnovm/pkg/gnolang/preprocess.go | 190 ++++++++++---------- gnovm/pkg/gnolang/types.go | 60 ++++--- gnovm/pkg/gnolang/values_conversions.go | 6 +- gnovm/tests/files/types/0a6_filetest.gno | 12 ++ gnovm/tests/files/types/0f30_filetest.gno | 8 + gnovm/tests/files/types/0f31_filetest.gno | 13 ++ gnovm/tests/files/types/22a17a_filetest.gno | 3 +- gnovm/tests/files/types/23a4_filetest.gno | 2 +- gnovm/tests/files/types/24a0_filetest.gno | 11 ++ gnovm/tests/files/types/24a1_filetest.gno | 9 + gnovm/tests/files/types/24a2_filetest.gno | 9 + gnovm/tests/files/types/24a3_filetest.gno | 8 + gnovm/tests/files/types/others/README.md | 15 +- 15 files changed, 220 insertions(+), 186 deletions(-) create mode 100644 gnovm/tests/files/types/0a6_filetest.gno create mode 100644 gnovm/tests/files/types/0f30_filetest.gno create mode 100644 gnovm/tests/files/types/0f31_filetest.gno create mode 100644 gnovm/tests/files/types/24a0_filetest.gno create mode 100644 gnovm/tests/files/types/24a1_filetest.gno create mode 100644 gnovm/tests/files/types/24a2_filetest.gno create mode 100644 gnovm/tests/files/types/24a3_filetest.gno diff --git a/gnovm/pkg/gnolang/debug.go b/gnovm/pkg/gnolang/debug.go index 6714116fd41..a467e389229 100644 --- a/gnovm/pkg/gnolang/debug.go +++ b/gnovm/pkg/gnolang/debug.go @@ -24,11 +24,11 @@ type debugPreprocess bool // using a const is probably faster. // const debug debugging = true // or flip var debug debugging = false -var depp debugPreprocess = false +var debugPP debugPreprocess = false func init() { debug = os.Getenv("DEBUG") == "1" - depp = os.Getenv("DEPP") == "1" + debugPP = os.Getenv("DEPP") == "1" if debug { go func() { // e.g. diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 735ec73f3e3..8e9dc977a46 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -71,7 +71,7 @@ func (m *Machine) doOpLand() { } func (m *Machine) doOpEql() { - depp.Println("doOpEql") + debugPP.Println("doOpEql") m.PopExpr() // get right and left operands. @@ -80,19 +80,9 @@ func (m *Machine) doOpEql() { if debug { assertEqualityTypes(lv.T, rv.T) } - depp.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - //// strict type match check, after preprocess - //// TODO: fix databytetype - //if (lv.T != nil && rv.T != nil) && (lv.T.TypeID() != rv.T.TypeID()) { - // // TODO: in golang, this would not panic, but give a false as result - // fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "EQL", rv.T.TypeID()) - // res = false - //} else { - // res = isEql(m.Store, lv, rv) - //} - // TODO: this should be in preprocess too // TODO: only assert here if isSameTypes(lv.T, rv.T) { @@ -110,7 +100,7 @@ func (m *Machine) doOpEql() { } func (m *Machine) doOpNeq() { - depp.Println("doOpNeq") + debugPP.Println("doOpNeq") m.PopExpr() // get right and left operands. @@ -119,18 +109,9 @@ func (m *Machine) doOpNeq() { if debug { assertEqualityTypes(lv.T, rv.T) } - depp.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - //// strict type match check, after preprocess - //if (lv.T != nil && rv.T != nil) && (lv.T.TypeID() != rv.T.TypeID()) { - // // TODO: in golang, this would not panic, but give a false as result - // fmt.Printf("operands type mismatch, left %v, op: %v, right:%v \n", lv.T.TypeID(), "EQL", rv.T.TypeID()) - // res = true // not equal - //} else { - // res = !isEql(m.Store, lv, rv) - //} - if isSameTypes(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { @@ -382,9 +363,9 @@ func isEql(store Store, lv, rv *TypedValue) bool { return false } if lnt, ok := lv.T.(*NativeType); ok { - depp.Println("left is native type") + debugPP.Println("left is native type") if rnt, ok := rv.T.(*NativeType); ok { - depp.Println("right is native type") + debugPP.Println("right is native type") if lnt.Type != rnt.Type { return false } @@ -703,10 +684,6 @@ func isGeq(lv, rv *TypedValue) bool { // for doOpAdd and doOpAddAssign. func addAssign(alloc *Allocator, lv, rv *TypedValue) { - //if !isSameTypes(lv.T, rv.T) { - // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - //} - // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -765,9 +742,6 @@ func addAssign(alloc *Allocator, lv, rv *TypedValue) { // for doOpSub and doOpSubAssign. func subAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -824,9 +798,6 @@ func subAssign(lv, rv *TypedValue) { // for doOpMul and doOpMulAssign. func mulAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -881,9 +852,6 @@ func mulAssign(lv, rv *TypedValue) { // for doOpQuo and doOpQuoAssign. func quoAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -940,9 +908,6 @@ func quoAssign(lv, rv *TypedValue) { // for doOpRem and doOpRemAssign. func remAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -982,9 +947,6 @@ func remAssign(lv, rv *TypedValue) { // for doOpBand and doOpBandAssign. func bandAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -1024,9 +986,6 @@ func bandAssign(lv, rv *TypedValue) { // for doOpBandn and doOpBandnAssign. func bandnAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { @@ -1066,9 +1025,6 @@ func bandnAssign(lv, rv *TypedValue) { // for doOpBor and doOpBorAssign. func borAssign(lv, rv *TypedValue) { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lv.T, rv.T)) - } // set the result in lv. // NOTE this block is replicated in op_assign.go switch baseOf(lv.T) { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 51794e0f381..e7b5c81e6d1 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -738,7 +738,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: - depp.Printf("--binary expr---, OP: %v \n", n.Op) + debugPP.Printf("--binary expr---, OP: %v \n", n.Op) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. @@ -760,9 +760,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) if lic { - depp.Println("left is const") + debugPP.Println("left is const") if ric { - depp.Println("right is const") + debugPP.Println("right is const") // special case, check zero divisor // should check in after type check //checkOperand(rcx, n.Op) @@ -770,7 +770,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. if !isShift { - depp.Println("not shift") + debugPP.Println("not shift") //// is this implied implicitly? rest of the binary operators after SHL and SHR is excluded //// Note: this check happens only when left and right are both typed, if not, the checkOrConvert logic will be run if cmp not 0 //// TODO: checkOrConvertType, same way around @@ -788,11 +788,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // at least one of left or right is untyped cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // this always implies untyped>? - depp.Println("cmp < 0, ->") + debugPP.Println("cmp < 0, ->") // convert n.Left to right type. checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rcx.T, n.Op, false) } else if cmp == 0 { - depp.Println("cmp == 0") + debugPP.Println("cmp == 0") // NOTE: the following doesn't work. // TODO: make it work. // convert n.Left to right type, @@ -801,7 +801,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // also need to check checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rcx.T, n.Op, false) } else { // this always implies untyped>? - depp.Println("cmp > 0, <-") + debugPP.Println("cmp > 0, <-") // convert n.Right to left type. // TODO: this looks wired checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lcx.T, n.Op, false) @@ -811,10 +811,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { - depp.Println("left is untyped const, right not const") + debugPP.Println("left is untyped const, right not const") // Left untyped const, Right not ---------------- if rnt, ok := rt.(*NativeType); ok { - depp.Println("right native type") + debugPP.Println("right native type") if isShift { panic("should not happen") } @@ -838,42 +838,34 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - depp.Println("right not native") + debugPP.Println("right not native") if isShift { // nothing to do, right type is (already) uint type. // we don't yet know what this type should be, // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). } else { - depp.Println("not shift, convert") - depp.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) - depp.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) + debugPP.Println("not shift, convert") + debugPP.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) + debugPP.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const - depp.Println("left is typed const, right is not const, should check type too") - // NOTE: only in case == or !=, should using assert to make sure left and right equality - // in case of add, etc. should use checkOrConvert - // TODO: expand? - //if n.Op == EQL || n.Op == NEQ { - // assertTypeMatchStrict(lt, rt, n.Op) - //} else { - // checkOrConvertType(store, last, &n.Left, rt, n.Op, false) - //} + debugPP.Println("left is typed const, right is not const, should check type too") checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) - } else if lcx.T == nil { - depp.Println("lcx.T is nil") + } else if lcx.T == nil { // LHS is nil + debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } // TODO: 912 line? } else if ric { - depp.Println("left not const, right is const") + debugPP.Println("left not const, right is const") if isUntyped(rcx.T) { - depp.Println("right untyped") + debugPP.Println("right untyped") // Left not, Right untyped const ---------------- if isShift { if baseOf(rt) != UintType { @@ -909,15 +901,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } //} else if rcx.T == nil { - } else if rcx.T == nil { - depp.Println("rcx.T == nil ") + } else if rcx.T == nil { // RHS is nil + debugPP.Println("rcx.T == nil ") // convert n.Right to typed-nil type. checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) } else if !isShift { checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) } } else { - depp.Printf("both not const, lt: %v, rt:%v \n", lt, rt) + debugPP.Printf("both not const, lt: %v, rt:%v \n", lt, rt) if n.Op == SHL || n.Op == SHR { // shift operator, nothing yet to do. code like this will work //package main @@ -967,11 +959,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // computed in gno, never with // reflect. } else { - depp.Println("no-shift, non-const, need all go through check") + debugPP.Println("no-shift, non-const, need all go through check") // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) - depp.Println("liu", liu) - depp.Println("rie", riu) + debugPP.Println("liu", liu) + debugPP.Println("rie", riu) if liu { if riu { if lt.TypeID() != rt.TypeID() { @@ -980,7 +972,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Left, n.Op, n.Right)) } } else { - depp.Println("left untyped, right is typed") + debugPP.Println("left untyped, right is typed") checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) } } else if riu { @@ -1256,10 +1248,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: - depp.Printf("---unaryExpr, op: %v \n", n.Op) + debugPP.Printf("---unaryExpr, op: %v \n", n.Op) xt := evalStaticTypeOf(store, last, n.X) if xnt, ok := xt.(*NativeType); ok { - depp.Println("nativeType") + debugPP.Println("nativeType") // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) // convert n.X to gno type, @@ -1280,13 +1272,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const X. // checkOp, like +a, while a should be numeric if cx, ok := n.X.(*ConstExpr); ok { - depp.Println("not native, ConstExpr") + debugPP.Println("not native, ConstExpr") // checkOp, e.g. +a while a is numeric checkOp(nil, cx.T, n.Op, false) cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } - depp.Println("else") + debugPP.Println("else") checkOp(nil, xt, n.Op, false) // TRANS_LEAVE ----------------------- @@ -1558,7 +1550,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: - depp.Printf("---AssignStmt, Op: %v \n", n.Op) + debugPP.Printf("---AssignStmt, Op: %v \n", n.Op) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { // Rhs consts become default *ConstExprs. @@ -1633,7 +1625,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { // ASSIGN. - depp.Println("assign") + debugPP.Println("assign") // NOTE: Keep in sync with DEFINE above. if len(n.Lhs) > len(n.Rhs) { // TODO dry code w/ above. @@ -1675,29 +1667,29 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TODO: use the other one, like map key checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], UintType, n.Op, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { - depp.Printf("op is %v \n", n.Op) + debugPP.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, // TODO: assert length - depp.Println("len of LHS: ", len(n.Lhs)) - depp.Println("len of RHS: ", len(n.Rhs)) + debugPP.Println("len of LHS: ", len(n.Lhs)) + debugPP.Println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], lt, n.Op, false) } else { // all else, like BAND_ASSIGN, etc - depp.Println("case: a, b = x, y") - depp.Printf("Op: %v \n", n.Op) + debugPP.Println("case: a, b = x, y") + debugPP.Printf("Op: %v \n", n.Op) // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) // is x or y is untyped, convert, else check type rt := evalStaticTypeOf(store, last, n.Rhs[i]) if isUntyped(rt) { - depp.Println("rt is untyped, convert") + debugPP.Println("rt is untyped, convert") // is untyped // converts if rx is "nil". checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) } else { - depp.Println("rt not untyped, check strict") + debugPP.Println("rt not untyped, check strict") checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) } } @@ -2371,17 +2363,17 @@ func isConstType(x Expr) bool { } func cmpSpecificity(t1, t2 Type) int { - depp.Printf("cmpSpecificity, t1:%v, t2:%v \n", t1, t2) + debugPP.Printf("cmpSpecificity, t1:%v, t2:%v \n", t1, t2) t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { - depp.Println("t1 i prime type") + debugPP.Println("t1 i prime type") t1s = t1p.Specificity() } if t2p, ok := t2.(PrimitiveType); ok { - depp.Println("t2 i prime type") + debugPP.Println("t2 i prime type") t2s = t2p.Specificity() } - depp.Println("t1s, t2s: ", t1s, t2s) + debugPP.Println("t1s, t2s: ", t1s, t2s) if t1s < t2s { // NOTE: higher specificity has lower value, so backwards. return 1 @@ -2394,7 +2386,7 @@ func cmpSpecificity(t1, t2 Type) int { // for special case of index conversion func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { - depp.Printf("convertConstType, x: %v, t:%v, \n", x, t) + debugPP.Printf("convertConstType, x: %v, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { convertConst(store, last, cx, t) } @@ -2412,21 +2404,21 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // TODO: this should be awareness at its origin func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { op := ILLEGAL - depp.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) + debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { // here we should check too, e.g. primitive to declared type is convertable if _, ok := t.(*NativeType); !ok { // not native type - depp.Println("ConstExpr is not nativeType, go check") - checkType(cx.T, t, op, autoNative) + debugPP.Println("ConstExpr is not nativeType, go check") + checkType(cx.T, t, op, autoNative) // refer to 22a17a_filetest, or should check in callExpr as a specific requirement? } - depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) + debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - depp.Println("SHL or SHR") + debugPP.Println("SHL or SHR") // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { - depp.Println("else, xt not nil") + debugPP.Println("else, xt not nil") xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { @@ -2471,26 +2463,26 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // NOTE: y is used to check operand, e.g. zero divisor: a/0, any other cases? // additionally, if something like, int(1)/int8(0), should first check is type matches, prior to check zero divisor func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t Type, op Word, autoNative bool) { - depp.Printf("checkOrConvertTypeWithOp, x: %v:, t:%v, op: %v \n", x, t, op) + debugPP.Printf("checkOrConvertTypeWithOp, x: %v:, t:%v, op: %v \n", x, t, op) if cx, ok := (*x).(*ConstExpr); ok { // here we should check too, e.g. primitive to declared type is convertable if _, ok := t.(*NativeType); !ok { // not native type - depp.Println("ConstExpr is not nativeType, go check") + debugPP.Println("ConstExpr is not nativeType, go check") checkType(cx.T, t, op, autoNative) // check operand if cy, ok := (*y).(*ConstExpr); ok { checkOperand(cy, op) } } - depp.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) + debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) // TODO: check Op here? } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - depp.Println("SHL or SHR") + debugPP.Println("SHL or SHR") // "push" expected type into shift binary's left operand. checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { - depp.Println("else, xt not nil") + debugPP.Println("else, xt not nil") xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { @@ -2540,14 +2532,14 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - depp.Printf("convertConst, cx:%v, t:%v \n", cx, t) + debugPP.Printf("convertConst, cx:%v, t:%v \n", cx, t) // TODO: thought it should only be permmited to converted to default types, not convertable to interface not satisfied if t != nil && t.Kind() == InterfaceKind { - depp.Println("set t to nil, if its kind is interface") + debugPP.Println("set t to nil, if its kind is interface") t = nil // signifies to convert to default type. } if isUntyped(cx.T) { - depp.Println("untyped") + debugPP.Println("untyped") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) } else if t != nil { @@ -2611,12 +2603,12 @@ func checkOperand(cx *ConstExpr, op Word) { // TODO, check zero divisor // is there a sign method for numeric if cx.TypedValue.T != nil { - depp.Println("check operand, kind is: ", cx.TypedValue.T.Kind()) + debugPP.Println("check operand, kind is: ", cx.TypedValue.T.Kind()) } if cx.TypedValue.Sign() == 0 { panic("invalid operation: division by zero") } else { - depp.Println("sign is: ", cx.TypedValue.Sign()) + debugPP.Println("sign is: ", cx.TypedValue.Sign()) } } } @@ -2631,7 +2623,7 @@ func isComparison(op Word) bool { } func checkOp(xt Type, dt Type, op Word, binary bool) { - depp.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binary) + debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binary) if !binary { if pred, ok := unaryPredicates[op]; ok { if !pred(dt) { @@ -2640,7 +2632,7 @@ func checkOp(xt Type, dt Type, op Word, binary bool) { } } - // first check comparison + // is comparison if isComparison(op) { switch op { case EQL, NEQ: // check comparable @@ -2648,46 +2640,44 @@ func checkOp(xt Type, dt Type, op Word, binary bool) { // 2. comparable requires one is convertable to another // 3. handle nil if ok, code := comparable(dt); !ok { - depp.Printf("not comparable of dt :%v \n", dt) + debugPP.Printf("not comparable of dt :%v \n", dt) panic(code) } case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString - depp.Printf("L, G: %v \n", op) + debugPP.Printf("L, G: %v \n", op) if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } + default: + panic("invalid comparison operator") } - } - // two steps of check: - // first, check is the dt type satisfies op, the switch logic - // second, xt can be converted to dt, this is done below this - // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt - depp.Printf("check matchable with op: %v \n", op) - if pred, ok := binaryPredicates[op]; ok { - if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } else { + // two steps of check: + // first, check is the dt type satisfies op, the switch logic + // second, xt can be converted to dt, this is done below this + // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt + debugPP.Printf("check op: %v for Expressions \n", op) + if pred, ok := binaryPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } - } - if op != ILLEGAL { - switch op { - case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: - // TODO: check matchable here, not in runtime - // if both typed - if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if !isSameTypes(xt, dt) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + if op != ILLEGAL { + switch op { + case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: + // if both typed + if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped + if !isSameTypes(xt, dt) { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + } } + case SHL, SHR: + // TODO: right should be numeric + default: + // Note: others no check, assign will be check in convertable } - - // do nothing here, as a special case, EQL or NEQ is more relaxed than ADD, so convertable is checked as `equality` in logic below - // - case SHL, SHR: - // TODO: right should be numeric - default: - // do nothing - // TODO: should also check the divisor not zero } } } @@ -2697,12 +2687,12 @@ func checkOp(xt Type, dt Type, op Word, binary bool) { // a target native dt type, if and only if dt is a native type. func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded bool) { if xt == nil || dt == nil { - depp.Println("xt or dt is nil") + debugPP.Println("xt or dt is nil") return } - depp.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) + debugPP.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) checkOp(xt, dt, op, true) - depp.Println("ops checks pass, check convertable on operand") + debugPP.Println("ops checks pass, check convertable on operand") return convertable(xt, dt, autoNative) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index c34585e6096..fd78655063f 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1155,7 +1155,7 @@ func (it *InterfaceType) FindEmbeddedFieldType(callerPath string, n Name, m map[ // For run-time type assertion. // TODO: optimize somehow. func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { - depp.Printf("isImplementedBy, it %v, ot:%v \n", it, ot) + debugPP.Printf("isImplementedBy, it %v, ot:%v \n", it, ot) // empty interface{} //if iot, ok := baseOf(ot).(*InterfaceType); ok { // if iot.IsEmptyInterface() { @@ -1168,7 +1168,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // field is embedded interface... im2 := baseOf(im.Type).(*InterfaceType) if !im2.IsImplementedBy(ot) { - depp.Println("first false") + debugPP.Println("first false") return false } else { continue @@ -1177,7 +1177,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // find method in field. tr, hp, rt, ft, _ := findEmbeddedFieldType(it.PkgPath, ot, im.Name, nil) if tr == nil { // not found. - depp.Println("second false") + debugPP.Println("second false") return false } if nft, ok := ft.(*NativeType); ok { @@ -1188,7 +1188,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // ie, if each of ft's arg types can match // against the desired arg types in im.Types. if !gno2GoTypeMatches(im.Type, nft.Type) { - depp.Println("third false") + debugPP.Println("third false") return false } } else if mt, ok := ft.(*FuncType); ok { @@ -1200,7 +1200,7 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { dmtid := mt.TypeID() imtid := im.Type.TypeID() if dmtid != imtid { - depp.Println("fourth false") + debugPP.Println("fourth false") return false } } @@ -2290,45 +2290,48 @@ func assertSameTypes(lt, rt Type) { // TODO: change to only check typed func isSameTypes(lt, rt Type) bool { - depp.Printf("check isSameTypes, lt: %v, rt: %v \n", lt, rt) - depp.Println("is lt data byte: ", isDataByte(lt)) - depp.Println("is rt data byte: ", isDataByte(rt)) + debugPP.Printf("check isSameTypes, lt: %v, rt: %v \n", lt, rt) + debugPP.Println("is lt data byte: ", isDataByte(lt)) + debugPP.Println("is rt data byte: ", isDataByte(rt)) + // refer to std3.gno, untyped byte has no typeID if lpt, ok := lt.(*PointerType); ok { - depp.Println("lt is pointer type, typeid: ", lpt.typeid) + debugPP.Println("lt is pointer type, typeid: ", lpt.typeid) if isDataByte(lpt.Elt) { - depp.Println("got data byte, left") + debugPP.Println("got data byte, left") return true } } if rpt, ok := rt.(*PointerType); ok { - depp.Println("rt is pointer type, typeid: ", rpt.typeid) + debugPP.Println("rt is pointer type, typeid: ", rpt.typeid) if isDataByte(rpt.Elt) { - depp.Println("got data byte, right") + debugPP.Println("got data byte, right") return true } } if isDataByte(lt) || isDataByte(rt) { - depp.Println("one is date byte") + debugPP.Println("one is date byte") return true } + // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { + debugPP.Println("both type nil") // both are nil. } else if lt == nil || rt == nil { + debugPP.Println("one type nil") // one is nil. see function comment. - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. } else if lt.Kind() == rt.Kind() && isDataByte(lt) { + debugPP.Println("both date byte") // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? } else if lt.TypeID() == rt.TypeID() { + debugPP.Println("typeID equal") // non-nil types are identical. } else { return false @@ -2366,16 +2369,17 @@ func assertEqualityTypes(lt, rt Type) { // t is the target type in convert process, check it firstly, then check if convertable func comparable(t Type) (bool, string) { - depp.Printf("check comparable, t is %v \n", t) + debugPP.Printf("check comparable, t is %v \n", t) // primitive is comparable switch ct := baseOf(t).(type) { case PrimitiveType: - depp.Println("primitive type, return true") + debugPP.Println("primitive type, return true") return true, "" case *ArrayType: // NOTE: no recursive allowed // TODO: check length? but that needs check after convert, indicates checkOp after convert? make more sense seems + // TODO: check at least length here switch baseOf(ct.Elem()).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // TODO: + case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // TODO: nativeType? return true, "" default: return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) @@ -2417,18 +2421,18 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // if xt or dt is empty interface, convertable // if no empty interface, then check if xt satisfied dt if dt.Kind() == InterfaceKind { - depp.Println("dt is interface") + debugPP.Println("dt is interface") if idt, ok := baseOf(dt).(*InterfaceType); ok { if idt.IsEmptyInterface() { - depp.Println("dt is empty interface") + debugPP.Println("dt is empty interface") // if dt is an empty Gno interface, any x ok. return // ok } else if idt.IsImplementedBy(xt) { - depp.Println("dt is implemented by xt") + debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6 - depp.Println("xt is empty interface: ", iot) + debugPP.Println("xt is empty interface: ", iot) if iot.IsEmptyInterface() { return // ok } @@ -2480,14 +2484,14 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { panic("should not happen") } } else if xt.Kind() == InterfaceKind { - depp.Println("xt is interface") + debugPP.Println("xt is interface") if ixt, ok := baseOf(xt).(*InterfaceType); ok { if ixt.IsEmptyInterface() { - depp.Println("xt is empty interface") + debugPP.Println("xt is empty interface") // if dt is an empty Gno interface, any x ok. return // ok } else if ixt.IsImplementedBy(dt) { - depp.Println("xt is implemented by dt") + debugPP.Println("xt is implemented by dt") // if dt implements idt, ok. return // ok } else if idt, ok := dt.(*InterfaceType); ok { @@ -2597,7 +2601,7 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // special case if implicitly named primitive type. // TODO simplify with .IsNamedType(). if _, ok := xt.(PrimitiveType); ok { - depp.Println("xt is primitiveType") + debugPP.Println("xt is primitiveType") // this is special when dt is the declared type of x if !isUntyped(xt) { panic(fmt.Sprintf( @@ -2617,7 +2621,7 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // General cases. switch cdt := dt.(type) { case PrimitiveType: // case 1 - depp.Println("primitive type") + debugPP.Println("primitive type") // if xt is untyped, ensure dt is compatible. switch xt { case UntypedBoolType: diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 33966846e55..18ff7ae52ab 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -877,7 +877,7 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { - depp.Printf("ConvertUntypedTo, tv:%v, t:%v \n", tv, t) + debugPP.Printf("ConvertUntypedTo, tv:%v, t:%v \n", tv, t) if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( @@ -924,7 +924,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { // general case if t == nil { t = defaultTypeOf(tv.T) - depp.Printf("give t its default type, to be:%v \n", t) + debugPP.Printf("give t its default type, to be:%v \n", t) } switch tv.T { case UntypedBoolType: @@ -1051,7 +1051,7 @@ func ConvertUntypedRuneTo(dst *TypedValue, t Type) { } func ConvertUntypedBigintTo(dst *TypedValue, bv BigintValue, t Type) { - depp.Printf("ConvertUntypedBigintTo, dst: %v, bv:%v, t:%v \n", dst, bv, t) + debugPP.Printf("ConvertUntypedBigintTo, dst: %v, bv:%v, t:%v \n", dst, bv, t) k := t.Kind() bi := bv.V var sv int64 = 0 // if signed. diff --git a/gnovm/tests/files/types/0a6_filetest.gno b/gnovm/tests/files/types/0a6_filetest.gno new file mode 100644 index 00000000000..98bc3a38c9b --- /dev/null +++ b/gnovm/tests/files/types/0a6_filetest.gno @@ -0,0 +1,12 @@ +package main + +var r rune + +// assign +func main() { + r = "a" + println(r) +} + +// Error: +// main/files/types/0a6_filetest.gno:7: cannot use untyped string as Int32Kind diff --git a/gnovm/tests/files/types/0f30_filetest.gno b/gnovm/tests/files/types/0f30_filetest.gno new file mode 100644 index 00000000000..0c859b35d50 --- /dev/null +++ b/gnovm/tests/files/types/0f30_filetest.gno @@ -0,0 +1,8 @@ +package main + +// both not const, and both interface +func main() { + println([]byte("a") == []byte("b")) +} + +// Error: diff --git a/gnovm/tests/files/types/0f31_filetest.gno b/gnovm/tests/files/types/0f31_filetest.gno new file mode 100644 index 00000000000..bcb62dc76c3 --- /dev/null +++ b/gnovm/tests/files/types/0f31_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "bytes" + +// both not const, and both interface +func main() { + // lv.T: * uint8, rv.T: * uint8 + cmp := bytes.Compare([]byte("a"), []byte("b")) + println(cmp) +} + +// Output: +// -1 diff --git a/gnovm/tests/files/types/22a17a_filetest.gno b/gnovm/tests/files/types/22a17a_filetest.gno index e145dd61251..ef14dd28120 100644 --- a/gnovm/tests/files/types/22a17a_filetest.gno +++ b/gnovm/tests/files/types/22a17a_filetest.gno @@ -6,10 +6,11 @@ func Add(a, b Int) Int { return a + b } +// No binaryExpr or unaryExpr, no op related, still need checkType func main() { r := Add(0, int8(1)) println(r) } // Error: -// main/files/types/22a17a_filetest.gno:10: cannot use int8 as main.Int without explicit conversion +// main/files/types/22a17a_filetest.gno:11: cannot use int8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index c8a311b4a2a..f0b0de98e05 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x1400003b970 +// 0x1400003b0e0 diff --git a/gnovm/tests/files/types/24a0_filetest.gno b/gnovm/tests/files/types/24a0_filetest.gno new file mode 100644 index 00000000000..e3ecefd621f --- /dev/null +++ b/gnovm/tests/files/types/24a0_filetest.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const Huge = 1e1000 + fmt.Println(Huge / 1e999) +} + +// Output: +// 10 diff --git a/gnovm/tests/files/types/24a1_filetest.gno b/gnovm/tests/files/types/24a1_filetest.gno new file mode 100644 index 00000000000..bd893312cf2 --- /dev/null +++ b/gnovm/tests/files/types/24a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + const Huge = 1e1000 + println(Huge) +} + +// Error: +// cannot convert untyped bigdec to float64: strconv.ParseFloat: parsing "1E+1000": value out of range diff --git a/gnovm/tests/files/types/24a2_filetest.gno b/gnovm/tests/files/types/24a2_filetest.gno new file mode 100644 index 00000000000..8add4bad19d --- /dev/null +++ b/gnovm/tests/files/types/24a2_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + type Char byte + var c Char = '世' +} + +// Error: +// main/files/types/24a2_filetest.gno:3: rune overflows target kind diff --git a/gnovm/tests/files/types/24a3_filetest.gno b/gnovm/tests/files/types/24a3_filetest.gno new file mode 100644 index 00000000000..1645e46aaf8 --- /dev/null +++ b/gnovm/tests/files/types/24a3_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const MaxUint uint = ^0 +} + +// Error: +// main/files/types/24a3_filetest.gno:4: not yet implemented diff --git a/gnovm/tests/files/types/others/README.md b/gnovm/tests/files/types/others/README.md index 5550932e85e..7decd02594d 100644 --- a/gnovm/tests/files/types/others/README.md +++ b/gnovm/tests/files/types/others/README.md @@ -1,5 +1,18 @@ +Context: -binaryExpression + mix of numeric types + + comparable + + special case + + + + + +Flow: + + binaryExpression/unaryExpression check comparison: assignableTo(type), LHS or RHS is assignable to the other From eed16b735560a59baa8ff42ce600df34568d52d1 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Dec 2023 11:45:13 +0800 Subject: [PATCH 016/193] optimize --- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 4 +- gnovm/pkg/gnolang/preprocess.go | 327 ++++++++---------- gnovm/pkg/gnolang/types.go | 76 +--- gnovm/tests/files/types/0f16_filetest.gno | 2 +- gnovm/tests/files/types/0f20_filetest.gno | 2 +- gnovm/tests/files/types/0f21_filetest.gno | 2 +- .../{0f31_filetest.gno => 0f31_filetest.gnoa} | 0 gnovm/tests/files/types/22a17a_filetest.gno | 3 +- gnovm/tests/files/types/23a4_filetest.gno | 2 +- 10 files changed, 164 insertions(+), 256 deletions(-) rename gnovm/tests/files/types/{0f31_filetest.gno => 0f31_filetest.gnoa} (100%) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 69e468f755a..86b3cc8a4b2 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -901,7 +901,7 @@ func gno2GoType(t Type) reflect.Type { // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). -// This is called when autoNative is true in checkType(). +// This is called when autoNative is true in checkTypeConvertable(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 8e9dc977a46..7a8f28e3157 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -85,7 +85,7 @@ func (m *Machine) doOpEql() { var res bool // TODO: this should be in preprocess too // TODO: only assert here - if isSameTypes(lv.T, rv.T) { + if isComparableIdentical(lv.T, rv.T) { res = isEql(m.Store, lv, rv) } else { res = false @@ -112,7 +112,7 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - if isSameTypes(lv.T, rv.T) { + if isComparableIdentical(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { res = true diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e7b5c81e6d1..250092ae319 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -7,6 +7,52 @@ import ( "reflect" ) +type f func(t Type) bool + +var binaryPredicates map[Word]f +var unaryPredicates map[Word]f + +func init() { + binaryPredicates = make(map[Word]f) + unaryPredicates = make(map[Word]f) + // add,sub,mul,quo,rem with assgin + binaryPredicates[ADD] = isNumericOrString + binaryPredicates[ADD_ASSIGN] = isNumericOrString + binaryPredicates[SUB] = isNumeric + binaryPredicates[SUB_ASSIGN] = isNumeric + binaryPredicates[MUL] = isNumeric + binaryPredicates[MUL_ASSIGN] = isNumeric + binaryPredicates[QUO] = isNumeric + binaryPredicates[QUO_ASSIGN] = isNumeric + binaryPredicates[REM] = isIntNum + binaryPredicates[REM_ASSIGN] = isIntNum + + // bit op + binaryPredicates[BAND] = isIntNum + binaryPredicates[BAND_ASSIGN] = isIntNum + binaryPredicates[XOR] = isIntNum + binaryPredicates[XOR_ASSIGN] = isIntNum + binaryPredicates[BOR] = isIntNum + binaryPredicates[BOR_ASSIGN] = isIntNum + binaryPredicates[BAND_NOT] = isIntNum + binaryPredicates[BAND_NOT_ASSIGN] = isIntNum + // logic op + binaryPredicates[LAND] = isBoolean + binaryPredicates[LOR] = isBoolean + + // compare + binaryPredicates[LSS] = isOrdered + binaryPredicates[LEQ] = isOrdered + binaryPredicates[GTR] = isOrdered + binaryPredicates[GEQ] = isOrdered + + // unary + unaryPredicates[ADD] = isNumeric + unaryPredicates[SUB] = isNumeric + unaryPredicates[XOR] = isIntNum + unaryPredicates[NOT] = isBoolean +} + // In the case of a *FileSet, some declaration steps have to happen // in a restricted parallel way across all the files. // Anything predefined or preprocessed here get skipped during the Preprocess @@ -621,7 +667,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // The main TRANS_LEAVE switch. switch n := n.(type) { // TRANS_LEAVE ----------------------- - case *NameExpr: + case *NameExpr: // e.g. var a int, a is NameExpr // Validity: check that name isn't reserved. if isReservedName(n.Name) { panic(fmt.Sprintf( @@ -763,9 +809,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("left is const") if ric { debugPP.Println("right is const") - // special case, check zero divisor - // should check in after type check - //checkOperand(rcx, n.Op) // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. @@ -774,23 +817,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { //// is this implied implicitly? rest of the binary operators after SHL and SHR is excluded //// Note: this check happens only when left and right are both typed, if not, the checkOrConvert logic will be run if cmp not 0 //// TODO: checkOrConvertType, same way around - //if !isUntyped(lcx.T) && !isUntyped(rcx.T) { - // if n.Op == EQL || n.Op == NEQ || n.Op == ADD || n.Op == SUB || n.Op == MUL || n.Op == QUO || n.Op == REM || n.Op == BAND || n.Op == BOR || n.Op == XOR || n.Op == BAND_NOT { - // fmt.Printf("Op: %v \n", n.Op) - // fmt.Printf("lt typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) - // fmt.Printf("rt typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) - // // strict - // if lt.TypeID() != rt.TypeID() { - // panic("mismatch type for EQL || NEQ || ADD") - // } - // } - //} // at least one of left or right is untyped cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // this always implies untyped>? debugPP.Println("cmp < 0, ->") // convert n.Left to right type. - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rcx.T, n.Op, false) + checkOp(store, last, &n.Left, rcx.T, n.Op, true) + checkOrConvertType(store, last, &n.Left, rcx.T, false) } else if cmp == 0 { debugPP.Println("cmp == 0") // NOTE: the following doesn't work. @@ -799,14 +832,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // or check for compatibility. // (the other way around would work too) // also need to check - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rcx.T, n.Op, false) + checkOp(store, last, &n.Left, rcx.T, n.Op, true) + checkOrConvertType(store, last, &n.Left, rcx.T, false) } else { // this always implies untyped>? debugPP.Println("cmp > 0, <-") // convert n.Right to left type. - // TODO: this looks wired - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lcx.T, n.Op, false) + checkOp(store, last, &n.Right, lcx.T, n.Op, true) + checkOrConvertType(store, last, &n.Right, lcx.T, false) } } + // check special case: zero divisor before eval + if isQuoOrRem(n.Op) { + checkOperand(rcx) + } // Then, evaluate the expression. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE @@ -821,7 +859,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, pt, n.Op, false) + checkOp(store, last, &n.Left, pt, n.Op, true) + checkOrConvertType(store, last, &n.Left, pt, false) // convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. @@ -849,17 +888,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) debugPP.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const debugPP.Println("left is typed const, right is not const, should check type too") - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) - + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) } else if lcx.T == nil { // LHS is nil debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) } // TODO: 912 line? } else if ric { @@ -870,7 +911,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { if baseOf(rt) != UintType { // convert n.Right to (gno) uint type. - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, UintType, n.Op, false) + //checkOp(store, last, &n.Right, UintType, n.Op, true) + checkOrConvertType(store, last, &n.Right, UintType, false) } else { // leave n.Left as is and baseOf(n.Right) as UintType. } @@ -881,7 +923,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, pt, n.Op, false) + checkOp(store, last, &n.Right, pt, n.Op, true) + checkOrConvertType(store, last, &n.Right, pt, false) // and convert result back. tx := constType(n, lnt) // reset/create n2 to preprocess left child. @@ -897,16 +940,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) + checkOp(store, last, &n.Right, lt, n.Op, true) + checkOrConvertType(store, last, &n.Right, lt, false) } } //} else if rcx.T == nil { } else if rcx.T == nil { // RHS is nil debugPP.Println("rcx.T == nil ") // convert n.Right to typed-nil type. - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) + checkOp(store, last, &n.Right, lt, n.Op, true) + checkOrConvertType(store, last, &n.Right, lt, false) } else if !isShift { - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) + checkOp(store, last, &n.Right, lt, n.Op, true) + checkOrConvertType(store, last, &n.Right, lt, false) } } else { debugPP.Printf("both not const, lt: %v, rt:%v \n", lt, rt) @@ -973,24 +1019,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { debugPP.Println("left untyped, right is typed") - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) } } else if riu { - checkOrConvertTypeWithOp(store, last, &n.Right, &n.Right, lt, n.Op, false) + checkOp(store, last, &n.Right, lt, n.Op, true) + checkOrConvertType(store, last, &n.Right, lt, false) } else { - checkOrConvertTypeWithOp(store, last, &n.Left, &n.Right, rt, n.Op, false) - //// left is untyped, right is not. - //if lt.TypeID() != rt.TypeID() { - // panic(fmt.Sprintf( - // "incompatible types in binary expression: %v %v %v", - // n.Left, n.Op, n.Right)) - //} + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) } } } // TRANS_LEAVE ----------------------- case *CallExpr: + debugPP.Println("---CallExpr") // Func type evaluation. var ft *FuncType ift := evalStaticTypeOf(store, last, n.Func) @@ -1173,31 +1217,37 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, tv := range argTVs { if hasVarg { if (len(spts) - 1) <= i { - checkType(tv.T, spts[len(spts)-1].Type.Elem(), ILLEGAL, true) + checkTypeConvertable(tv.T, spts[len(spts)-1].Type.Elem(), true) } else { - checkType(tv.T, spts[i].Type, ILLEGAL, true) + checkTypeConvertable(tv.T, spts[i].Type, true) } } else { - checkType(tv.T, spts[i].Type, ILLEGAL, true) + checkTypeConvertable(tv.T, spts[i].Type, true) } } } else { + debugPP.Println("check or convert args") for i := range n.Args { if hasVarg { + debugPP.Println("has varg") if (len(spts) - 1) <= i { if isVarg { if len(spts) <= i { panic("expected final vargs slice but got many") } + debugPP.Println("is varg") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } else { + debugPP.Println("not varg") checkOrConvertType(store, last, &n.Args[i], spts[len(spts)-1].Type.Elem(), true) } } else { + debugPP.Println("not <=") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } else { + debugPP.Println("has not varg") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } @@ -1273,13 +1323,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // checkOp, like +a, while a should be numeric if cx, ok := n.X.(*ConstExpr); ok { debugPP.Println("not native, ConstExpr") - // checkOp, e.g. +a while a is numeric - checkOp(nil, cx.T, n.Op, false) + // checkOp, e.g. +a while a should be numeric + checkOp(store, last, nil, cx.T, n.Op, false) cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } debugPP.Println("else") - checkOp(nil, xt, n.Op, false) + checkOp(store, last, nil, xt, n.Op, false) // TRANS_LEAVE ----------------------- case *CompositeLitExpr: @@ -1664,8 +1714,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } // Special case if shift assign <<= or >>=. - // TODO: use the other one, like map key - checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], UintType, n.Op, false) + // TODO: no need here, like index convert + //checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) + checkOrConvertType(store, last, &n.Rhs[0], UintType, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { debugPP.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, @@ -1674,7 +1725,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion - checkOrConvertTypeWithOp(store, last, &n.Rhs[0], &n.Rhs[0], lt, n.Op, false) + checkOp(store, last, &n.Rhs[0], lt, n.Op, false) + checkOrConvertType(store, last, &n.Rhs[0], lt, false) } else { // all else, like BAND_ASSIGN, etc debugPP.Println("case: a, b = x, y") debugPP.Printf("Op: %v \n", n.Op) @@ -1687,10 +1739,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("rt is untyped, convert") // is untyped // converts if rx is "nil". - checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) - } else { + checkOp(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertType(store, last, &n.Rhs[i], lt, false) + } else { // TODO: optimize debugPP.Println("rt not untyped, check strict") - checkOrConvertTypeWithOp(store, last, &n.Rhs[i], &n.Rhs[i], lt, n.Op, false) + checkOp(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertType(store, last, &n.Rhs[i], lt, false) } } } @@ -2403,13 +2457,12 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // TODO: but if it's bind to ops like +, type conversion should be checked // TODO: this should be awareness at its origin func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { - op := ILLEGAL debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { // here we should check too, e.g. primitive to declared type is convertable if _, ok := t.(*NativeType); !ok { // not native type debugPP.Println("ConstExpr is not nativeType, go check") - checkType(cx.T, t, op, autoNative) // refer to 22a17a_filetest, or should check in callExpr as a specific requirement? + checkTypeConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) @@ -2422,8 +2475,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { - //checkType(xt, t, op, autoNative) - conversionNeeded = checkType(xt, t, op, autoNative) + conversionNeeded = checkTypeConvertable(xt, t, autoNative) } if isUntyped(xt) { if t == nil { @@ -2459,71 +2511,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } -// add operands here -// NOTE: y is used to check operand, e.g. zero divisor: a/0, any other cases? -// additionally, if something like, int(1)/int8(0), should first check is type matches, prior to check zero divisor -func checkOrConvertTypeWithOp(store Store, last BlockNode, x *Expr, y *Expr, t Type, op Word, autoNative bool) { - debugPP.Printf("checkOrConvertTypeWithOp, x: %v:, t:%v, op: %v \n", x, t, op) - if cx, ok := (*x).(*ConstExpr); ok { - // here we should check too, e.g. primitive to declared type is convertable - if _, ok := t.(*NativeType); !ok { // not native type - debugPP.Println("ConstExpr is not nativeType, go check") - checkType(cx.T, t, op, autoNative) - // check operand - if cy, ok := (*y).(*ConstExpr); ok { - checkOperand(cy, op) - } - } - debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) - convertConst(store, last, cx, t) - // TODO: check Op here? - } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - debugPP.Println("SHL or SHR") - // "push" expected type into shift binary's left operand. - checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) - } else if *x != nil { // XXX if x != nil && t != nil { - debugPP.Println("else, xt not nil") - xt := evalStaticTypeOf(store, last, *x) - var conversionNeeded bool - if t != nil { - conversionNeeded = checkType(xt, t, op, autoNative) - } - if isUntyped(xt) { - if t == nil { - t = defaultTypeOf(xt) - } - // Push type into expr if qualifying binary expr. - if bx, ok := (*x).(*BinaryExpr); ok { - switch bx.Op { - case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, - BAND_NOT, LAND, LOR: - // push t into bx.Left and bx.Right - checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) - checkOrConvertTypeWithOp(store, last, &bx.Right, y, t, op, autoNative) - return - case SHL, SHR: - // push t into bx.Left - checkOrConvertTypeWithOp(store, last, &bx.Left, y, t, op, autoNative) - return - // case EQL, LSS, GTR, NEQ, LEQ, GEQ: - // default: - } - } - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx - // TODO: check op here - } - // cover all declared type case - if conversionNeeded { - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx - // TODO: check op here - } - } -} - // like checkOrConvertType(last, x, nil) func convertIfConst(store Store, last BlockNode, x Expr) { if cx, ok := x.(*ConstExpr); ok { @@ -2533,83 +2520,39 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { debugPP.Printf("convertConst, cx:%v, t:%v \n", cx, t) - // TODO: thought it should only be permmited to converted to default types, not convertable to interface not satisfied if t != nil && t.Kind() == InterfaceKind { debugPP.Println("set t to nil, if its kind is interface") t = nil // signifies to convert to default type. } if isUntyped(cx.T) { - debugPP.Println("untyped") + debugPP.Println("convert untyped const") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) } else if t != nil { + debugPP.Println("convert typed const for indexing") // e.g. a named type or uint8 type to int for indexing. ConvertTo(nilAllocator, store, &cx.TypedValue, t) setConstAttrs(cx) } } -type f func(t Type) bool - -var binaryPredicates map[Word]f -var unaryPredicates map[Word]f - -func init() { - binaryPredicates = make(map[Word]f) - unaryPredicates = make(map[Word]f) - // add,sub,mul,quo,rem with assgin - binaryPredicates[ADD] = isNumericOrString - binaryPredicates[ADD_ASSIGN] = isNumericOrString - binaryPredicates[SUB] = isNumeric - binaryPredicates[SUB_ASSIGN] = isNumeric - binaryPredicates[MUL] = isNumeric - binaryPredicates[MUL_ASSIGN] = isNumeric - binaryPredicates[QUO] = isNumeric - binaryPredicates[QUO_ASSIGN] = isNumeric - binaryPredicates[REM] = isIntNum - binaryPredicates[REM_ASSIGN] = isIntNum - - // bit op - binaryPredicates[BAND] = isIntNum - binaryPredicates[BAND_ASSIGN] = isIntNum - binaryPredicates[XOR] = isIntNum - binaryPredicates[XOR_ASSIGN] = isIntNum - binaryPredicates[BOR] = isIntNum - binaryPredicates[BOR_ASSIGN] = isIntNum - binaryPredicates[BAND_NOT] = isIntNum - binaryPredicates[BAND_NOT_ASSIGN] = isIntNum - // logic op - binaryPredicates[LAND] = isBoolean - binaryPredicates[LOR] = isBoolean - - // compare - binaryPredicates[LSS] = isOrdered - binaryPredicates[LEQ] = isOrdered - binaryPredicates[GTR] = isOrdered - binaryPredicates[GEQ] = isOrdered - - // unary - unaryPredicates[ADD] = isNumeric - unaryPredicates[SUB] = isNumeric - unaryPredicates[XOR] = isIntNum - unaryPredicates[NOT] = isBoolean -} - -// post check after conversion -// TODO: this not right, since xt is not divisor -func checkOperand(cx *ConstExpr, op Word) { +func isQuoOrRem(op Word) bool { switch op { case QUO, QUO_ASSIGN, REM, REM_ASSIGN: - // TODO, check zero divisor - // is there a sign method for numeric - if cx.TypedValue.T != nil { - debugPP.Println("check operand, kind is: ", cx.TypedValue.T.Kind()) - } - if cx.TypedValue.Sign() == 0 { - panic("invalid operation: division by zero") - } else { - debugPP.Println("sign is: ", cx.TypedValue.Sign()) - } + return true + default: + return false + } +} + +func checkOperand(cx *ConstExpr) { + if cx.TypedValue.T != nil { + debugPP.Println("check operand, kind is: ", cx.TypedValue.T.Kind()) + } + if cx.TypedValue.Sign() == 0 { + panic("invalid operation: division by zero") + } else { + debugPP.Println("sign is: ", cx.TypedValue.Sign()) } } @@ -2622,7 +2565,17 @@ func isComparison(op Word) bool { } } -func checkOp(xt Type, dt Type, op Word, binary bool) { +// TODO: is x is necessary +func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool) { + var xt Type + if x != nil { // unaryExpr + if cx, ok := (*x).(*ConstExpr); ok { + xt = cx.T + } else if *x != nil { + xt = evalStaticTypeOf(store, last, *x) + } + } + debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binary) if !binary { if pred, ok := unaryPredicates[op]; ok { @@ -2631,8 +2584,6 @@ func checkOp(xt Type, dt Type, op Word, binary bool) { } } } - - // is comparison if isComparison(op) { switch op { case EQL, NEQ: // check comparable @@ -2669,7 +2620,7 @@ func checkOp(xt Type, dt Type, op Word, binary bool) { case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: // if both typed if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if !isSameTypes(xt, dt) { + if !isComparableIdentical(xt, dt) { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } @@ -2685,14 +2636,12 @@ func checkOp(xt Type, dt Type, op Word, binary bool) { // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func checkType(xt Type, dt Type, op Word, autoNative bool) (conversionNeeded bool) { - if xt == nil || dt == nil { +func checkTypeConvertable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { + if xt == nil || dt == nil { // TODO: counter case? debugPP.Println("xt or dt is nil") return } - debugPP.Printf("checkType, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, Op: %v, \n", xt, xt.Kind(), dt, dt.Kind(), op) - checkOp(xt, dt, op, true) - debugPP.Println("ops checks pass, check convertable on operand") + debugPP.Printf("checkTypeConvertable, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, \n", xt, xt.Kind(), dt, dt.Kind()) return convertable(xt, dt, autoNative) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index fd78655063f..d531cf3f97f 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -277,6 +277,7 @@ const ( IsConstType = IsBoolean | IsNumeric | IsString ) +// this is more convenient than compare with types func (pt PrimitiveType) Predicate() predicate { switch pt { case InvalidType: @@ -392,49 +393,6 @@ func isNumericOrString(t Type) bool { } } -//func isNumeric(t Type) bool { -// switch t := baseOf(t).(type) { -// case PrimitiveType: -// switch t { -// case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, Float32Type, Float64Type, UntypedBigintType, BigintType, UntypedBigdecType, BigdecType: -// return true -// default: -// return false -// } -// default: -// return false -// } -//} - -//// only for / and % /= %=, no support for float -//func isIntNumber(t Type) bool { -// switch t := baseOf(t).(type) { -// case PrimitiveType: -// switch t { -// case IntType, Int8Type, Int16Type, Int32Type, Int64Type, UintType, Uint8Type, Uint16Type, Uint32Type, Uint64Type, UntypedBigintType, BigintType: -// return true -// default: -// return false -// } -// default: -// return false -// } -//} - -func isTypedString(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - switch t { - case UntypedStringType, StringType: - return true - default: - return false - } - default: - return false - } -} - func (pt PrimitiveType) String() string { switch pt { case InvalidType: @@ -2288,9 +2246,11 @@ func assertSameTypes(lt, rt Type) { } } -// TODO: change to only check typed -func isSameTypes(lt, rt Type) bool { - debugPP.Printf("check isSameTypes, lt: %v, rt: %v \n", lt, rt) +// check with untyped excluded, it's used by checkOp and op_binary +// both typed(original typed, or be typed in runtime), or one is nil, or data byte +// only for comparable types +func isComparableIdentical(lt, rt Type) bool { + debugPP.Printf("check isComparableIdentical, lt: %v, rt: %v \n", lt, rt) debugPP.Println("is lt data byte: ", isDataByte(lt)) debugPP.Println("is rt data byte: ", isDataByte(rt)) @@ -2382,7 +2342,7 @@ func comparable(t Type) (bool, string) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // TODO: nativeType? return true, "" default: - return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) + return false, fmt.Sprintf("%v cannot be compared \n", ct) } case *StructType: for _, f := range ct.Fields { @@ -2390,7 +2350,7 @@ func comparable(t Type) (bool, string) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: return true, "" default: - return false, fmt.Sprintf("%v cannot be compared \n", ct.Elem()) + return false, fmt.Sprintf("%v cannot be compared \n", ct) } } return true, "" @@ -2673,23 +2633,23 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := checkType(pt.Elt, cdt.Elt, ILLEGAL, false) + cdt := checkTypeConvertable(pt.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := checkType(at.Elt, cdt.Elt, ILLEGAL, false) + cdt := checkTypeConvertable(at.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := checkType(st.Elt, cdt.Elt, ILLEGAL, false) + cdt := checkTypeConvertable(st.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := checkType(mt.Key, cdt.Key, ILLEGAL, false) - cn2 := checkType(mt.Value, cdt.Value, ILLEGAL, false) + cn1 := checkTypeConvertable(mt.Key, cdt.Key, false) + cn2 := checkTypeConvertable(mt.Value, cdt.Value, false) return cn1 || cn2 || conversionNeeded } case *FuncType: @@ -2749,12 +2709,12 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // NOTE: if both a typed, but not in the rule of declared type, no conversion. just check if they match. // 2. if one of LHS or RHS is constExpr(typed or untyped), it would be converted to the type of its -// corresponding side(using checkOrConvertType, iff it's convertable, using checkType), e.g. int-> int8, int-> (type Error int), +// corresponding side(using checkOrConvertType, iff it's convertable, using checkTypeConvertable), e.g. int-> int8, int-> (type Error int), // 3. if both LHS and RHS are not const, assertTypeMatchStrict -// 4. Operators. need one place in asset* or checkType, to switch operators +// 4. Operators. need one place in asset* or checkTypeConvertable, to switch operators -// TODO: merge this with checkType +// TODO: merge this with checkTypeConvertable //func assertTypeMatchStrict(lt, rt Type, op Word) { // if lt == nil && rt == nil { // println("1") @@ -3037,7 +2997,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkType(spec, match.Elem(), ILLEGAL, false) + checkTypeConvertable(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -3051,7 +3011,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkType(spec, match, ILLEGAL, false) + checkTypeConvertable(spec, match, false) return // ok } else { if isUntyped(spec) { diff --git a/gnovm/tests/files/types/0f16_filetest.gno b/gnovm/tests/files/types/0f16_filetest.gno index 19d64c69387..a82590a7ae1 100644 --- a/gnovm/tests/files/types/0f16_filetest.gno +++ b/gnovm/tests/files/types/0f16_filetest.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/types/0f16_filetest.gno:16: main.word cannot be compared +// main/files/types/0f16_filetest.gno:16: [2]main.word cannot be compared diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index edc43a21dda..4219cf89244 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// interface conversion: gnolang.Value is nil, not *gnolang.ArrayValue +// main/files/types/0f20_filetest.gno:10: [2]main.f cannot be compared diff --git a/gnovm/tests/files/types/0f21_filetest.gno b/gnovm/tests/files/types/0f21_filetest.gno index 163be3da4d4..7a607e09cab 100644 --- a/gnovm/tests/files/types/0f21_filetest.gno +++ b/gnovm/tests/files/types/0f21_filetest.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/types/0f21_filetest.gno:10: main.f cannot be compared +// main/files/types/0f21_filetest.gno:10: [2]main.f cannot be compared diff --git a/gnovm/tests/files/types/0f31_filetest.gno b/gnovm/tests/files/types/0f31_filetest.gnoa similarity index 100% rename from gnovm/tests/files/types/0f31_filetest.gno rename to gnovm/tests/files/types/0f31_filetest.gnoa diff --git a/gnovm/tests/files/types/22a17a_filetest.gno b/gnovm/tests/files/types/22a17a_filetest.gno index ef14dd28120..907d10807ef 100644 --- a/gnovm/tests/files/types/22a17a_filetest.gno +++ b/gnovm/tests/files/types/22a17a_filetest.gno @@ -8,8 +8,7 @@ func Add(a, b Int) Int { // No binaryExpr or unaryExpr, no op related, still need checkType func main() { - r := Add(0, int8(1)) - println(r) + println(Add(0, int8(1))) } // Error: diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index f0b0de98e05..bacc3123a44 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x1400003b0e0 +// 0x1400003a7d0 From 1c93d2c7deb9e732707204153a18528d544ee20e Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Dec 2023 17:07:49 +0800 Subject: [PATCH 017/193] inc,dec --- gnovm/pkg/gnolang/preprocess.go | 104 +++++++++----------- gnovm/pkg/gnolang/types.go | 46 +++++---- gnovm/tests/files/types/22a17i_filetest.gno | 49 +++++++++ gnovm/tests/files/types/23a4_filetest.gno | 2 +- gnovm/tests/files/types/25a0_filetest.gno | 10 ++ gnovm/tests/files/types/25a1_filetest.gno | 10 ++ gnovm/tests/files/types/25a2_filetest.gno | 29 ++++++ gnovm/tests/files/types/26a0_filetest.gno | 10 ++ gnovm/tests/files/types/26a0a_filetest.gno | 10 ++ gnovm/tests/files/types/26a1_filetest.gno | 10 ++ gnovm/tests/files/types/26a2_filetest.gno | 10 ++ 11 files changed, 213 insertions(+), 77 deletions(-) create mode 100644 gnovm/tests/files/types/22a17i_filetest.gno create mode 100644 gnovm/tests/files/types/25a0_filetest.gno create mode 100644 gnovm/tests/files/types/25a1_filetest.gno create mode 100644 gnovm/tests/files/types/25a2_filetest.gno create mode 100644 gnovm/tests/files/types/26a0_filetest.gno create mode 100644 gnovm/tests/files/types/26a0a_filetest.gno create mode 100644 gnovm/tests/files/types/26a1_filetest.gno create mode 100644 gnovm/tests/files/types/26a2_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 250092ae319..cf449575788 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -9,12 +9,11 @@ import ( type f func(t Type) bool -var binaryPredicates map[Word]f -var unaryPredicates map[Word]f +var binaryPredicates = make(map[Word]f) +var unaryPredicates = make(map[Word]f) +var IncDecStmtPredicates = make(map[Word]f) func init() { - binaryPredicates = make(map[Word]f) - unaryPredicates = make(map[Word]f) // add,sub,mul,quo,rem with assgin binaryPredicates[ADD] = isNumericOrString binaryPredicates[ADD_ASSIGN] = isNumericOrString @@ -51,6 +50,11 @@ func init() { unaryPredicates[SUB] = isNumeric unaryPredicates[XOR] = isIntNum unaryPredicates[NOT] = isBoolean + + // Inc Dec stmt + // NOTE: special case to be consistent with op_inc_dec, line3, no float support for now while go do. + IncDecStmtPredicates[INC] = isIntOrUint + IncDecStmtPredicates[DEC] = isIntOrUint } // In the case of a *FileSet, some declaration steps have to happen @@ -784,11 +788,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: - debugPP.Printf("--binary expr---, OP: %v \n", n.Op) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. - // TODO: should check convertable? isShift := n.Op == SHL || n.Op == SHR if isShift && baseOf(rt) != UintType { // convert n.Right to (gno) uint type, @@ -805,15 +807,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) + debugPP.Printf("---BinaryExpr---, OP: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) if lic { - debugPP.Println("left is const") if ric { - debugPP.Println("right is const") // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. if !isShift { - debugPP.Println("not shift") //// is this implied implicitly? rest of the binary operators after SHL and SHR is excluded //// Note: this check happens only when left and right are both typed, if not, the checkOrConvert logic will be run if cmp not 0 //// TODO: checkOrConvertType, same way around @@ -849,7 +849,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { - debugPP.Println("left is untyped const, right not const") // Left untyped const, Right not ---------------- if rnt, ok := rt.(*NativeType); ok { debugPP.Println("right native type") @@ -884,16 +883,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). } else { - debugPP.Println("not shift, convert") - debugPP.Printf("left typeID: %v, kind: %v \n", lt.TypeID(), lt.Kind()) - debugPP.Printf("right typeID: %v, kind: %v \n", rt.TypeID(), rt.Kind()) // convert n.Left to right type. checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const - debugPP.Println("left is typed const, right is not const, should check type too") checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } else if lcx.T == nil { // LHS is nil @@ -902,11 +897,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } - // TODO: 912 line? + // TODO: 942 line? } else if ric { - debugPP.Println("left not const, right is const") if isUntyped(rcx.T) { - debugPP.Println("right untyped") // Left not, Right untyped const ---------------- if isShift { if baseOf(rt) != UintType { @@ -955,7 +948,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Right, lt, false) } } else { - debugPP.Printf("both not const, lt: %v, rt:%v \n", lt, rt) if n.Op == SHL || n.Op == SHR { // shift operator, nothing yet to do. code like this will work //package main @@ -1005,11 +997,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // computed in gno, never with // reflect. } else { - debugPP.Println("no-shift, non-const, need all go through check") + debugPP.Println("lt not native") // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) - debugPP.Println("liu", liu) - debugPP.Println("rie", riu) if liu { if riu { if lt.TypeID() != rt.TypeID() { @@ -1034,7 +1024,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *CallExpr: - debugPP.Println("---CallExpr") + debugPP.Println("---CallExpr---") // Func type evaluation. var ft *FuncType ift := evalStaticTypeOf(store, last, n.Func) @@ -1088,7 +1078,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Handle special cases. // NOTE: these appear to be actually special cases in go. - // In general, a string is not convertable to []bytes + // In general, a string is not assignable to []bytes // without conversion. if cx, ok := n.Func.(*ConstExpr); ok { fv := cx.GetFunc() @@ -1217,37 +1207,31 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, tv := range argTVs { if hasVarg { if (len(spts) - 1) <= i { - checkTypeConvertable(tv.T, spts[len(spts)-1].Type.Elem(), true) + checkConvertable(tv.T, spts[len(spts)-1].Type.Elem(), true) } else { - checkTypeConvertable(tv.T, spts[i].Type, true) + checkConvertable(tv.T, spts[i].Type, true) } } else { - checkTypeConvertable(tv.T, spts[i].Type, true) + checkConvertable(tv.T, spts[i].Type, true) } } } else { - debugPP.Println("check or convert args") for i := range n.Args { if hasVarg { - debugPP.Println("has varg") if (len(spts) - 1) <= i { if isVarg { if len(spts) <= i { panic("expected final vargs slice but got many") } - debugPP.Println("is varg") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } else { - debugPP.Println("not varg") checkOrConvertType(store, last, &n.Args[i], spts[len(spts)-1].Type.Elem(), true) } } else { - debugPP.Println("not <=") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } else { - debugPP.Println("has not varg") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } @@ -1298,8 +1282,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: - debugPP.Printf("---unaryExpr, op: %v \n", n.Op) xt := evalStaticTypeOf(store, last, n.X) + debugPP.Printf("---unaryExpr---, op: %v, xt: %v \n", n.Op, xt) if xnt, ok := xt.(*NativeType); ok { debugPP.Println("nativeType") // get concrete native base type. @@ -1354,11 +1338,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *ArrayType: for i := 0; i < len(n.Elts); i++ { + // bypass check as a special case convertConstType(store, last, &n.Elts[i].Key, IntType, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { + // bypass check as a special case convertConstType(store, last, &n.Elts[i].Key, IntType, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } @@ -1600,7 +1586,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: - debugPP.Printf("---AssignStmt, Op: %v \n", n.Op) + debugPP.Printf("---AssignStmt---, Op: %v \n", n.Op) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { // Rhs consts become default *ConstExprs. @@ -1718,34 +1704,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { //checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) checkOrConvertType(store, last, &n.Rhs[0], UintType, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { - debugPP.Printf("op is %v \n", n.Op) // e.g. a += b, single value for lhs and rhs, // TODO: assert length - debugPP.Println("len of LHS: ", len(n.Lhs)) - debugPP.Println("len of RHS: ", len(n.Rhs)) lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion checkOp(store, last, &n.Rhs[0], lt, n.Op, false) checkOrConvertType(store, last, &n.Rhs[0], lt, false) } else { // all else, like BAND_ASSIGN, etc - debugPP.Println("case: a, b = x, y") - debugPP.Printf("Op: %v \n", n.Op) + debugPP.Println("case like: a, b = x, y") // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) // is x or y is untyped, convert, else check type - rt := evalStaticTypeOf(store, last, n.Rhs[i]) - if isUntyped(rt) { - debugPP.Println("rt is untyped, convert") - // is untyped - // converts if rx is "nil". - checkOp(store, last, &n.Rhs[i], lt, n.Op, false) - checkOrConvertType(store, last, &n.Rhs[i], lt, false) - } else { // TODO: optimize - debugPP.Println("rt not untyped, check strict") - checkOp(store, last, &n.Rhs[i], lt, n.Op, false) - checkOrConvertType(store, last, &n.Rhs[i], lt, false) - } + //rt := evalStaticTypeOf(store, last, n.Rhs[i]) + // all else check + checkOp(store, last, &n.Rhs[i], lt, n.Op, false) + checkOrConvertType(store, last, &n.Rhs[i], lt, false) } } } @@ -1777,6 +1751,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } + case *IncDecStmt: + debugPP.Println("---IncDecStmt---") + xt := evalStaticTypeOf(store, last, n.X) + checkOp(store, last, nil, xt, n.Op, false) + // TRANS_LEAVE ----------------------- case *ForStmt: // Cond consts become bool *ConstExprs. @@ -2459,10 +2438,10 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { - // here we should check too, e.g. primitive to declared type is convertable + // here we should check too, e.g. primitive to declared type is assignable if _, ok := t.(*NativeType); !ok { // not native type debugPP.Println("ConstExpr is not nativeType, go check") - checkTypeConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args + checkConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) @@ -2475,7 +2454,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { - conversionNeeded = checkTypeConvertable(xt, t, autoNative) + conversionNeeded = checkConvertable(xt, t, autoNative) } if isUntyped(xt) { if t == nil { @@ -2578,6 +2557,13 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binary) if !binary { + if op == INC || op == DEC { + if pred, ok := IncDecStmtPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } + } + } if pred, ok := unaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2588,7 +2574,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool switch op { case EQL, NEQ: // check comparable // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc - // 2. comparable requires one is convertable to another + // 2. comparable requires one is assignable to another // 3. handle nil if ok, code := comparable(dt); !ok { debugPP.Printf("not comparable of dt :%v \n", dt) @@ -2627,7 +2613,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool case SHL, SHR: // TODO: right should be numeric default: - // Note: others no check, assign will be check in convertable + // Note: others no check, assign will be check in assignable } } } @@ -2636,13 +2622,13 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func checkTypeConvertable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { +func checkConvertable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { if xt == nil || dt == nil { // TODO: counter case? debugPP.Println("xt or dt is nil") return } - debugPP.Printf("checkTypeConvertable, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, \n", xt, xt.Kind(), dt, dt.Kind()) - return convertable(xt, dt, autoNative) + debugPP.Printf("checkConvertable, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, \n", xt, xt.Kind(), dt, dt.Kind()) + return assignable(xt, dt, autoNative) } // Returns any names not yet defined nor predefined in expr. These happen diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index d531cf3f97f..3aa5ffc042e 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -265,7 +265,7 @@ const ( IsInteger IsUnsigned IsFloat - IsComplex + IsComplex // no use for now IsString IsUntyped IsBigInt @@ -296,7 +296,7 @@ func (pt PrimitiveType) Predicate() predicate { return IsInteger case Int16Type: return IsInteger - case UntypedRuneType: + case UntypedRuneType: // TODO: this is treat as DataByteType, GUESS, refer to op_inc_dec return IsRune case Int32Type: return IsInteger @@ -307,7 +307,7 @@ func (pt PrimitiveType) Predicate() predicate { case Uint8Type: return IsUnsigned case DataByteType: - return IsUnsigned + return IsUnsigned // TODO: consider this case Uint16Type: return IsUnsigned case Uint32Type: @@ -381,6 +381,18 @@ func isIntNum(t Type) bool { } } +func isIntOrUint(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate()&IsUnsigned != 0 || t.Predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + func isNumericOrString(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: @@ -2327,7 +2339,7 @@ func assertEqualityTypes(lt, rt Type) { } } -// t is the target type in convert process, check it firstly, then check if convertable +// t is the target type in convert process, check it firstly, then check if assignable func comparable(t Type) (bool, string) { debugPP.Printf("check comparable, t is %v \n", t) // primitive is comparable @@ -2376,9 +2388,9 @@ func comparable(t Type) (bool, string) { // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general convert, for composite types check -func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { +func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // case3 - // if xt or dt is empty interface, convertable + // if xt or dt is empty interface, assignable // if no empty interface, then check if xt satisfied dt if dt.Kind() == InterfaceKind { debugPP.Println("dt is interface") @@ -2633,23 +2645,23 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := checkTypeConvertable(pt.Elt, cdt.Elt, false) + cdt := checkConvertable(pt.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := checkTypeConvertable(at.Elt, cdt.Elt, false) + cdt := checkConvertable(at.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := checkTypeConvertable(st.Elt, cdt.Elt, false) + cdt := checkConvertable(st.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := checkTypeConvertable(mt.Key, cdt.Key, false) - cn2 := checkTypeConvertable(mt.Value, cdt.Value, false) + cn1 := checkConvertable(mt.Key, cdt.Key, false) + cn2 := checkConvertable(mt.Value, cdt.Value, false) return cn1 || cn2 || conversionNeeded } case *FuncType: @@ -2704,17 +2716,17 @@ func convertable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // e.g. : 1 + "a" is illegal, or int(1) + 0 is legal after convert // untyped 0 to int(0) implicitly(no cast), this is because "a" cannot be converted to 1, is untyped 0, which is // untyped bigint can be converted to int(0). -// special case in here is declared types, is A is declared type of B, and baseOf(A) == B, A and B is convertable in both direction +// special case in here is declared types, is A is declared type of B, and baseOf(A) == B, A and B is assignable in both direction // NOTE: Op like + - * / % ,etc. have a more strict constrain than equality == or != // NOTE: if both a typed, but not in the rule of declared type, no conversion. just check if they match. // 2. if one of LHS or RHS is constExpr(typed or untyped), it would be converted to the type of its -// corresponding side(using checkOrConvertType, iff it's convertable, using checkTypeConvertable), e.g. int-> int8, int-> (type Error int), +// corresponding side(using checkOrConvertType, iff it's assignable, using checkConvertable), e.g. int-> int8, int-> (type Error int), // 3. if both LHS and RHS are not const, assertTypeMatchStrict -// 4. Operators. need one place in asset* or checkTypeConvertable, to switch operators +// 4. Operators. need one place in asset* or checkConvertable, to switch operators -// TODO: merge this with checkTypeConvertable +// TODO: merge this with checkConvertable //func assertTypeMatchStrict(lt, rt Type, op Word) { // if lt == nil && rt == nil { // println("1") @@ -2997,7 +3009,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkTypeConvertable(spec, match.Elem(), false) + checkConvertable(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -3011,7 +3023,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkTypeConvertable(spec, match, false) + checkConvertable(spec, match, false) return // ok } else { if isUntyped(spec) { diff --git a/gnovm/tests/files/types/22a17i_filetest.gno b/gnovm/tests/files/types/22a17i_filetest.gno new file mode 100644 index 00000000000..973cd8c0995 --- /dev/null +++ b/gnovm/tests/files/types/22a17i_filetest.gno @@ -0,0 +1,49 @@ +package main + +type word uint +type nat []word + +// receiver +func (n nat) add() bool { + return true +} + +func Gen() interface{} { + n := []word{0} + return n +} + +func Gen2() interface{} { + n := nat([]word{0}) + return n +} + +// mapLit +func main() { + r := Gen() + switch t := r.(type) { + case nat: + println("nat") + println(t.add()) + case []word: + println("[]word") + default: + println("should not happen") + } + + r2 := Gen2() + switch t := r2.(type) { + case nat: + println("nat") + println(t.add()) + case []word: + println("[]word") + default: + println("should not happen") + } +} + +// Output: +// []word +// nat +// true diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index bacc3123a44..e2ad0063909 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x1400003a7d0 +// 0x140003b1c20 diff --git a/gnovm/tests/files/types/25a0_filetest.gno b/gnovm/tests/files/types/25a0_filetest.gno new file mode 100644 index 00000000000..8f3f97caaee --- /dev/null +++ b/gnovm/tests/files/types/25a0_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a++ + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/25a1_filetest.gno b/gnovm/tests/files/types/25a1_filetest.gno new file mode 100644 index 00000000000..51046e36ed4 --- /dev/null +++ b/gnovm/tests/files/types/25a1_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + a++ + println(a) +} + +// Error: +// main/files/types/25a1_filetest.gno:5: operator ++ not defined on: string diff --git a/gnovm/tests/files/types/25a2_filetest.gno b/gnovm/tests/files/types/25a2_filetest.gno new file mode 100644 index 00000000000..a91080a0d95 --- /dev/null +++ b/gnovm/tests/files/types/25a2_filetest.gno @@ -0,0 +1,29 @@ +package main + +func main() { + a := int(1) + a++ + println(a) + + // TODO: no support for now + //b := 1.0 + //b++ + //println(b) + // + //c := float32(1.0) + //c++ + //println(c) + + d := 'a' + d++ + println(d) + + e := uint(1) + e++ + println(e) +} + +// Output: +// 2 +// 98 +// 2 diff --git a/gnovm/tests/files/types/26a0_filetest.gno b/gnovm/tests/files/types/26a0_filetest.gno new file mode 100644 index 00000000000..a7a3e1f07d9 --- /dev/null +++ b/gnovm/tests/files/types/26a0_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << 1 + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/26a0a_filetest.gno b/gnovm/tests/files/types/26a0a_filetest.gno new file mode 100644 index 00000000000..f998381ef1c --- /dev/null +++ b/gnovm/tests/files/types/26a0a_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a <<= 1 + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/26a1_filetest.gno b/gnovm/tests/files/types/26a1_filetest.gno new file mode 100644 index 00000000000..0eba81f4a9c --- /dev/null +++ b/gnovm/tests/files/types/26a1_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << 1.0 // NOTE: go vet would fail, but still process + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/26a2_filetest.gno b/gnovm/tests/files/types/26a2_filetest.gno new file mode 100644 index 00000000000..753ed909aae --- /dev/null +++ b/gnovm/tests/files/types/26a2_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << "hello" // NOTE: go vet would fail, but still process + println(r) +} + +// Error: +// main/files/types/26a2_filetest.gno:3: cannot convert StringKind to UintKind From 5f0ac87c8d26f1eb2f124300e619b7642d93aefa Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Dec 2023 17:52:39 +0800 Subject: [PATCH 018/193] fixup --- .../p/demo/challenge/0c2_filetest.gno | 24 ------------- .../p/demo/challenge/others/2d_filetest.gno | 31 ---------------- .../others/comparison_0_filetest.gno | 27 -------------- .../others/comparison_0a_filetest.gno | 29 --------------- .../others/comparison_0b_filetest.gno | 29 --------------- .../others/comparison_0c_filetest.gno | 25 ------------- .../others/comparison_0d_filetest.gno | 25 ------------- .../others/comparison_0e_filetest.gno | 25 ------------- .../others/comparison_0f_filetest.gno | 25 ------------- .../others/comparison_0g_filetest.gno | 25 ------------- .../others/comparison_0h_filetest.gno | 10 ------ .../others/comparison_0i_filetest.gno | 8 ----- .../others/comparison_0j_filetest.gno | 8 ----- .../others/comparison_0k_filetest.gno | 8 ----- .../others/comparison_0l_filetest.gno | 8 ----- .../others/comparison_0m_filetest.gno | 8 ----- .../others/comparison_0n_filetest.gno | 14 -------- .../others/comparison_0z_filetest.gno | 11 ------ .../others/comparison_1a_filetest.gno | 23 ------------ .../others/comparison_2_filetest.gno | 36 ------------------- .../others/comparison_3_filetest.gno | 28 --------------- .../others/comparison_3a_filetest.gno | 24 ------------- .../others/comparison_3b_filetest.gno | 26 -------------- .../others/comparison_3c_filetest.gno | 25 ------------- .../others/comparison_3d_filetest.gno | 35 ------------------ .../others/comparison_3e_filetest.gno | 35 ------------------ .../others/comparison_3f_filetest.gno | 30 ---------------- .../others/comparison_3g_filetest.gno | 30 ---------------- .../others/comparison_3h_filetest.gno | 14 -------- .../others/comparison_3i_filetest.gno | 10 ------ .../others/comparison_3j_filetest.gno | 24 ------------- .../others/comparison_3k_filetest.gno | 12 ------- .../others/comparison_3l_filetest.gno | 11 ------ .../others/comparison_4_filetest.gno | 16 --------- .../others/comparison_5_filetest.gno | 15 -------- .../others/comparison_6_filetest.gno | 11 ------ .../others/comparison_6a_filetest.gno | 10 ------ .../others/comparison_7_filetest.gno | 10 ------ gnovm/pkg/gnolang/preprocess.go | 10 +++--- gnovm/pkg/gnolang/types.go | 5 ++- .../tests/files/types/others/2d2_filetest.gno | 25 ------------- .../tests/files/types/others/2d_filetest.gno | 31 ---------------- .../tests/files/types/others/2e_filetest.gno | 31 ---------------- .../tests/files/types/others/2f_filetest.gno | 31 ---------------- .../tests/files/types/others/2g_filetest.gno | 24 ------------- .../tests/files/types/others/2h_filetest.gno | 12 ------- .../tests/files/types/others/2i_filetest.gno | 8 ----- .../tests/files/types/others/2j_filetest.gno | 32 ----------------- .../tests/files/types/others/2k_filetest.gno | 27 -------------- .../tests/files/types/others/2l_filetest.gno | 24 ------------- .../types/others/comparison_0_filetest.gno | 27 -------------- .../types/others/comparison_0a_filetest.gno | 29 --------------- .../types/others/comparison_0b_filetest.gno | 29 --------------- .../types/others/comparison_0c_filetest.gno | 25 ------------- .../types/others/comparison_0d_filetest.gno | 25 ------------- .../types/others/comparison_0e_filetest.gno | 25 ------------- .../types/others/comparison_0f_filetest.gno | 25 ------------- .../types/others/comparison_0g_filetest.gno | 25 ------------- .../types/others/comparison_0h_filetest.gno | 10 ------ .../types/others/comparison_0i_filetest.gno | 8 ----- .../types/others/comparison_0j_filetest.gno | 8 ----- .../types/others/comparison_0k_filetest.gno | 8 ----- .../types/others/comparison_0l_filetest.gno | 8 ----- .../types/others/comparison_0m_filetest.gno | 8 ----- .../types/others/comparison_0n_filetest.gno | 14 -------- .../types/others/comparison_0z_filetest.gno | 11 ------ .../types/others/comparison_1a_filetest.gno | 23 ------------ .../types/others/comparison_2_filetest.gno | 36 ------------------- .../types/others/comparison_3_filetest.gno | 28 --------------- .../types/others/comparison_3a_filetest.gno | 24 ------------- .../types/others/comparison_3b_filetest.gno | 26 -------------- .../types/others/comparison_3c_filetest.gno | 25 ------------- .../types/others/comparison_3d_filetest.gno | 35 ------------------ .../types/others/comparison_3e_filetest.gno | 35 ------------------ .../types/others/comparison_3f_filetest.gno | 30 ---------------- .../types/others/comparison_3g_filetest.gno | 30 ---------------- .../types/others/comparison_3h_filetest.gno | 14 -------- .../types/others/comparison_3i_filetest.gno | 10 ------ .../types/others/comparison_3j_filetest.gno | 24 ------------- .../types/others/comparison_3k_filetest.gno | 12 ------- .../types/others/comparison_3l_filetest.gno | 11 ------ .../types/others/comparison_4_filetest.gno | 16 --------- .../types/others/comparison_5_filetest.gno | 15 -------- .../types/others/comparison_6_filetest.gno | 11 ------ .../types/others/comparison_6a_filetest.gno | 10 ------ .../types/others/comparison_7_filetest.gno | 10 ------ .../files/types/{others => readme}/README.md | 3 +- 87 files changed, 12 insertions(+), 1726 deletions(-) delete mode 100644 examples/gno.land/p/demo/challenge/0c2_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/2d_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0a_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0b_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0c_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0d_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0e_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0f_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0g_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0h_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0i_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0j_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0k_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0l_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0m_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0n_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_0z_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_1a_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_2_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3a_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3b_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3c_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3d_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3e_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3f_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3g_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3h_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3i_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3j_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3k_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_3l_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_4_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_5_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_6_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_6a_filetest.gno delete mode 100644 examples/gno.land/p/demo/challenge/others/comparison_7_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2d2_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2d_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2e_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2f_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2g_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2h_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2i_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2j_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2k_filetest.gno delete mode 100644 gnovm/tests/files/types/others/2l_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0a_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0b_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0c_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0d_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0e_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0f_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0g_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0h_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0i_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0j_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0k_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0l_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0m_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0n_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_0z_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_1a_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_2_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3a_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3b_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3c_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3d_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3e_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3f_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3g_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3h_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3i_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3j_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3k_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_3l_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_4_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_5_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_6_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_6a_filetest.gno delete mode 100644 gnovm/tests/files/types/others/comparison_7_filetest.gno rename gnovm/tests/files/types/{others => readme}/README.md (99%) diff --git a/examples/gno.land/p/demo/challenge/0c2_filetest.gno b/examples/gno.land/p/demo/challenge/0c2_filetest.gno deleted file mode 100644 index 19010b53804..00000000000 --- a/examples/gno.land/p/demo/challenge/0c2_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is typed const, right is untyped const -// NOTE: overflow -func main() { - if Error(1) == 128 { // note, this would overflow as expected - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/0c2_filetest.gno:16: bigint overflows target kind diff --git a/examples/gno.land/p/demo/challenge/others/2d_filetest.gno b/examples/gno.land/p/demo/challenge/others/2d_filetest.gno deleted file mode 100644 index 62d952adae4..00000000000 --- a/examples/gno.land/p/demo/challenge/others/2d_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, check + -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 + e2) -} - -// Error: -// main/gno.land/p/demo/challenge/2d_filetest.gno:27: + should have operand number or string, while have: main.E diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0_filetest.gno deleted file mode 100644 index 939f5f9c46b..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// left is typed const, right is not const -// compile pass since both conform to same interface -func main() { - if Error(0) == errCmp { // both conform same interface, compile pass, runtime evaluation not equal - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0a_filetest.gno deleted file mode 100644 index 67a0439dcca..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0a_filetest.gno +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, both typed, compile fail -func main() { - if Error1(0) == Error2(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0a_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0b_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0b_filetest.gno deleted file mode 100644 index 76b7c0bd46f..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0b_filetest.gno +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - if Error1(0) != Error2(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0b_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0c_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0c_filetest.gno deleted file mode 100644 index 27d63abceab..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0c_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) + Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0c_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0d_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0d_filetest.gno deleted file mode 100644 index f6598c1a69b..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0d_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) - Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0d_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0e_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0e_filetest.gno deleted file mode 100644 index b908906c6b6..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0e_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) * Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0e_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0f_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0f_filetest.gno deleted file mode 100644 index b5fc715f6bc..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0f_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) / Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0f_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0g_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0g_filetest.gno deleted file mode 100644 index 9f04d0d800a..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0g_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) % Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0g_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0h_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0h_filetest.gno deleted file mode 100644 index ab9827f79cc..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0h_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 0 - b := 1 - println(a & b) -} - -// Output: -// 0 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0i_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0i_filetest.gno deleted file mode 100644 index 297af6dcd25..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0i_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(0 & 1) -} - -// Output: -// 0 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0j_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0j_filetest.gno deleted file mode 100644 index 2c398df9a3d..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0j_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) & int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0j_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0k_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0k_filetest.gno deleted file mode 100644 index 3b0572e7dfc..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0k_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) | int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0k_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0l_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0l_filetest.gno deleted file mode 100644 index 378b1f5084f..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0l_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) ^ int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0l_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0m_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0m_filetest.gno deleted file mode 100644 index 1e28fef5014..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0m_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) &^ int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0m_filetest.gno:4: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0n_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0n_filetest.gno deleted file mode 100644 index 319bd102ef5..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0n_filetest.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -func main() { - println(int(0) & int(1)) - println(int(0) | int(1)) - println(int(0) ^ int(1)) - println(int(0) &^ int(1)) -} - -// Output: -// 0 -// 1 -// 1 -// 0 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_0z_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_0z_filetest.gno deleted file mode 100644 index 20a609fabfe..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_0z_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// both not const -func main() { - a := 0 - b := "hi" - println(a & b) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0z_filetest.gno:7: cannot use int as string diff --git a/examples/gno.land/p/demo/challenge/others/comparison_1a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_1a_filetest.gno deleted file mode 100644 index 7d2740709a5..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_1a_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, left is untyped -func main() { - if 1 == Error(1) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// what the firetruck? diff --git a/examples/gno.land/p/demo/challenge/others/comparison_2_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_2_filetest.gno deleted file mode 100644 index 30899d4d981..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_2_filetest.gno +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - if e1 == e2 { - println("what the firetruck?") - } else { - // supposed print this - println("something else") - } -} - -// Output: -// something else diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3_filetest.gno deleted file mode 100644 index ac21c5b6bf5..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - if Error1(0) == Error2(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3a_filetest.gno deleted file mode 100644 index 53fe7b61bbd..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3a_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - println(Error1(0) + Error2(0)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3a_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3b_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3b_filetest.gno deleted file mode 100644 index d3b0c363714..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3b_filetest.gno +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - e1 := Error1(0) - e2 := Error2(0) - e1 += e2 -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3b_filetest.gno:22: mismatch type for Assign diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3c_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3c_filetest.gno deleted file mode 100644 index 0862b3f3d3e..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3c_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - e1 = Error2(0) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3c_filetest.gno:21: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3d_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3d_filetest.gno deleted file mode 100644 index c6dd8c1cfd5..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3d_filetest.gno +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error3 int64 - -func (e Error3) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - - e1, e2 = 0, 0 - - println(e1, e2) -} - -// Output: -// error: 0 error: 0 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3e_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3e_filetest.gno deleted file mode 100644 index cf4799deae5..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3e_filetest.gno +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error3 int64 - -func (e Error3) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - - e1, e2 = 0, Error3(0) - - println(e1, e2) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3e_filetest.gno:29: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3f_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3f_filetest.gno deleted file mode 100644 index 4690ead2607..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3f_filetest.gno +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - var a int = 0 - - e1, e2 = a, 0 - - println(e1, e2) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3f_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3g_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3g_filetest.gno deleted file mode 100644 index 819be76c281..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3g_filetest.gno +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - var b int32 = 0 - - e1, e2 = 0, b - - println(e1, e2) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3g_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3h_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3h_filetest.gno deleted file mode 100644 index ebb546282cc..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3h_filetest.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -func main() { - - var a int = 0 - var i int32 = 1 - a += i - - println(a) - -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3h_filetest.gno:7: mismatch type for Assign diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3i_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3i_filetest.gno deleted file mode 100644 index a8e8a2f47ef..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3i_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - var a int = 0 - a += 1 - println(a) -} - -// Output: -// 1 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3j_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3j_filetest.gno deleted file mode 100644 index 4b135e1b239..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3j_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -func main() { - var a int = 1 - a -= 1 - println(a) //0 - - a += 1 - a *= 2 - println(a) //2 - - a /= 2 - println(a) //1 - - a += 2 //3 - a %= 2 //1 - println(a) -} - -// Output: -// 0 -// 2 -// 1 -// 1 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3k_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3k_filetest.gno deleted file mode 100644 index 9ccbc1b795a..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3k_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -func main() { - a := 6 // a is 6 (binary 110) - b := 3 // b is 3 (binary 011) - a &= b // Now a is 2 (binary 010) - - println(a) -} - -// Output: -// 2 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_3l_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_3l_filetest.gno deleted file mode 100644 index c903dc1b440..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_3l_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -func main() { - a := 6 - b := "3" - a &= b // Error: mismatched types int and string - println(a) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3l_filetest.gno:6: mismatch type for Assign, in case: a, b = x, y diff --git a/examples/gno.land/p/demo/challenge/others/comparison_4_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_4_filetest.gno deleted file mode 100644 index c09475f2a01..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_4_filetest.gno +++ /dev/null @@ -1,16 +0,0 @@ -package main - -var a int = 0 -var b int64 = 0 - -func main() { - // suppose compile fail - if a == b { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_4_filetest.gno:8: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_5_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_5_filetest.gno deleted file mode 100644 index c2cb3eb6472..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_5_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -var a int = 0 -var b bool = false - -func main() { - if a == b { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_5_filetest.gno:7: cannot use int as bool diff --git a/examples/gno.land/p/demo/challenge/others/comparison_6_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_6_filetest.gno deleted file mode 100644 index db0f0e6e86f..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_6_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -var a int = 0 -var b int64 = 1 - -func main() { - println(a + b) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_6_filetest.gno:7: cannot use int as int64 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_6a_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_6a_filetest.gno deleted file mode 100644 index a106f1acb78..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_6a_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - var b int64 = 1 - r := 0 + b // const - println(r) -} - -// Output: -// 1 diff --git a/examples/gno.land/p/demo/challenge/others/comparison_7_filetest.gno b/examples/gno.land/p/demo/challenge/others/comparison_7_filetest.gno deleted file mode 100644 index f435f587ca8..00000000000 --- a/examples/gno.land/p/demo/challenge/others/comparison_7_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 0 - var b int64 = 0 - println(a == b) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_7_filetest.gno:6: cannot use int as int64 diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cf449575788..66de3244c13 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2439,8 +2439,10 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { // here we should check too, e.g. primitive to declared type is assignable - if _, ok := t.(*NativeType); !ok { // not native type - debugPP.Println("ConstExpr is not nativeType, go check") + // TODO: file why we need this, regular check with native skipped + // TODO, it's reasonable for gno is a superset of go type, like bigint + if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno + debugPP.Println("x is ConstExpr, not nativeType, go check") checkConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) @@ -2595,7 +2597,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt - debugPP.Printf("check op: %v for Expressions \n", op) + debugPP.Printf("check op: %v \n", op) if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2613,7 +2615,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool case SHL, SHR: // TODO: right should be numeric default: - // Note: others no check, assign will be check in assignable + // Note: readme no check, assign will be check in assignable } } } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 3aa5ffc042e..9e45cb89a5d 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2231,7 +2231,7 @@ func KindOf(t Type) Kind { // TODO: document what class of problems its for. // One of them can be nil, and this lets uninitialized primitives -// and others serve as empty values. See doOpAdd() +// and readme serve as empty values. See doOpAdd() // usage: if debug { assertSameTypes() } func assertSameTypes(lt, rt Type) { if lt == nil && rt == nil { @@ -2389,6 +2389,7 @@ func comparable(t Type) (bool, string) { // case 3. dt is interface, xt satisfied dt // case 4. general convert, for composite types check func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { + debugPP.Printf("assignable, xt: %v, dt:%v, autoNative: %t \n", xt, dt, autoNative) // case3 // if xt or dt is empty interface, assignable // if no empty interface, then check if xt satisfied dt @@ -2684,6 +2685,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *NativeType: if !autoNative { + debugPP.Printf("native type, xt.TypeID: %v, cdt.TypeID: %v \n", xt.TypeID(), cdt.TypeID()) if xt.TypeID() == cdt.TypeID() { return // ok } @@ -2695,6 +2697,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { if gno2GoTypeMatches(xt, cdt.Type) { return // ok } + debugPP.Println("gno2Go type not match") } default: panic(fmt.Sprintf( diff --git a/gnovm/tests/files/types/others/2d2_filetest.gno b/gnovm/tests/files/types/others/2d2_filetest.gno deleted file mode 100644 index 63525588d3a..00000000000 --- a/gnovm/tests/files/types/others/2d2_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const, check + -func main() { - println(Error1(0) + Error2(0)) -} - -// Error: -// main/gno.land/p/demo/challenge/2d2_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/2d_filetest.gno b/gnovm/tests/files/types/others/2d_filetest.gno deleted file mode 100644 index 62d952adae4..00000000000 --- a/gnovm/tests/files/types/others/2d_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, check + -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 + e2) -} - -// Error: -// main/gno.land/p/demo/challenge/2d_filetest.gno:27: + should have operand number or string, while have: main.E diff --git a/gnovm/tests/files/types/others/2e_filetest.gno b/gnovm/tests/files/types/others/2e_filetest.gno deleted file mode 100644 index c7cbe4bc290..00000000000 --- a/gnovm/tests/files/types/others/2e_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, check + -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 - e2) -} - -// Error: -// main/gno.land/p/demo/challenge/2e_filetest.gno:27: - should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2f_filetest.gno b/gnovm/tests/files/types/others/2f_filetest.gno deleted file mode 100644 index 5b476552c40..00000000000 --- a/gnovm/tests/files/types/others/2f_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, check + -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 * e2) -} - -// Error: -// main/gno.land/p/demo/challenge/2f_filetest.gno:27: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2g_filetest.gno b/gnovm/tests/files/types/others/2g_filetest.gno deleted file mode 100644 index bcfef66acf2..00000000000 --- a/gnovm/tests/files/types/others/2g_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, check + -func main() { - var e1 E = Error1(0) - println(e1 * 0) -} - -// Error: -// main/gno.land/p/demo/challenge/2g_filetest.gno:20: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2h_filetest.gno b/gnovm/tests/files/types/others/2h_filetest.gno deleted file mode 100644 index 9486642a29f..00000000000 --- a/gnovm/tests/files/types/others/2h_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -// TODO: result still incorrect, should be decimal -func main() { - println(1.0 * 0) - println(1.0 * int(0)) - -} - -// Output: -// 0 -// 0 diff --git a/gnovm/tests/files/types/others/2i_filetest.gno b/gnovm/tests/files/types/others/2i_filetest.gno deleted file mode 100644 index b8bfcd9395e..00000000000 --- a/gnovm/tests/files/types/others/2i_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(float32(1.0) * int(0)) -} - -// Error: -// main/gno.land/p/demo/challenge/2i_filetest.gno:4: cannot use float32 as int diff --git a/gnovm/tests/files/types/others/2j_filetest.gno b/gnovm/tests/files/types/others/2j_filetest.gno deleted file mode 100644 index 0b3c5f992e9..00000000000 --- a/gnovm/tests/files/types/others/2j_filetest.gno +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 * e2) - println(int(0) * float32(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/2j_filetest.gno:27: * should have operand number, while have: main.E diff --git a/gnovm/tests/files/types/others/2k_filetest.gno b/gnovm/tests/files/types/others/2k_filetest.gno deleted file mode 100644 index 4e398c6b566..00000000000 --- a/gnovm/tests/files/types/others/2k_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// div -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 / e2) -} - -// Error: -// main/gno.land/p/demo/challenge/2k_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/2l_filetest.gno b/gnovm/tests/files/types/others/2l_filetest.gno deleted file mode 100644 index ac5d3132669..00000000000 --- a/gnovm/tests/files/types/others/2l_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - println(Error1(0) / Error2(0)) -} - -// Error: -// main/gno.land/p/demo/challenge/2l_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0_filetest.gno b/gnovm/tests/files/types/others/comparison_0_filetest.gno deleted file mode 100644 index 939f5f9c46b..00000000000 --- a/gnovm/tests/files/types/others/comparison_0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// left is typed const, right is not const -// compile pass since both conform to same interface -func main() { - if Error(0) == errCmp { // both conform same interface, compile pass, runtime evaluation not equal - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/others/comparison_0a_filetest.gno b/gnovm/tests/files/types/others/comparison_0a_filetest.gno deleted file mode 100644 index 67a0439dcca..00000000000 --- a/gnovm/tests/files/types/others/comparison_0a_filetest.gno +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, both typed, compile fail -func main() { - if Error1(0) == Error2(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0a_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0b_filetest.gno b/gnovm/tests/files/types/others/comparison_0b_filetest.gno deleted file mode 100644 index 76b7c0bd46f..00000000000 --- a/gnovm/tests/files/types/others/comparison_0b_filetest.gno +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - if Error1(0) != Error2(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0b_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0c_filetest.gno b/gnovm/tests/files/types/others/comparison_0c_filetest.gno deleted file mode 100644 index 27d63abceab..00000000000 --- a/gnovm/tests/files/types/others/comparison_0c_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) + Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0c_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0d_filetest.gno b/gnovm/tests/files/types/others/comparison_0d_filetest.gno deleted file mode 100644 index f6598c1a69b..00000000000 --- a/gnovm/tests/files/types/others/comparison_0d_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) - Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0d_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0e_filetest.gno b/gnovm/tests/files/types/others/comparison_0e_filetest.gno deleted file mode 100644 index b908906c6b6..00000000000 --- a/gnovm/tests/files/types/others/comparison_0e_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) * Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0e_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0f_filetest.gno b/gnovm/tests/files/types/others/comparison_0f_filetest.gno deleted file mode 100644 index b5fc715f6bc..00000000000 --- a/gnovm/tests/files/types/others/comparison_0f_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) / Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0f_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0g_filetest.gno b/gnovm/tests/files/types/others/comparison_0g_filetest.gno deleted file mode 100644 index 9f04d0d800a..00000000000 --- a/gnovm/tests/files/types/others/comparison_0g_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, compile fail -func main() { - println(Error1(0) % Error2(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0g_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_0h_filetest.gno b/gnovm/tests/files/types/others/comparison_0h_filetest.gno deleted file mode 100644 index ab9827f79cc..00000000000 --- a/gnovm/tests/files/types/others/comparison_0h_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 0 - b := 1 - println(a & b) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/others/comparison_0i_filetest.gno b/gnovm/tests/files/types/others/comparison_0i_filetest.gno deleted file mode 100644 index 297af6dcd25..00000000000 --- a/gnovm/tests/files/types/others/comparison_0i_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(0 & 1) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/others/comparison_0j_filetest.gno b/gnovm/tests/files/types/others/comparison_0j_filetest.gno deleted file mode 100644 index 2c398df9a3d..00000000000 --- a/gnovm/tests/files/types/others/comparison_0j_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) & int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0j_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0k_filetest.gno b/gnovm/tests/files/types/others/comparison_0k_filetest.gno deleted file mode 100644 index 3b0572e7dfc..00000000000 --- a/gnovm/tests/files/types/others/comparison_0k_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) | int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0k_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0l_filetest.gno b/gnovm/tests/files/types/others/comparison_0l_filetest.gno deleted file mode 100644 index 378b1f5084f..00000000000 --- a/gnovm/tests/files/types/others/comparison_0l_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) ^ int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0l_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0m_filetest.gno b/gnovm/tests/files/types/others/comparison_0m_filetest.gno deleted file mode 100644 index 1e28fef5014..00000000000 --- a/gnovm/tests/files/types/others/comparison_0m_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) &^ int64(1)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0m_filetest.gno:4: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_0n_filetest.gno b/gnovm/tests/files/types/others/comparison_0n_filetest.gno deleted file mode 100644 index 319bd102ef5..00000000000 --- a/gnovm/tests/files/types/others/comparison_0n_filetest.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -func main() { - println(int(0) & int(1)) - println(int(0) | int(1)) - println(int(0) ^ int(1)) - println(int(0) &^ int(1)) -} - -// Output: -// 0 -// 1 -// 1 -// 0 diff --git a/gnovm/tests/files/types/others/comparison_0z_filetest.gno b/gnovm/tests/files/types/others/comparison_0z_filetest.gno deleted file mode 100644 index 20a609fabfe..00000000000 --- a/gnovm/tests/files/types/others/comparison_0z_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// both not const -func main() { - a := 0 - b := "hi" - println(a & b) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_0z_filetest.gno:7: cannot use int as string diff --git a/gnovm/tests/files/types/others/comparison_1a_filetest.gno b/gnovm/tests/files/types/others/comparison_1a_filetest.gno deleted file mode 100644 index 7d2740709a5..00000000000 --- a/gnovm/tests/files/types/others/comparison_1a_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is const, right is const, left is untyped -func main() { - if 1 == Error(1) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// what the firetruck? diff --git a/gnovm/tests/files/types/others/comparison_2_filetest.gno b/gnovm/tests/files/types/others/comparison_2_filetest.gno deleted file mode 100644 index 30899d4d981..00000000000 --- a/gnovm/tests/files/types/others/comparison_2_filetest.gno +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - if e1 == e2 { - println("what the firetruck?") - } else { - // supposed print this - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/others/comparison_3_filetest.gno b/gnovm/tests/files/types/others/comparison_3_filetest.gno deleted file mode 100644 index ac21c5b6bf5..00000000000 --- a/gnovm/tests/files/types/others/comparison_3_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - if Error1(0) == Error2(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_3a_filetest.gno b/gnovm/tests/files/types/others/comparison_3a_filetest.gno deleted file mode 100644 index 53fe7b61bbd..00000000000 --- a/gnovm/tests/files/types/others/comparison_3a_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - println(Error1(0) + Error2(0)) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3a_filetest.gno:20: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/others/comparison_3b_filetest.gno b/gnovm/tests/files/types/others/comparison_3b_filetest.gno deleted file mode 100644 index d3b0c363714..00000000000 --- a/gnovm/tests/files/types/others/comparison_3b_filetest.gno +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - e1 := Error1(0) - e2 := Error2(0) - e1 += e2 -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3b_filetest.gno:22: mismatch type for Assign diff --git a/gnovm/tests/files/types/others/comparison_3c_filetest.gno b/gnovm/tests/files/types/others/comparison_3c_filetest.gno deleted file mode 100644 index 0862b3f3d3e..00000000000 --- a/gnovm/tests/files/types/others/comparison_3c_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - e1 = Error2(0) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3c_filetest.gno:21: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3d_filetest.gno b/gnovm/tests/files/types/others/comparison_3d_filetest.gno deleted file mode 100644 index c6dd8c1cfd5..00000000000 --- a/gnovm/tests/files/types/others/comparison_3d_filetest.gno +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error3 int64 - -func (e Error3) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - - e1, e2 = 0, 0 - - println(e1, e2) -} - -// Output: -// error: 0 error: 0 diff --git a/gnovm/tests/files/types/others/comparison_3e_filetest.gno b/gnovm/tests/files/types/others/comparison_3e_filetest.gno deleted file mode 100644 index cf4799deae5..00000000000 --- a/gnovm/tests/files/types/others/comparison_3e_filetest.gno +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error3 int64 - -func (e Error3) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - - e1, e2 = 0, Error3(0) - - println(e1, e2) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3e_filetest.gno:29: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3f_filetest.gno b/gnovm/tests/files/types/others/comparison_3f_filetest.gno deleted file mode 100644 index 4690ead2607..00000000000 --- a/gnovm/tests/files/types/others/comparison_3f_filetest.gno +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - var a int = 0 - - e1, e2 = a, 0 - - println(e1, e2) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3f_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3g_filetest.gno b/gnovm/tests/files/types/others/comparison_3g_filetest.gno deleted file mode 100644 index 819be76c281..00000000000 --- a/gnovm/tests/files/types/others/comparison_3g_filetest.gno +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 - var e2 Error2 - var b int32 = 0 - - e1, e2 = 0, b - - println(e1, e2) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3g_filetest.gno:24: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_3h_filetest.gno b/gnovm/tests/files/types/others/comparison_3h_filetest.gno deleted file mode 100644 index ebb546282cc..00000000000 --- a/gnovm/tests/files/types/others/comparison_3h_filetest.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -func main() { - - var a int = 0 - var i int32 = 1 - a += i - - println(a) - -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3h_filetest.gno:7: mismatch type for Assign diff --git a/gnovm/tests/files/types/others/comparison_3i_filetest.gno b/gnovm/tests/files/types/others/comparison_3i_filetest.gno deleted file mode 100644 index a8e8a2f47ef..00000000000 --- a/gnovm/tests/files/types/others/comparison_3i_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - var a int = 0 - a += 1 - println(a) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/others/comparison_3j_filetest.gno b/gnovm/tests/files/types/others/comparison_3j_filetest.gno deleted file mode 100644 index 4b135e1b239..00000000000 --- a/gnovm/tests/files/types/others/comparison_3j_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -func main() { - var a int = 1 - a -= 1 - println(a) //0 - - a += 1 - a *= 2 - println(a) //2 - - a /= 2 - println(a) //1 - - a += 2 //3 - a %= 2 //1 - println(a) -} - -// Output: -// 0 -// 2 -// 1 -// 1 diff --git a/gnovm/tests/files/types/others/comparison_3k_filetest.gno b/gnovm/tests/files/types/others/comparison_3k_filetest.gno deleted file mode 100644 index 9ccbc1b795a..00000000000 --- a/gnovm/tests/files/types/others/comparison_3k_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -func main() { - a := 6 // a is 6 (binary 110) - b := 3 // b is 3 (binary 011) - a &= b // Now a is 2 (binary 010) - - println(a) -} - -// Output: -// 2 diff --git a/gnovm/tests/files/types/others/comparison_3l_filetest.gno b/gnovm/tests/files/types/others/comparison_3l_filetest.gno deleted file mode 100644 index c903dc1b440..00000000000 --- a/gnovm/tests/files/types/others/comparison_3l_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -func main() { - a := 6 - b := "3" - a &= b // Error: mismatched types int and string - println(a) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_3l_filetest.gno:6: mismatch type for Assign, in case: a, b = x, y diff --git a/gnovm/tests/files/types/others/comparison_4_filetest.gno b/gnovm/tests/files/types/others/comparison_4_filetest.gno deleted file mode 100644 index c09475f2a01..00000000000 --- a/gnovm/tests/files/types/others/comparison_4_filetest.gno +++ /dev/null @@ -1,16 +0,0 @@ -package main - -var a int = 0 -var b int64 = 0 - -func main() { - // suppose compile fail - if a == b { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_4_filetest.gno:8: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_5_filetest.gno b/gnovm/tests/files/types/others/comparison_5_filetest.gno deleted file mode 100644 index c2cb3eb6472..00000000000 --- a/gnovm/tests/files/types/others/comparison_5_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -var a int = 0 -var b bool = false - -func main() { - if a == b { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_5_filetest.gno:7: cannot use int as bool diff --git a/gnovm/tests/files/types/others/comparison_6_filetest.gno b/gnovm/tests/files/types/others/comparison_6_filetest.gno deleted file mode 100644 index db0f0e6e86f..00000000000 --- a/gnovm/tests/files/types/others/comparison_6_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -var a int = 0 -var b int64 = 1 - -func main() { - println(a + b) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_6_filetest.gno:7: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/comparison_6a_filetest.gno b/gnovm/tests/files/types/others/comparison_6a_filetest.gno deleted file mode 100644 index a106f1acb78..00000000000 --- a/gnovm/tests/files/types/others/comparison_6a_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - var b int64 = 1 - r := 0 + b // const - println(r) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/others/comparison_7_filetest.gno b/gnovm/tests/files/types/others/comparison_7_filetest.gno deleted file mode 100644 index f435f587ca8..00000000000 --- a/gnovm/tests/files/types/others/comparison_7_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 0 - var b int64 = 0 - println(a == b) -} - -// Error: -// main/gno.land/p/demo/challenge/comparison_7_filetest.gno:6: cannot use int as int64 diff --git a/gnovm/tests/files/types/others/README.md b/gnovm/tests/files/types/readme/README.md similarity index 99% rename from gnovm/tests/files/types/others/README.md rename to gnovm/tests/files/types/readme/README.md index 7decd02594d..1f1e9f49767 100644 --- a/gnovm/tests/files/types/others/README.md +++ b/gnovm/tests/files/types/readme/README.md @@ -8,10 +8,11 @@ Context: - Flow: + explain const + binaryExpression/unaryExpression check comparison: From d6000c53319ed2ebda8829bc6a9190de2ac0edbc Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Dec 2023 18:01:30 +0800 Subject: [PATCH 019/193] fixup --- gno.land/Makefile | 5 +++++ gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/tests/files/types/23a4_filetest.gno | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gno.land/Makefile b/gno.land/Makefile index 29c192e9987..e8b385e454b 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -36,6 +36,11 @@ fclean: clean clean: rm -rf build + +.PHONY: reset +reset: install clean build + gnoland start + .PHONY: lint lint: $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint run --config ../.github/golangci.yml ./... diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 86b3cc8a4b2..7e3992559e6 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -901,7 +901,7 @@ func gno2GoType(t Type) reflect.Type { // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). -// This is called when autoNative is true in checkTypeConvertable(). +// This is called when autoNative is true in checkConvertable(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index e2ad0063909..9baf33630a7 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x140003b1c20 +// 0x140007053f0 From 812e64dcec5ac82924fe3cbb4d14bfef9f77fa63 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Dec 2023 22:10:15 +0800 Subject: [PATCH 020/193] fixup --- gnovm/pkg/gnolang/op_binary.go | 4 +-- gnovm/pkg/gnolang/preprocess.go | 3 ++- gnovm/pkg/gnolang/types.go | 5 ++-- gnovm/tests/files/types/0f2a_filetest.gno | 29 ++++++++++++++++++++ gnovm/tests/files/types/23a4_filetest.gno | 2 +- gnovm/tests/files/types/readme/README.md | 32 +++++++++++++++++++++++ 6 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 gnovm/tests/files/types/0f2a_filetest.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 7a8f28e3157..8cda5748351 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -85,7 +85,7 @@ func (m *Machine) doOpEql() { var res bool // TODO: this should be in preprocess too // TODO: only assert here - if isComparableIdentical(lv.T, rv.T) { + if isArithTypeIdentical(lv.T, rv.T) { res = isEql(m.Store, lv, rv) } else { res = false @@ -112,7 +112,7 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - if isComparableIdentical(lv.T, rv.T) { + if isArithTypeIdentical(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { res = true diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 66de3244c13..a2809c0382d 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2608,9 +2608,10 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: // if both typed if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if !isComparableIdentical(xt, dt) { + if !isArithTypeIdentical(xt, dt) { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } + debugPP.Println("typed and identical as comparable") } case SHL, SHR: // TODO: right should be numeric diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 9e45cb89a5d..e6ca292fb77 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2261,8 +2261,8 @@ func assertSameTypes(lt, rt Type) { // check with untyped excluded, it's used by checkOp and op_binary // both typed(original typed, or be typed in runtime), or one is nil, or data byte // only for comparable types -func isComparableIdentical(lt, rt Type) bool { - debugPP.Printf("check isComparableIdentical, lt: %v, rt: %v \n", lt, rt) +func isArithTypeIdentical(lt, rt Type) bool { + debugPP.Printf("check isArithTypeIdentical, lt: %v, rt: %v \n", lt, rt) debugPP.Println("is lt data byte: ", isDataByte(lt)) debugPP.Println("is rt data byte: ", isDataByte(rt)) @@ -2878,6 +2878,7 @@ func fillEmbeddedName(ft *FieldType) { ft.Embedded = true } +// TODO: empty interface? refer to assignable func IsImplementedBy(it Type, ot Type) bool { switch cbt := baseOf(it).(type) { case *InterfaceType: diff --git a/gnovm/tests/files/types/0f2a_filetest.gno b/gnovm/tests/files/types/0f2a_filetest.gno new file mode 100644 index 00000000000..169e30a3bab --- /dev/null +++ b/gnovm/tests/files/types/0f2a_filetest.gno @@ -0,0 +1,29 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// typed +var errCmp error = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + const e Error = Error(0) // typed const + if e == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index 9baf33630a7..d01344d7e1a 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x140007053f0 +// 0x140002cab80 diff --git a/gnovm/tests/files/types/readme/README.md b/gnovm/tests/files/types/readme/README.md index 1f1e9f49767..5456c425542 100644 --- a/gnovm/tests/files/types/readme/README.md +++ b/gnovm/tests/files/types/readme/README.md @@ -1,7 +1,39 @@ Context: + 1. regular type mix check missing + + `package main + // both typed(different) const + func main() { + println(int(1) == int8(1)) + } + + // Error: + // main/files/types/0a0_filetest.gno:5: invalid operation: mismatched types int8 and int + ` + + this is for arith and comparable operators + + specical case: bigInt to gonative time.Month. skipped + mix of numeric types + + 2. regular opertors check missing + + binary + comparable + arith + + unary + + inc + + 2. unamed to named conversion missed + + + + comparable special case From fe948bbf1ed2e511feaea75885c05e8e733ee6a7 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Dec 2023 23:02:41 +0800 Subject: [PATCH 021/193] doc --- gnovm/tests/files/types/readme/README.md | 138 +++++++++++++++++++---- 1 file changed, 113 insertions(+), 25 deletions(-) diff --git a/gnovm/tests/files/types/readme/README.md b/gnovm/tests/files/types/readme/README.md index 5456c425542..2fb0249c9d8 100644 --- a/gnovm/tests/files/types/readme/README.md +++ b/gnovm/tests/files/types/readme/README.md @@ -1,53 +1,134 @@ Context: - 1. regular type mix check missing +The problem is from []... - `package main - // both typed(different) const - func main() { - println(int(1) == int8(1)) - } - // Error: - // main/files/types/0a0_filetest.gno:5: invalid operation: mismatched types int8 and int - ` +`package main - this is for arith and comparable operators +import ( +"errors" +"strconv" +) - specical case: bigInt to gonative time.Month. skipped - - mix of numeric types +type Error int64 +func (e Error) Error() string { +return "error: " + strconv.Itoa(int(e)) +} - 2. regular opertors check missing +var errCmp = errors.New("XXXX") - binary - comparable - arith +// specil case: +// one is interface +func main() { +if Error(1) == errCmp { +println("what the firetruck?") +} else { +println("something else") +} +}` - unary - inc - 2. unamed to named conversion missed +first,why this compiles? the reason for this is Error(1) satisfies interface of error, which indicates Error(1) can be assigned to errCmp, Error(1) and errCmp is comparable. +"lhs is assignable to rhs, or vice versa", according to spec. + +But it gives out incorrect result. in the code above, it should give out :// something else +but gives out: what the firetruck? + +The cause for this is about type check, in the case, the Error(1) and errCmp is both mistakenly treated as int64, which +is the underlying type if Error(1), the value of LHS after evaluation is 1 and the RHS is 0, so the == check will give false. +as a simple prove, if you check this: Error(0) = errCmp, the result will be true. + +In the right way, the LHS and RHS has different underlying type, so the result should be false. + +It's a corner of the iceberg after some more digging: + +Type mix check missing + +`// both typed(different) const +func main() { +println(int(1) == int8(1)) +} + +in this case, it should not compile for the mismatch of type, but it works(as unexpected). +the reason for this is the missing of a regular type check, the type is cast forcibly while it should not。 + + +Operators check missing or incorrect +`package main + +// one untyped const, one typed const +func main() { +println(1 / "a") +} + +// Error: +// main/files/types/4b2_filetest.gno:5: operator / not defined on: string` +it should give out this error, but gives ... + +The reason for this is in golang, binary expression, unary expression, and INC/DEC stmt are close related to operators. e.g. for ADD, a + b, a and b must be both numericOrString, + for Sub, a - b, where a and b must be both numeric. + + The current situation is there check around operators happens in runtime, while they should be executed in preprocess stage. + this non-trivial as for performance, we want these check happens in compile time - - comparable +3.unamed to named conversion missed - special case +`package main +type word uint +type nat []word +// receiver +func (n nat) add() bool { +return true +} +func Gen() nat { +n := []word{0} +return n +} + +// mapLit +func main() { +r := Gen() +switch r.(type) { +case nat: +println("nat") +println(r.add()) +default: +println("should not happen") +} +} + +// Output: +// nat +// true` + +unamed (composite) literals should be converted to named implicitly in preprocess time. + Flow: + checkOp for binary expr, unary expr and inc/dec stmt + comparable, == != + + arith + - ... + isNumericOrString + + checkOperand for special case, in / and %, divisor should not be zero. + + regular type check for const, with nativeType excluded + regular type check for others, check assignable + + + - explain const binaryExpression/unaryExpression check comparison: - assignableTo(type), LHS or RHS is assignable to the other isIdentical primitive, struct, map, ... @@ -194,6 +275,13 @@ TODOs: // TODO: preCheck->Convert->postCheck, all in `checkOrConvertType` + this is for arith and comparable operators + + specical case: bigInt to gonative time.Month. skipped + + mix of numeric types + + NOTE: // in 13f1, indicates that, in preCheck, From 52d8221b9402f9812dcccdc41bf20855bfea24cd Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 11:48:06 +0800 Subject: [PATCH 022/193] more test --- gnovm/pkg/gnolang/preprocess.go | 4 +- gnovm/pkg/gnolang/types.go | 15 ++----- gnovm/tests/files/types/14a0_filetest.gno | 9 ++++ gnovm/tests/files/types/14a1_filetest.gno | 25 +++++++++++ gnovm/tests/files/types/14b0_filetest.gno | 13 ++++++ gnovm/tests/files/types/14b1_filetest.gno | 13 ++++++ .../{21a1_filetest.gno => 14b2_filetest.gno} | 7 +-- gnovm/tests/files/types/14d0_filetest.gno | 12 +++++ gnovm/tests/files/types/14e0_filetest.gno | 28 ++++++++++++ gnovm/tests/files/types/14e1_filetest.gno | 20 +++++++++ gnovm/tests/files/types/14e_filetest.gno | 21 +++++++++ gnovm/tests/files/types/14f0_filetest.gno | 25 +++++++++++ gnovm/tests/files/types/14f1_filetest.gno | 22 +++++++++ gnovm/tests/files/types/14f2_filetest.gno | 45 +++++++++++++++++++ gnovm/tests/files/types/14f3_filetest.gno | 32 +++++++++++++ gnovm/tests/files/types/14f4_filetest.gno | 9 ++++ gnovm/tests/files/types/14f5_filetest.gno | 10 +++++ gnovm/tests/files/types/15a0_filetest.gno | 8 ++++ gnovm/tests/files/types/21a0_filetest.gno | 10 ----- gnovm/tests/files/types/22a0a_filetest.gno | 19 ++++++++ gnovm/tests/files/types/22a12a_filetest.gno | 24 ++++++++++ gnovm/tests/files/types/22a12b_filetest.gno | 22 +++++++++ gnovm/tests/files/types/22a12c_filetest.gno | 24 ++++++++++ ...22a14_filetest.gno => 22a14_filetest.gnoa} | 0 gnovm/tests/files/types/22a17h_filetest.gno | 1 - gnovm/tests/files/types/22a17i_filetest.gno | 1 - gnovm/tests/files/types/23a4_filetest.gno | 2 +- 27 files changed, 392 insertions(+), 29 deletions(-) create mode 100644 gnovm/tests/files/types/14a0_filetest.gno create mode 100644 gnovm/tests/files/types/14a1_filetest.gno create mode 100644 gnovm/tests/files/types/14b0_filetest.gno create mode 100644 gnovm/tests/files/types/14b1_filetest.gno rename gnovm/tests/files/types/{21a1_filetest.gno => 14b2_filetest.gno} (53%) create mode 100644 gnovm/tests/files/types/14d0_filetest.gno create mode 100644 gnovm/tests/files/types/14e0_filetest.gno create mode 100644 gnovm/tests/files/types/14e1_filetest.gno create mode 100644 gnovm/tests/files/types/14e_filetest.gno create mode 100644 gnovm/tests/files/types/14f0_filetest.gno create mode 100644 gnovm/tests/files/types/14f1_filetest.gno create mode 100644 gnovm/tests/files/types/14f2_filetest.gno create mode 100644 gnovm/tests/files/types/14f3_filetest.gno create mode 100644 gnovm/tests/files/types/14f4_filetest.gno create mode 100644 gnovm/tests/files/types/14f5_filetest.gno create mode 100644 gnovm/tests/files/types/15a0_filetest.gno delete mode 100644 gnovm/tests/files/types/21a0_filetest.gno create mode 100644 gnovm/tests/files/types/22a0a_filetest.gno create mode 100644 gnovm/tests/files/types/22a12a_filetest.gno create mode 100644 gnovm/tests/files/types/22a12b_filetest.gno create mode 100644 gnovm/tests/files/types/22a12c_filetest.gno rename gnovm/tests/files/types/{22a14_filetest.gno => 22a14_filetest.gnoa} (100%) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a2809c0382d..867951ce007 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2456,7 +2456,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { - conversionNeeded = checkConvertable(xt, t, autoNative) + if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno + conversionNeeded = checkConvertable(xt, t, autoNative) + } } if isUntyped(xt) { if t == nil { diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index e6ca292fb77..29d711d4bac 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2262,42 +2262,33 @@ func assertSameTypes(lt, rt Type) { // both typed(original typed, or be typed in runtime), or one is nil, or data byte // only for comparable types func isArithTypeIdentical(lt, rt Type) bool { - debugPP.Printf("check isArithTypeIdentical, lt: %v, rt: %v \n", lt, rt) - debugPP.Println("is lt data byte: ", isDataByte(lt)) - debugPP.Println("is rt data byte: ", isDataByte(rt)) - + debugPP.Printf("check isArithTypeIdentical, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID if lpt, ok := lt.(*PointerType); ok { - debugPP.Println("lt is pointer type, typeid: ", lpt.typeid) if isDataByte(lpt.Elt) { - debugPP.Println("got data byte, left") + debugPP.Println("lt is pointer type and base type is data byte") return true } } if rpt, ok := rt.(*PointerType); ok { - debugPP.Println("rt is pointer type, typeid: ", rpt.typeid) if isDataByte(rpt.Elt) { - debugPP.Println("got data byte, right") + debugPP.Println("rt is pointer type and base type is data byte") return true } } if isDataByte(lt) || isDataByte(rt) { - debugPP.Println("one is date byte") return true } // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { - debugPP.Println("both type nil") // both are nil. } else if lt == nil || rt == nil { - debugPP.Println("one type nil") // one is nil. see function comment. } else if lt.Kind() == rt.Kind() && isDataByte(lt) { - debugPP.Println("both date byte") // left is databyte of same kind, // specifically for assignments. // TODO: make another function diff --git a/gnovm/tests/files/types/14a0_filetest.gno b/gnovm/tests/files/types/14a0_filetest.gno new file mode 100644 index 00000000000..a725f856db6 --- /dev/null +++ b/gnovm/tests/files/types/14a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + int(0) -= int8(1) +} + +// Error: +// main/files/types/14a0_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/14a1_filetest.gno b/gnovm/tests/files/types/14a1_filetest.gno new file mode 100644 index 00000000000..02c7c952268 --- /dev/null +++ b/gnovm/tests/files/types/14a1_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + Error1(0) -= Error2(0) +} + +// Error: +// main/files/types/14a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/14b0_filetest.gno b/gnovm/tests/files/types/14b0_filetest.gno new file mode 100644 index 00000000000..3ca7463828f --- /dev/null +++ b/gnovm/tests/files/types/14b0_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + r := 1 + r -= Error(1) + println(r) +} + +// Error: +// main/files/types/14b0_filetest.gno:8: invalid operation: mismatched types int and main.Error diff --git a/gnovm/tests/files/types/14b1_filetest.gno b/gnovm/tests/files/types/14b1_filetest.gno new file mode 100644 index 00000000000..60daad58194 --- /dev/null +++ b/gnovm/tests/files/types/14b1_filetest.gno @@ -0,0 +1,13 @@ +package main + +type Error int8 + +// one untyped const, one typed const +func main() { + r := Error(1) + r -= 1 + println(r) +} + +// Output: +// (0 main.Error) diff --git a/gnovm/tests/files/types/21a1_filetest.gno b/gnovm/tests/files/types/14b2_filetest.gno similarity index 53% rename from gnovm/tests/files/types/21a1_filetest.gno rename to gnovm/tests/files/types/14b2_filetest.gno index 12486ff0ded..c351754d256 100644 --- a/gnovm/tests/files/types/21a1_filetest.gno +++ b/gnovm/tests/files/types/14b2_filetest.gno @@ -1,9 +1,10 @@ package main func main() { - a := int8(1) - println(a) + r := 1 + r -= 'a' + println(r) } // Output: -// 1 +// -96 diff --git a/gnovm/tests/files/types/14d0_filetest.gno b/gnovm/tests/files/types/14d0_filetest.gno new file mode 100644 index 00000000000..e830d7d269d --- /dev/null +++ b/gnovm/tests/files/types/14d0_filetest.gno @@ -0,0 +1,12 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + r := 1.0 + r -= 1 + println(r) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/14e0_filetest.gno b/gnovm/tests/files/types/14e0_filetest.gno new file mode 100644 index 00000000000..0b9d0baa96e --- /dev/null +++ b/gnovm/tests/files/types/14e0_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error2 = Error2(0) + e1 -= e2 + println(e1) +} + +// Error: +// main/files/types/14e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/14e1_filetest.gno b/gnovm/tests/files/types/14e1_filetest.gno new file mode 100644 index 00000000000..a351bb7af8b --- /dev/null +++ b/gnovm/tests/files/types/14e1_filetest.gno @@ -0,0 +1,20 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 = Error1(0) + e1 -= 1 + println(e1) +} + +// Output: +// error: -1 diff --git a/gnovm/tests/files/types/14e_filetest.gno b/gnovm/tests/files/types/14e_filetest.gno new file mode 100644 index 00000000000..1696128422e --- /dev/null +++ b/gnovm/tests/files/types/14e_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +func main() { + var e1 Error1 = Error1(0) + var e2 int64 = 1 + e1 -= Error1(e2) + println(e1) +} + +// Output: +// error: -1 diff --git a/gnovm/tests/files/types/14f0_filetest.gno b/gnovm/tests/files/types/14f0_filetest.gno new file mode 100644 index 00000000000..bc09ab42871 --- /dev/null +++ b/gnovm/tests/files/types/14f0_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + r := 1 + r -= errCmp + println(r) +} + +// Error: +// main/files/types/14f0_filetest.gno:20: invalid operation: mismatched types int and .uverse.error diff --git a/gnovm/tests/files/types/14f1_filetest.gno b/gnovm/tests/files/types/14f1_filetest.gno new file mode 100644 index 00000000000..6cebbd719aa --- /dev/null +++ b/gnovm/tests/files/types/14f1_filetest.gno @@ -0,0 +1,22 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +func main() { + r := Error(0) + r -= errCmp // in case of this, should panic mismatch on operand, except RHS is untyped +} + +// Error: +// main/files/types/14f1_filetest.gno:18: invalid operation: mismatched types main.Error and .uverse.error diff --git a/gnovm/tests/files/types/14f2_filetest.gno b/gnovm/tests/files/types/14f2_filetest.gno new file mode 100644 index 00000000000..abfb343706b --- /dev/null +++ b/gnovm/tests/files/types/14f2_filetest.gno @@ -0,0 +1,45 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// NOTE: in golang, this won't compile by type mismatch +// code like this : won't compile by : "invalid operation: operator + not defined on err1 (variable of type error)" +// which indicates that golang will check type match first, and operand legality secondly +// that is, for op =+, first check type match, second check operand +// in our condition, should check convert first, after that, check operand? + +//package main +// +//import ( +//"errors" +//) +// +//var err1 = errors.New("XXXX") +//var err2 = errors.New("XXXX") +// +//func main() { +// err1 += err2 +// println(err1) +//} + +// specil case: +// one is interface +func main() { + r := Error(0) + errCmp -= r + println(errCmp) +} + +// Error: +// main/files/types/14f2_filetest.gno:40: operator -= not defined on: .uverse.error diff --git a/gnovm/tests/files/types/14f3_filetest.gno b/gnovm/tests/files/types/14f3_filetest.gno new file mode 100644 index 00000000000..71eea3f78f8 --- /dev/null +++ b/gnovm/tests/files/types/14f3_filetest.gno @@ -0,0 +1,32 @@ +package main + +import ( + "strconv" +) + +type E interface { + Error() string +} + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, and both interface +func main() { + var e1 E = Error1(0) + var e2 E = Error2(0) + e1 -= e2 + println(e1) +} + +// Error: +// main/files/types/14f3_filetest.gno:27: operator -= not defined on: main.E \ No newline at end of file diff --git a/gnovm/tests/files/types/14f4_filetest.gno b/gnovm/tests/files/types/14f4_filetest.gno new file mode 100644 index 00000000000..35558501b46 --- /dev/null +++ b/gnovm/tests/files/types/14f4_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both not const, and both interface +func main() { + "a" -= "b" +} + +// Error: +// main/files/types/14f4_filetest.gno:5: operator -= not defined on: string diff --git a/gnovm/tests/files/types/14f5_filetest.gno b/gnovm/tests/files/types/14f5_filetest.gno new file mode 100644 index 00000000000..facc612de18 --- /dev/null +++ b/gnovm/tests/files/types/14f5_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both not const, and both interface +func main() { + var a string = "a" + a -= "b" +} + +// Error: +// main/files/types/14f5_filetest.gno:6: operator -= not defined on: string diff --git a/gnovm/tests/files/types/15a0_filetest.gno b/gnovm/tests/files/types/15a0_filetest.gno new file mode 100644 index 00000000000..1d57c84a818 --- /dev/null +++ b/gnovm/tests/files/types/15a0_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 % 1.0 +} + +// Error: +// main/files/types/15a0_filetest.gno:4: operator % not defined on: bigdec diff --git a/gnovm/tests/files/types/21a0_filetest.gno b/gnovm/tests/files/types/21a0_filetest.gno deleted file mode 100644 index 0a661854805..00000000000 --- a/gnovm/tests/files/types/21a0_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - var a int - a = int8(1) - println(a) -} - -// Error: -// main/files/types/21a0_filetest.gno:5: cannot use int8 as int diff --git a/gnovm/tests/files/types/22a0a_filetest.gno b/gnovm/tests/files/types/22a0a_filetest.gno new file mode 100644 index 00000000000..f257b822f8e --- /dev/null +++ b/gnovm/tests/files/types/22a0a_filetest.gno @@ -0,0 +1,19 @@ +package main + +type Int int8 + +func (i Int) Inc() Int { + i++ + return i +} + +// right is typed const, can not use as its correspondence declared type +func main() { + var a Int + a = Int(int8(0)) + a = a.Inc() + println(a) +} + +// Output: +// (1 main.Int) diff --git a/gnovm/tests/files/types/22a12a_filetest.gno b/gnovm/tests/files/types/22a12a_filetest.gno new file mode 100644 index 00000000000..7c757ff6347 --- /dev/null +++ b/gnovm/tests/files/types/22a12a_filetest.gno @@ -0,0 +1,24 @@ +package main + +import "fmt" + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + abs = []word{0} // unname-Composit to named DeclaredTypes + println(abs.add()) + + var s []word + s = abs + fmt.Printf("%T", s) +} + +// Output: +// true +// []uint diff --git a/gnovm/tests/files/types/22a12b_filetest.gno b/gnovm/tests/files/types/22a12b_filetest.gno new file mode 100644 index 00000000000..ab2b0d969ad --- /dev/null +++ b/gnovm/tests/files/types/22a12b_filetest.gno @@ -0,0 +1,22 @@ +package main + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +// TODO: improve err, like :s.add undefined (type []word has no field or method add) +func main() { + var abs nat + abs = []word{0} // unname-Composit to named DeclaredTypes + println(abs.add()) + + var s []word + s = abs + println(s.add()) +} + +// Error: +// main/files/types/22a12b_filetest.gno:18: unexpected selector expression type *gnolang.SliceType diff --git a/gnovm/tests/files/types/22a12c_filetest.gno b/gnovm/tests/files/types/22a12c_filetest.gno new file mode 100644 index 00000000000..e14c582a659 --- /dev/null +++ b/gnovm/tests/files/types/22a12c_filetest.gno @@ -0,0 +1,24 @@ +package main + +import "fmt" + +type word uint +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + abs = []word{0} // unname-Composit to named DeclaredTypes + fmt.Printf("%T \n", abs) + + var s []word + s = abs + fmt.Printf("%T \n", s) +} + +// Output: +// []uint +// []uint diff --git a/gnovm/tests/files/types/22a14_filetest.gno b/gnovm/tests/files/types/22a14_filetest.gnoa similarity index 100% rename from gnovm/tests/files/types/22a14_filetest.gno rename to gnovm/tests/files/types/22a14_filetest.gnoa diff --git a/gnovm/tests/files/types/22a17h_filetest.gno b/gnovm/tests/files/types/22a17h_filetest.gno index 6acba35183c..9b7f2c80a64 100644 --- a/gnovm/tests/files/types/22a17h_filetest.gno +++ b/gnovm/tests/files/types/22a17h_filetest.gno @@ -22,7 +22,6 @@ func main() { println(r.add()) default: println("should not happen") - } } diff --git a/gnovm/tests/files/types/22a17i_filetest.gno b/gnovm/tests/files/types/22a17i_filetest.gno index 973cd8c0995..e9c4c395a77 100644 --- a/gnovm/tests/files/types/22a17i_filetest.gno +++ b/gnovm/tests/files/types/22a17i_filetest.gno @@ -18,7 +18,6 @@ func Gen2() interface{} { return n } -// mapLit func main() { r := Gen() switch t := r.(type) { diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index d01344d7e1a..47e65bc30fd 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x140002cab80 +// 0x14000190ae0 From ec6fd0ee5cc00317b94a344eea4ff289445cbeb0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 11:49:23 +0800 Subject: [PATCH 023/193] readme --- gnovm/tests/files/types/readme/README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/gnovm/tests/files/types/readme/README.md b/gnovm/tests/files/types/readme/README.md index 2fb0249c9d8..a906b907e91 100644 --- a/gnovm/tests/files/types/readme/README.md +++ b/gnovm/tests/files/types/readme/README.md @@ -42,7 +42,7 @@ as a simple prove, if you check this: Error(0) = errCmp, the result will be true In the right way, the LHS and RHS has different underlying type, so the result should be false. -It's a corner of the iceberg after some more digging: +Deeper analysis: Type mix check missing @@ -111,18 +111,23 @@ println("should not happen") unamed (composite) literals should be converted to named implicitly in preprocess time. +To sums up, the solution is: + Flow: + regular type check for const, with some specific case whitelisted, e.g. array key, and nativeType excluded + checkOp for binary expr, unary expr and inc/dec stmt comparable, == != arith + - ... isNumericOrString - checkOperand for special case, in / and %, divisor should not be zero. + Note: this only check dt, - regular type check for const, with nativeType excluded - regular type check for others, check assignable + checkOperand for special case, in / and %, divisor should not be zero. + if check pass(or in cases with no Op to check), carry on checking if the corresponding side can be assigned to dt, throught assignable. + regular type check for others, check assignable. From cde9ed53cb46c91cac028540ea29944fa7e88876 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 15:10:50 +0800 Subject: [PATCH 024/193] fixup --- gnovm/pkg/gnolang/op_binary.go | 4 +-- gnovm/pkg/gnolang/preprocess.go | 20 ++++++----- gnovm/pkg/gnolang/types.go | 36 ++++++++++--------- .../{0a0_filetest.gno => 0a01_filetest.gno} | 2 +- gnovm/tests/files/types/0f20_filetest.gno | 5 ++- .../{0f31_filetest.gnoa => 0f31_filetest.gno} | 0 gnovm/tests/files/types/0f6_filetest.gno | 8 ----- gnovm/tests/files/types/18a2_filetest.gno | 2 +- gnovm/tests/files/types/22a12c_filetest.gno | 1 + gnovm/tests/files/types/22a17j_filetest.gno | 28 +++++++++++++++ gnovm/tests/files/types/23a4_filetest.gno | 2 +- gnovm/tests/files/types/6a0_filetest.gno | 2 +- gnovm/tests/files/types/6a1_filetest.gno | 2 +- gnovm/tests/files/types/6e0_filetest.gno | 2 +- gnovm/tests/files/types/7a0_filetest.gno | 2 +- gnovm/tests/files/types/7a1_filetest.gno | 2 +- gnovm/tests/files/types/7e0_filetest.gno | 2 +- gnovm/tests/files/types/8a0_filetest.gno | 2 +- gnovm/tests/files/types/8a1_filetest.gno | 2 +- gnovm/tests/files/types/8e0_filetest.gno | 2 +- gnovm/tests/files/types/9a0_filetest.gno | 2 +- gnovm/tests/files/types/9a1_filetest.gno | 2 +- gnovm/tests/files/types/9e0_filetest.gno | 2 +- 23 files changed, 79 insertions(+), 53 deletions(-) rename gnovm/tests/files/types/{0a0_filetest.gno => 0a01_filetest.gno} (60%) rename gnovm/tests/files/types/{0f31_filetest.gnoa => 0f31_filetest.gno} (100%) delete mode 100644 gnovm/tests/files/types/0f6_filetest.gno create mode 100644 gnovm/tests/files/types/22a17j_filetest.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 8cda5748351..9aae7629e74 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -85,7 +85,7 @@ func (m *Machine) doOpEql() { var res bool // TODO: this should be in preprocess too // TODO: only assert here - if isArithTypeIdentical(lv.T, rv.T) { + if isBinOperandTypeIdentical(lv.T, rv.T) { res = isEql(m.Store, lv, rv) } else { res = false @@ -112,7 +112,7 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) var res bool - if isArithTypeIdentical(lv.T, rv.T) { + if isBinOperandTypeIdentical(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { res = true diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 867951ce007..cc0c2e7452b 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -937,9 +937,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Right, lt, false) } } - //} else if rcx.T == nil { } else if rcx.T == nil { // RHS is nil - debugPP.Println("rcx.T == nil ") + debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest // convert n.Right to typed-nil type. checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) @@ -2456,9 +2455,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative xt := evalStaticTypeOf(store, last, *x) var conversionNeeded bool if t != nil { - if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno - conversionNeeded = checkConvertable(xt, t, autoNative) - } + conversionNeeded = checkConvertable(xt, t, autoNative) } if isUntyped(xt) { if t == nil { @@ -2606,12 +2603,17 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool } } if op != ILLEGAL { - switch op { - case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN: + switch op { // TODO: how about BAND, BOR, etc? + case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BAND_NOT, BAND_NOT_ASSIGN, XOR, XOR_ASSIGN, LAND, LOR: // if both typed if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if !isArithTypeIdentical(xt, dt) { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + //if !isBinOperandTypeIdentical(xt, dt) { + // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + //} + if xt != nil && dt != nil { + if xt.TypeID() != dt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + } } debugPP.Println("typed and identical as comparable") } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 29d711d4bac..044bd91127a 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1126,8 +1126,8 @@ func (it *InterfaceType) FindEmbeddedFieldType(callerPath string, n Name, m map[ // TODO: optimize somehow. func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { debugPP.Printf("isImplementedBy, it %v, ot:%v \n", it, ot) - // empty interface{} - //if iot, ok := baseOf(ot).(*InterfaceType); ok { + //// empty interface{} + //if iot, ok := ot.(*InterfaceType); ok { // if iot.IsEmptyInterface() { // return true // } @@ -2231,9 +2231,10 @@ func KindOf(t Type) Kind { // TODO: document what class of problems its for. // One of them can be nil, and this lets uninitialized primitives -// and readme serve as empty values. See doOpAdd() +// and others serve as empty values. See doOpAdd() // usage: if debug { assertSameTypes() } func assertSameTypes(lt, rt Type) { + debugPP.Println("assert same types") if lt == nil && rt == nil { // both are nil. } else if lt == nil || rt == nil { @@ -2250,6 +2251,7 @@ func assertSameTypes(lt, rt Type) { } else if lt.TypeID() == rt.TypeID() { // non-nil types are identical. } else { + panic("panic assertSameTypes") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -2258,11 +2260,12 @@ func assertSameTypes(lt, rt Type) { } } -// check with untyped excluded, it's used by checkOp and op_binary -// both typed(original typed, or be typed in runtime), or one is nil, or data byte -// only for comparable types -func isArithTypeIdentical(lt, rt Type) bool { - debugPP.Printf("check isArithTypeIdentical, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) +// both typed, or one is nil, or data byte(special case) +// only for comparable types for runtime, op_binary +// any implicit identical check is in preprocess stage and excluded from here +// TODO: a better name? +func isBinOperandTypeIdentical(lt, rt Type) bool { + debugPP.Printf("check isBinOperandTypeIdentical, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID if lpt, ok := lt.(*PointerType); ok { if isDataByte(lpt.Elt) { @@ -2270,18 +2273,15 @@ func isArithTypeIdentical(lt, rt Type) bool { return true } } - if rpt, ok := rt.(*PointerType); ok { if isDataByte(rpt.Elt) { debugPP.Println("rt is pointer type and base type is data byte") return true } } - if isDataByte(lt) || isDataByte(rt) { return true } - // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { // both are nil. @@ -2330,7 +2330,10 @@ func assertEqualityTypes(lt, rt Type) { } } -// t is the target type in convert process, check it firstly, then check if assignable +// NOTE: comparable is a more strict check than assertSameTypes, refer to 0f20_filetest.gno, +// which pass the later one, but is not comparable. +// The logic here is, when compare operators show, check if t is comparable, if yes, +// then check the corresponding type(the other side of the operator) is convertable to t. func comparable(t Type) (bool, string) { debugPP.Printf("check comparable, t is %v \n", t) // primitive is comparable @@ -2339,10 +2342,9 @@ func comparable(t Type) (bool, string) { debugPP.Println("primitive type, return true") return true, "" case *ArrayType: // NOTE: no recursive allowed - // TODO: check length? but that needs check after convert, indicates checkOp after convert? make more sense seems // TODO: check at least length here switch baseOf(ct.Elem()).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // TODO: nativeType? + case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? return true, "" default: return false, fmt.Sprintf("%v cannot be compared \n", ct) @@ -2374,11 +2376,13 @@ func comparable(t Type) (bool, string) { } } -// check if xt can be converted to dt, conversionNeeded indicate need convert from unnamed -> named +// check if xt can be converted to dt, conversionNeeded indicates further conversion needed from unnamed -> named // case 1. untyped const to typed const with same kind // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general convert, for composite types check +// XXX. the name of assignable should be considered, or convertable? +// they have same function but implies different application scenarios func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Printf("assignable, xt: %v, dt:%v, autoNative: %t \n", xt, dt, autoNative) // case3 @@ -2395,7 +2399,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok - } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6 + } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6_filetest.gno debugPP.Println("xt is empty interface: ", iot) if iot.IsEmptyInterface() { return // ok diff --git a/gnovm/tests/files/types/0a0_filetest.gno b/gnovm/tests/files/types/0a01_filetest.gno similarity index 60% rename from gnovm/tests/files/types/0a0_filetest.gno rename to gnovm/tests/files/types/0a01_filetest.gno index 24fbd6b7516..cbfe8aab0c7 100644 --- a/gnovm/tests/files/types/0a0_filetest.gno +++ b/gnovm/tests/files/types/0a01_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a0_filetest.gno:5: cannot use int as int8 +// main/files/types/0a01_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index 4219cf89244..69230cb58a5 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -5,10 +5,9 @@ type f func() bool var a [2]f var b [2]f -// TODO: review where it happens func main() { - println(a == nil) + println(a == nil) // rcx.T == nil } // Error: -// main/files/types/0f20_filetest.gno:10: [2]main.f cannot be compared +// main/files/types/0f20_filetest.gno:9: [2]main.f cannot be compared diff --git a/gnovm/tests/files/types/0f31_filetest.gnoa b/gnovm/tests/files/types/0f31_filetest.gno similarity index 100% rename from gnovm/tests/files/types/0f31_filetest.gnoa rename to gnovm/tests/files/types/0f31_filetest.gno diff --git a/gnovm/tests/files/types/0f6_filetest.gno b/gnovm/tests/files/types/0f6_filetest.gno deleted file mode 100644 index 501d54dce64..00000000000 --- a/gnovm/tests/files/types/0f6_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -// TODO: declared(unamed type) logic -type Error []string - -func main() { - -} diff --git a/gnovm/tests/files/types/18a2_filetest.gno b/gnovm/tests/files/types/18a2_filetest.gno index ef5970417c9..c6c825b1ac9 100644 --- a/gnovm/tests/files/types/18a2_filetest.gno +++ b/gnovm/tests/files/types/18a2_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/18a2_filetest.gno:5: cannot use int8 as int +// main/files/types/18a2_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/22a12c_filetest.gno b/gnovm/tests/files/types/22a12c_filetest.gno index e14c582a659..df2dc499c85 100644 --- a/gnovm/tests/files/types/22a12c_filetest.gno +++ b/gnovm/tests/files/types/22a12c_filetest.gno @@ -9,6 +9,7 @@ func (n nat) add() bool { return true } +// TODO: seems fmt prints the underlying type, this is another problem to fix. func main() { var abs nat abs = []word{0} // unname-Composit to named DeclaredTypes diff --git a/gnovm/tests/files/types/22a17j_filetest.gno b/gnovm/tests/files/types/22a17j_filetest.gno new file mode 100644 index 00000000000..507b5ca7051 --- /dev/null +++ b/gnovm/tests/files/types/22a17j_filetest.gno @@ -0,0 +1,28 @@ +package main + +import "fmt" + +type nat []int + +func main() { + + var a nat + a = []int{0} + b := []int{1} + + fmt.Printf("%v \n ", a) + fmt.Printf("%v \n ", b) + + a = nat{0} + b = a + + fmt.Printf("%v \n ", a) + fmt.Printf("%v \n ", b) + +} + +// Output: +// [0] +// [1] +// [0] +// [0] diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index 47e65bc30fd..830875a68e8 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x14000190ae0 +// 0x14001f42ac0 diff --git a/gnovm/tests/files/types/6a0_filetest.gno b/gnovm/tests/files/types/6a0_filetest.gno index 76ac2dcd4f9..6c90121daeb 100644 --- a/gnovm/tests/files/types/6a0_filetest.gno +++ b/gnovm/tests/files/types/6a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/6a0_filetest.gno:5: cannot use int as int8 +// main/files/types/6a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/6a1_filetest.gno b/gnovm/tests/files/types/6a1_filetest.gno index 81bfd16a3c5..b95f2cecf24 100644 --- a/gnovm/tests/files/types/6a1_filetest.gno +++ b/gnovm/tests/files/types/6a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/6a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/6a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/6e0_filetest.gno b/gnovm/tests/files/types/6e0_filetest.gno index 6a82079919e..a7d605ee834 100644 --- a/gnovm/tests/files/types/6e0_filetest.gno +++ b/gnovm/tests/files/types/6e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/6e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/6e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/7a0_filetest.gno b/gnovm/tests/files/types/7a0_filetest.gno index e20da0c8fe9..45a7cdf4bdc 100644 --- a/gnovm/tests/files/types/7a0_filetest.gno +++ b/gnovm/tests/files/types/7a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/7a0_filetest.gno:5: cannot use int as int8 +// main/files/types/7a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/7a1_filetest.gno b/gnovm/tests/files/types/7a1_filetest.gno index df1072fff7a..9fec5f4f466 100644 --- a/gnovm/tests/files/types/7a1_filetest.gno +++ b/gnovm/tests/files/types/7a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/7a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/7a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/7e0_filetest.gno b/gnovm/tests/files/types/7e0_filetest.gno index f3dbe2f08cc..699c6538fb2 100644 --- a/gnovm/tests/files/types/7e0_filetest.gno +++ b/gnovm/tests/files/types/7e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/7e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/7e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/8a0_filetest.gno b/gnovm/tests/files/types/8a0_filetest.gno index 27582c36122..0d58e905d7c 100644 --- a/gnovm/tests/files/types/8a0_filetest.gno +++ b/gnovm/tests/files/types/8a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/8a0_filetest.gno:5: cannot use int as int8 +// main/files/types/8a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/8a1_filetest.gno b/gnovm/tests/files/types/8a1_filetest.gno index c4e63ba9986..8d677c807cb 100644 --- a/gnovm/tests/files/types/8a1_filetest.gno +++ b/gnovm/tests/files/types/8a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/8a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/8a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/8e0_filetest.gno b/gnovm/tests/files/types/8e0_filetest.gno index 393c2d9be3d..b09844c2702 100644 --- a/gnovm/tests/files/types/8e0_filetest.gno +++ b/gnovm/tests/files/types/8e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/8e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/8e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/9a0_filetest.gno b/gnovm/tests/files/types/9a0_filetest.gno index 2abfadea84d..87701d56e40 100644 --- a/gnovm/tests/files/types/9a0_filetest.gno +++ b/gnovm/tests/files/types/9a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/9a0_filetest.gno:5: cannot use int as int8 +// main/files/types/9a0_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/9a1_filetest.gno b/gnovm/tests/files/types/9a1_filetest.gno index 2a426d60e53..842843852be 100644 --- a/gnovm/tests/files/types/9a1_filetest.gno +++ b/gnovm/tests/files/types/9a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/9a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/9a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 diff --git a/gnovm/tests/files/types/9e0_filetest.gno b/gnovm/tests/files/types/9e0_filetest.gno index 7f8d83a5f4e..e23ad2b37a5 100644 --- a/gnovm/tests/files/types/9e0_filetest.gno +++ b/gnovm/tests/files/types/9e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/9e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/9e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 From 80508da3714cbea0691e1657504d202958e6126a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 16:02:51 +0800 Subject: [PATCH 025/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 37 ++++++++--------------- gnovm/pkg/gnolang/types.go | 2 +- gnovm/tests/files/types/0a01_filetest.gno | 5 ++- gnovm/tests/files/types/0a0_filetest.gno | 9 ++++++ gnovm/tests/files/types/23a4_filetest.gno | 2 +- 5 files changed, 26 insertions(+), 29 deletions(-) create mode 100644 gnovm/tests/files/types/0a0_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cc0c2e7452b..94ee8965012 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -905,7 +905,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if baseOf(rt) != UintType { // convert n.Right to (gno) uint type. //checkOp(store, last, &n.Right, UintType, n.Op, true) - checkOrConvertType(store, last, &n.Right, UintType, false) + //checkOrConvertType(store, last, &n.Right, UintType, false) + convertConstType(store, last, &n.Right, UintType, false) // bypass check } else { // leave n.Left as is and baseOf(n.Right) as UintType. } @@ -938,7 +939,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil - debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest + debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest, if8_filetest // convert n.Right to typed-nil type. checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) @@ -1701,7 +1702,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Special case if shift assign <<= or >>=. // TODO: no need here, like index convert //checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) - checkOrConvertType(store, last, &n.Rhs[0], UintType, false) + //checkOrConvertType(store, last, &n.Rhs[0], UintType, false) + convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check + } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, // TODO: assert length @@ -2416,7 +2419,7 @@ func cmpSpecificity(t1, t2 Type) int { } } -// for special case of index conversion +// for special case to bypass check for typed -> typed conversion, e.g. array index conversion func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { debugPP.Printf("convertConstType, x: %v, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { @@ -2430,16 +2433,10 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() - -// TODO: NOTE, more about const, sometimes we convert it anyway, like uint8 -> int as index of an array -// TODO: but if it's bind to ops like +, type conversion should be checked -// TODO: this should be awareness at its origin func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { - // here we should check too, e.g. primitive to declared type is assignable - // TODO: file why we need this, regular check with native skipped - // TODO, it's reasonable for gno is a superset of go type, like bigint + // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno debugPP.Println("x is ConstExpr, not nativeType, go check") checkConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args @@ -2545,7 +2542,7 @@ func isComparison(op Word) bool { } } -// TODO: is x is necessary +// check operand types with operators func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool) { var xt Type if x != nil { // unaryExpr @@ -2578,11 +2575,9 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool // 2. comparable requires one is assignable to another // 3. handle nil if ok, code := comparable(dt); !ok { - debugPP.Printf("not comparable of dt :%v \n", dt) panic(code) } case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString - debugPP.Printf("L, G: %v \n", op) if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2596,20 +2591,16 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt - debugPP.Printf("check op: %v \n", op) if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } if op != ILLEGAL { - switch op { // TODO: how about BAND, BOR, etc? + switch op { case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BAND_NOT, BAND_NOT_ASSIGN, XOR, XOR_ASSIGN, LAND, LOR: // if both typed if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - //if !isBinOperandTypeIdentical(xt, dt) { - // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) - //} if xt != nil && dt != nil { if xt.TypeID() != dt.TypeID() { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) @@ -2618,9 +2609,8 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool debugPP.Println("typed and identical as comparable") } case SHL, SHR: - // TODO: right should be numeric default: - // Note: readme no check, assign will be check in assignable + // Note: others no check, assign will be check in assignable } } } @@ -2630,11 +2620,10 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. func checkConvertable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { - if xt == nil || dt == nil { // TODO: counter case? - debugPP.Println("xt or dt is nil") + if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno + debugPP.Println("checkConvertable, xt or dt is nil") return } - debugPP.Printf("checkConvertable, xt: %v, xt.Kind: %v, dt: %v, dt.Kind: %v, \n", xt, xt.Kind(), dt, dt.Kind()) return assignable(xt, dt, autoNative) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 044bd91127a..7ba9cc23730 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2384,7 +2384,7 @@ func comparable(t Type) (bool, string) { // XXX. the name of assignable should be considered, or convertable? // they have same function but implies different application scenarios func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { - debugPP.Printf("assignable, xt: %v, dt:%v, autoNative: %t \n", xt, dt, autoNative) + debugPP.Printf("assignable, xt: %v dt: %v \n", xt, dt) // case3 // if xt or dt is empty interface, assignable // if no empty interface, then check if xt satisfied dt diff --git a/gnovm/tests/files/types/0a01_filetest.gno b/gnovm/tests/files/types/0a01_filetest.gno index cbfe8aab0c7..dea72835ee3 100644 --- a/gnovm/tests/files/types/0a01_filetest.gno +++ b/gnovm/tests/files/types/0a01_filetest.gno @@ -1,9 +1,8 @@ package main -// both typed(different) const func main() { - println(int(1) == int8(1)) + println(nil == nil) } // Error: -// main/files/types/0a01_filetest.gno:5: cannot use int as int8 +// main/files/types/0a01_filetest.gno:4: is not comparable diff --git a/gnovm/tests/files/types/0a0_filetest.gno b/gnovm/tests/files/types/0a0_filetest.gno new file mode 100644 index 00000000000..24fbd6b7516 --- /dev/null +++ b/gnovm/tests/files/types/0a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) == int8(1)) +} + +// Error: +// main/files/types/0a0_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index 830875a68e8..819526bd179 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x14001f42ac0 +// 0x140039f0110 From 7af6623a9dd9a55748a60b0ebd74c70fb8d129eb Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 17:42:07 +0800 Subject: [PATCH 026/193] restore unwanted --- gno.land/Makefile | 21 +++-- gno.land/pkg/sdk/vm/keeper.go | 111 +++++++++++++++++++++++---- tm2/pkg/crypto/keys/client/addpkg.go | 15 +--- 3 files changed, 109 insertions(+), 38 deletions(-) diff --git a/gno.land/Makefile b/gno.land/Makefile index e8b385e454b..56908009b18 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -5,8 +5,16 @@ help: rundep=go run -modfile ../misc/devdeps/go.mod -.PHONY: gnoland.start -gnoland.start:; go run ./cmd/gnoland start +gnoland.start: + @#TODO: remove this makefile directive in a few weeks. + @echo "DEPRECATED: use 'start.gnoland' instead of 'gnoland.start'" + go run ./cmd/gnoland start + +.PHONY: start.gnoland +start.gnoland:; go run ./cmd/gnoland start + +.PHONY: start.gnoweb +start.gnoweb:; go run ./cmd/gnoweb .PHONY: build build: build.gnoland build.gnokey build.gnoweb build.gnofaucet build.gnotxsync build.genesis @@ -18,6 +26,9 @@ build.gnokey:; go build -o build/gnokey ./cmd/gnokey build.gnotxsync:; go build -o build/gnotxsync ./cmd/gnotxsync build.genesis:; go build -o build/genesis ./cmd/genesis +run.gnoland:; go run ./cmd/gnoland start +run.gnoweb:; go run ./cmd/gnoweb + .PHONY: install install: install.gnoland install.gnoweb install.gnofaucet install.gnokey install.gnotxsync install.genesis @@ -36,11 +47,6 @@ fclean: clean clean: rm -rf build - -.PHONY: reset -reset: install clean build - gnoland start - .PHONY: lint lint: $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint run --config ../.github/golangci.yml ./... @@ -63,4 +69,3 @@ _test.gnokey:; go test $(GOTEST_FLAGS) ./cmd/gnokey _test.pkgs:; go test $(GOTEST_FLAGS) ./pkg/... _test.pkgs.sync:; UPDATE_SCRIPTS=true go test $(GOTEST_FLAGS) ./pkg/... - diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index e5ef5c19fdd..b0ae2180c36 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -3,8 +3,10 @@ package vm // TODO: move most of the logic in ROOT/gno.land/... import ( + "bytes" "fmt" "os" + "regexp" "strings" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -27,6 +29,7 @@ const ( type VMKeeperI interface { AddPackage(ctx sdk.Context, msg MsgAddPackage) error Call(ctx sdk.Context, msg MsgCall) (res string, err error) + Run(ctx sdk.Context, msg MsgRun) (res string, err error) } var _ VMKeeperI = &VMKeeper{} @@ -128,6 +131,10 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } } +const ( + reReservedPath = `gno\.land/r/g[a-z0-9]+/run` +) + // AddPackage adds a package with given fileset. func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { creator := msg.Creator @@ -150,6 +157,11 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { if pv := store.GetPackage(pkgPath, false); pv != nil { return ErrInvalidPkgPath("package already exists: " + pkgPath) } + + if ok, _ := regexp.MatchString(reReservedPath, pkgPath); ok { + return ErrInvalidPkgPath("reserved package name: " + pkgPath) + } + // Pay deposit from creator. pkgAddr := gno.DerivePkgAddr(pkgPath) @@ -197,12 +209,12 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { pkgPath := msg.PkgPath // to import fnc := msg.Func - gnoStore := vm.getGnoStore(ctx) + store := vm.getGnoStore(ctx) // Get the package and function type. - pv := gnoStore.GetPackage(pkgPath, false) + pv := store.GetPackage(pkgPath, false) pl := gno.PackageNodeLocation(pkgPath) - pn := gnoStore.GetBlockNode(pl).(*gno.PackageNode) - ft := pn.GetStaticTypeOf(gnoStore, gno.Name(fnc)).(*gno.FuncType) + pn := store.GetBlockNode(pl).(*gno.PackageNode) + ft := pn.GetStaticTypeOf(store, gno.Name(fnc)).(*gno.FuncType) // Make main Package with imports. mpn := gno.NewPackageNode("main", "main", nil) mpn.Define("pkg", gno.TypedValue{T: &gno.PackageType{}, V: pv}) @@ -256,25 +268,16 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { gno.MachineOptions{ PkgPath: "", Output: os.Stdout, // XXX - Store: gnoStore, + Store: store, Context: msgCtx, - Alloc: gnoStore.GetAllocator(), + Alloc: store.GetAllocator(), MaxCycles: vm.maxCycles, }) m.SetActivePackage(mpv) defer func() { if r := recover(); r != nil { - switch ex := r.(type) { - case store.OutOfGasException: - log := fmt.Sprintf( - "out of gas in location: %v;", - ex.Descriptor) - err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s", - log, m.String()) - default: - err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s", - r, m.String()) - } + err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s\n", + r, m.String()) return } m.Release() @@ -291,6 +294,80 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { // TODO pay for gas? TODO see context? } +// Run executes arbitrary Gno code in the context of the caller's realm. +func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { + caller := msg.Caller + pkgAddr := caller + store := vm.getGnoStore(ctx) + send := msg.Send + memPkg := msg.Package + + // Validate arguments. + callerAcc := vm.acck.GetAccount(ctx, caller) + if callerAcc == nil { + return "", std.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", caller)) + } + if err := msg.Package.Validate(); err != nil { + return "", ErrInvalidPkgPath(err.Error()) + } + + // Send send-coins to pkg from caller. + err = vm.bank.SendCoins(ctx, caller, pkgAddr, send) + if err != nil { + return "", err + } + + // Parse and run the files, construct *PV. + msgCtx := stdlibs.ExecContext{ + ChainID: ctx.ChainID(), + Height: ctx.BlockHeight(), + Timestamp: ctx.BlockTime().Unix(), + Msg: msg, + OrigCaller: caller.Bech32(), + OrigSend: send, + OrigSendSpent: new(std.Coins), + OrigPkgAddr: pkgAddr.Bech32(), + Banker: NewSDKBanker(vm, ctx), + } + // Parse and run the files, construct *PV. + buf := new(bytes.Buffer) + m := gno.NewMachineWithOptions( + gno.MachineOptions{ + PkgPath: "", + Output: buf, + Store: store, + Alloc: store.GetAllocator(), + Context: msgCtx, + MaxCycles: vm.maxCycles, + }) + defer m.Release() + _, pv := m.RunMemPackage(memPkg, false) + ctx.Logger().Info("CPUCYCLES", "addpkg", m.Cycles) + + m2 := gno.NewMachineWithOptions( + gno.MachineOptions{ + PkgPath: "", + Output: buf, + Store: store, + Alloc: store.GetAllocator(), + Context: msgCtx, + MaxCycles: vm.maxCycles, + }) + m2.SetActivePackage(pv) + defer func() { + if r := recover(); r != nil { + err = errors.Wrap(fmt.Errorf("%v", r), "VM call panic: %v\n%s\n", + r, m2.String()) + return + } + m2.Release() + }() + m2.RunMain() + ctx.Logger().Info("CPUCYCLES call: ", m2.Cycles) + res = buf.String() + return res, nil +} + // QueryFuncs returns public facing function signatures. func (vm *VMKeeper) QueryFuncs(ctx sdk.Context, pkgPath string) (fsigs FunctionSignatures, err error) { store := vm.getGnoStore(ctx) diff --git a/tm2/pkg/crypto/keys/client/addpkg.go b/tm2/pkg/crypto/keys/client/addpkg.go index a13f9063fd9..5bbd3f08ad0 100644 --- a/tm2/pkg/crypto/keys/client/addpkg.go +++ b/tm2/pkg/crypto/keys/client/addpkg.go @@ -14,7 +14,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto/keys" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/std" - "strings" ) type addPkgCfg struct { @@ -209,10 +208,10 @@ func signAndBroadcast( return errors.Wrap(err, "broadcast tx") } if bres.CheckTx.IsErr() { - return errors.Wrap(bres.CheckTx.Error, "check transaction failed: errMsg: \n%s", indentString(bres.CheckTx.Log, " ")) + return errors.Wrap(bres.CheckTx.Error, "check transaction failed: log:%s", bres.CheckTx.Log) } if bres.DeliverTx.IsErr() { - return errors.Wrap(bres.DeliverTx.Error, "deliver transaction failed: errMsg: %s", bres.DeliverTx.Log) + return errors.Wrap(bres.DeliverTx.Error, "deliver transaction failed: log:%s", bres.DeliverTx.Log) } io.Println(string(bres.DeliverTx.Data)) io.Println("OK!") @@ -221,13 +220,3 @@ func signAndBroadcast( return nil } - -// indentString indents each line of a multi-line string. -func indentString(str, indent string) string { - var indentedLines []string - lines := strings.Split(str, "\n") - for _, line := range lines { - indentedLines = append(indentedLines, indent+line) - } - return strings.Join(indentedLines, "\n") -} From 55e6cc02c50603c633609886eb18837f39534cf9 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 17:51:47 +0800 Subject: [PATCH 027/193] restore --- gno.land/Makefile | 13 +++---------- gno.land/pkg/sdk/vm/keeper.go | 12 ++++++------ tm2/pkg/crypto/keys/client/addpkg.go | 8 ++++---- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/gno.land/Makefile b/gno.land/Makefile index 56908009b18..1297da393cb 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -5,16 +5,8 @@ help: rundep=go run -modfile ../misc/devdeps/go.mod -gnoland.start: - @#TODO: remove this makefile directive in a few weeks. - @echo "DEPRECATED: use 'start.gnoland' instead of 'gnoland.start'" - go run ./cmd/gnoland start - -.PHONY: start.gnoland -start.gnoland:; go run ./cmd/gnoland start - -.PHONY: start.gnoweb -start.gnoweb:; go run ./cmd/gnoweb +.PHONY: gnoland.start +gnoland.start:; go run ./cmd/gnoland start .PHONY: build build: build.gnoland build.gnokey build.gnoweb build.gnofaucet build.gnotxsync build.genesis @@ -69,3 +61,4 @@ _test.gnokey:; go test $(GOTEST_FLAGS) ./cmd/gnokey _test.pkgs:; go test $(GOTEST_FLAGS) ./pkg/... _test.pkgs.sync:; UPDATE_SCRIPTS=true go test $(GOTEST_FLAGS) ./pkg/... + diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index b0ae2180c36..90e64d6b32d 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -50,12 +50,12 @@ type VMKeeper struct { // NewVMKeeper returns a new VMKeeper. func NewVMKeeper( - baseKey store.StoreKey, - iavlKey store.StoreKey, - acck auth.AccountKeeper, - bank bank.BankKeeper, - stdlibsDir string, - maxCycles int64, + baseKey store.StoreKey, + iavlKey store.StoreKey, + acck auth.AccountKeeper, + bank bank.BankKeeper, + stdlibsDir string, + maxCycles int64, ) *VMKeeper { // TODO: create an Options struct to avoid too many constructor parameters vmk := &VMKeeper{ diff --git a/tm2/pkg/crypto/keys/client/addpkg.go b/tm2/pkg/crypto/keys/client/addpkg.go index 5bbd3f08ad0..5d40bf59d36 100644 --- a/tm2/pkg/crypto/keys/client/addpkg.go +++ b/tm2/pkg/crypto/keys/client/addpkg.go @@ -139,10 +139,10 @@ func execAddPkg(cfg *addPkgCfg, args []string, io commands.IO) error { } func signAndBroadcast( - cfg *makeTxCfg, - args []string, - tx std.Tx, - io commands.IO, + cfg *makeTxCfg, + args []string, + tx std.Tx, + io commands.IO, ) error { baseopts := cfg.rootCfg txopts := cfg From fa7f8d47e23bef333c98a174c14d47e9fc2708d6 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:11:05 +0800 Subject: [PATCH 028/193] restore --- ...persist_valids.gnoa => zpersist_valids.gno} | 0 tm2/pkg/sdk/baseapp.go | 18 ++++-------------- 2 files changed, 4 insertions(+), 14 deletions(-) rename gnovm/tests/files/{zpersist_valids.gnoa => zpersist_valids.gno} (100%) diff --git a/gnovm/tests/files/zpersist_valids.gnoa b/gnovm/tests/files/zpersist_valids.gno similarity index 100% rename from gnovm/tests/files/zpersist_valids.gnoa rename to gnovm/tests/files/zpersist_valids.gno diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index c42d21f1675..1d356f7ad65 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -653,15 +653,15 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res // stop execution and return on first failed message if !msgResult.IsOK() { msgLogs = append(msgLogs, - fmt.Sprintf("msg:%d,success:%v,events:%v,log start:------>\n%s<------end log", - i, false, events, indentString(msgResult.Log, " "))) + fmt.Sprintf("msg:%d,success:%v,log:%s,events:%v", + i, false, msgResult.Log, events)) err = msgResult.Error break } msgLogs = append(msgLogs, - fmt.Sprintf("msg:%d,success:%v,events:%v,log start:------>\n%s<------end log", - i, true, events, indentString(msgResult.Log, " "))) + fmt.Sprintf("msg:%d,success:%v,log:%s,events:%v", + i, true, msgResult.Log, events)) } result.Error = ABCIError(err) @@ -672,16 +672,6 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res return result } -// indentString indents each line of a multi-line string. -func indentString(str, indent string) string { - var indentedLines []string - lines := strings.Split(str, "\n") - for _, line := range lines { - indentedLines = append(indentedLines, indent+line) - } - return strings.Join(indentedLines, "\n") -} - // Returns the applications's deliverState if app is in RunTxModeDeliver, // otherwise it returns the application's checkstate. func (app *BaseApp) getState(mode RunTxMode) *state { From 6a31cb8a28a1823763f2d70d232a9adbbdff7ca9 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:13:13 +0800 Subject: [PATCH 029/193] restore --- tm2/pkg/crypto/keys/client/addpkg.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tm2/pkg/crypto/keys/client/addpkg.go b/tm2/pkg/crypto/keys/client/addpkg.go index 5d40bf59d36..5bbd3f08ad0 100644 --- a/tm2/pkg/crypto/keys/client/addpkg.go +++ b/tm2/pkg/crypto/keys/client/addpkg.go @@ -139,10 +139,10 @@ func execAddPkg(cfg *addPkgCfg, args []string, io commands.IO) error { } func signAndBroadcast( - cfg *makeTxCfg, - args []string, - tx std.Tx, - io commands.IO, + cfg *makeTxCfg, + args []string, + tx std.Tx, + io commands.IO, ) error { baseopts := cfg.rootCfg txopts := cfg From 0b095c32bc3ba8cf7abf58ea9ae75458cebd95dc Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:15:20 +0800 Subject: [PATCH 030/193] restore --- gno.land/Makefile | 1 - gno.land/pkg/sdk/vm/keeper.go | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/gno.land/Makefile b/gno.land/Makefile index 982063d155c..56908009b18 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -69,4 +69,3 @@ _test.gnokey:; go test $(GOTEST_FLAGS) ./cmd/gnokey _test.pkgs:; go test $(GOTEST_FLAGS) ./pkg/... _test.pkgs.sync:; UPDATE_SCRIPTS=true go test $(GOTEST_FLAGS) ./pkg/... - diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 90e64d6b32d..b0ae2180c36 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -50,12 +50,12 @@ type VMKeeper struct { // NewVMKeeper returns a new VMKeeper. func NewVMKeeper( - baseKey store.StoreKey, - iavlKey store.StoreKey, - acck auth.AccountKeeper, - bank bank.BankKeeper, - stdlibsDir string, - maxCycles int64, + baseKey store.StoreKey, + iavlKey store.StoreKey, + acck auth.AccountKeeper, + bank bank.BankKeeper, + stdlibsDir string, + maxCycles int64, ) *VMKeeper { // TODO: create an Options struct to avoid too many constructor parameters vmk := &VMKeeper{ From 34588a1a9710f1ee606aac696c377613c0bd5907 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:17:55 +0800 Subject: [PATCH 031/193] restore --- gno.land/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/gno.land/Makefile b/gno.land/Makefile index 56908009b18..e20c6e5daee 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -68,4 +68,3 @@ _test.gnoweb:; go test $(GOTEST_FLAGS) ./cmd/gnoweb _test.gnokey:; go test $(GOTEST_FLAGS) ./cmd/gnokey _test.pkgs:; go test $(GOTEST_FLAGS) ./pkg/... _test.pkgs.sync:; UPDATE_SCRIPTS=true go test $(GOTEST_FLAGS) ./pkg/... - From edc8c5b3a3726494c9c3638103be9ab4f2422767 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:18:39 +0800 Subject: [PATCH 032/193] restore --- gno.land/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gno.land/Makefile b/gno.land/Makefile index e20c6e5daee..982063d155c 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -68,3 +68,5 @@ _test.gnoweb:; go test $(GOTEST_FLAGS) ./cmd/gnoweb _test.gnokey:; go test $(GOTEST_FLAGS) ./cmd/gnokey _test.pkgs:; go test $(GOTEST_FLAGS) ./pkg/... _test.pkgs.sync:; UPDATE_SCRIPTS=true go test $(GOTEST_FLAGS) ./pkg/... + + From 1513d78a19feb964760320a813a4491a7f4b2118 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:20:51 +0800 Subject: [PATCH 033/193] restore --- gnovm/tests/files/{access2.gnoa => access2.gno} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename gnovm/tests/files/{access2.gnoa => access2.gno} (91%) diff --git a/gnovm/tests/files/access2.gnoa b/gnovm/tests/files/access2.gno similarity index 91% rename from gnovm/tests/files/access2.gnoa rename to gnovm/tests/files/access2.gno index 4c9eb952914..46b17136b54 100644 --- a/gnovm/tests/files/access2.gnoa +++ b/gnovm/tests/files/access2.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/access_test -package main +package access_test import ( "gno.land/p/demo/testutils" From 5dbf7f405d2adbe0a785af95f55b6e4a07a531c0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 18:26:37 +0800 Subject: [PATCH 034/193] sync --- gnovm/tests/files/{persist_map.gno.a => persist_map.gno} | 2 +- gnovm/tests/files/{stdlibs_stdlibs.gnoa => stdlibs_stdlibs.gno} | 2 +- gnovm/tests/files/zpersist_valids.gno | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename gnovm/tests/files/{persist_map.gno.a => persist_map.gno} (96%) rename gnovm/tests/files/{stdlibs_stdlibs.gnoa => stdlibs_stdlibs.gno} (94%) diff --git a/gnovm/tests/files/persist_map.gno.a b/gnovm/tests/files/persist_map.gno similarity index 96% rename from gnovm/tests/files/persist_map.gno.a rename to gnovm/tests/files/persist_map.gno index f062bf877ee..53a1ad80f77 100644 --- a/gnovm/tests/files/persist_map.gno.a +++ b/gnovm/tests/files/persist_map.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/demo/tests_test -package main +package tests_test var amap map[string]string = map[string]string{"a": "1"} diff --git a/gnovm/tests/files/stdlibs_stdlibs.gnoa b/gnovm/tests/files/stdlibs_stdlibs.gno similarity index 94% rename from gnovm/tests/files/stdlibs_stdlibs.gnoa rename to gnovm/tests/files/stdlibs_stdlibs.gno index fbbfcd82845..261e7fbe78c 100644 --- a/gnovm/tests/files/stdlibs_stdlibs.gnoa +++ b/gnovm/tests/files/stdlibs_stdlibs.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/test -package main +package test import "time" diff --git a/gnovm/tests/files/zpersist_valids.gno b/gnovm/tests/files/zpersist_valids.gno index 1095b1ae02b..2709a243adf 100644 --- a/gnovm/tests/files/zpersist_valids.gno +++ b/gnovm/tests/files/zpersist_valids.gno @@ -1,5 +1,5 @@ // PKGPATH: gno.land/r/demo/tests_test -package main +package tests_test type myStruct struct { A int From 96560565fa005041a5451094fb28c3db3c7b8d9a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 20:16:28 +0800 Subject: [PATCH 035/193] fix inc float --- gnovm/pkg/gnolang/preprocess.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 94ee8965012..cf2d8d94ecf 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -53,8 +53,8 @@ func init() { // Inc Dec stmt // NOTE: special case to be consistent with op_inc_dec, line3, no float support for now while go do. - IncDecStmtPredicates[INC] = isIntOrUint - IncDecStmtPredicates[DEC] = isIntOrUint + IncDecStmtPredicates[INC] = isNumeric + IncDecStmtPredicates[DEC] = isNumeric } // In the case of a *FileSet, some declaration steps have to happen From fa3acd094ca70f4eeb2a848d47ac5375f7d0bac1 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 20:17:14 +0800 Subject: [PATCH 036/193] fixup --- gnovm/tests/files/types/23a4_filetest.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index 819526bd179..8080efd64a3 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x140039f0110 +// 0x14002ad2220 From 068e368fdf6b04de0d3cf929b3f7dc71a84a8867 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 21:45:44 +0800 Subject: [PATCH 037/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 9 +++++++-- gnovm/tests/files/types/23a4_filetest.gno | 2 +- gnovm/tests/files/types/26a3_filetest.gno | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 gnovm/tests/files/types/26a3_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cf2d8d94ecf..ad5f55777d4 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -890,8 +890,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else if !isUntyped(lcx.T) { // left is typed const, right is not const checkOp(store, last, &n.Left, rt, n.Op, true) - checkOrConvertType(store, last, &n.Left, rt, false) - } else if lcx.T == nil { // LHS is nil + if n.Op == SHR || n.Op == SHL { + convertConstType(store, last, &n.Left, lt, false) // bypass check + } else { + debugPP.Println("-----shift-----") + checkOrConvertType(store, last, &n.Left, rt, false) + } + } else if lcx.T == nil { // LHS is nil // TODO: consider this debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. checkOp(store, last, &n.Left, rt, n.Op, true) diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index 8080efd64a3..7fc39a019dd 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Output: -// 0x14002ad2220 +// 0x140054e16b0 diff --git a/gnovm/tests/files/types/26a3_filetest.gno b/gnovm/tests/files/types/26a3_filetest.gno new file mode 100644 index 00000000000..02a3cd14b64 --- /dev/null +++ b/gnovm/tests/files/types/26a3_filetest.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +func main() { + a := uint(1) + r := uint64(1) << a + println(r) + fmt.Printf("%T \n", r) + + //r1 := uint64(1) << (63 - 1) + //println(r1) +} + +// Output: +// 2 +// uint64 From 2f4136f4e039acc9249230ab58a8088643b94283 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 21:50:46 +0800 Subject: [PATCH 038/193] fmt --- gnovm/pkg/gnolang/debug.go | 12 ++++++++---- gnovm/pkg/gnolang/op_binary.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 21 ++++++++++++--------- gnovm/pkg/gnolang/types.go | 6 +++--- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/gnovm/pkg/gnolang/debug.go b/gnovm/pkg/gnolang/debug.go index a467e389229..21985884aed 100644 --- a/gnovm/pkg/gnolang/debug.go +++ b/gnovm/pkg/gnolang/debug.go @@ -18,13 +18,17 @@ import ( // so it is still faster to first check the truth value // before calling debug.Println or debug.Printf. -type debugging bool -type debugPreprocess bool +type ( + debugging bool + debugPreprocess bool +) // using a const is probably faster. // const debug debugging = true // or flip -var debug debugging = false -var debugPP debugPreprocess = false +var ( + debug debugging = false + debugPP debugPreprocess = false +) func init() { debug = os.Getenv("DEBUG") == "1" diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 2798c27f128..307c4ae56de 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -471,7 +471,7 @@ func isEql(store Store, lv, rv *TypedValue) bool { } return lv.V == rv.V case FuncKind: - //if debug { + // if debug { if lv.V != nil && rv.V != nil { panic("function can only be compared with `nil`") } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ad5f55777d4..d18b64a22ba 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,16 +2,19 @@ package gnolang import ( "fmt" - "github.com/gnolang/gno/tm2/pkg/errors" "math/big" "reflect" + + "github.com/gnolang/gno/tm2/pkg/errors" ) type f func(t Type) bool -var binaryPredicates = make(map[Word]f) -var unaryPredicates = make(map[Word]f) -var IncDecStmtPredicates = make(map[Word]f) +var ( + binaryPredicates = make(map[Word]f) + unaryPredicates = make(map[Word]f) + IncDecStmtPredicates = make(map[Word]f) +) func init() { // add,sub,mul,quo,rem with assgin @@ -909,8 +912,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { if baseOf(rt) != UintType { // convert n.Right to (gno) uint type. - //checkOp(store, last, &n.Right, UintType, n.Op, true) - //checkOrConvertType(store, last, &n.Right, UintType, false) + // checkOp(store, last, &n.Right, UintType, n.Op, true) + // checkOrConvertType(store, last, &n.Right, UintType, false) convertConstType(store, last, &n.Right, UintType, false) // bypass check } else { // leave n.Left as is and baseOf(n.Right) as UintType. @@ -1706,8 +1709,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // Special case if shift assign <<= or >>=. // TODO: no need here, like index convert - //checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) - //checkOrConvertType(store, last, &n.Rhs[0], UintType, false) + // checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) + // checkOrConvertType(store, last, &n.Rhs[0], UintType, false) convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { @@ -1723,7 +1726,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) // is x or y is untyped, convert, else check type - //rt := evalStaticTypeOf(store, last, n.Rhs[i]) + // rt := evalStaticTypeOf(store, last, n.Rhs[i]) // all else check checkOp(store, last, &n.Rhs[i], lt, n.Op, false) checkOrConvertType(store, last, &n.Rhs[i], lt, false) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 7ba9cc23730..d8c7cf6b909 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2321,7 +2321,7 @@ func assertEqualityTypes(lt, rt Type) { } else if lt.TypeID() == rt.TypeID() { // non-nil types are identical. } else { - //panic("7, incompatible operands") + // panic("7, incompatible operands") debug.Errorf( "incompatible operands in binary (eql/neq) expression: %s and %s", lt.String(), @@ -2558,7 +2558,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { "cannot use %s as %s without explicit conversion", dxt.String(), dt.String())) - //xt = dxt.Base + // xt = dxt.Base } else { // carry on with baseOf(dxt) xt = dxt.Base @@ -2669,7 +2669,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { case *DeclaredType: // do nothing, untyped to declared type return - //panic("should not happen") + // panic("should not happen") case *StructType, *PackageType, *ChanType: if xt.TypeID() == cdt.TypeID() { return // ok From 1497c4a2868af47b42aa16b8776f0229b951c538 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 22:36:22 +0800 Subject: [PATCH 039/193] lint --- gnovm/pkg/gnolang/preprocess.go | 16 +++++------ gnovm/pkg/gnolang/types.go | 49 ++++++++++++++++----------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index d18b64a22ba..3f279a1e4f1 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2395,10 +2395,10 @@ func anyValue(t Type) TypedValue { } } -func isConst(x Expr) bool { - _, ok := x.(*ConstExpr) - return ok -} +//func isConst(x Expr) bool { +// _, ok := x.(*ConstExpr) +// return ok +//} func isConstType(x Expr) bool { _, ok := x.(*constTypeExpr) @@ -2578,11 +2578,11 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool } if isComparison(op) { switch op { - case EQL, NEQ: // check comparable + case EQL, NEQ: // check isComparable // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc - // 2. comparable requires one is assignable to another + // 2. isComparable requires one is assignable to another // 3. handle nil - if ok, code := comparable(dt); !ok { + if ok, code := isComparable(dt); !ok { panic(code) } case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString @@ -2614,7 +2614,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } - debugPP.Println("typed and identical as comparable") + debugPP.Println("typed and identical as isComparable") } case SHL, SHR: default: diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index d8c7cf6b909..81cbe7df17f 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -272,9 +272,9 @@ const ( IsBigDec IsRune - IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned - IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec - IsConstType = IsBoolean | IsNumeric | IsString + IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned + IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec + //IsConstType = IsBoolean | IsNumeric | IsString ) // this is more convenient than compare with types @@ -381,17 +381,17 @@ func isIntNum(t Type) bool { } } -func isIntOrUint(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate()&IsUnsigned != 0 || t.Predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} +//func isIntOrUint(t Type) bool { +// switch t := baseOf(t).(type) { +// case PrimitiveType: +// if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate()&IsUnsigned != 0 || t.Predicate()&IsRune != 0 { +// return true +// } +// return false +// default: +// return false +// } +//} func isNumericOrString(t Type) bool { switch t := baseOf(t).(type) { @@ -2261,7 +2261,7 @@ func assertSameTypes(lt, rt Type) { } // both typed, or one is nil, or data byte(special case) -// only for comparable types for runtime, op_binary +// only for isComparable types for runtime, op_binary // any implicit identical check is in preprocess stage and excluded from here // TODO: a better name? func isBinOperandTypeIdentical(lt, rt Type) bool { @@ -2330,13 +2330,13 @@ func assertEqualityTypes(lt, rt Type) { } } -// NOTE: comparable is a more strict check than assertSameTypes, refer to 0f20_filetest.gno, -// which pass the later one, but is not comparable. -// The logic here is, when compare operators show, check if t is comparable, if yes, +// NOTE: isComparable is a more strict check than assertSameTypes, refer to 0f20_filetest.gno, +// which pass the later one, but is not isComparable. +// The logic here is, when compare operators show, check if t is isComparable, if yes, // then check the corresponding type(the other side of the operator) is convertable to t. -func comparable(t Type) (bool, string) { - debugPP.Printf("check comparable, t is %v \n", t) - // primitive is comparable +func isComparable(t Type) (bool, string) { + debugPP.Printf("check isComparable, t is %v \n", t) + // primitive is isComparable switch ct := baseOf(t).(type) { case PrimitiveType: debugPP.Println("primitive type, return true") @@ -2364,15 +2364,15 @@ func comparable(t Type) (bool, string) { case *InterfaceType: return true, "" case *SliceType, *FuncType: - // only comparable with nil, runtime check + // only isComparable with nil, runtime check return true, "" case *NativeType: if ct.Type.Comparable() { return true, "" } - return false, fmt.Sprintf("%v is not comparable \n", t) + return false, fmt.Sprintf("%v is not isComparable \n", t) default: - return false, fmt.Sprintf("%v is not comparable \n", t) + return false, fmt.Sprintf("%v is not isComparable \n", t) } } @@ -2577,7 +2577,6 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { xt.String(), ddt.String())) } - } else { // carry on with baseOf(ddt) dt = ddt.Base From 709e13ab2156da5aff613ca3f72beea9170be81c Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 22:40:28 +0800 Subject: [PATCH 040/193] lint --- gnovm/pkg/gnolang/preprocess.go | 1 - gnovm/pkg/gnolang/types.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 3f279a1e4f1..cac306e1073 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1712,7 +1712,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) // checkOrConvertType(store, last, &n.Rhs[0], UintType, false) convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check - } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, // TODO: assert length diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 81cbe7df17f..d0218fa0ad3 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -274,7 +274,7 @@ const ( IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec - //IsConstType = IsBoolean | IsNumeric | IsString + // IsConstType = IsBoolean | IsNumeric | IsString ) // this is more convenient than compare with types From 8fd16fc3909fa4de56a1497ff39d846813402950 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Dec 2023 22:59:06 +0800 Subject: [PATCH 041/193] fix map comparable --- gnovm/pkg/gnolang/types.go | 6 +++--- gnovm/tests/files/types/23a4_filetest.gno | 6 ++---- gnovm/tests/files/types/27a0_filetest.gno | 10 ++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 gnovm/tests/files/types/27a0_filetest.gno diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index d0218fa0ad3..2196d47c048 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2363,16 +2363,16 @@ func isComparable(t Type) (bool, string) { return true, "" case *InterfaceType: return true, "" - case *SliceType, *FuncType: + case *SliceType, *FuncType, *MapType: // only isComparable with nil, runtime check return true, "" case *NativeType: if ct.Type.Comparable() { return true, "" } - return false, fmt.Sprintf("%v is not isComparable \n", t) + return false, fmt.Sprintf("%v is not comparable \n", t) default: - return false, fmt.Sprintf("%v is not isComparable \n", t) + return false, fmt.Sprintf("%v is not comparable \n", t) } } diff --git a/gnovm/tests/files/types/23a4_filetest.gno b/gnovm/tests/files/types/23a4_filetest.gno index 7fc39a019dd..caaf1ed0438 100644 --- a/gnovm/tests/files/types/23a4_filetest.gno +++ b/gnovm/tests/files/types/23a4_filetest.gno @@ -1,12 +1,10 @@ package main -import "fmt" - func main() { v := 42 p := &v - fmt.Println(p) // Output: memory address of v + println(v == *p) } // Output: -// 0x140054e16b0 +// true diff --git a/gnovm/tests/files/types/27a0_filetest.gno b/gnovm/tests/files/types/27a0_filetest.gno new file mode 100644 index 00000000000..efb63d40b97 --- /dev/null +++ b/gnovm/tests/files/types/27a0_filetest.gno @@ -0,0 +1,10 @@ +package main + +var m map[string]int + +func main() { + println(m == nil) +} + +// Output: +// true From 8a63e0c6b5ec841cb61e7482010d8bb5b9e6bf62 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 10 Dec 2023 23:18:30 +0800 Subject: [PATCH 042/193] fixup --- .../gno.land/r/demo/foo1155/foo1155_test.gno | 4 ++-- .../gno.land/r/demo/foo721/foo721_test.gno | 4 ++-- gnovm/pkg/gnolang/op_binary.go | 13 ++++++++----- gnovm/pkg/gnolang/preprocess.go | 14 ++++++++++++++ gnovm/pkg/gnolang/types.go | 3 +++ gnovm/pkg/gnolang/values_conversions.go | 4 ++++ gnovm/tests/files/types/0a1a_filetest.gno | 11 +++++++++++ gnovm/tests/files/types/0a1b_filetest.gno | 18 ++++++++++++++++++ gnovm/tests/files/types/0a1c_filetest.gno | 17 +++++++++++++++++ gnovm/tests/files/types/0a1d_filetest.gno | 12 ++++++++++++ 10 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 gnovm/tests/files/types/0a1a_filetest.gno create mode 100644 gnovm/tests/files/types/0a1b_filetest.gno create mode 100644 gnovm/tests/files/types/0a1c_filetest.gno create mode 100644 gnovm/tests/files/types/0a1d_filetest.gno diff --git a/examples/gno.land/r/demo/foo1155/foo1155_test.gno b/examples/gno.land/r/demo/foo1155/foo1155_test.gno index 30663ab2c95..695c3f3bae4 100644 --- a/examples/gno.land/r/demo/foo1155/foo1155_test.gno +++ b/examples/gno.land/r/demo/foo1155/foo1155_test.gno @@ -18,8 +18,8 @@ func TestFoo721(t *testing.T) { expected interface{} fn func() interface{} }{ - {"BalanceOf(admin, tid1)", 100, func() interface{} { return BalanceOf(admin, tid1) }}, - {"BalanceOf(bob, tid1)", 0, func() interface{} { return BalanceOf(bob, tid1) }}, + {"BalanceOf(admin, tid1)", uint64(100), func() interface{} { return BalanceOf(admin, tid1) }}, + {"BalanceOf(bob, tid1)", uint64(0), func() interface{} { return BalanceOf(bob, tid1) }}, {"IsApprovedForAll(admin, bob)", false, func() interface{} { return IsApprovedForAll(admin, bob) }}, } { t.Run(tc.name, func(t *testing.T) { diff --git a/examples/gno.land/r/demo/foo721/foo721_test.gno b/examples/gno.land/r/demo/foo721/foo721_test.gno index 8fb5c6d4f94..618cff55bc2 100644 --- a/examples/gno.land/r/demo/foo721/foo721_test.gno +++ b/examples/gno.land/r/demo/foo721/foo721_test.gno @@ -16,8 +16,8 @@ func TestFoo721(t *testing.T) { expected interface{} fn func() interface{} }{ - {"BalanceOf(admin)", 10, func() interface{} { return BalanceOf(admin) }}, - {"BalanceOf(hariom)", 5, func() interface{} { return BalanceOf(hariom) }}, + {"BalanceOf(admin)", uint64(10), func() interface{} { return BalanceOf(admin) }}, + {"BalanceOf(hariom)", uint64(5), func() interface{} { return BalanceOf(hariom) }}, {"OwnerOf(0)", admin.Resolve(), func() interface{} { return OwnerOf(grc721.TokenID("0")) }}, {"IsApprovedForAll(admin, hariom)", false, func() interface{} { return IsApprovedForAll(admin, hariom) }}, } { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 307c4ae56de..1ff808bf4c0 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -80,19 +80,19 @@ func (m *Machine) doOpEql() { if debug { assertEqualityTypes(lv.T, rv.T) } - debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool // TODO: this should be in preprocess too // TODO: only assert here if isBinOperandTypeIdentical(lv.T, rv.T) { + debugPP.Println("-----type identical------") res = isEql(m.Store, lv, rv) + debugPP.Println("is equal?", res) } else { + debugPP.Println("-----type not identical------") res = false } - lv.T = UntypedBoolType - lv.V = nil - lv.SetBool(res) lv.T = UntypedBoolType lv.V = nil @@ -109,12 +109,15 @@ func (m *Machine) doOpNeq() { if debug { assertEqualityTypes(lv.T, rv.T) } - debugPP.Printf("lv.T: %v, rv.T: %v \n", lv.T, rv.T) + debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool if isBinOperandTypeIdentical(lv.T, rv.T) { + debugPP.Println("-----type identical------") res = !isEql(m.Store, lv, rv) + debugPP.Println("is not equal?", res) } else { + debugPP.Println("-----type not identical------") res = true } lv.T = UntypedBoolType diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cac306e1073..b02857648f0 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1331,7 +1331,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { CLT_TYPE_SWITCH: switch cclt := baseOf(clt).(type) { case *StructType: + debugPP.Println("---struct type---") if n.IsKeyed() { + debugPP.Println("keyed") for i := 0; i < len(n.Elts); i++ { key := n.Elts[i].Key.(*NameExpr).Name path := cclt.GetPathForName(key) @@ -1339,6 +1341,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) } } else { + debugPP.Println("not keyed") for i := 0; i < len(n.Elts); i++ { ft := cclt.Fields[i].Type checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) @@ -1590,6 +1593,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *StructTypeExpr: + debugPP.Println("---structTypeExpr---") evalStaticType(store, last, n) // TRANS_LEAVE ----------------------- @@ -1597,12 +1601,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Printf("---AssignStmt---, Op: %v \n", n.Op) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { + debugPP.Println("define") + // lt := evalStaticTypeOf(store, last, n.Lhs) + // Rhs consts become default *ConstExprs. for _, rx := range n.Rhs { + debugPP.Println("convert if const") // NOTE: does nothing if rx is "nil". convertIfConst(store, last, rx) } if len(n.Lhs) > len(n.Rhs) { + debugPP.Println("lhs > rhs") // Unpack n.Rhs[0] to n.Lhs[:] if len(n.Rhs) != 1 { panic("should not happen") @@ -1653,6 +1662,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { default: panic("should not happen") } + debugPP.Println("else") } else { // General case: a, b := x, y for i, lx := range n.Lhs { @@ -2461,7 +2471,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if t != nil { conversionNeeded = checkConvertable(xt, t, autoNative) } + debugPP.Println("need conversion: ", conversionNeeded) if isUntyped(xt) { + debugPP.Println("xt untyped") if t == nil { t = defaultTypeOf(xt) } @@ -2500,6 +2512,7 @@ func convertIfConst(store Store, last BlockNode, x Expr) { if cx, ok := x.(*ConstExpr); ok { convertConst(store, last, cx, nil) } + debugPP.Printf("x: %v not const, no convert \n", x) } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { @@ -2512,6 +2525,7 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { debugPP.Println("convert untyped const") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) + debug.Printf("after conversion: cx: %v \n", cx) } else if t != nil { debugPP.Println("convert typed const for indexing") // e.g. a named type or uint8 type to int for indexing. diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 2196d47c048..72c850b737f 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2287,6 +2287,9 @@ func isBinOperandTypeIdentical(lt, rt Type) bool { // both are nil. } else if lt == nil || rt == nil { // one is nil. see function comment. + } else if lt.Kind() == rt.Kind() && // NOTE: keep untyped, there would be runtime untyped, e.g. `hello`[1:0] will create a runtime untype string, and + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // left is databyte of same kind, diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index f8b937cf489..e87e78d2fff 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -904,6 +904,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { } // special case: native if nt, ok := t.(*NativeType); ok { + debugPP.Println("native type") // first convert untyped to typed gno value. gnot := go2GnoBaseType(nt.Type) if debug { @@ -919,6 +920,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { // special case: simple conversion if t != nil && tv.T.Kind() == t.Kind() { tv.T = t + debugPP.Printf("simple conversion, tv.T: %v \n", tv.T) return } // general case @@ -947,11 +949,13 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { } ConvertUntypedBigdecTo(tv, tv.V.(BigdecValue), t) case UntypedStringType: + debugPP.Println("untype string to string") if preprocessing == 0 { panic("untyped String conversion should not happen during interpretation") } if t.Kind() == StringKind { tv.T = t + debugPP.Printf("tv.T %v \n", tv.T) return } else { ConvertTo(nilAllocator, nil, tv, t) diff --git a/gnovm/tests/files/types/0a1a_filetest.gno b/gnovm/tests/files/types/0a1a_filetest.gno new file mode 100644 index 00000000000..4134740f90f --- /dev/null +++ b/gnovm/tests/files/types/0a1a_filetest.gno @@ -0,0 +1,11 @@ +package main + +// both typed(different) const +func main() { + println(int(1) == 1) + println(int(1) != 1) +} + +// Output: +// true +// false diff --git a/gnovm/tests/files/types/0a1b_filetest.gno b/gnovm/tests/files/types/0a1b_filetest.gno new file mode 100644 index 00000000000..150e6820c72 --- /dev/null +++ b/gnovm/tests/files/types/0a1b_filetest.gno @@ -0,0 +1,18 @@ +package main + +type S struct { + expected string +} + +func main() { + s := S{ + expected: `hello`[:], // this is not converted + } + a := "hello" + + println(a == s.expected) + +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0a1c_filetest.gno b/gnovm/tests/files/types/0a1c_filetest.gno new file mode 100644 index 00000000000..ffaaf26e2e2 --- /dev/null +++ b/gnovm/tests/files/types/0a1c_filetest.gno @@ -0,0 +1,17 @@ +package main + +type S struct { + expected string +} + +func main() { + expected := `hello`[:] // this kind of untyped non const will be converted + a := "hello" + + a == expected + + //println(r) + +} + +// Output: diff --git a/gnovm/tests/files/types/0a1d_filetest.gno b/gnovm/tests/files/types/0a1d_filetest.gno new file mode 100644 index 00000000000..0ec740927b1 --- /dev/null +++ b/gnovm/tests/files/types/0a1d_filetest.gno @@ -0,0 +1,12 @@ +package main + +func gen() interface{} { + return uint64(0) +} +func main() { + println(0 == gen()) + +} + +// Output: +// false From ad8768b1161c77285f7013fb71856e51f2a5bda8 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 11 Dec 2023 17:31:48 +0800 Subject: [PATCH 043/193] fix slice type --- gnovm/pkg/gnolang/op_expressions.go | 17 +++++++++++++---- gnovm/pkg/gnolang/types.go | 8 ++++---- gnovm/tests/files/types/0a1b_filetest.gno | 1 + gnovm/tests/files/types/0a1c_filetest.gno | 10 +++------- gnovm/tests/files/types/0a1d_filetest.gno | 14 ++++++++++---- gnovm/tests/files/types/0a1e_filetest.gno | 19 +++++++++++++++++++ 6 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 gnovm/tests/files/types/0a1e_filetest.gno diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index b46e343b00e..967541c6e8f 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -83,6 +83,7 @@ func (m *Machine) doOpSelector() { } func (m *Machine) doOpSlice() { + debugPP.Println("doOpSlice") sx := m.PopExpr().(*SliceExpr) var low, high, max int = -1, -1, -1 // max @@ -112,14 +113,20 @@ func (m *Machine) doOpSlice() { if sx.High == nil { high = xv.GetLength() } + debugPP.Printf("low: %v , high: %v \n", low, high) // all low:high:max cases + var sv TypedValue if max == -1 { - sv := xv.GetSlice(m.Alloc, low, high) - m.PushValue(sv) + sv = xv.GetSlice(m.Alloc, low, high) + debugPP.Printf("sv: %v \n", sv) } else { - sv := xv.GetSlice2(m.Alloc, low, high, max) - m.PushValue(sv) + sv = xv.GetSlice2(m.Alloc, low, high, max) + debugPP.Printf("sv: %v \n", sv) } + if isUntyped(sv.T) { + ConvertUntypedTo(&sv, defaultTypeOf(sv.T)) + } + m.PushValue(sv) } // If the referred value is undefined, and the pointer @@ -476,9 +483,11 @@ func (m *Machine) doOpArrayLit() { } func (m *Machine) doOpSliceLit() { + debugPP.Println("doOpSliceLit") // assess performance TODO x := m.PopExpr().(*CompositeLitExpr) el := len(x.Elts) + debugPP.Println("el: ", el) // peek slice type. st := m.PeekValue(1 + el).V.(TypeValue).Type // construct element buf slice. diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 72c850b737f..35427d7160b 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2287,9 +2287,9 @@ func isBinOperandTypeIdentical(lt, rt Type) bool { // both are nil. } else if lt == nil || rt == nil { // one is nil. see function comment. - } else if lt.Kind() == rt.Kind() && // NOTE: keep untyped, there would be runtime untyped, e.g. `hello`[1:0] will create a runtime untype string, and - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. + //} else if lt.Kind() == rt.Kind() && // TODO: this should not be right. keep untyped, there would be runtime untyped, e.g. `hello`[1:0] will create a runtime untype string, and + // isUntyped(lt) || isUntyped(rt) { + // // one is untyped of same kind. } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // left is databyte of same kind, @@ -2366,7 +2366,7 @@ func isComparable(t Type) (bool, string) { return true, "" case *InterfaceType: return true, "" - case *SliceType, *FuncType, *MapType: + case *SliceType, *FuncType, *MapType: // TODO: check only comparable with nil // only isComparable with nil, runtime check return true, "" case *NativeType: diff --git a/gnovm/tests/files/types/0a1b_filetest.gno b/gnovm/tests/files/types/0a1b_filetest.gno index 150e6820c72..ba630d6269a 100644 --- a/gnovm/tests/files/types/0a1b_filetest.gno +++ b/gnovm/tests/files/types/0a1b_filetest.gno @@ -8,6 +8,7 @@ func main() { s := S{ expected: `hello`[:], // this is not converted } + a := "hello" println(a == s.expected) diff --git a/gnovm/tests/files/types/0a1c_filetest.gno b/gnovm/tests/files/types/0a1c_filetest.gno index ffaaf26e2e2..a8551f6ba4d 100644 --- a/gnovm/tests/files/types/0a1c_filetest.gno +++ b/gnovm/tests/files/types/0a1c_filetest.gno @@ -1,17 +1,13 @@ package main -type S struct { - expected string -} - func main() { expected := `hello`[:] // this kind of untyped non const will be converted - a := "hello" - a == expected + a := "hello" - //println(r) + println(a == expected) } // Output: +// true diff --git a/gnovm/tests/files/types/0a1d_filetest.gno b/gnovm/tests/files/types/0a1d_filetest.gno index 0ec740927b1..4e8d690895c 100644 --- a/gnovm/tests/files/types/0a1d_filetest.gno +++ b/gnovm/tests/files/types/0a1d_filetest.gno @@ -1,12 +1,18 @@ package main -func gen() interface{} { - return uint64(0) +type S struct { + expected string } + func main() { - println(0 == gen()) + + //a := "hello" + + println("hello" == S{ + expected: `hello`[:], + }.expected) } // Output: -// false +// true diff --git a/gnovm/tests/files/types/0a1e_filetest.gno b/gnovm/tests/files/types/0a1e_filetest.gno new file mode 100644 index 00000000000..a21fb23f87c --- /dev/null +++ b/gnovm/tests/files/types/0a1e_filetest.gno @@ -0,0 +1,19 @@ +package main + +type S struct { + expected string +} + +func main() { + var s = S{ + expected: `hello`[:], // this is not converted + } + + a := "hello" + + println(a == s.expected) + +} + +// Output: +// true From 0f828f51c7000183cfecc74766690c319240d897 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 00:08:28 +0800 Subject: [PATCH 044/193] fix comparable --- gnovm/pkg/gnolang/preprocess.go | 29 ++++++++++---- gnovm/pkg/gnolang/types.go | 36 +++++++++++------ gnovm/tests/files/types/0a01_filetest.gno | 4 +- gnovm/tests/files/types/0f17_filetest.gno | 2 +- gnovm/tests/files/types/0f30_filetest.gno | 1 + gnovm/tests/files/types/0f32_filetest.gno | 9 +++++ gnovm/tests/files/types/0f33_filetest.gno | 49 +++++++++++++++++++++++ gnovm/tests/files/types/0f34_filetest.gno | 49 +++++++++++++++++++++++ 8 files changed, 157 insertions(+), 22 deletions(-) create mode 100644 gnovm/tests/files/types/0f32_filetest.gno create mode 100644 gnovm/tests/files/types/0f33_filetest.gno create mode 100644 gnovm/tests/files/types/0f34_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index b02857648f0..32cab78614c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -811,6 +811,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) debugPP.Printf("---BinaryExpr---, OP: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + debugPP.Printf("left: %v, right: %v \n", n.Left, n.Right) if lic { if ric { // Left const, Right const ---------------------- @@ -947,11 +948,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil - debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest, if8_filetest + debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest, 1f8_filetest // convert n.Right to typed-nil type. checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) - } else if !isShift { + } else if !isShift { // TODO: consider this checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) } @@ -1024,6 +1025,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) } else { + debugPP.Println("else") checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } @@ -1039,9 +1041,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { switch cft := baseOf(ift).(type) { case *FuncType: ft = cft + debugPP.Printf("func type, ft: %v \n", ft) case *NativeType: + debugPP.Println("native type") ft = store.Go2GnoType(cft.Type).(*FuncType) case *TypeType: + debugPP.Println("type type") if len(n.Args) != 1 { panic("type conversion requires single argument") } @@ -1117,6 +1122,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } + debugPP.Println("general case") // Continue with general case. hasVarg := ft.HasVarg() isVarg := n.Varg @@ -1209,6 +1215,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Check given argument type against required. // Also replace const Args with *ConstExpr unless embedded. if embedded { + debugPP.Println("embedded") if isVarg { panic("should not happen") } @@ -1224,8 +1231,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { + debugPP.Println("not embedded") for i := range n.Args { if hasVarg { + debugPP.Println("has varg") if (len(spts) - 1) <= i { if isVarg { if len(spts) <= i { @@ -1240,6 +1249,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } else { + debugPP.Println("no varg") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } @@ -1598,7 +1608,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: - debugPP.Printf("---AssignStmt---, Op: %v \n", n.Op) + debugPP.Printf("---AssignStmt---, Op: %v, LHS: %v, RHS:%v \n", n.Op, n.Lhs, n.Rhs) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { debugPP.Println("define") @@ -2451,6 +2461,9 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { + //if debugPP { + // rd.PrintStack() + //} debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint @@ -2465,8 +2478,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative) } else if *x != nil { // XXX if x != nil && t != nil { - debugPP.Println("else, xt not nil") xt := evalStaticTypeOf(store, last, *x) + debugPP.Printf("else, xt not nil, xt: %v \n", xt) var conversionNeeded bool if t != nil { conversionNeeded = checkConvertable(xt, t, autoNative) @@ -2509,10 +2522,11 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // like checkOrConvertType(last, x, nil) func convertIfConst(store Store, last BlockNode, x Expr) { + debugPP.Printf("convertIfConst: x:%v \n", x) if cx, ok := x.(*ConstExpr); ok { + debugPP.Printf("is ConstExpr: cx:%v \n", cx) convertConst(store, last, cx, nil) } - debugPP.Printf("x: %v not const, no convert \n", x) } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { @@ -2566,7 +2580,7 @@ func isComparison(op Word) bool { // check operand types with operators func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool) { var xt Type - if x != nil { // unaryExpr + if x != nil { // unaryExpr Todo: consider if cx, ok := (*x).(*ConstExpr); ok { xt = cx.T } else if *x != nil { @@ -2595,7 +2609,8 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc // 2. isComparable requires one is assignable to another // 3. handle nil - if ok, code := isComparable(dt); !ok { + // TODO: is xt is nil + if ok, code := isComparable(xt, dt); !ok { panic(code) } case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 35427d7160b..0ac26dfae63 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2337,28 +2337,28 @@ func assertEqualityTypes(lt, rt Type) { // which pass the later one, but is not isComparable. // The logic here is, when compare operators show, check if t is isComparable, if yes, // then check the corresponding type(the other side of the operator) is convertable to t. -func isComparable(t Type) (bool, string) { - debugPP.Printf("check isComparable, t is %v \n", t) +func isComparable(xt, dt Type) (bool, string) { + debugPP.Printf("check isComparable, xt: %v, dt: %v \n", xt, dt) // primitive is isComparable - switch ct := baseOf(t).(type) { + switch cdt := baseOf(dt).(type) { case PrimitiveType: debugPP.Println("primitive type, return true") return true, "" case *ArrayType: // NOTE: no recursive allowed // TODO: check at least length here - switch baseOf(ct.Elem()).(type) { + switch baseOf(cdt.Elem()).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? return true, "" default: - return false, fmt.Sprintf("%v cannot be compared \n", ct) + return false, fmt.Sprintf("%v cannot be compared \n", cdt) } case *StructType: - for _, f := range ct.Fields { + for _, f := range cdt.Fields { switch baseOf(f.Type).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: return true, "" default: - return false, fmt.Sprintf("%v cannot be compared \n", ct) + return false, fmt.Sprintf("%v cannot be compared \n", cdt) } } return true, "" @@ -2367,15 +2367,27 @@ func isComparable(t Type) (bool, string) { case *InterfaceType: return true, "" case *SliceType, *FuncType, *MapType: // TODO: check only comparable with nil - // only isComparable with nil, runtime check - return true, "" + if xt != nil { + return false, fmt.Sprintf("%v can only be compared to nil \n", dt) + } else { + // only isComparable with nil, runtime check + return true, "" + } case *NativeType: - if ct.Type.Comparable() { + if cdt.Type.Comparable() { return true, "" } - return false, fmt.Sprintf("%v is not comparable \n", t) + return false, fmt.Sprintf("%v is not comparable \n", xt, dt) + case nil: // TODO: have this case? targe type is nil? + switch cxt := baseOf(xt).(type) { + case *SliceType, *FuncType, *MapType, *InterfaceType: + return true, "" + default: + return false, fmt.Sprintf("invalide operation, %v can only be compared to hasNil \n", cxt) + } + default: - return false, fmt.Sprintf("%v is not comparable \n", t) + return false, fmt.Sprintf("%v is not comparable \n", xt, dt) } } diff --git a/gnovm/tests/files/types/0a01_filetest.gno b/gnovm/tests/files/types/0a01_filetest.gno index dea72835ee3..3a37fa86ce8 100644 --- a/gnovm/tests/files/types/0a01_filetest.gno +++ b/gnovm/tests/files/types/0a01_filetest.gno @@ -1,8 +1,8 @@ package main func main() { - println(nil == nil) + println(nil == nil) // xt: , dt: } // Error: -// main/files/types/0a01_filetest.gno:4: is not comparable +// main/files/types/0a01_filetest.gno:4: invalide operation, can only be compared to hasNil diff --git a/gnovm/tests/files/types/0f17_filetest.gno b/gnovm/tests/files/types/0f17_filetest.gno index 6665a44014b..a892b4c1b0e 100644 --- a/gnovm/tests/files/types/0f17_filetest.gno +++ b/gnovm/tests/files/types/0f17_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// function can only be compared with `nil` +// main/files/types/0f17_filetest.gno:9: main.f can only be compared to nil diff --git a/gnovm/tests/files/types/0f30_filetest.gno b/gnovm/tests/files/types/0f30_filetest.gno index 0c859b35d50..c5640c491a6 100644 --- a/gnovm/tests/files/types/0f30_filetest.gno +++ b/gnovm/tests/files/types/0f30_filetest.gno @@ -6,3 +6,4 @@ func main() { } // Error: +// main/files/debug/0f30_filetest.gno:5: []uint8 can only be compared to nil diff --git a/gnovm/tests/files/types/0f32_filetest.gno b/gnovm/tests/files/types/0f32_filetest.gno new file mode 100644 index 00000000000..c9d65acd3d7 --- /dev/null +++ b/gnovm/tests/files/types/0f32_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both not const, and both interface +func main() { + println([]byte("a") == nil) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/0f33_filetest.gno b/gnovm/tests/files/types/0f33_filetest.gno new file mode 100644 index 00000000000..e7aac0cf069 --- /dev/null +++ b/gnovm/tests/files/types/0f33_filetest.gno @@ -0,0 +1,49 @@ +package main + +import "fmt" + +// var f func() +var a *struct{} +var b interface{} +var c map[string]int +var s []int + +func main() { + if a == nil { + fmt.Println("pointer == nil") + } else { + println("not nil!") + } + fmt.Println("----") + + if b == nil { + fmt.Println("interface == nil") + } else { + println("not nil!") + } + fmt.Println("----") + + if c == nil { + fmt.Println("map == nil") + } else { + println("not nil!") + } + fmt.Println("----") + + if s == nil { + fmt.Println("slice == nil") + } else { + println("not nil!") + } + fmt.Println("----") +} + +// Output: +// pointer == nil +// ---- +// interface == nil +// ---- +// map == nil +// ---- +// slice == nil +// ---- diff --git a/gnovm/tests/files/types/0f34_filetest.gno b/gnovm/tests/files/types/0f34_filetest.gno new file mode 100644 index 00000000000..8b5d3830091 --- /dev/null +++ b/gnovm/tests/files/types/0f34_filetest.gno @@ -0,0 +1,49 @@ +package main + +import "fmt" + +// var f func() +var a *struct{} +var b interface{} +var c map[string]int +var s []int + +func main() { + if nil == a { + fmt.Println("pointer == nil") + } else { + println("not nil!") + } + fmt.Println("----") + + if nil == b { + fmt.Println("interface == nil") + } else { + println("not nil!") + } + fmt.Println("----") + + if nil == c { + fmt.Println("map == nil") + } else { + println("not nil!") + } + fmt.Println("----") + + if nil == s { + fmt.Println("slice == nil") + } else { + println("not nil!") + } + fmt.Println("----") +} + +// Output: +// pointer == nil +// ---- +// interface == nil +// ---- +// map == nil +// ---- +// slice == nil +// ---- From 937723ecbfa0f924a08498816c356370032d4920 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 00:15:04 +0800 Subject: [PATCH 045/193] fixup --- gnovm/tests/files/types/0f30_filetest.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/tests/files/types/0f30_filetest.gno b/gnovm/tests/files/types/0f30_filetest.gno index c5640c491a6..fef910b442f 100644 --- a/gnovm/tests/files/types/0f30_filetest.gno +++ b/gnovm/tests/files/types/0f30_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/debug/0f30_filetest.gno:5: []uint8 can only be compared to nil +// main/files/types/0f30_filetest.gno:5: []uint8 can only be compared to nil From 218c8342ff48c0220d0139001161e4e6296f218a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 00:31:19 +0800 Subject: [PATCH 046/193] fixup --- gnovm/pkg/gnolang/types.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 0ac26dfae63..c740d60c977 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2377,7 +2377,7 @@ func isComparable(xt, dt Type) (bool, string) { if cdt.Type.Comparable() { return true, "" } - return false, fmt.Sprintf("%v is not comparable \n", xt, dt) + return false, fmt.Sprintf("%v is not comparable \n", dt) case nil: // TODO: have this case? targe type is nil? switch cxt := baseOf(xt).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType: @@ -2385,9 +2385,8 @@ func isComparable(xt, dt Type) (bool, string) { default: return false, fmt.Sprintf("invalide operation, %v can only be compared to hasNil \n", cxt) } - default: - return false, fmt.Sprintf("%v is not comparable \n", xt, dt) + return false, fmt.Sprintf("%v is not comparable \n", dt) } } From 8c5ce249a8cabdf40c091d5ceb46158523759d71 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 09:48:48 +0800 Subject: [PATCH 047/193] fixup --- gnovm/pkg/gnolang/debug.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 5 ----- gnovm/pkg/gnolang/values_conversions.go | 2 +- gnovm/tests/files/types/0a1d_filetest.gno | 2 -- gnovm/tests/files/types/0a1f_filetest.gno | 12 ++++++++++++ gnovm/tests/files/types/0f30a_filetest.gno | 8 ++++++++ gnovm/tests/files/types/0f30b_filetest.gno | 13 +++++++++++++ gnovm/tests/files/types/0f30c_filetest.gno | 11 +++++++++++ gnovm/tests/files/types/0f30d_filetest.gno | 8 ++++++++ gnovm/tests/files/types/0f30e_filetest.gno | 8 ++++++++ 10 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 gnovm/tests/files/types/0a1f_filetest.gno create mode 100644 gnovm/tests/files/types/0f30a_filetest.gno create mode 100644 gnovm/tests/files/types/0f30b_filetest.gno create mode 100644 gnovm/tests/files/types/0f30c_filetest.gno create mode 100644 gnovm/tests/files/types/0f30d_filetest.gno create mode 100644 gnovm/tests/files/types/0f30e_filetest.gno diff --git a/gnovm/pkg/gnolang/debug.go b/gnovm/pkg/gnolang/debug.go index 21985884aed..33ad29bbaae 100644 --- a/gnovm/pkg/gnolang/debug.go +++ b/gnovm/pkg/gnolang/debug.go @@ -32,7 +32,7 @@ var ( func init() { debug = os.Getenv("DEBUG") == "1" - debugPP = os.Getenv("DEPP") == "1" + debugPP = os.Getenv("DEBUG_PP") == "1" if debug { go func() { // e.g. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 32cab78614c..830a3316979 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1330,7 +1330,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } - debugPP.Println("else") checkOp(store, last, nil, xt, n.Op, false) // TRANS_LEAVE ----------------------- @@ -1341,9 +1340,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { CLT_TYPE_SWITCH: switch cclt := baseOf(clt).(type) { case *StructType: - debugPP.Println("---struct type---") if n.IsKeyed() { - debugPP.Println("keyed") for i := 0; i < len(n.Elts); i++ { key := n.Elts[i].Key.(*NameExpr).Name path := cclt.GetPathForName(key) @@ -1351,7 +1348,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) } } else { - debugPP.Println("not keyed") for i := 0; i < len(n.Elts); i++ { ft := cclt.Fields[i].Type checkOrConvertType(store, last, &n.Elts[i].Value, ft, false) @@ -2524,7 +2520,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative func convertIfConst(store Store, last BlockNode, x Expr) { debugPP.Printf("convertIfConst: x:%v \n", x) if cx, ok := x.(*ConstExpr); ok { - debugPP.Printf("is ConstExpr: cx:%v \n", cx) convertConst(store, last, cx, nil) } } diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index e87e78d2fff..60274e67693 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -949,7 +949,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { } ConvertUntypedBigdecTo(tv, tv.V.(BigdecValue), t) case UntypedStringType: - debugPP.Println("untype string to string") + debugPP.Println("untyped string to string") if preprocessing == 0 { panic("untyped String conversion should not happen during interpretation") } diff --git a/gnovm/tests/files/types/0a1d_filetest.gno b/gnovm/tests/files/types/0a1d_filetest.gno index 4e8d690895c..92413c908b1 100644 --- a/gnovm/tests/files/types/0a1d_filetest.gno +++ b/gnovm/tests/files/types/0a1d_filetest.gno @@ -6,8 +6,6 @@ type S struct { func main() { - //a := "hello" - println("hello" == S{ expected: `hello`[:], }.expected) diff --git a/gnovm/tests/files/types/0a1f_filetest.gno b/gnovm/tests/files/types/0a1f_filetest.gno new file mode 100644 index 00000000000..9049c1f9d41 --- /dev/null +++ b/gnovm/tests/files/types/0a1f_filetest.gno @@ -0,0 +1,12 @@ +package main + +func main() { + expected := `hello`[:] // this kind of untyped non const will be converted + + a := 1 + + println(a == expected) +} + +// Error: +// main/files/types/0a1f_filetest.gno:8: cannot use int as string diff --git a/gnovm/tests/files/types/0f30a_filetest.gno b/gnovm/tests/files/types/0f30a_filetest.gno new file mode 100644 index 00000000000..675535a7c7b --- /dev/null +++ b/gnovm/tests/files/types/0f30a_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(map[string]int{"a": 1} == map[string]int{"b": 2}) +} + +// Error: +// main/files/types/0f30a_filetest.gno:4: map[string]int can only be compared to nil diff --git a/gnovm/tests/files/types/0f30b_filetest.gno b/gnovm/tests/files/types/0f30b_filetest.gno new file mode 100644 index 00000000000..5e65be495e0 --- /dev/null +++ b/gnovm/tests/files/types/0f30b_filetest.gno @@ -0,0 +1,13 @@ +package main + +type f func() + +var f1 f +var f2 f + +func main() { + println(f1 == f2) +} + +// Error: +// main/files/types/0f30b_filetest.gno:9: main.f can only be compared to nil diff --git a/gnovm/tests/files/types/0f30c_filetest.gno b/gnovm/tests/files/types/0f30c_filetest.gno new file mode 100644 index 00000000000..63e9d04fb7f --- /dev/null +++ b/gnovm/tests/files/types/0f30c_filetest.gno @@ -0,0 +1,11 @@ +package main + +var f1 func() +var f2 func() + +func main() { + println(f1 == nil) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f30d_filetest.gno b/gnovm/tests/files/types/0f30d_filetest.gno new file mode 100644 index 00000000000..d583f11c0d6 --- /dev/null +++ b/gnovm/tests/files/types/0f30d_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println([]int{1} == []int{1}) +} + +// Error: +// main/files/types/0f30d_filetest.gno:4: []int can only be compared to nil diff --git a/gnovm/tests/files/types/0f30e_filetest.gno b/gnovm/tests/files/types/0f30e_filetest.gno new file mode 100644 index 00000000000..002910072c3 --- /dev/null +++ b/gnovm/tests/files/types/0f30e_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println([]int{1} == nil) +} + +// Output: +// false From abff0736d856c4479b73f43dac6cbfc1a9ad9f1b Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 11:41:51 +0800 Subject: [PATCH 048/193] fixup --- gnovm/Makefile | 2 + gnovm/pkg/gnolang/preprocess.go | 45 +-- gnovm/pkg/gnolang/types.go | 2 +- gnovm/tests/file_test.go | 10 + gnovm/tests/files/types/0a1a_filetest.gno | 2 +- gnovm/tests/files/types/0a1b_filetest.gno | 1 + gnovm/tests/files/types/0a1c_filetest.gno | 5 +- gnovm/tests/files/types/0a1d_filetest.gno | 2 - gnovm/tests/files/types/0a1e_filetest.gno | 3 - gnovm/tests/files/types/0a1f_filetest.gno | 6 +- gnovm/tests/files/types/0b3_filetest.gno | 27 ++ .../tests/files/types/0b4_native_filetest.gno | 13 + .../files/types/0b4_stdlibs_filetest.gno | 13 + .../tests/files/types/0b5_native_filetest.gno | 11 + ...0_filetest.gno => 0f0_native_filetest.gno} | 4 +- .../files/types/0f0_stdlibs_filetest.gno | 28 ++ ..._filetest.gno => 0f1_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 0f26_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 0f27_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 0f8_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 13f0_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 13f1_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 13f2_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 14f0_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 14f1_stdlibs_filetest.gno} | 2 +- ...filetest.gno => 14f2_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 1f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 1f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 1f6_stdlibs_filetest.gno} | 0 ..._filetest.gno => 1f7_stdlibs_filetest.gno} | 0 ..._filetest.gno => 1f8_stdlibs_filetest.gno} | 0 ..._filetest.gno => 1f9_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 2f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 2f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 3f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 3f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 4f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 4f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 5f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 5f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 6f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 6f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 7f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 7f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 8f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 8f1_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 9f0_stdlibs_filetest.gno} | 2 +- ..._filetest.gno => 9f1_stdlibs_filetest.gno} | 2 +- gnovm/tests/files/types/readme/README.md | 301 ------------------ 49 files changed, 154 insertions(+), 379 deletions(-) create mode 100644 gnovm/tests/files/types/0b3_filetest.gno create mode 100644 gnovm/tests/files/types/0b4_native_filetest.gno create mode 100644 gnovm/tests/files/types/0b4_stdlibs_filetest.gno create mode 100644 gnovm/tests/files/types/0b5_native_filetest.gno rename gnovm/tests/files/types/{0f0_filetest.gno => 0f0_native_filetest.gno} (75%) create mode 100644 gnovm/tests/files/types/0f0_stdlibs_filetest.gno rename gnovm/tests/files/types/{0f1_filetest.gno => 0f1_stdlibs_filetest.gno} (80%) rename gnovm/tests/files/types/{0f26_filetest.gno => 0f26_stdlibs_filetest.gno} (78%) rename gnovm/tests/files/types/{0f27_filetest.gno => 0f27_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{0f8_filetest.gno => 0f8_stdlibs_filetest.gno} (79%) rename gnovm/tests/files/types/{13f0_filetest.gno => 13f0_stdlibs_filetest.gno} (71%) rename gnovm/tests/files/types/{13f1_filetest.gno => 13f1_stdlibs_filetest.gno} (81%) rename gnovm/tests/files/types/{13f2_filetest.gno => 13f2_stdlibs_filetest.gno} (90%) rename gnovm/tests/files/types/{14f0_filetest.gno => 14f0_stdlibs_filetest.gno} (71%) rename gnovm/tests/files/types/{14f1_filetest.gno => 14f1_stdlibs_filetest.gno} (72%) rename gnovm/tests/files/types/{14f2_filetest.gno => 14f2_stdlibs_filetest.gno} (90%) rename gnovm/tests/files/types/{1f0_filetest.gno => 1f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{1f1_filetest.gno => 1f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{1f6_filetest.gno => 1f6_stdlibs_filetest.gno} (100%) rename gnovm/tests/files/types/{1f7_filetest.gno => 1f7_stdlibs_filetest.gno} (100%) rename gnovm/tests/files/types/{1f8_filetest.gno => 1f8_stdlibs_filetest.gno} (100%) rename gnovm/tests/files/types/{1f9_filetest.gno => 1f9_stdlibs_filetest.gno} (81%) rename gnovm/tests/files/types/{2f0_filetest.gno => 2f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{2f1_filetest.gno => 2f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{3f0_filetest.gno => 3f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{3f1_filetest.gno => 3f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{4f0_filetest.gno => 4f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{4f1_filetest.gno => 4f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{5f0_filetest.gno => 5f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{5f1_filetest.gno => 5f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{6f0_filetest.gno => 6f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{6f1_filetest.gno => 6f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{7f0_filetest.gno => 7f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{7f1_filetest.gno => 7f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{8f0_filetest.gno => 8f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{8f1_filetest.gno => 8f1_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{9f0_filetest.gno => 9f0_stdlibs_filetest.gno} (74%) rename gnovm/tests/files/types/{9f1_filetest.gno => 9f1_stdlibs_filetest.gno} (74%) delete mode 100644 gnovm/tests/files/types/readme/README.md diff --git a/gnovm/Makefile b/gnovm/Makefile index f933d5ca4c0..f258081145a 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -62,6 +62,8 @@ _test.gnolang.native.sync:; go test tests/*.go -test.short -run "TestFilesNativ _test.gnolang.stdlibs.sync:; go test tests/*.go -test.short -run 'TestFiles$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallenges$$/' $(GOTEST_FLAGS) _test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.debug:; go test tests/*.go -test.short -run 'TestDebug$$/' --update-golden-tests $(GOTEST_FLAGS) ######################################## # Code gen diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 830a3316979..39fde476eb3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -17,7 +17,7 @@ var ( ) func init() { - // add,sub,mul,quo,rem with assgin + // add,sub,mul,quo,rem with assign binaryPredicates[ADD] = isNumericOrString binaryPredicates[ADD_ASSIGN] = isNumericOrString binaryPredicates[SUB] = isNumeric @@ -810,18 +810,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) - debugPP.Printf("---BinaryExpr---, OP: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) - debugPP.Printf("left: %v, right: %v \n", n.Left, n.Right) + debugPP.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) if lic { if ric { // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. + // refer to 0a0_filetest if !isShift { - //// is this implied implicitly? rest of the binary operators after SHL and SHR is excluded - //// Note: this check happens only when left and right are both typed, if not, the checkOrConvert logic will be run if cmp not 0 - //// TODO: checkOrConvertType, same way around - // at least one of left or right is untyped cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // this always implies untyped>? debugPP.Println("cmp < 0, ->") @@ -830,22 +826,18 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rcx.T, false) } else if cmp == 0 { debugPP.Println("cmp == 0") - // NOTE: the following doesn't work. - // TODO: make it work. - // convert n.Left to right type, - // or check for compatibility. - // (the other way around would work too) - // also need to check + // TODO: consider check dir in here checkOp(store, last, &n.Left, rcx.T, n.Op, true) checkOrConvertType(store, last, &n.Left, rcx.T, false) - } else { // this always implies untyped>? + } else { debugPP.Println("cmp > 0, <-") // convert n.Right to left type. checkOp(store, last, &n.Right, lcx.T, n.Op, true) checkOrConvertType(store, last, &n.Right, lcx.T, false) } } - // check special case: zero divisor before eval + // check special case: zero divisor + // TODO: always check when ric? if isQuoOrRem(n.Op) { checkOperand(rcx) } @@ -853,9 +845,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { - // Left untyped const, Right not ---------------- - if rnt, ok := rt.(*NativeType); ok { - debugPP.Println("right native type") + debugPP.Printf("left: %v is untyped const, right: %v is not const \n", lt, rt) + // Left untyped const, Right not const ---------------- + if rnt, ok := rt.(*NativeType); ok { // TODO: check this case + debugPP.Println("right is native type") if isShift { panic("should not happen") } @@ -895,18 +888,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if !isUntyped(lcx.T) { // left is typed const, right is not const checkOp(store, last, &n.Left, rt, n.Op, true) if n.Op == SHR || n.Op == SHL { + debugPP.Println("-----shift-----") convertConstType(store, last, &n.Left, lt, false) // bypass check } else { - debugPP.Println("-----shift-----") checkOrConvertType(store, last, &n.Left, rt, false) } - } else if lcx.T == nil { // LHS is nil // TODO: consider this + } else if lcx.T == nil { // LHS is nil // XXX? debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } - // TODO: 942 line? } else if ric { if isUntyped(rcx.T) { // Left not, Right untyped const ---------------- @@ -1041,9 +1033,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { switch cft := baseOf(ift).(type) { case *FuncType: ft = cft - debugPP.Printf("func type, ft: %v \n", ft) case *NativeType: - debugPP.Println("native type") ft = store.Go2GnoType(cft.Type).(*FuncType) case *TypeType: debugPP.Println("type type") @@ -1122,7 +1112,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } - debugPP.Println("general case") // Continue with general case. hasVarg := ft.HasVarg() isVarg := n.Varg @@ -1231,10 +1220,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { - debugPP.Println("not embedded") for i := range n.Args { if hasVarg { - debugPP.Println("has varg") if (len(spts) - 1) <= i { if isVarg { if len(spts) <= i { @@ -1249,7 +1236,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } else { - debugPP.Println("no varg") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } @@ -2421,17 +2407,13 @@ func isConstType(x Expr) bool { } func cmpSpecificity(t1, t2 Type) int { - debugPP.Printf("cmpSpecificity, t1:%v, t2:%v \n", t1, t2) t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { - debugPP.Println("t1 i prime type") t1s = t1p.Specificity() } if t2p, ok := t2.(PrimitiveType); ok { - debugPP.Println("t2 i prime type") t2s = t2p.Specificity() } - debugPP.Println("t1s, t2s: ", t1s, t2s) if t1s < t2s { // NOTE: higher specificity has lower value, so backwards. return 1 @@ -2518,7 +2500,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // like checkOrConvertType(last, x, nil) func convertIfConst(store Store, last BlockNode, x Expr) { - debugPP.Printf("convertIfConst: x:%v \n", x) if cx, ok := x.(*ConstExpr); ok { convertConst(store, last, cx, nil) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index c740d60c977..d9bab6a65df 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2413,7 +2413,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok - } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6_filetest.gno + } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6_stdlibs_filetest.gno debugPP.Println("xt is empty interface: ", iot) if iot.IsEmptyInterface() { return // ok diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index 53b2d7cc960..402728d6902 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -39,6 +39,16 @@ func TestChallenges(t *testing.T) { func TestTypes(t *testing.T) { baseDir := filepath.Join(".", "files/types") + runFileTests(t, baseDir, []string{"*_native*"}) +} + +func TestTypesNative(t *testing.T) { + baseDir := filepath.Join(".", "files/types") + runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) +} + +func TestDebug(t *testing.T) { + baseDir := filepath.Join(".", "files/debug") runFileTests(t, baseDir, nil) } diff --git a/gnovm/tests/files/types/0a1a_filetest.gno b/gnovm/tests/files/types/0a1a_filetest.gno index 4134740f90f..deb369511fd 100644 --- a/gnovm/tests/files/types/0a1a_filetest.gno +++ b/gnovm/tests/files/types/0a1a_filetest.gno @@ -1,6 +1,6 @@ package main -// both typed(different) const +// left typed, right untyped func main() { println(int(1) == 1) println(int(1) != 1) diff --git a/gnovm/tests/files/types/0a1b_filetest.gno b/gnovm/tests/files/types/0a1b_filetest.gno index ba630d6269a..1db537a4d8c 100644 --- a/gnovm/tests/files/types/0a1b_filetest.gno +++ b/gnovm/tests/files/types/0a1b_filetest.gno @@ -4,6 +4,7 @@ type S struct { expected string } +// special case when RHS is result of slice operation, its type is determined in runtime func main() { s := S{ expected: `hello`[:], // this is not converted diff --git a/gnovm/tests/files/types/0a1c_filetest.gno b/gnovm/tests/files/types/0a1c_filetest.gno index a8551f6ba4d..76f2db8d7d8 100644 --- a/gnovm/tests/files/types/0a1c_filetest.gno +++ b/gnovm/tests/files/types/0a1c_filetest.gno @@ -1,12 +1,9 @@ package main func main() { - expected := `hello`[:] // this kind of untyped non const will be converted - + expected := `hello`[:] a := "hello" - println(a == expected) - } // Output: diff --git a/gnovm/tests/files/types/0a1d_filetest.gno b/gnovm/tests/files/types/0a1d_filetest.gno index 92413c908b1..018d53fa81a 100644 --- a/gnovm/tests/files/types/0a1d_filetest.gno +++ b/gnovm/tests/files/types/0a1d_filetest.gno @@ -5,11 +5,9 @@ type S struct { } func main() { - println("hello" == S{ expected: `hello`[:], }.expected) - } // Output: diff --git a/gnovm/tests/files/types/0a1e_filetest.gno b/gnovm/tests/files/types/0a1e_filetest.gno index a21fb23f87c..cac0716b937 100644 --- a/gnovm/tests/files/types/0a1e_filetest.gno +++ b/gnovm/tests/files/types/0a1e_filetest.gno @@ -8,11 +8,8 @@ func main() { var s = S{ expected: `hello`[:], // this is not converted } - a := "hello" - println(a == s.expected) - } // Output: diff --git a/gnovm/tests/files/types/0a1f_filetest.gno b/gnovm/tests/files/types/0a1f_filetest.gno index 9049c1f9d41..d5268239128 100644 --- a/gnovm/tests/files/types/0a1f_filetest.gno +++ b/gnovm/tests/files/types/0a1f_filetest.gno @@ -1,12 +1,10 @@ package main func main() { - expected := `hello`[:] // this kind of untyped non const will be converted - + expected := `hello`[:] a := 1 - println(a == expected) } // Error: -// main/files/types/0a1f_filetest.gno:8: cannot use int as string +// main/files/types/0a1f_filetest.gno:6: cannot use int as string diff --git a/gnovm/tests/files/types/0b3_filetest.gno b/gnovm/tests/files/types/0b3_filetest.gno new file mode 100644 index 00000000000..86f2f4d3972 --- /dev/null +++ b/gnovm/tests/files/types/0b3_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "strconv" +) + +type Error int8 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// left is untyped const, right is not const + +var a int8 + +func main() { + a = 1 + if 1 == a { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// what the firetruck? diff --git a/gnovm/tests/files/types/0b4_native_filetest.gno b/gnovm/tests/files/types/0b4_native_filetest.gno new file mode 100644 index 00000000000..ae73a2dbd66 --- /dev/null +++ b/gnovm/tests/files/types/0b4_native_filetest.gno @@ -0,0 +1,13 @@ +package main + +import ( + "errors" +) + +func main() { + errCmp := errors.New("xxx") + println(5 == errCmp) +} + +// Error: +// interface conversion: gnolang.Type is *gnolang.NativeType, not gnolang.PrimitiveType diff --git a/gnovm/tests/files/types/0b4_stdlibs_filetest.gno b/gnovm/tests/files/types/0b4_stdlibs_filetest.gno new file mode 100644 index 00000000000..a297069c444 --- /dev/null +++ b/gnovm/tests/files/types/0b4_stdlibs_filetest.gno @@ -0,0 +1,13 @@ +package main + +import ( + "errors" +) + +func main() { + errCmp := errors.New("xxx") + println(5 == errCmp) +} + +// Error: +// main/files/types/0b4_stdlibs_filetest.gno:9: bigint does not implement .uverse.error diff --git a/gnovm/tests/files/types/0b5_native_filetest.gno b/gnovm/tests/files/types/0b5_native_filetest.gno new file mode 100644 index 00000000000..7860292a6d2 --- /dev/null +++ b/gnovm/tests/files/types/0b5_native_filetest.gno @@ -0,0 +1,11 @@ +package main + +import ( + "math/rand" +) + +func main() { + println(5 == rand.Uint32()) +} + +// Error: diff --git a/gnovm/tests/files/types/0f0_filetest.gno b/gnovm/tests/files/types/0f0_native_filetest.gno similarity index 75% rename from gnovm/tests/files/types/0f0_filetest.gno rename to gnovm/tests/files/types/0f0_native_filetest.gno index d25609c8ab7..d625f5deb4f 100644 --- a/gnovm/tests/files/types/0f0_filetest.gno +++ b/gnovm/tests/files/types/0f0_native_filetest.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if 1 == errCmp { @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f0_filetest.gno:19: bigint does not implement .uverse.error +// interface conversion: gnolang.Type is *gnolang.NativeType, not gnolang.PrimitiveType diff --git a/gnovm/tests/files/types/0f0_stdlibs_filetest.gno b/gnovm/tests/files/types/0f0_stdlibs_filetest.gno new file mode 100644 index 00000000000..be93f777339 --- /dev/null +++ b/gnovm/tests/files/types/0f0_stdlibs_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if 1 == errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f0_stdlibs_filetest.gno:19: bigint does not implement .uverse.error diff --git a/gnovm/tests/files/types/0f1_filetest.gno b/gnovm/tests/files/types/0f1_stdlibs_filetest.gno similarity index 80% rename from gnovm/tests/files/types/0f1_filetest.gno rename to gnovm/tests/files/types/0f1_stdlibs_filetest.gno index 255cfb2b170..0c221be5cf9 100644 --- a/gnovm/tests/files/types/0f1_filetest.gno +++ b/gnovm/tests/files/types/0f1_stdlibs_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f1_filetest.gno:19: int64 does not implement .uverse.error +// main/files/types/0f1_stdlibs_filetest.gno:19: int64 does not implement .uverse.error diff --git a/gnovm/tests/files/types/0f26_filetest.gno b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno similarity index 78% rename from gnovm/tests/files/types/0f26_filetest.gno rename to gnovm/tests/files/types/0f26_stdlibs_filetest.gno index a05d236f661..5c4ed0646d2 100644 --- a/gnovm/tests/files/types/0f26_filetest.gno +++ b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0f26_filetest.gno:19: operator > not defined on: .uverse.error +// main/files/types/0f26_stdlibs_filetest.gno:19: operator > not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f27_filetest.gno b/gnovm/tests/files/types/0f27_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/0f27_filetest.gno rename to gnovm/tests/files/types/0f27_stdlibs_filetest.gno index 0731f838d5c..2115456eac1 100644 --- a/gnovm/tests/files/types/0f27_filetest.gno +++ b/gnovm/tests/files/types/0f27_stdlibs_filetest.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/types/0f27_filetest.gno:13: operator > not defined on: .uverse.error +// main/files/types/0f27_stdlibs_filetest.gno:13: operator > not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f8_filetest.gno b/gnovm/tests/files/types/0f8_stdlibs_filetest.gno similarity index 79% rename from gnovm/tests/files/types/0f8_filetest.gno rename to gnovm/tests/files/types/0f8_stdlibs_filetest.gno index 114655295f5..8282621df1d 100644 --- a/gnovm/tests/files/types/0f8_filetest.gno +++ b/gnovm/tests/files/types/0f8_stdlibs_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0f8_filetest.gno:19: int64 does not implement .uverse.error +// main/files/types/0f8_stdlibs_filetest.gno:19: int64 does not implement .uverse.error diff --git a/gnovm/tests/files/types/13f0_filetest.gno b/gnovm/tests/files/types/13f0_stdlibs_filetest.gno similarity index 71% rename from gnovm/tests/files/types/13f0_filetest.gno rename to gnovm/tests/files/types/13f0_stdlibs_filetest.gno index c27fa805169..7d4ccdc0fc8 100644 --- a/gnovm/tests/files/types/13f0_filetest.gno +++ b/gnovm/tests/files/types/13f0_stdlibs_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/13f0_filetest.gno:20: invalid operation: mismatched types int and .uverse.error +// main/files/types/13f0_stdlibs_filetest.gno:20: invalid operation: mismatched types int and .uverse.error diff --git a/gnovm/tests/files/types/13f1_filetest.gno b/gnovm/tests/files/types/13f1_stdlibs_filetest.gno similarity index 81% rename from gnovm/tests/files/types/13f1_filetest.gno rename to gnovm/tests/files/types/13f1_stdlibs_filetest.gno index 817f2b6dac2..48a6c75c4b7 100644 --- a/gnovm/tests/files/types/13f1_filetest.gno +++ b/gnovm/tests/files/types/13f1_stdlibs_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/13f1_filetest.gno:21: invalid operation: mismatched types main.Error and .uverse.error +// main/files/types/13f1_stdlibs_filetest.gno:21: invalid operation: mismatched types main.Error and .uverse.error diff --git a/gnovm/tests/files/types/13f2_filetest.gno b/gnovm/tests/files/types/13f2_stdlibs_filetest.gno similarity index 90% rename from gnovm/tests/files/types/13f2_filetest.gno rename to gnovm/tests/files/types/13f2_stdlibs_filetest.gno index c323d24ed95..f218300c53f 100644 --- a/gnovm/tests/files/types/13f2_filetest.gno +++ b/gnovm/tests/files/types/13f2_stdlibs_filetest.gno @@ -42,4 +42,4 @@ func main() { } // Error: -// main/files/types/13f2_filetest.gno:40: operator += not defined on: .uverse.error +// main/files/types/13f2_stdlibs_filetest.gno:40: operator += not defined on: .uverse.error diff --git a/gnovm/tests/files/types/14f0_filetest.gno b/gnovm/tests/files/types/14f0_stdlibs_filetest.gno similarity index 71% rename from gnovm/tests/files/types/14f0_filetest.gno rename to gnovm/tests/files/types/14f0_stdlibs_filetest.gno index bc09ab42871..4177a20d602 100644 --- a/gnovm/tests/files/types/14f0_filetest.gno +++ b/gnovm/tests/files/types/14f0_stdlibs_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/14f0_filetest.gno:20: invalid operation: mismatched types int and .uverse.error +// main/files/types/14f0_stdlibs_filetest.gno:20: invalid operation: mismatched types int and .uverse.error diff --git a/gnovm/tests/files/types/14f1_filetest.gno b/gnovm/tests/files/types/14f1_stdlibs_filetest.gno similarity index 72% rename from gnovm/tests/files/types/14f1_filetest.gno rename to gnovm/tests/files/types/14f1_stdlibs_filetest.gno index 6cebbd719aa..a26fdf054ba 100644 --- a/gnovm/tests/files/types/14f1_filetest.gno +++ b/gnovm/tests/files/types/14f1_stdlibs_filetest.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/types/14f1_filetest.gno:18: invalid operation: mismatched types main.Error and .uverse.error +// main/files/types/14f1_stdlibs_filetest.gno:18: invalid operation: mismatched types main.Error and .uverse.error diff --git a/gnovm/tests/files/types/14f2_filetest.gno b/gnovm/tests/files/types/14f2_stdlibs_filetest.gno similarity index 90% rename from gnovm/tests/files/types/14f2_filetest.gno rename to gnovm/tests/files/types/14f2_stdlibs_filetest.gno index abfb343706b..7ccdebaadbd 100644 --- a/gnovm/tests/files/types/14f2_filetest.gno +++ b/gnovm/tests/files/types/14f2_stdlibs_filetest.gno @@ -42,4 +42,4 @@ func main() { } // Error: -// main/files/types/14f2_filetest.gno:40: operator -= not defined on: .uverse.error +// main/files/types/14f2_stdlibs_filetest.gno:40: operator -= not defined on: .uverse.error diff --git a/gnovm/tests/files/types/1f0_filetest.gno b/gnovm/tests/files/types/1f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/1f0_filetest.gno rename to gnovm/tests/files/types/1f0_stdlibs_filetest.gno index a673615effe..06411f00584 100644 --- a/gnovm/tests/files/types/1f0_filetest.gno +++ b/gnovm/tests/files/types/1f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/1f0_filetest.gno:19: operator + not defined on: .uverse.error +// main/files/types/1f0_stdlibs_filetest.gno:19: operator + not defined on: .uverse.error diff --git a/gnovm/tests/files/types/1f1_filetest.gno b/gnovm/tests/files/types/1f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/1f1_filetest.gno rename to gnovm/tests/files/types/1f1_stdlibs_filetest.gno index 4f66992c8cb..76a880f2c5d 100644 --- a/gnovm/tests/files/types/1f1_filetest.gno +++ b/gnovm/tests/files/types/1f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/1f1_filetest.gno:19: operator + not defined on: .uverse.error +// main/files/types/1f1_stdlibs_filetest.gno:19: operator + not defined on: .uverse.error diff --git a/gnovm/tests/files/types/1f6_filetest.gno b/gnovm/tests/files/types/1f6_stdlibs_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f6_filetest.gno rename to gnovm/tests/files/types/1f6_stdlibs_filetest.gno diff --git a/gnovm/tests/files/types/1f7_filetest.gno b/gnovm/tests/files/types/1f7_stdlibs_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f7_filetest.gno rename to gnovm/tests/files/types/1f7_stdlibs_filetest.gno diff --git a/gnovm/tests/files/types/1f8_filetest.gno b/gnovm/tests/files/types/1f8_stdlibs_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f8_filetest.gno rename to gnovm/tests/files/types/1f8_stdlibs_filetest.gno diff --git a/gnovm/tests/files/types/1f9_filetest.gno b/gnovm/tests/files/types/1f9_stdlibs_filetest.gno similarity index 81% rename from gnovm/tests/files/types/1f9_filetest.gno rename to gnovm/tests/files/types/1f9_stdlibs_filetest.gno index 146f8d09492..ad5fffd45f8 100644 --- a/gnovm/tests/files/types/1f9_filetest.gno +++ b/gnovm/tests/files/types/1f9_stdlibs_filetest.gno @@ -32,4 +32,4 @@ func main() { } // Error: -// main/files/types/1f9_filetest.gno:27: main.animal does not implement .uverse.error +// main/files/types/1f9_stdlibs_filetest.gno:27: main.animal does not implement .uverse.error diff --git a/gnovm/tests/files/types/2f0_filetest.gno b/gnovm/tests/files/types/2f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/2f0_filetest.gno rename to gnovm/tests/files/types/2f0_stdlibs_filetest.gno index a665ce179b6..d56001a9b68 100644 --- a/gnovm/tests/files/types/2f0_filetest.gno +++ b/gnovm/tests/files/types/2f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/2f0_filetest.gno:19: operator - not defined on: .uverse.error +// main/files/types/2f0_stdlibs_filetest.gno:19: operator - not defined on: .uverse.error diff --git a/gnovm/tests/files/types/2f1_filetest.gno b/gnovm/tests/files/types/2f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/2f1_filetest.gno rename to gnovm/tests/files/types/2f1_stdlibs_filetest.gno index 16eede87661..028a85b675b 100644 --- a/gnovm/tests/files/types/2f1_filetest.gno +++ b/gnovm/tests/files/types/2f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/2f1_filetest.gno:19: operator - not defined on: .uverse.error +// main/files/types/2f1_stdlibs_filetest.gno:19: operator - not defined on: .uverse.error diff --git a/gnovm/tests/files/types/3f0_filetest.gno b/gnovm/tests/files/types/3f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/3f0_filetest.gno rename to gnovm/tests/files/types/3f0_stdlibs_filetest.gno index 8d9d1817029..540c1cd9476 100644 --- a/gnovm/tests/files/types/3f0_filetest.gno +++ b/gnovm/tests/files/types/3f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/3f0_filetest.gno:19: operator * not defined on: .uverse.error +// main/files/types/3f0_stdlibs_filetest.gno:19: operator * not defined on: .uverse.error diff --git a/gnovm/tests/files/types/3f1_filetest.gno b/gnovm/tests/files/types/3f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/3f1_filetest.gno rename to gnovm/tests/files/types/3f1_stdlibs_filetest.gno index 8edc5cc2e98..56ff40457fd 100644 --- a/gnovm/tests/files/types/3f1_filetest.gno +++ b/gnovm/tests/files/types/3f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/3f1_filetest.gno:19: operator * not defined on: .uverse.error +// main/files/types/3f1_stdlibs_filetest.gno:19: operator * not defined on: .uverse.error diff --git a/gnovm/tests/files/types/4f0_filetest.gno b/gnovm/tests/files/types/4f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/4f0_filetest.gno rename to gnovm/tests/files/types/4f0_stdlibs_filetest.gno index 5b1f5df3430..03456e40d50 100644 --- a/gnovm/tests/files/types/4f0_filetest.gno +++ b/gnovm/tests/files/types/4f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/4f0_filetest.gno:19: operator / not defined on: .uverse.error +// main/files/types/4f0_stdlibs_filetest.gno:19: operator / not defined on: .uverse.error diff --git a/gnovm/tests/files/types/4f1_filetest.gno b/gnovm/tests/files/types/4f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/4f1_filetest.gno rename to gnovm/tests/files/types/4f1_stdlibs_filetest.gno index 52e1d7612a2..cbd90a9d0e3 100644 --- a/gnovm/tests/files/types/4f1_filetest.gno +++ b/gnovm/tests/files/types/4f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/4f1_filetest.gno:19: operator / not defined on: .uverse.error +// main/files/types/4f1_stdlibs_filetest.gno:19: operator / not defined on: .uverse.error diff --git a/gnovm/tests/files/types/5f0_filetest.gno b/gnovm/tests/files/types/5f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/5f0_filetest.gno rename to gnovm/tests/files/types/5f0_stdlibs_filetest.gno index 52bb636e087..233ba6f64b3 100644 --- a/gnovm/tests/files/types/5f0_filetest.gno +++ b/gnovm/tests/files/types/5f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/5f0_filetest.gno:19: operator % not defined on: .uverse.error +// main/files/types/5f0_stdlibs_filetest.gno:19: operator % not defined on: .uverse.error diff --git a/gnovm/tests/files/types/5f1_filetest.gno b/gnovm/tests/files/types/5f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/5f1_filetest.gno rename to gnovm/tests/files/types/5f1_stdlibs_filetest.gno index 7c5d88e3c3c..91120567d40 100644 --- a/gnovm/tests/files/types/5f1_filetest.gno +++ b/gnovm/tests/files/types/5f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/5f1_filetest.gno:19: operator % not defined on: .uverse.error +// main/files/types/5f1_stdlibs_filetest.gno:19: operator % not defined on: .uverse.error diff --git a/gnovm/tests/files/types/6f0_filetest.gno b/gnovm/tests/files/types/6f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/6f0_filetest.gno rename to gnovm/tests/files/types/6f0_stdlibs_filetest.gno index f7d3c3dbef6..84171f05703 100644 --- a/gnovm/tests/files/types/6f0_filetest.gno +++ b/gnovm/tests/files/types/6f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/6f0_filetest.gno:19: operator & not defined on: .uverse.error +// main/files/types/6f0_stdlibs_filetest.gno:19: operator & not defined on: .uverse.error diff --git a/gnovm/tests/files/types/6f1_filetest.gno b/gnovm/tests/files/types/6f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/6f1_filetest.gno rename to gnovm/tests/files/types/6f1_stdlibs_filetest.gno index f0e7a42c63c..824c1630a6a 100644 --- a/gnovm/tests/files/types/6f1_filetest.gno +++ b/gnovm/tests/files/types/6f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/6f1_filetest.gno:19: operator & not defined on: .uverse.error +// main/files/types/6f1_stdlibs_filetest.gno:19: operator & not defined on: .uverse.error diff --git a/gnovm/tests/files/types/7f0_filetest.gno b/gnovm/tests/files/types/7f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/7f0_filetest.gno rename to gnovm/tests/files/types/7f0_stdlibs_filetest.gno index a90fd3e0902..5ea7e257e82 100644 --- a/gnovm/tests/files/types/7f0_filetest.gno +++ b/gnovm/tests/files/types/7f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/7f0_filetest.gno:19: operator | not defined on: .uverse.error +// main/files/types/7f0_stdlibs_filetest.gno:19: operator | not defined on: .uverse.error diff --git a/gnovm/tests/files/types/7f1_filetest.gno b/gnovm/tests/files/types/7f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/7f1_filetest.gno rename to gnovm/tests/files/types/7f1_stdlibs_filetest.gno index d901e3af7ca..28f4a1483fc 100644 --- a/gnovm/tests/files/types/7f1_filetest.gno +++ b/gnovm/tests/files/types/7f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/7f1_filetest.gno:19: operator | not defined on: .uverse.error +// main/files/types/7f1_stdlibs_filetest.gno:19: operator | not defined on: .uverse.error diff --git a/gnovm/tests/files/types/8f0_filetest.gno b/gnovm/tests/files/types/8f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/8f0_filetest.gno rename to gnovm/tests/files/types/8f0_stdlibs_filetest.gno index 6e0b3f76a03..5a37308ff4a 100644 --- a/gnovm/tests/files/types/8f0_filetest.gno +++ b/gnovm/tests/files/types/8f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/8f0_filetest.gno:19: operator ^ not defined on: .uverse.error +// main/files/types/8f0_stdlibs_filetest.gno:19: operator ^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/8f1_filetest.gno b/gnovm/tests/files/types/8f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/8f1_filetest.gno rename to gnovm/tests/files/types/8f1_stdlibs_filetest.gno index 9e72a7609f2..8020e24f2fd 100644 --- a/gnovm/tests/files/types/8f1_filetest.gno +++ b/gnovm/tests/files/types/8f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/8f1_filetest.gno:19: operator ^ not defined on: .uverse.error +// main/files/types/8f1_stdlibs_filetest.gno:19: operator ^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/9f0_filetest.gno b/gnovm/tests/files/types/9f0_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/9f0_filetest.gno rename to gnovm/tests/files/types/9f0_stdlibs_filetest.gno index bd169eb32e0..7c97f2c37f1 100644 --- a/gnovm/tests/files/types/9f0_filetest.gno +++ b/gnovm/tests/files/types/9f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/9f0_filetest.gno:19: operator &^ not defined on: .uverse.error +// main/files/types/9f0_stdlibs_filetest.gno:19: operator &^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/9f1_filetest.gno b/gnovm/tests/files/types/9f1_stdlibs_filetest.gno similarity index 74% rename from gnovm/tests/files/types/9f1_filetest.gno rename to gnovm/tests/files/types/9f1_stdlibs_filetest.gno index ecb77efbe74..9124443e6e5 100644 --- a/gnovm/tests/files/types/9f1_filetest.gno +++ b/gnovm/tests/files/types/9f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/9f1_filetest.gno:19: operator &^ not defined on: .uverse.error +// main/files/types/9f1_stdlibs_filetest.gno:19: operator &^ not defined on: .uverse.error diff --git a/gnovm/tests/files/types/readme/README.md b/gnovm/tests/files/types/readme/README.md deleted file mode 100644 index a906b907e91..00000000000 --- a/gnovm/tests/files/types/readme/README.md +++ /dev/null @@ -1,301 +0,0 @@ -Context: - -The problem is from []... - - -`package main - -import ( -"errors" -"strconv" -) - -type Error int64 - -func (e Error) Error() string { -return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { -if Error(1) == errCmp { -println("what the firetruck?") -} else { -println("something else") -} -}` - - - -first,why this compiles? the reason for this is Error(1) satisfies interface of error, which indicates Error(1) can be assigned to errCmp, Error(1) and errCmp is comparable. -"lhs is assignable to rhs, or vice versa", according to spec. - -But it gives out incorrect result. in the code above, it should give out :// something else -but gives out: what the firetruck? - -The cause for this is about type check, in the case, the Error(1) and errCmp is both mistakenly treated as int64, which -is the underlying type if Error(1), the value of LHS after evaluation is 1 and the RHS is 0, so the == check will give false. -as a simple prove, if you check this: Error(0) = errCmp, the result will be true. - -In the right way, the LHS and RHS has different underlying type, so the result should be false. - -Deeper analysis: - -Type mix check missing - -`// both typed(different) const -func main() { -println(int(1) == int8(1)) -} - -in this case, it should not compile for the mismatch of type, but it works(as unexpected). -the reason for this is the missing of a regular type check, the type is cast forcibly while it should not。 - - -Operators check missing or incorrect -`package main - -// one untyped const, one typed const -func main() { -println(1 / "a") -} - -// Error: -// main/files/types/4b2_filetest.gno:5: operator / not defined on: string` -it should give out this error, but gives ... - -The reason for this is in golang, binary expression, unary expression, and INC/DEC stmt are close related to operators. e.g. for ADD, a + b, a and b must be both numericOrString, - for Sub, a - b, where a and b must be both numeric. - - The current situation is there check around operators happens in runtime, while they should be executed in preprocess stage. - this non-trivial as for performance, we want these check happens in compile time - - - -3.unamed to named conversion missed - -`package main - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { -return true -} - -func Gen() nat { -n := []word{0} -return n -} - -// mapLit -func main() { -r := Gen() -switch r.(type) { -case nat: -println("nat") -println(r.add()) -default: -println("should not happen") -} -} - -// Output: -// nat -// true` - -unamed (composite) literals should be converted to named implicitly in preprocess time. - - -To sums up, the solution is: - -Flow: - regular type check for const, with some specific case whitelisted, e.g. array key, and nativeType excluded - - checkOp for binary expr, unary expr and inc/dec stmt - comparable, == != - - arith + - ... - isNumericOrString - - Note: this only check dt, - - checkOperand for special case, in / and %, divisor should not be zero. - - if check pass(or in cases with no Op to check), carry on checking if the corresponding side can be assigned to dt, throught assignable. - regular type check for others, check assignable. - - - - - binaryExpression/unaryExpression - check comparison: - assignableTo(type), LHS or RHS is assignable to the other - isIdentical - primitive, struct, map, ... - untyped -> typed - unnamed -> named - type(Impl) -> interface - - EQU NEQ - LHS, RHS both comparable - - LSS, GTR,,, - LHS, RHS ordered - - NOTE: above no requre for match type, e,g. Main.Error and error to compare - - // else ops - first check (if typed) LHS, RHS, panic mismatch directly - check predicates - check special case like zero divisor - check implicit convertable, same logic assignableTo(Type) - - - - - - - -Scenarios: - binary expression: - left expression [Op] right expression - - // both const - const [Op] const - left typed Op right typed - left untyped Op right typed - left typed Op right untyped - left untyped Op right untyped // println(1.0 * 0) - // one is const - Not const [Op] const - Not const [Op] untyped const - Not const [Op] typed const - const [Op] Not const - untyped const [Op] const - typed const [Op] const - - // both not const - Not const [Op] Not const - -Untyped Convert rule: - - here describes convert rules on both prime or composite values - - // untyped value can be converted to its correspondence value when: - // a) it's (untyped) const, and conform to convert rules, - e.g. println(int(0) + 1) will work - e.g. println(int(0) + "a") will not work - - // b) it's declared type of value, like type Error int8, 0 will be able to converted to Error - e.g. - type Error int64 - func main() { - println(Error(0) == "0") // will work - println(Error(0) == "a") // not work - println(Error(0) == []string{"hello"}) // not work - } - - actually, declard type is a special case of convert rule - -Special case: - - when one of LHS or RHS is interface, and the other implement the interface, it will comform some - `equlaity` rule, which means they are treated as equal in type-check in compile time, but do the - strict check in runtime. TODO: understand wo golang really do in runtime - - This is pretty similar with the `declared type rule` as above, the both conforms some specific constraint - -Operators: - - // general rule, arith operators has higher precedence, required `strict` check - // In contrast, equlity == or != has a lower precedence - // in case of +=, its precedence is a combination of + and =, it's given + precedence - - ADD // + - SUB // - - MUL // * - QUO // / - REM // % - - BAND // & - BOR // | - XOR // ^ - SHL // << - SHR // >> - BAND_NOT // &^ - - LAND // && - LOR // || - ARROW // <- - INC // ++ - DEC // -- - - ------------------------------------------------------- - - ADD_ASSIGN // += - SUB_ASSIGN // -= - MUL_ASSIGN // *= - QUO_ASSIGN // /= - REM_ASSIGN // %= - BAND_ASSIGN // &= - BOR_ASSIGN // |= - XOR_ASSIGN // ^= - SHL_ASSIGN // <<= - SHR_ASSIGN // >>= - BAND_NOT_ASSIGN // &^= - - ------------------------------------------------------- - - EQL // == - LSS // < - GTR // > - ASSIGN // = - NOT // ! - - NEQ // != - LEQ // <= - GEQ // >= - DEFINE // := - - -others: - callExpr - params, return value(multi) - - untyped composite value is not const, but a unamed type? - -thoughts: - rule based code gen, Peg? - - -TODOs: - - // TODO: dec value representation - // TODO: Current flow : check op operand, check type convertable, and convert, and check type match again, means, this kind of check should still in preprocess - // TODO: preCheck->Convert->postCheck, all in `checkOrConvertType` - - - this is for arith and comparable operators - - specical case: bigInt to gonative time.Month. skipped - - mix of numeric types - - -NOTE: - - // in 13f1, indicates that, in preCheck, - // if dt is not match with op - // else if LHS,RHS is typed and mismatched, panic - // else, check untyped(const), unnamed(composite) cases - *** is straight forward, if we have right and left types, use it. how about interface and declared types? if LHS and RHS in one of this? so not only untyped passthrough, these latter two needs passthrouh from preCheck too. *** - - // wired that == accepts LHS impl RHS or visa versa, while += not accpet this - - - // only change for binary unary ,assign ,etc, op related, using another func like checkOperand, else checkOrConvert remains \ No newline at end of file From af0de1160eab80effef26ba8aec7c7159e4fc138 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 12:21:51 +0800 Subject: [PATCH 049/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 21 +++++++++++---------- gnovm/tests/files/types/0a1e_filetest.gno | 2 +- gnovm/tests/files/types/26a4_filetest.gno | 10 ++++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 gnovm/tests/files/types/26a4_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 39fde476eb3..fbe3c8c8fdf 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -879,7 +879,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // we don't yet know what this type should be, // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). - } else { + } else { // not shift // convert n.Left to right type. checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) @@ -887,19 +887,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else if !isUntyped(lcx.T) { // left is typed const, right is not const checkOp(store, last, &n.Left, rt, n.Op, true) - if n.Op == SHR || n.Op == SHL { + if n.Op == SHR || n.Op == SHL { // refer to 26a3_filetest debugPP.Println("-----shift-----") - convertConstType(store, last, &n.Left, lt, false) // bypass check - } else { + // do nothing, final type is bind to left + //convertConstType(store, last, &n.Left, lt, false) // bypass check + } else { // refer to 26a4_filetest checkOrConvertType(store, last, &n.Left, rt, false) } - } else if lcx.T == nil { // LHS is nil // XXX? - debugPP.Println("lcx.T is nil") - // convert n.Left to typed-nil type. - checkOp(store, last, &n.Left, rt, n.Op, true) - checkOrConvertType(store, last, &n.Left, rt, false) + //} else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable + // debugPP.Println("lcx.T is nil") + // // convert n.Left to typed-nil type. + // checkOp(store, last, &n.Left, rt, n.Op, true) + // checkOrConvertType(store, last, &n.Left, rt, false) } - } else if ric { + } else if ric { // right is const, left is not--- if isUntyped(rcx.T) { // Left not, Right untyped const ---------------- if isShift { diff --git a/gnovm/tests/files/types/0a1e_filetest.gno b/gnovm/tests/files/types/0a1e_filetest.gno index cac0716b937..2795d618e91 100644 --- a/gnovm/tests/files/types/0a1e_filetest.gno +++ b/gnovm/tests/files/types/0a1e_filetest.gno @@ -6,7 +6,7 @@ type S struct { func main() { var s = S{ - expected: `hello`[:], // this is not converted + expected: `hello`[:], } a := "hello" println(a == s.expected) diff --git a/gnovm/tests/files/types/26a4_filetest.gno b/gnovm/tests/files/types/26a4_filetest.gno new file mode 100644 index 00000000000..1646346b158 --- /dev/null +++ b/gnovm/tests/files/types/26a4_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := uint(1) + println(uint64(1) == a) + println(r) +} + +// Error: +// main/files/types/26a4_filetest.gno:5: cannot use uint64 as uint From e673dac9dffe5e1c9cf64c5c2a009d378f2fd6d4 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 12:22:30 +0800 Subject: [PATCH 050/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index fbe3c8c8fdf..d6333a39f34 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -890,7 +890,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if n.Op == SHR || n.Op == SHL { // refer to 26a3_filetest debugPP.Println("-----shift-----") // do nothing, final type is bind to left - //convertConstType(store, last, &n.Left, lt, false) // bypass check + // convertConstType(store, last, &n.Left, lt, false) // bypass check } else { // refer to 26a4_filetest checkOrConvertType(store, last, &n.Left, rt, false) } From cfcbddae87b97e4a0fd5ba9a7f63949196785e57 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 12:42:01 +0800 Subject: [PATCH 051/193] restore --- gnovm/pkg/gnolang/preprocess.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index d6333a39f34..0d6a948befb 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -894,11 +894,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // refer to 26a4_filetest checkOrConvertType(store, last, &n.Left, rt, false) } - //} else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable - // debugPP.Println("lcx.T is nil") - // // convert n.Left to typed-nil type. - // checkOp(store, last, &n.Left, rt, n.Op, true) - // checkOrConvertType(store, last, &n.Left, rt, false) + } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable + debugPP.Println("lcx.T is nil") + // convert n.Left to typed-nil type. + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) } } else if ric { // right is const, left is not--- if isUntyped(rcx.T) { From 268e84902cb78dbffd1972b06b1d452ff38b677f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 21:25:36 +0800 Subject: [PATCH 052/193] fix shift --- gnovm/pkg/gnolang/preprocess.go | 104 ++++++++++++---------- gnovm/tests/files/types/26a5_filetest.gno | 13 +++ gnovm/tests/files/types/26a6_filetest.gno | 10 +++ gnovm/tests/files/types/26a7_filetest.gno | 9 ++ gnovm/tests/files/types/28a0_filetest.gno | 9 ++ gnovm/tests/files/types/28a1_filetest.gno | 9 ++ 6 files changed, 107 insertions(+), 47 deletions(-) create mode 100644 gnovm/tests/files/types/26a5_filetest.gno create mode 100644 gnovm/tests/files/types/26a6_filetest.gno create mode 100644 gnovm/tests/files/types/26a7_filetest.gno create mode 100644 gnovm/tests/files/types/28a0_filetest.gno create mode 100644 gnovm/tests/files/types/28a1_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0d6a948befb..09deb4f8db8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -28,6 +28,10 @@ func init() { binaryPredicates[QUO_ASSIGN] = isNumeric binaryPredicates[REM] = isIntNum binaryPredicates[REM_ASSIGN] = isIntNum + binaryPredicates[SHL] = isNumeric + binaryPredicates[SHL_ASSIGN] = isNumeric + binaryPredicates[SHR] = isNumeric + binaryPredicates[SHR_ASSIGN] = isNumeric // bit op binaryPredicates[BAND] = isIntNum @@ -795,18 +799,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR - if isShift && baseOf(rt) != UintType { - // convert n.Right to (gno) uint type, - rn := Expr(Call("uint", n.Right)) - // reset/create n2 to preprocess right child. - n2 := &BinaryExpr{ - Left: n.Left, - Op: n.Op, - Right: rn, - } - resn := Preprocess(store, last, n2) - return resn, TRANS_CONTINUE + if isShift { + checkOp(store, last, &n.Left, lt, n.Op, true) + if baseOf(rt) != UintType { + // checkOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* + // convert n.Right to (gno) uint type, + rn := Expr(Call("uint", n.Right)) + // reset/create n2 to preprocess right child. + n2 := &BinaryExpr{ + Left: n.Left, + Op: n.Op, + Right: rn, + } + resn := Preprocess(store, last, n2) + return resn, TRANS_CONTINUE + } } + // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) @@ -817,6 +826,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. // refer to 0a0_filetest + //if isShift { + // checkOp(store, last, &n.Left, lt, n.Op, true) + //} if !isShift { cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // this always implies untyped>? @@ -844,10 +856,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Then, evaluate the expression. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE - } else if isUntyped(lcx.T) { + } else if isUntyped(lcx.T) { // untyped -> not const, e.g. var a int = 1 debugPP.Printf("left: %v is untyped const, right: %v is not const \n", lt, rt) // Left untyped const, Right not const ---------------- - if rnt, ok := rt.(*NativeType); ok { // TODO: check this case + if rnt, ok := rt.(*NativeType); ok { // typed <- untyped, native TODO: check this case debugPP.Println("right is native type") if isShift { panic("should not happen") @@ -885,13 +897,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false) } } - } else if !isUntyped(lcx.T) { // left is typed const, right is not const + } else if !isUntyped(lcx.T) { // left is typed const, right is not const(also typed) checkOp(store, last, &n.Left, rt, n.Op, true) - if n.Op == SHR || n.Op == SHL { // refer to 26a3_filetest + // if n.Op == SHR || n.Op == SHL { + if isShift { // refer to 26a3_filetest debugPP.Println("-----shift-----") // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check } else { // refer to 26a4_filetest + checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable @@ -942,24 +956,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else if rcx.T == nil { // RHS is nil debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest, 1f8_filetest + // TODO: shift // convert n.Right to typed-nil type. checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) - } else if !isShift { // TODO: consider this + } else if !isShift { // left not const(typed), right is typed const checkOp(store, last, &n.Right, lt, n.Op, true) checkOrConvertType(store, last, &n.Right, lt, false) } - } else { + if isQuoOrRem(n.Op) { + checkOperand(rcx) + } + } else { // ---both not const--- if n.Op == SHL || n.Op == SHR { // shift operator, nothing yet to do. code like this will work - //package main - // - //type Error int8 - //type index int8 - // - //func main() { - // println(Error(1) << index(0)) - //} } else if lnt, ok := lt.(*NativeType); ok { if debug { if !isShift { @@ -1009,18 +1019,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { "incompatible types in binary expression: %v %v %v", n.Left, n.Op, n.Right)) } - } else { + } else { // left untyped, right typed debugPP.Println("left untyped, right is typed") checkOp(store, last, &n.Left, rt, n.Op, true) checkOrConvertType(store, last, &n.Left, rt, false) } - } else if riu { - checkOp(store, last, &n.Right, lt, n.Op, true) - checkOrConvertType(store, last, &n.Right, lt, false) - } else { - debugPP.Println("else") - checkOp(store, last, &n.Left, rt, n.Op, true) - checkOrConvertType(store, last, &n.Left, rt, false) + } else if riu { // left typed, right untyped + if !isShift { + checkOp(store, last, &n.Right, lt, n.Op, true) + checkOrConvertType(store, last, &n.Right, lt, false) + } + } else { // both typed vars, refer to 0a1f_filetest + debugPP.Printf("else, is lt untyped: %t, is rt untyped: %t \n", liu, riu) + if !isShift { + checkOp(store, last, &n.Left, rt, n.Op, true) + checkOrConvertType(store, last, &n.Left, rt, false) + } } } } @@ -1037,7 +1051,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *NativeType: ft = store.Go2GnoType(cft.Type).(*FuncType) case *TypeType: - debugPP.Println("type type") if len(n.Args) != 1 { panic("type conversion requires single argument") } @@ -1594,17 +1607,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Printf("---AssignStmt---, Op: %v, LHS: %v, RHS:%v \n", n.Op, n.Lhs, n.Rhs) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { - debugPP.Println("define") - // lt := evalStaticTypeOf(store, last, n.Lhs) - // Rhs consts become default *ConstExprs. for _, rx := range n.Rhs { - debugPP.Println("convert if const") // NOTE: does nothing if rx is "nil". convertIfConst(store, last, rx) } if len(n.Lhs) > len(n.Rhs) { - debugPP.Println("lhs > rhs") // Unpack n.Rhs[0] to n.Lhs[:] if len(n.Rhs) != 1 { panic("should not happen") @@ -1720,8 +1728,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TODO: assert length lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion - checkOp(store, last, &n.Rhs[0], lt, n.Op, false) - checkOrConvertType(store, last, &n.Rhs[0], lt, false) + checkOp(store, last, &n.Rhs[0], lt, n.Op, true) + checkOrConvertType(store, last, &n.Rhs[0], lt, true) } else { // all else, like BAND_ASSIGN, etc debugPP.Println("case like: a, b = x, y") // General case: a, b = x, y. @@ -1730,8 +1738,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // is x or y is untyped, convert, else check type // rt := evalStaticTypeOf(store, last, n.Rhs[i]) // all else check - checkOp(store, last, &n.Rhs[i], lt, n.Op, false) - checkOrConvertType(store, last, &n.Rhs[i], lt, false) + checkOp(store, last, &n.Rhs[i], lt, n.Op, true) + checkOrConvertType(store, last, &n.Rhs[i], lt, true) } } } @@ -2555,9 +2563,9 @@ func isComparison(op Word) bool { } // check operand types with operators -func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool) { +func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binaryOrAssign bool) { var xt Type - if x != nil { // unaryExpr Todo: consider + if binaryOrAssign { if cx, ok := (*x).(*ConstExpr); ok { xt = cx.T } else if *x != nil { @@ -2565,8 +2573,8 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool } } - debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binary) - if !binary { + debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binaryOrAssign) + if !binaryOrAssign { if op == INC || op == DEC { if pred, ok := IncDecStmtPredicates[op]; ok { if !pred(dt) { @@ -2574,6 +2582,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool } } } + // unary if pred, ok := unaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2600,6 +2609,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binary bool panic("invalid comparison operator") } } else { + debugPP.Println("else---") // two steps of check: // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this diff --git a/gnovm/tests/files/types/26a5_filetest.gno b/gnovm/tests/files/types/26a5_filetest.gno new file mode 100644 index 00000000000..7d70cc3589a --- /dev/null +++ b/gnovm/tests/files/types/26a5_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + var r uint64 = 1 << int8(1) + fmt.Printf("%T \n", r) + println(r) +} + +// Output: +// uint64 +// 2 diff --git a/gnovm/tests/files/types/26a6_filetest.gno b/gnovm/tests/files/types/26a6_filetest.gno new file mode 100644 index 00000000000..e9d8065e967 --- /dev/null +++ b/gnovm/tests/files/types/26a6_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + r := a << 1 + println(r) +} + +// Error: +// main/files/types/26a6_filetest.gno:5: operator << not defined on: string diff --git a/gnovm/tests/files/types/26a7_filetest.gno b/gnovm/tests/files/types/26a7_filetest.gno new file mode 100644 index 00000000000..67fdc8b9d12 --- /dev/null +++ b/gnovm/tests/files/types/26a7_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := "hello" << 1 + println(r) +} + +// Error: +// main/files/types/26a7_filetest.gno:4: operator << not defined on: string diff --git a/gnovm/tests/files/types/28a0_filetest.gno b/gnovm/tests/files/types/28a0_filetest.gno new file mode 100644 index 00000000000..43b3ea3667c --- /dev/null +++ b/gnovm/tests/files/types/28a0_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := 1 + println(a / 0) +} + +// Error: +// main/files/types/28a0_filetest.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/28a1_filetest.gno b/gnovm/tests/files/types/28a1_filetest.gno new file mode 100644 index 00000000000..9f13276c132 --- /dev/null +++ b/gnovm/tests/files/types/28a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := 1 + println(a % 0) +} + +// Error: +// main/files/types/28a1_filetest.gno:5: invalid operation: division by zero From 097244e7309c46704a58f275ab899df94316f9de Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 12 Dec 2023 22:48:08 +0800 Subject: [PATCH 053/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 116 ++++++++++++++------- gnovm/tests/files/types/26a6a_filetest.gno | 10 ++ gnovm/tests/files/types/29a0_filetest.gno | 10 ++ 3 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 gnovm/tests/files/types/26a6a_filetest.gno create mode 100644 gnovm/tests/files/types/29a0_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 09deb4f8db8..41e26478938 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -14,34 +14,36 @@ var ( binaryPredicates = make(map[Word]f) unaryPredicates = make(map[Word]f) IncDecStmtPredicates = make(map[Word]f) + AssignStmtPredicates = make(map[Word]f) ) func init() { // add,sub,mul,quo,rem with assign + // TODO: *_assign is actually assign stmt binaryPredicates[ADD] = isNumericOrString - binaryPredicates[ADD_ASSIGN] = isNumericOrString + AssignStmtPredicates[ADD_ASSIGN] = isNumericOrString binaryPredicates[SUB] = isNumeric - binaryPredicates[SUB_ASSIGN] = isNumeric + AssignStmtPredicates[SUB_ASSIGN] = isNumeric binaryPredicates[MUL] = isNumeric - binaryPredicates[MUL_ASSIGN] = isNumeric + AssignStmtPredicates[MUL_ASSIGN] = isNumeric binaryPredicates[QUO] = isNumeric - binaryPredicates[QUO_ASSIGN] = isNumeric + AssignStmtPredicates[QUO_ASSIGN] = isNumeric binaryPredicates[REM] = isIntNum - binaryPredicates[REM_ASSIGN] = isIntNum + AssignStmtPredicates[REM_ASSIGN] = isIntNum binaryPredicates[SHL] = isNumeric - binaryPredicates[SHL_ASSIGN] = isNumeric + AssignStmtPredicates[SHL_ASSIGN] = isNumeric binaryPredicates[SHR] = isNumeric - binaryPredicates[SHR_ASSIGN] = isNumeric + AssignStmtPredicates[SHR_ASSIGN] = isNumeric // bit op binaryPredicates[BAND] = isIntNum - binaryPredicates[BAND_ASSIGN] = isIntNum + AssignStmtPredicates[BAND_ASSIGN] = isIntNum binaryPredicates[XOR] = isIntNum - binaryPredicates[XOR_ASSIGN] = isIntNum + AssignStmtPredicates[XOR_ASSIGN] = isIntNum binaryPredicates[BOR] = isIntNum - binaryPredicates[BOR_ASSIGN] = isIntNum + AssignStmtPredicates[BOR_ASSIGN] = isIntNum binaryPredicates[BAND_NOT] = isIntNum - binaryPredicates[BAND_NOT_ASSIGN] = isIntNum + AssignStmtPredicates[BAND_NOT_ASSIGN] = isIntNum // logic op binaryPredicates[LAND] = isBoolean binaryPredicates[LOR] = isBoolean @@ -795,12 +797,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: + debugPP.Println("---binaryExpr---, op: ", n.Op) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR if isShift { - checkOp(store, last, &n.Left, lt, n.Op, true) + checkOp(store, last, &n.Left, lt, n.Op, Binary) if baseOf(rt) != UintType { // checkOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* // convert n.Right to (gno) uint type, @@ -834,17 +837,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cmp < 0 { // this always implies untyped>? debugPP.Println("cmp < 0, ->") // convert n.Left to right type. - checkOp(store, last, &n.Left, rcx.T, n.Op, true) + checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false) } else if cmp == 0 { debugPP.Println("cmp == 0") // TODO: consider check dir in here - checkOp(store, last, &n.Left, rcx.T, n.Op, true) + checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false) } else { debugPP.Println("cmp > 0, <-") // convert n.Right to left type. - checkOp(store, last, &n.Right, lcx.T, n.Op, true) + checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false) } } @@ -867,7 +870,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOp(store, last, &n.Left, pt, n.Op, true) + checkOp(store, last, &n.Left, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, pt, false) // convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) @@ -893,25 +896,25 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // (e.g. from AssignStmt or other). } else { // not shift // convert n.Left to right type. - checkOp(store, last, &n.Left, rt, n.Op, true) + checkOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false) } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const(also typed) - checkOp(store, last, &n.Left, rt, n.Op, true) + checkOp(store, last, &n.Left, rt, n.Op, Binary) // if n.Op == SHR || n.Op == SHL { if isShift { // refer to 26a3_filetest debugPP.Println("-----shift-----") // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check } else { // refer to 26a4_filetest - checkOp(store, last, &n.Left, rt, n.Op, true) + checkOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false) } } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. - checkOp(store, last, &n.Left, rt, n.Op, true) + checkOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false) } } else if ric { // right is const, left is not--- @@ -933,7 +936,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOp(store, last, &n.Right, pt, n.Op, true) + checkOp(store, last, &n.Right, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, pt, false) // and convert result back. tx := constType(n, lnt) @@ -950,7 +953,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOp(store, last, &n.Right, lt, n.Op, true) + checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) } } @@ -958,10 +961,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest, 1f8_filetest // TODO: shift // convert n.Right to typed-nil type. - checkOp(store, last, &n.Right, lt, n.Op, true) + checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) } else if !isShift { // left not const(typed), right is typed const - checkOp(store, last, &n.Right, lt, n.Op, true) + checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) } if isQuoOrRem(n.Op) { @@ -1021,18 +1024,18 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // left untyped, right typed debugPP.Println("left untyped, right is typed") - checkOp(store, last, &n.Left, rt, n.Op, true) + checkOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false) } } else if riu { // left typed, right untyped if !isShift { - checkOp(store, last, &n.Right, lt, n.Op, true) + checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) } } else { // both typed vars, refer to 0a1f_filetest debugPP.Printf("else, is lt untyped: %t, is rt untyped: %t \n", liu, riu) if !isShift { - checkOp(store, last, &n.Left, rt, n.Op, true) + checkOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false) } } @@ -1326,11 +1329,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cx, ok := n.X.(*ConstExpr); ok { debugPP.Println("not native, ConstExpr") // checkOp, e.g. +a while a should be numeric - checkOp(store, last, nil, cx.T, n.Op, false) + checkOp(store, last, nil, cx.T, n.Op, Unary) cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } - checkOp(store, last, nil, xt, n.Op, false) + checkOp(store, last, nil, xt, n.Op, Unary) // TRANS_LEAVE ----------------------- case *CompositeLitExpr: @@ -1720,15 +1723,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // Special case if shift assign <<= or >>=. // TODO: no need here, like index convert - // checkOp(store, last, &n.Rhs[0], UintType, n.Op, false) // checkOrConvertType(store, last, &n.Rhs[0], UintType, false) convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check + lt := evalStaticTypeOf(store, last, n.Lhs[0]) + checkOp(store, last, &n.Lhs[0], lt, n.Op, Assign) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, // TODO: assert length lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion - checkOp(store, last, &n.Rhs[0], lt, n.Op, true) + checkOp(store, last, &n.Rhs[0], lt, n.Op, Assign) checkOrConvertType(store, last, &n.Rhs[0], lt, true) } else { // all else, like BAND_ASSIGN, etc debugPP.Println("case like: a, b = x, y") @@ -1738,7 +1742,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // is x or y is untyped, convert, else check type // rt := evalStaticTypeOf(store, last, n.Rhs[i]) // all else check - checkOp(store, last, &n.Rhs[i], lt, n.Op, true) + checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) checkOrConvertType(store, last, &n.Rhs[i], lt, true) } } @@ -1774,7 +1778,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *IncDecStmt: debugPP.Println("---IncDecStmt---") xt := evalStaticTypeOf(store, last, n.X) - checkOp(store, last, nil, xt, n.Op, false) + checkOp(store, last, nil, xt, n.Op, IncDec) // TRANS_LEAVE ----------------------- case *ForStmt: @@ -2562,10 +2566,19 @@ func isComparison(op Word) bool { } } +type checkMode int + +const ( + Binary = iota + Unary + IncDec + Assign +) + // check operand types with operators -func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binaryOrAssign bool) { +func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, mode checkMode) { var xt Type - if binaryOrAssign { + if mode == Binary || mode == Assign { if cx, ok := (*x).(*ConstExpr); ok { xt = cx.T } else if *x != nil { @@ -2573,8 +2586,8 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binaryOrAss } } - debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %t \n", xt, dt, op, binaryOrAssign) - if !binaryOrAssign { + debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %v \n", xt, dt, op, mode) + if mode == Unary || mode == IncDec { if op == INC || op == DEC { if pred, ok := IncDecStmtPredicates[op]; ok { if !pred(dt) { @@ -2608,8 +2621,31 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binaryOrAss default: panic("invalid comparison operator") } - } else { - debugPP.Println("else---") + } else if mode == Assign { + debugPP.Println("assign---") + if pred, ok := AssignStmtPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } + if op != ILLEGAL { + switch op { + case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: + // if both typed + if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped + if xt != nil && dt != nil { + if xt.TypeID() != dt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + } + } + debugPP.Println("typed and identical as isComparable") + } + default: + // Note: others no check, assign will be check in assignable + } + } + } + } else if mode == Binary { + debugPP.Println("binary---") // two steps of check: // first, check is the dt type satisfies op, the switch logic // second, xt can be converted to dt, this is done below this @@ -2621,7 +2657,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, binaryOrAss } if op != ILLEGAL { switch op { - case ADD, ADD_ASSIGN, SUB, SUB_ASSIGN, MUL, MUL_ASSIGN, QUO, QUO_ASSIGN, REM, REM_ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BAND_NOT, BAND_NOT_ASSIGN, XOR, XOR_ASSIGN, LAND, LOR: + case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: // if both typed if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped if xt != nil && dt != nil { diff --git a/gnovm/tests/files/types/26a6a_filetest.gno b/gnovm/tests/files/types/26a6a_filetest.gno new file mode 100644 index 00000000000..b92db4b4b9f --- /dev/null +++ b/gnovm/tests/files/types/26a6a_filetest.gno @@ -0,0 +1,10 @@ +package main + +// TODO: fix in assignment +func main() { + a := "hello" + a <<= 1 +} + +// Error: +// main/files/types/26a6a_filetest.gno:6: operator <<= not defined on: string \ No newline at end of file diff --git a/gnovm/tests/files/types/29a0_filetest.gno b/gnovm/tests/files/types/29a0_filetest.gno new file mode 100644 index 00000000000..bb4083e8935 --- /dev/null +++ b/gnovm/tests/files/types/29a0_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a += int(1) + println(a) +} + +// Output: +// 2 From 6858e8018363d9b027557e0ab61c2945d1742f89 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 13 Dec 2023 17:48:51 +0800 Subject: [PATCH 054/193] fixup --- gnovm/pkg/gnolang/op_assign.go | 46 +++--- gnovm/pkg/gnolang/op_binary.go | 99 ++++++++----- gnovm/pkg/gnolang/preprocess.go | 134 +++++++++--------- gnovm/pkg/gnolang/types.go | 22 +-- gnovm/tests/files/types/0f2b_filetest.gno | 28 ++++ gnovm/tests/files/types/0f2c_filetest.gno | 28 ++++ gnovm/tests/files/types/26a3_filetest.gno | 3 - .../tests/files/types/30a0_LAND_filetest.gno | 8 ++ .../tests/files/types/30a1_LAND_filetest.gno | 8 ++ .../tests/files/types/30a2_LAND_filetest.gno | 8 ++ .../tests/files/types/30a3_LAND_filetest.gno | 8 ++ .../tests/files/types/30a4_LAND_filetest.gno | 8 ++ 12 files changed, 262 insertions(+), 138 deletions(-) create mode 100644 gnovm/tests/files/types/0f2b_filetest.gno create mode 100644 gnovm/tests/files/types/0f2c_filetest.gno create mode 100644 gnovm/tests/files/types/30a0_LAND_filetest.gno create mode 100644 gnovm/tests/files/types/30a1_LAND_filetest.gno create mode 100644 gnovm/tests/files/types/30a2_LAND_filetest.gno create mode 100644 gnovm/tests/files/types/30a3_LAND_filetest.gno create mode 100644 gnovm/tests/files/types/30a4_LAND_filetest.gno diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index 0cc30861355..8d15669f7de 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -1,5 +1,7 @@ package gnolang +import "fmt" + func (m *Machine) doOpDefine() { s := m.PopStmt().(*AssignStmt) // Define each value evaluated for Lhs. @@ -50,7 +52,9 @@ func (m *Machine) doOpAddAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } // XXX HACK (until value persistence impl'd) @@ -73,9 +77,10 @@ func (m *Machine) doOpSubAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -96,9 +101,10 @@ func (m *Machine) doOpMulAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -119,9 +125,10 @@ func (m *Machine) doOpQuoAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -142,9 +149,10 @@ func (m *Machine) doOpRemAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -165,9 +173,10 @@ func (m *Machine) doOpBandAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -188,9 +197,10 @@ func (m *Machine) doOpBandnAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -211,9 +221,10 @@ func (m *Machine) doOpBorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -234,9 +245,10 @@ func (m *Machine) doOpXorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + if !isIdenticalType(lv.TV.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) + } } - // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 1ff808bf4c0..ac60bb089ef 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -40,14 +40,22 @@ func (m *Machine) doOpBinary1() { } } +// XXX. in preprocess stage, we have checked: +// 1. if dt(type of lhs or rhs, depends on its convert dir); +// 2. whether lt and rt is identical if they are typed(typeID ==); or if one is not typed, but is +// assignable to the other side. +// so, logically, there's no need to check the type equivalence here. leave the check in debug mode. +// NOTE: one exception is for == and !=, where there's a relaxed scope of operands for compare(maybeIdentical), +// there might be cases lt and rt is not identical. e.g. two different types conform same interface. func (m *Machine) doOpLor() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // set result in lv. if isUntyped(lv.T) { lv.T = rv.T @@ -60,9 +68,10 @@ func (m *Machine) doOpLand() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // set result in lv. if isUntyped(lv.T) { lv.T = rv.T @@ -77,18 +86,14 @@ func (m *Machine) doOpEql() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - if debug { - assertEqualityTypes(lv.T, rv.T) - } + //if debug { + // assertEqualityTypes(lv.T, rv.T) + //} debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - // TODO: this should be in preprocess too - // TODO: only assert here - if isBinOperandTypeIdentical(lv.T, rv.T) { - debugPP.Println("-----type identical------") + if isIdenticalType(lv.T, rv.T) { res = isEql(m.Store, lv, rv) - debugPP.Println("is equal?", res) } else { debugPP.Println("-----type not identical------") res = false @@ -106,16 +111,14 @@ func (m *Machine) doOpNeq() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - if debug { - assertEqualityTypes(lv.T, rv.T) - } + //if debug { + // assertEqualityTypes(lv.T, rv.T) + //} debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isBinOperandTypeIdentical(lv.T, rv.T) { - debugPP.Println("-----type identical------") + if isIdenticalType(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) - debugPP.Println("is not equal?", res) } else { debugPP.Println("-----type not identical------") res = true @@ -132,9 +135,10 @@ func (m *Machine) doOpLss() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // set the result in lv. res := isLss(lv, rv) lv.T = UntypedBoolType @@ -149,9 +153,10 @@ func (m *Machine) doOpLeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // set the result in lv. res := isLeq(lv, rv) lv.T = UntypedBoolType @@ -166,9 +171,10 @@ func (m *Machine) doOpGtr() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // set the result in lv. res := isGtr(lv, rv) lv.T = UntypedBoolType @@ -183,9 +189,10 @@ func (m *Machine) doOpGeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // set the result in lv. res := isGeq(lv, rv) lv.T = UntypedBoolType @@ -200,9 +207,10 @@ func (m *Machine) doOpAdd() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // add rv to lv. addAssign(m.Alloc, lv, rv) } @@ -214,9 +222,10 @@ func (m *Machine) doOpSub() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // sub rv from lv. subAssign(lv, rv) } @@ -228,9 +237,10 @@ func (m *Machine) doOpBor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // lv | rv borAssign(lv, rv) } @@ -242,9 +252,10 @@ func (m *Machine) doOpXor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } - // lv ^ rv xorAssign(lv, rv) } @@ -256,7 +267,9 @@ func (m *Machine) doOpMul() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } // lv * rv @@ -270,7 +283,9 @@ func (m *Machine) doOpQuo() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } // lv / rv @@ -284,7 +299,9 @@ func (m *Machine) doOpRem() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } // lv % rv @@ -330,7 +347,9 @@ func (m *Machine) doOpBand() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } // lv & rv @@ -344,7 +363,9 @@ func (m *Machine) doOpBandn() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + if !isIdenticalType(lv.T, rv.T) { + panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) + } } // lv &^ rv diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 41e26478938..c7360c1bb45 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -823,15 +823,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) debugPP.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + // TODO: improve readibility if lic { if ric { // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. // refer to 0a0_filetest - //if isShift { - // checkOp(store, last, &n.Left, lt, n.Op, true) - //} if !isShift { cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // this always implies untyped>? @@ -852,7 +850,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } // check special case: zero divisor - // TODO: always check when ric? if isQuoOrRem(n.Op) { checkOperand(rcx) } @@ -972,11 +969,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // ---both not const--- if n.Op == SHL || n.Op == SHR { - // shift operator, nothing yet to do. code like this will work } else if lnt, ok := lt.(*NativeType); ok { if debug { if !isShift { - assertSameTypes(lt, rt) + assertSameTypes(lt, rt) // TODO: what is this for? possible untyped? } } // If left and right are native type, @@ -2577,85 +2573,64 @@ const ( // check operand types with operators func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, mode checkMode) { - var xt Type - if mode == Binary || mode == Assign { - if cx, ok := (*x).(*ConstExpr); ok { - xt = cx.T - } else if *x != nil { - xt = evalStaticTypeOf(store, last, *x) - } - } - - debugPP.Printf("checkOp, xt: %v, dt: %v, op: %v, isBinary: %v \n", xt, dt, op, mode) + debugPP.Printf("checkOp, dt: %v, op: %v, mode: %v \n", dt, op, mode) if mode == Unary || mode == IncDec { - if op == INC || op == DEC { - if pred, ok := IncDecStmtPredicates[op]; ok { + switch mode { + case Unary: + // unary + if pred, ok := unaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } - } - // unary - if pred, ok := unaryPredicates[op]; ok { - if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) - } - } - } - if isComparison(op) { - switch op { - case EQL, NEQ: // check isComparable - // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc - // 2. isComparable requires one is assignable to another - // 3. handle nil - // TODO: is xt is nil - if ok, code := isComparable(xt, dt); !ok { - panic(code) - } - case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString - if pred, ok := binaryPredicates[op]; ok { + case IncDec: + if pred, ok := IncDecStmtPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } default: - panic("invalid comparison operator") + panic("should not happen") } - } else if mode == Assign { - debugPP.Println("assign---") - if pred, ok := AssignStmtPredicates[op]; ok { - if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) - } - if op != ILLEGAL { + } else { + var xt Type + if cx, ok := (*x).(*ConstExpr); ok { + xt = cx.T + } else if *x != nil { + xt = evalStaticTypeOf(store, last, *x) + } + switch mode { + case Binary: + if isComparison(op) { switch op { - case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: - // if both typed - if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if xt != nil && dt != nil { - if xt.TypeID() != dt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) - } + case EQL, NEQ: // check maybeIdenticalType + // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc + // 2. maybeIdenticalType requires one is assignable to another + // 3. handle nil + // TODO: is xt is nil + if ok, code := maybeIdenticalType(xt, dt); !ok { + panic(code) + } + case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString + if pred, ok := binaryPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } - debugPP.Println("typed and identical as isComparable") } default: - // Note: others no check, assign will be check in assignable + panic("invalid comparison operator") } } - } - } else if mode == Binary { - debugPP.Println("binary---") - // two steps of check: - // first, check is the dt type satisfies op, the switch logic - // second, xt can be converted to dt, this is done below this - // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt - if pred, ok := binaryPredicates[op]; ok { - if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + debugPP.Println("binary---") + // two steps of check: + // first, check is the dt type satisfies op, the switch logic + // second, xt can be converted to dt, this is done below this + // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt + if pred, ok := binaryPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } - } - if op != ILLEGAL { switch op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: // if both typed @@ -2665,12 +2640,35 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, mode checkM panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } - debugPP.Println("typed and identical as isComparable") + debugPP.Println("typed and identical as maybeIdenticalType") } case SHL, SHR: default: // Note: others no check, assign will be check in assignable } + case Assign: + debugPP.Println("assign---") + if pred, ok := AssignStmtPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } + switch op { + case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: + // if both typed + if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped + if xt != nil && dt != nil { + if xt.TypeID() != dt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + } + } + debugPP.Println("typed and identical as maybeIdenticalType") + } + default: + // Note: others no check, assign will be check in assignable + } + } + default: + panic("should not happen") } } } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index d9bab6a65df..bb118b56841 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2261,11 +2261,11 @@ func assertSameTypes(lt, rt Type) { } // both typed, or one is nil, or data byte(special case) -// only for isComparable types for runtime, op_binary +// only for runtime type checks, op_binary // any implicit identical check is in preprocess stage and excluded from here -// TODO: a better name? -func isBinOperandTypeIdentical(lt, rt Type) bool { - debugPP.Printf("check isBinOperandTypeIdentical, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) +// TODO: is untyped 100% excluded? this is major difference from assertSameTypes +func isIdenticalType(lt, rt Type) bool { + debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID if lpt, ok := lt.(*PointerType); ok { if isDataByte(lpt.Elt) { @@ -2333,13 +2333,13 @@ func assertEqualityTypes(lt, rt Type) { } } -// NOTE: isComparable is a more strict check than assertSameTypes, refer to 0f20_filetest.gno, -// which pass the later one, but is not isComparable. -// The logic here is, when compare operators show, check if t is isComparable, if yes, +// XXX: maybeIdenticalType is a more strict check than assertSameTypes, refer to 0f20_filetest.gno, +// maybeIdenticalType is relaxed than isIdentical in preprocess. +// The logic here is, when != or == shows up, check if t is maybeIdenticalType, if yes, // then check the corresponding type(the other side of the operator) is convertable to t. -func isComparable(xt, dt Type) (bool, string) { - debugPP.Printf("check isComparable, xt: %v, dt: %v \n", xt, dt) - // primitive is isComparable +func maybeIdenticalType(xt, dt Type) (bool, string) { + debugPP.Printf("check maybeIdenticalType, xt: %v, dt: %v \n", xt, dt) + // primitive is maybeIdenticalType switch cdt := baseOf(dt).(type) { case PrimitiveType: debugPP.Println("primitive type, return true") @@ -2370,7 +2370,7 @@ func isComparable(xt, dt Type) (bool, string) { if xt != nil { return false, fmt.Sprintf("%v can only be compared to nil \n", dt) } else { - // only isComparable with nil, runtime check + // only maybeIdenticalType with nil, runtime check return true, "" } case *NativeType: diff --git a/gnovm/tests/files/types/0f2b_filetest.gno b/gnovm/tests/files/types/0f2b_filetest.gno new file mode 100644 index 00000000000..5e548ab0d65 --- /dev/null +++ b/gnovm/tests/files/types/0f2b_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) <= errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f2b_filetest.gno:19: operator <= not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f2c_filetest.gno b/gnovm/tests/files/types/0f2c_filetest.gno new file mode 100644 index 00000000000..2b7ef210041 --- /dev/null +++ b/gnovm/tests/files/types/0f2c_filetest.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) < errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f2c_filetest.gno:19: operator < not defined on: .uverse.error diff --git a/gnovm/tests/files/types/26a3_filetest.gno b/gnovm/tests/files/types/26a3_filetest.gno index 02a3cd14b64..5735854d684 100644 --- a/gnovm/tests/files/types/26a3_filetest.gno +++ b/gnovm/tests/files/types/26a3_filetest.gno @@ -7,9 +7,6 @@ func main() { r := uint64(1) << a println(r) fmt.Printf("%T \n", r) - - //r1 := uint64(1) << (63 - 1) - //println(r1) } // Output: diff --git a/gnovm/tests/files/types/30a0_LAND_filetest.gno b/gnovm/tests/files/types/30a0_LAND_filetest.gno new file mode 100644 index 00000000000..ba0333b4eb1 --- /dev/null +++ b/gnovm/tests/files/types/30a0_LAND_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(true && false) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/30a1_LAND_filetest.gno b/gnovm/tests/files/types/30a1_LAND_filetest.gno new file mode 100644 index 00000000000..ada74750bad --- /dev/null +++ b/gnovm/tests/files/types/30a1_LAND_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(true && 0) +} + +// Error: +// main/files/types/30a1_LAND_filetest.gno:4: operator && not defined on: bigint \ No newline at end of file diff --git a/gnovm/tests/files/types/30a2_LAND_filetest.gno b/gnovm/tests/files/types/30a2_LAND_filetest.gno new file mode 100644 index 00000000000..3e669976b95 --- /dev/null +++ b/gnovm/tests/files/types/30a2_LAND_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(0 && true) +} + +// Error: +// main/files/types/30a2_LAND_filetest.gno:4: operator && not defined on: bigint diff --git a/gnovm/tests/files/types/30a3_LAND_filetest.gno b/gnovm/tests/files/types/30a3_LAND_filetest.gno new file mode 100644 index 00000000000..2d4e3cb9711 --- /dev/null +++ b/gnovm/tests/files/types/30a3_LAND_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(int(0) && true) // left typed, right untyped +} + +// Error: +// main/files/types/30a3_LAND_filetest.gno:4: operator && not defined on: int diff --git a/gnovm/tests/files/types/30a4_LAND_filetest.gno b/gnovm/tests/files/types/30a4_LAND_filetest.gno new file mode 100644 index 00000000000..753967ca55b --- /dev/null +++ b/gnovm/tests/files/types/30a4_LAND_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(bool(true) && 0) // left typed, right untyped +} + +// Error: +// main/files/types/30a4_LAND_filetest.gno:4: cannot use untyped Bigint/Bigdec as BoolKind From db12d88847a5b5e9141adf3d7195f3659cb836e3 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 13 Dec 2023 21:30:13 +0800 Subject: [PATCH 055/193] tidy --- gnovm/pkg/gnolang/nodes_string.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 2 -- gnovm/pkg/gnolang/preprocess.go | 14 ++++++-------- gnovm/pkg/gnolang/types.go | 2 +- .../{0a0_filetest.gno => 0a0_EQL_filetest.gno} | 2 +- .../{26a4_filetest.gno => 0a1a0_filetest.gno} | 2 +- .../{0a5_filetest.gno => 0a5_rune_filetest.gno} | 0 .../{0a6_filetest.gno => 0a6_rune_filetest.gno} | 2 +- .../types/{1f3_filetest.gno => 0f35_filetest.gno} | 0 .../types/{1f4_filetest.gno => 0f36_filetest.gno} | 0 .../types/{1f5_filetest.gno => 0f37_filetest.gno} | 0 ...ibs_filetest.gno => 0f38_stdlibs_filetest.gno} | 0 ...ibs_filetest.gno => 0f39_stdlibs_filetest.gno} | 0 ...ibs_filetest.gno => 0f40_stdlibs_filetest.gno} | 0 ...ibs_filetest.gno => 0f41_stdlibs_filetest.gno} | 2 +- .../{27a0_filetest.gno => 0f42_filetest.gno} | 0 ...{10a0_filetest.gno => 10a0_SHIFT_filetest.gno} | 0 gnovm/tests/files/types/10a10_filetest.gno | 10 ++++++++++ gnovm/tests/files/types/10a11_filetest.gno | 10 ++++++++++ gnovm/tests/files/types/10a12_filetest.gno | 14 ++++++++++++++ .../{26a5_filetest.gno => 10a13_filetest.gno} | 0 .../{26a6_filetest.gno => 10a14_filetest.gno} | 2 +- .../{26a6a_filetest.gno => 10a15_filetest.gno} | 2 +- gnovm/tests/files/types/10a16_filetest.gno | 9 +++++++++ gnovm/tests/files/types/10a5_filetest.gno | 10 +++++----- .../{19a0_filetest.gno => 10a6_filetest.gno} | 0 .../{19a1_filetest.gno => 10a7_filetest.gno} | 2 +- .../{26a0_filetest.gno => 10a8_filetest.gno} | 0 .../{26a0a_filetest.gno => 10a9_filetest.gno} | 0 .../{11a0_filetest.gno => 11a0_LAND_filetest.gno} | 2 +- ...0_LAND_filetest.gno => 11a4_LAND_filetest.gno} | 0 gnovm/tests/files/types/11a5_LAND_filetest.gno | 8 ++++++++ ...2_LAND_filetest.gno => 11a6_LAND_filetest.gno} | 2 +- ...3_LAND_filetest.gno => 11a7_LAND_filetest.gno} | 2 +- ...4_LAND_filetest.gno => 11a8_LAND_filetest.gno} | 2 +- .../{12a0_filetest.gno => 12a0_LOR_filetest.gno} | 2 +- .../files/types/13a0_ADD_ASSIGN_filetest.gno | 9 +++++++++ gnovm/tests/files/types/13a0_filetest.gno | 9 --------- .../{29a0_filetest.gno => 13f4_filetest.gno} | 0 .../files/types/14a0_SUB_ASSIGN_filetest.gno | 9 +++++++++ gnovm/tests/files/types/14a0_filetest.gno | 9 --------- gnovm/tests/files/types/15a01_filetest.gno | 10 ++++++++++ gnovm/tests/files/types/15a02_filetest.gno | 10 ++++++++++ gnovm/tests/files/types/15a03_filetest.gno | 10 ++++++++++ gnovm/tests/files/types/15a04_filetest.gno | 10 ++++++++++ .../files/types/15a0_REM_ASSIGN_filetest.gno | 10 ++++++++++ gnovm/tests/files/types/15a0_filetest.gno | 8 -------- ..._filetest.gno => 18a0_AND_ASSIGN_filetest.gno} | 0 .../{1a0_filetest.gno => 1a0_ADD_filetest.gno} | 2 +- .../{20a0_filetest.gno => 20a0_LSS_filetest.gno} | 2 +- ...a1_filetest.gno => 22a1_IMPLICIT_filetest.gno} | 0 ...{23a0_filetest.gno => 23a0_UNARY_filetest.gno} | 0 ...a0_filetest.gno => 24a0_OVERFLOW_filetest.gno} | 0 ...25a0_filetest.gno => 25a0_INCDEC_filetest.gno} | 0 .../{22a0a_filetest.gno => 25a3_filetest.gno} | 0 ...22a0_filetest.gno => 25a4_INCDEC_filetest.gno} | 2 +- gnovm/tests/files/types/26a0_runtime_filetest.gno | 9 +++++++++ .../tests/files/types/26a0a_runtime_filetest.gno | 8 ++++++++ gnovm/tests/files/types/26a1_filetest.gno | 8 ++++---- gnovm/tests/files/types/26a2_filetest.gno | 15 ++++++++++----- gnovm/tests/files/types/26a3_filetest.gno | 13 ++++--------- gnovm/tests/files/types/26a7_filetest.gno | 9 --------- gnovm/tests/files/types/28a0_filetest.gno | 9 --------- gnovm/tests/files/types/28a1_filetest.gno | 9 --------- .../{2a0_filetest.gno => 2a0_SUB_filetest.gno} | 2 +- gnovm/tests/files/types/30a1_LAND_filetest.gno | 8 -------- .../{3a0_filetest.gno => 3a0_MUL_filetest.gno} | 2 +- .../{4a0_filetest.gno => 4a0_QUO_filetest.gno} | 2 +- gnovm/tests/files/types/4f0_filetest.gno | 9 +++++++++ .../{5a0_filetest.gno => 5a0_REM_filetest.gno} | 2 +- gnovm/tests/files/types/5f3_filetest.gno | 9 +++++++++ .../{6a0_filetest.gno => 6a0_AND_filetest.gno} | 2 +- .../{7a0_filetest.gno => 7a0_OR_filetest.gno} | 2 +- .../{8a0_filetest.gno => 8a0_XOR_filetest.gno} | 2 +- .../{9a0_filetest.gno => 9a0_ANDNOT_filetest.gno} | 2 +- 75 files changed, 208 insertions(+), 119 deletions(-) rename gnovm/tests/files/types/{0a0_filetest.gno => 0a0_EQL_filetest.gno} (59%) rename gnovm/tests/files/types/{26a4_filetest.gno => 0a1a0_filetest.gno} (57%) rename gnovm/tests/files/types/{0a5_filetest.gno => 0a5_rune_filetest.gno} (100%) rename gnovm/tests/files/types/{0a6_filetest.gno => 0a6_rune_filetest.gno} (50%) rename gnovm/tests/files/types/{1f3_filetest.gno => 0f35_filetest.gno} (100%) rename gnovm/tests/files/types/{1f4_filetest.gno => 0f36_filetest.gno} (100%) rename gnovm/tests/files/types/{1f5_filetest.gno => 0f37_filetest.gno} (100%) rename gnovm/tests/files/types/{1f6_stdlibs_filetest.gno => 0f38_stdlibs_filetest.gno} (100%) rename gnovm/tests/files/types/{1f7_stdlibs_filetest.gno => 0f39_stdlibs_filetest.gno} (100%) rename gnovm/tests/files/types/{1f8_stdlibs_filetest.gno => 0f40_stdlibs_filetest.gno} (100%) rename gnovm/tests/files/types/{1f9_stdlibs_filetest.gno => 0f41_stdlibs_filetest.gno} (80%) rename gnovm/tests/files/types/{27a0_filetest.gno => 0f42_filetest.gno} (100%) rename gnovm/tests/files/types/{10a0_filetest.gno => 10a0_SHIFT_filetest.gno} (100%) create mode 100644 gnovm/tests/files/types/10a10_filetest.gno create mode 100644 gnovm/tests/files/types/10a11_filetest.gno create mode 100644 gnovm/tests/files/types/10a12_filetest.gno rename gnovm/tests/files/types/{26a5_filetest.gno => 10a13_filetest.gno} (100%) rename gnovm/tests/files/types/{26a6_filetest.gno => 10a14_filetest.gno} (50%) rename gnovm/tests/files/types/{26a6a_filetest.gno => 10a15_filetest.gno} (53%) create mode 100644 gnovm/tests/files/types/10a16_filetest.gno rename gnovm/tests/files/types/{19a0_filetest.gno => 10a6_filetest.gno} (100%) rename gnovm/tests/files/types/{19a1_filetest.gno => 10a7_filetest.gno} (57%) rename gnovm/tests/files/types/{26a0_filetest.gno => 10a8_filetest.gno} (100%) rename gnovm/tests/files/types/{26a0a_filetest.gno => 10a9_filetest.gno} (100%) rename gnovm/tests/files/types/{11a0_filetest.gno => 11a0_LAND_filetest.gno} (55%) rename gnovm/tests/files/types/{30a0_LAND_filetest.gno => 11a4_LAND_filetest.gno} (100%) create mode 100644 gnovm/tests/files/types/11a5_LAND_filetest.gno rename gnovm/tests/files/types/{30a2_LAND_filetest.gno => 11a6_LAND_filetest.gno} (57%) rename gnovm/tests/files/types/{30a3_LAND_filetest.gno => 11a7_LAND_filetest.gno} (63%) rename gnovm/tests/files/types/{30a4_LAND_filetest.gno => 11a8_LAND_filetest.gno} (65%) rename gnovm/tests/files/types/{12a0_filetest.gno => 12a0_LOR_filetest.gno} (56%) create mode 100644 gnovm/tests/files/types/13a0_ADD_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/files/types/13a0_filetest.gno rename gnovm/tests/files/types/{29a0_filetest.gno => 13f4_filetest.gno} (100%) create mode 100644 gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/files/types/14a0_filetest.gno create mode 100644 gnovm/tests/files/types/15a01_filetest.gno create mode 100644 gnovm/tests/files/types/15a02_filetest.gno create mode 100644 gnovm/tests/files/types/15a03_filetest.gno create mode 100644 gnovm/tests/files/types/15a04_filetest.gno create mode 100644 gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/files/types/15a0_filetest.gno rename gnovm/tests/files/types/{18a0_filetest.gno => 18a0_AND_ASSIGN_filetest.gno} (100%) rename gnovm/tests/files/types/{1a0_filetest.gno => 1a0_ADD_filetest.gno} (51%) rename gnovm/tests/files/types/{20a0_filetest.gno => 20a0_LSS_filetest.gno} (50%) rename gnovm/tests/files/types/{22a1_filetest.gno => 22a1_IMPLICIT_filetest.gno} (100%) rename gnovm/tests/files/types/{23a0_filetest.gno => 23a0_UNARY_filetest.gno} (100%) rename gnovm/tests/files/types/{24a0_filetest.gno => 24a0_OVERFLOW_filetest.gno} (100%) rename gnovm/tests/files/types/{25a0_filetest.gno => 25a0_INCDEC_filetest.gno} (100%) rename gnovm/tests/files/types/{22a0a_filetest.gno => 25a3_filetest.gno} (100%) rename gnovm/tests/files/types/{22a0_filetest.gno => 25a4_INCDEC_filetest.gno} (65%) create mode 100644 gnovm/tests/files/types/26a0_runtime_filetest.gno create mode 100644 gnovm/tests/files/types/26a0a_runtime_filetest.gno delete mode 100644 gnovm/tests/files/types/26a7_filetest.gno delete mode 100644 gnovm/tests/files/types/28a0_filetest.gno delete mode 100644 gnovm/tests/files/types/28a1_filetest.gno rename gnovm/tests/files/types/{2a0_filetest.gno => 2a0_SUB_filetest.gno} (51%) delete mode 100644 gnovm/tests/files/types/30a1_LAND_filetest.gno rename gnovm/tests/files/types/{3a0_filetest.gno => 3a0_MUL_filetest.gno} (51%) rename gnovm/tests/files/types/{4a0_filetest.gno => 4a0_QUO_filetest.gno} (51%) create mode 100644 gnovm/tests/files/types/4f0_filetest.gno rename gnovm/tests/files/types/{5a0_filetest.gno => 5a0_REM_filetest.gno} (51%) create mode 100644 gnovm/tests/files/types/5f3_filetest.gno rename gnovm/tests/files/types/{6a0_filetest.gno => 6a0_AND_filetest.gno} (51%) rename gnovm/tests/files/types/{7a0_filetest.gno => 7a0_OR_filetest.gno} (51%) rename gnovm/tests/files/types/{8a0_filetest.gno => 8a0_XOR_filetest.gno} (51%) rename gnovm/tests/files/types/{9a0_filetest.gno => 9a0_ANDNOT_filetest.gno} (51%) diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index 17849057f38..353fd1e5127 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -24,7 +24,7 @@ var wordTokenStrings = map[Word]string{ SUB_ASSIGN: "-=", MUL_ASSIGN: "*=", QUO_ASSIGN: "/=", - REM_ASSIGN: "%=", + REM_ASSIGN: "%%=", BAND_ASSIGN: "&=", BOR_ASSIGN: "|=", XOR_ASSIGN: "^=", diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index ac60bb089ef..84de6411b57 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -387,9 +387,7 @@ func isEql(store Store, lv, rv *TypedValue) bool { return false } if lnt, ok := lv.T.(*NativeType); ok { - debugPP.Println("left is native type") if rnt, ok := rv.T.(*NativeType); ok { - debugPP.Println("right is native type") if lnt.Type != rnt.Type { return false } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c7360c1bb45..fd7752e7860 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -18,8 +18,6 @@ var ( ) func init() { - // add,sub,mul,quo,rem with assign - // TODO: *_assign is actually assign stmt binaryPredicates[ADD] = isNumericOrString AssignStmtPredicates[ADD_ASSIGN] = isNumericOrString binaryPredicates[SUB] = isNumeric @@ -66,6 +64,8 @@ func init() { IncDecStmtPredicates[DEC] = isNumeric } +// ------------------------------------------------------------------------------------------- + // In the case of a *FileSet, some declaration steps have to happen // in a restricted parallel way across all the files. // Anything predefined or preprocessed here get skipped during the Preprocess @@ -900,11 +900,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if !isUntyped(lcx.T) { // left is typed const, right is not const(also typed) checkOp(store, last, &n.Left, rt, n.Op, Binary) // if n.Op == SHR || n.Op == SHL { - if isShift { // refer to 26a3_filetest + if isShift { debugPP.Println("-----shift-----") // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check - } else { // refer to 26a4_filetest + } else { checkOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false) } @@ -955,7 +955,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil - debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest, 1f8_filetest + debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest // TODO: shift // convert n.Right to typed-nil type. checkOp(store, last, &n.Right, lt, n.Op, Binary) @@ -2455,12 +2455,11 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if cx, ok := (*x).(*ConstExpr); ok { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno - debugPP.Println("x is ConstExpr, not nativeType, go check") checkConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } - debugPP.Printf("ConstExpr, convertConst, cx: %v, t:%v \n", cx, t) convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + // TODO: check this debugPP.Println("SHL or SHR") // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative) @@ -2473,7 +2472,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } debugPP.Println("need conversion: ", conversionNeeded) if isUntyped(xt) { - debugPP.Println("xt untyped") if t == nil { t = defaultTypeOf(xt) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index bb118b56841..974dd873434 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2413,7 +2413,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok - } else if iot, ok := xt.(*InterfaceType); ok { // case 1f6_stdlibs_filetest.gno + } else if iot, ok := xt.(*InterfaceType); ok { // case 0f38_stdlibs_filetest.gno debugPP.Println("xt is empty interface: ", iot) if iot.IsEmptyInterface() { return // ok diff --git a/gnovm/tests/files/types/0a0_filetest.gno b/gnovm/tests/files/types/0a0_EQL_filetest.gno similarity index 59% rename from gnovm/tests/files/types/0a0_filetest.gno rename to gnovm/tests/files/types/0a0_EQL_filetest.gno index 24fbd6b7516..6ddb8b993c0 100644 --- a/gnovm/tests/files/types/0a0_filetest.gno +++ b/gnovm/tests/files/types/0a0_EQL_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a0_filetest.gno:5: cannot use int as int8 +// main/files/types/0a0_EQL_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/26a4_filetest.gno b/gnovm/tests/files/types/0a1a0_filetest.gno similarity index 57% rename from gnovm/tests/files/types/26a4_filetest.gno rename to gnovm/tests/files/types/0a1a0_filetest.gno index 1646346b158..2ab23e5d8f3 100644 --- a/gnovm/tests/files/types/26a4_filetest.gno +++ b/gnovm/tests/files/types/0a1a0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/26a4_filetest.gno:5: cannot use uint64 as uint +// main/files/types/0a1a0_filetest.gno:5: cannot use uint64 as uint diff --git a/gnovm/tests/files/types/0a5_filetest.gno b/gnovm/tests/files/types/0a5_rune_filetest.gno similarity index 100% rename from gnovm/tests/files/types/0a5_filetest.gno rename to gnovm/tests/files/types/0a5_rune_filetest.gno diff --git a/gnovm/tests/files/types/0a6_filetest.gno b/gnovm/tests/files/types/0a6_rune_filetest.gno similarity index 50% rename from gnovm/tests/files/types/0a6_filetest.gno rename to gnovm/tests/files/types/0a6_rune_filetest.gno index 98bc3a38c9b..9171d738d07 100644 --- a/gnovm/tests/files/types/0a6_filetest.gno +++ b/gnovm/tests/files/types/0a6_rune_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/types/0a6_filetest.gno:7: cannot use untyped string as Int32Kind +// main/files/types/0a6_rune_filetest.gno:7: cannot use untyped string as Int32Kind diff --git a/gnovm/tests/files/types/1f3_filetest.gno b/gnovm/tests/files/types/0f35_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f3_filetest.gno rename to gnovm/tests/files/types/0f35_filetest.gno diff --git a/gnovm/tests/files/types/1f4_filetest.gno b/gnovm/tests/files/types/0f36_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f4_filetest.gno rename to gnovm/tests/files/types/0f36_filetest.gno diff --git a/gnovm/tests/files/types/1f5_filetest.gno b/gnovm/tests/files/types/0f37_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f5_filetest.gno rename to gnovm/tests/files/types/0f37_filetest.gno diff --git a/gnovm/tests/files/types/1f6_stdlibs_filetest.gno b/gnovm/tests/files/types/0f38_stdlibs_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f6_stdlibs_filetest.gno rename to gnovm/tests/files/types/0f38_stdlibs_filetest.gno diff --git a/gnovm/tests/files/types/1f7_stdlibs_filetest.gno b/gnovm/tests/files/types/0f39_stdlibs_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f7_stdlibs_filetest.gno rename to gnovm/tests/files/types/0f39_stdlibs_filetest.gno diff --git a/gnovm/tests/files/types/1f8_stdlibs_filetest.gno b/gnovm/tests/files/types/0f40_stdlibs_filetest.gno similarity index 100% rename from gnovm/tests/files/types/1f8_stdlibs_filetest.gno rename to gnovm/tests/files/types/0f40_stdlibs_filetest.gno diff --git a/gnovm/tests/files/types/1f9_stdlibs_filetest.gno b/gnovm/tests/files/types/0f41_stdlibs_filetest.gno similarity index 80% rename from gnovm/tests/files/types/1f9_stdlibs_filetest.gno rename to gnovm/tests/files/types/0f41_stdlibs_filetest.gno index ad5fffd45f8..ea37f9ff40d 100644 --- a/gnovm/tests/files/types/1f9_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/0f41_stdlibs_filetest.gno @@ -32,4 +32,4 @@ func main() { } // Error: -// main/files/types/1f9_stdlibs_filetest.gno:27: main.animal does not implement .uverse.error +// main/files/types/0f41_stdlibs_filetest.gno:27: main.animal does not implement .uverse.error diff --git a/gnovm/tests/files/types/27a0_filetest.gno b/gnovm/tests/files/types/0f42_filetest.gno similarity index 100% rename from gnovm/tests/files/types/27a0_filetest.gno rename to gnovm/tests/files/types/0f42_filetest.gno diff --git a/gnovm/tests/files/types/10a0_filetest.gno b/gnovm/tests/files/types/10a0_SHIFT_filetest.gno similarity index 100% rename from gnovm/tests/files/types/10a0_filetest.gno rename to gnovm/tests/files/types/10a0_SHIFT_filetest.gno diff --git a/gnovm/tests/files/types/10a10_filetest.gno b/gnovm/tests/files/types/10a10_filetest.gno new file mode 100644 index 00000000000..0eba81f4a9c --- /dev/null +++ b/gnovm/tests/files/types/10a10_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << 1.0 // NOTE: go vet would fail, but still process + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/10a11_filetest.gno b/gnovm/tests/files/types/10a11_filetest.gno new file mode 100644 index 00000000000..1937f52c336 --- /dev/null +++ b/gnovm/tests/files/types/10a11_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << "hello" // NOTE: go vet would fail, but still process + println(r) +} + +// Error: +// main/files/types/10a11_filetest.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types/10a12_filetest.gno b/gnovm/tests/files/types/10a12_filetest.gno new file mode 100644 index 00000000000..5735854d684 --- /dev/null +++ b/gnovm/tests/files/types/10a12_filetest.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + a := uint(1) + r := uint64(1) << a + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 2 +// uint64 diff --git a/gnovm/tests/files/types/26a5_filetest.gno b/gnovm/tests/files/types/10a13_filetest.gno similarity index 100% rename from gnovm/tests/files/types/26a5_filetest.gno rename to gnovm/tests/files/types/10a13_filetest.gno diff --git a/gnovm/tests/files/types/26a6_filetest.gno b/gnovm/tests/files/types/10a14_filetest.gno similarity index 50% rename from gnovm/tests/files/types/26a6_filetest.gno rename to gnovm/tests/files/types/10a14_filetest.gno index e9d8065e967..cc18b2ff469 100644 --- a/gnovm/tests/files/types/26a6_filetest.gno +++ b/gnovm/tests/files/types/10a14_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/26a6_filetest.gno:5: operator << not defined on: string +// main/files/types/10a14_filetest.gno:5: operator << not defined on: string diff --git a/gnovm/tests/files/types/26a6a_filetest.gno b/gnovm/tests/files/types/10a15_filetest.gno similarity index 53% rename from gnovm/tests/files/types/26a6a_filetest.gno rename to gnovm/tests/files/types/10a15_filetest.gno index b92db4b4b9f..eacc1897428 100644 --- a/gnovm/tests/files/types/26a6a_filetest.gno +++ b/gnovm/tests/files/types/10a15_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/26a6a_filetest.gno:6: operator <<= not defined on: string \ No newline at end of file +// main/files/types/10a15_filetest.gno:6: operator <<= not defined on: string diff --git a/gnovm/tests/files/types/10a16_filetest.gno b/gnovm/tests/files/types/10a16_filetest.gno new file mode 100644 index 00000000000..65562d2cb2f --- /dev/null +++ b/gnovm/tests/files/types/10a16_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := "hello" << 1 + println(r) +} + +// Error: +// main/files/types/10a16_filetest.gno:4: operator << not defined on: string diff --git a/gnovm/tests/files/types/10a5_filetest.gno b/gnovm/tests/files/types/10a5_filetest.gno index 5c54ead8c8d..7538b2f4b10 100644 --- a/gnovm/tests/files/types/10a5_filetest.gno +++ b/gnovm/tests/files/types/10a5_filetest.gno @@ -1,10 +1,10 @@ package main -// both typed(different) const +// TODO: support this? func main() { - //println(1.0 << 1) - //println(1.0 >> 1) + println(1.0 << 1) + println(1.0 >> 1) } -// TODO: no support for this for now -// Output: +// Error: +// main/files/types/10a5_filetest.gno:4: operators << and <<= not defined for bigdec diff --git a/gnovm/tests/files/types/19a0_filetest.gno b/gnovm/tests/files/types/10a6_filetest.gno similarity index 100% rename from gnovm/tests/files/types/19a0_filetest.gno rename to gnovm/tests/files/types/10a6_filetest.gno diff --git a/gnovm/tests/files/types/19a1_filetest.gno b/gnovm/tests/files/types/10a7_filetest.gno similarity index 57% rename from gnovm/tests/files/types/19a1_filetest.gno rename to gnovm/tests/files/types/10a7_filetest.gno index 0cfee424bf2..896cc48d4f3 100644 --- a/gnovm/tests/files/types/19a1_filetest.gno +++ b/gnovm/tests/files/types/10a7_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/19a1_filetest.gno:3: cannot convert StringKind to UintKind +// main/files/types/10a7_filetest.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types/26a0_filetest.gno b/gnovm/tests/files/types/10a8_filetest.gno similarity index 100% rename from gnovm/tests/files/types/26a0_filetest.gno rename to gnovm/tests/files/types/10a8_filetest.gno diff --git a/gnovm/tests/files/types/26a0a_filetest.gno b/gnovm/tests/files/types/10a9_filetest.gno similarity index 100% rename from gnovm/tests/files/types/26a0a_filetest.gno rename to gnovm/tests/files/types/10a9_filetest.gno diff --git a/gnovm/tests/files/types/11a0_filetest.gno b/gnovm/tests/files/types/11a0_LAND_filetest.gno similarity index 55% rename from gnovm/tests/files/types/11a0_filetest.gno rename to gnovm/tests/files/types/11a0_LAND_filetest.gno index 7315ac56c7c..fad0c255443 100644 --- a/gnovm/tests/files/types/11a0_filetest.gno +++ b/gnovm/tests/files/types/11a0_LAND_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/11a0_filetest.gno:5: operator && not defined on: int \ No newline at end of file +// main/files/types/11a0_LAND_filetest.gno:5: operator && not defined on: int diff --git a/gnovm/tests/files/types/30a0_LAND_filetest.gno b/gnovm/tests/files/types/11a4_LAND_filetest.gno similarity index 100% rename from gnovm/tests/files/types/30a0_LAND_filetest.gno rename to gnovm/tests/files/types/11a4_LAND_filetest.gno diff --git a/gnovm/tests/files/types/11a5_LAND_filetest.gno b/gnovm/tests/files/types/11a5_LAND_filetest.gno new file mode 100644 index 00000000000..363a98a8f1e --- /dev/null +++ b/gnovm/tests/files/types/11a5_LAND_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(true && 0) +} + +// Error: +// main/files/types/11a5_LAND_filetest.gno:4: operator && not defined on: bigint diff --git a/gnovm/tests/files/types/30a2_LAND_filetest.gno b/gnovm/tests/files/types/11a6_LAND_filetest.gno similarity index 57% rename from gnovm/tests/files/types/30a2_LAND_filetest.gno rename to gnovm/tests/files/types/11a6_LAND_filetest.gno index 3e669976b95..156a7740c2e 100644 --- a/gnovm/tests/files/types/30a2_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a6_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/30a2_LAND_filetest.gno:4: operator && not defined on: bigint +// main/files/types/11a6_LAND_filetest.gno:4: operator && not defined on: bigint diff --git a/gnovm/tests/files/types/30a3_LAND_filetest.gno b/gnovm/tests/files/types/11a7_LAND_filetest.gno similarity index 63% rename from gnovm/tests/files/types/30a3_LAND_filetest.gno rename to gnovm/tests/files/types/11a7_LAND_filetest.gno index 2d4e3cb9711..7adac5f84d8 100644 --- a/gnovm/tests/files/types/30a3_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a7_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/30a3_LAND_filetest.gno:4: operator && not defined on: int +// main/files/types/11a7_LAND_filetest.gno:4: operator && not defined on: int diff --git a/gnovm/tests/files/types/30a4_LAND_filetest.gno b/gnovm/tests/files/types/11a8_LAND_filetest.gno similarity index 65% rename from gnovm/tests/files/types/30a4_LAND_filetest.gno rename to gnovm/tests/files/types/11a8_LAND_filetest.gno index 753967ca55b..19505bf3574 100644 --- a/gnovm/tests/files/types/30a4_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a8_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/30a4_LAND_filetest.gno:4: cannot use untyped Bigint/Bigdec as BoolKind +// main/files/types/11a8_LAND_filetest.gno:4: cannot use untyped Bigint/Bigdec as BoolKind diff --git a/gnovm/tests/files/types/12a0_filetest.gno b/gnovm/tests/files/types/12a0_LOR_filetest.gno similarity index 56% rename from gnovm/tests/files/types/12a0_filetest.gno rename to gnovm/tests/files/types/12a0_LOR_filetest.gno index 8db29851474..be8bbba2529 100644 --- a/gnovm/tests/files/types/12a0_filetest.gno +++ b/gnovm/tests/files/types/12a0_LOR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/12a0_filetest.gno:5: operator || not defined on: int +// main/files/types/12a0_LOR_filetest.gno:5: operator || not defined on: int diff --git a/gnovm/tests/files/types/13a0_ADD_ASSIGN_filetest.gno b/gnovm/tests/files/types/13a0_ADD_ASSIGN_filetest.gno new file mode 100644 index 00000000000..d6feb59bee4 --- /dev/null +++ b/gnovm/tests/files/types/13a0_ADD_ASSIGN_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + int(0) += int8(1) +} + +// Error: +// main/files/types/13a0_ADD_ASSIGN_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/13a0_filetest.gno b/gnovm/tests/files/types/13a0_filetest.gno deleted file mode 100644 index e31be679bf8..00000000000 --- a/gnovm/tests/files/types/13a0_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - int(0) += int8(1) -} - -// Error: -// main/files/types/13a0_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/29a0_filetest.gno b/gnovm/tests/files/types/13f4_filetest.gno similarity index 100% rename from gnovm/tests/files/types/29a0_filetest.gno rename to gnovm/tests/files/types/13f4_filetest.gno diff --git a/gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno b/gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno new file mode 100644 index 00000000000..6f8845190fa --- /dev/null +++ b/gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + int(0) -= int8(1) +} + +// Error: +// main/files/types/14a0_SUB_ASSIGN_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/14a0_filetest.gno b/gnovm/tests/files/types/14a0_filetest.gno deleted file mode 100644 index a725f856db6..00000000000 --- a/gnovm/tests/files/types/14a0_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - int(0) -= int8(1) -} - -// Error: -// main/files/types/14a0_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/15a01_filetest.gno b/gnovm/tests/files/types/15a01_filetest.gno new file mode 100644 index 00000000000..e866e059361 --- /dev/null +++ b/gnovm/tests/files/types/15a01_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 10 + a %= 3.0 + println(a) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/15a02_filetest.gno b/gnovm/tests/files/types/15a02_filetest.gno new file mode 100644 index 00000000000..9637380913f --- /dev/null +++ b/gnovm/tests/files/types/15a02_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + a %= 3 + println(a) +} + +// Error: +// main/files/types/15a02_filetest.gno:5: operator %= not defined on: string diff --git a/gnovm/tests/files/types/15a03_filetest.gno b/gnovm/tests/files/types/15a03_filetest.gno new file mode 100644 index 00000000000..918b47fb31c --- /dev/null +++ b/gnovm/tests/files/types/15a03_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 10 + a %= "a" + println(a) +} + +// Error: +// main/files/types/15a03_filetest.gno:5: cannot use untyped string as IntKind diff --git a/gnovm/tests/files/types/15a04_filetest.gno b/gnovm/tests/files/types/15a04_filetest.gno new file mode 100644 index 00000000000..c5aaea85298 --- /dev/null +++ b/gnovm/tests/files/types/15a04_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 10.0 + a %= 3.0 + println(a) +} + +// Error: +// main/files/types/15a04_filetest.gno:5: operator %= not defined on: float64 diff --git a/gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno b/gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno new file mode 100644 index 00000000000..363252d58e0 --- /dev/null +++ b/gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 10 + a %= 3 + println(a) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/15a0_filetest.gno b/gnovm/tests/files/types/15a0_filetest.gno deleted file mode 100644 index 1d57c84a818..00000000000 --- a/gnovm/tests/files/types/15a0_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - 1 % 1.0 -} - -// Error: -// main/files/types/15a0_filetest.gno:4: operator % not defined on: bigdec diff --git a/gnovm/tests/files/types/18a0_filetest.gno b/gnovm/tests/files/types/18a0_AND_ASSIGN_filetest.gno similarity index 100% rename from gnovm/tests/files/types/18a0_filetest.gno rename to gnovm/tests/files/types/18a0_AND_ASSIGN_filetest.gno diff --git a/gnovm/tests/files/types/1a0_filetest.gno b/gnovm/tests/files/types/1a0_ADD_filetest.gno similarity index 51% rename from gnovm/tests/files/types/1a0_filetest.gno rename to gnovm/tests/files/types/1a0_ADD_filetest.gno index 65b4cef3ae4..8bc3c607c42 100644 --- a/gnovm/tests/files/types/1a0_filetest.gno +++ b/gnovm/tests/files/types/1a0_ADD_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/1a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/1a0_ADD_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/20a0_filetest.gno b/gnovm/tests/files/types/20a0_LSS_filetest.gno similarity index 50% rename from gnovm/tests/files/types/20a0_filetest.gno rename to gnovm/tests/files/types/20a0_LSS_filetest.gno index fe43114da90..f11bda7fd5c 100644 --- a/gnovm/tests/files/types/20a0_filetest.gno +++ b/gnovm/tests/files/types/20a0_LSS_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/20a0_filetest.gno:4: cannot use int as int8 +// main/files/types/20a0_LSS_filetest.gno:4: cannot use int as int8 diff --git a/gnovm/tests/files/types/22a1_filetest.gno b/gnovm/tests/files/types/22a1_IMPLICIT_filetest.gno similarity index 100% rename from gnovm/tests/files/types/22a1_filetest.gno rename to gnovm/tests/files/types/22a1_IMPLICIT_filetest.gno diff --git a/gnovm/tests/files/types/23a0_filetest.gno b/gnovm/tests/files/types/23a0_UNARY_filetest.gno similarity index 100% rename from gnovm/tests/files/types/23a0_filetest.gno rename to gnovm/tests/files/types/23a0_UNARY_filetest.gno diff --git a/gnovm/tests/files/types/24a0_filetest.gno b/gnovm/tests/files/types/24a0_OVERFLOW_filetest.gno similarity index 100% rename from gnovm/tests/files/types/24a0_filetest.gno rename to gnovm/tests/files/types/24a0_OVERFLOW_filetest.gno diff --git a/gnovm/tests/files/types/25a0_filetest.gno b/gnovm/tests/files/types/25a0_INCDEC_filetest.gno similarity index 100% rename from gnovm/tests/files/types/25a0_filetest.gno rename to gnovm/tests/files/types/25a0_INCDEC_filetest.gno diff --git a/gnovm/tests/files/types/22a0a_filetest.gno b/gnovm/tests/files/types/25a3_filetest.gno similarity index 100% rename from gnovm/tests/files/types/22a0a_filetest.gno rename to gnovm/tests/files/types/25a3_filetest.gno diff --git a/gnovm/tests/files/types/22a0_filetest.gno b/gnovm/tests/files/types/25a4_INCDEC_filetest.gno similarity index 65% rename from gnovm/tests/files/types/22a0_filetest.gno rename to gnovm/tests/files/types/25a4_INCDEC_filetest.gno index 1904b59edb6..5dadbb90917 100644 --- a/gnovm/tests/files/types/22a0_filetest.gno +++ b/gnovm/tests/files/types/25a4_INCDEC_filetest.gno @@ -15,4 +15,4 @@ func main() { } // Error: -// main/files/types/22a0_filetest.gno:12: cannot use int8 as main.Int without explicit conversion +// main/files/types/25a4_INCDEC_filetest.gno:12: cannot use int8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/26a0_runtime_filetest.gno b/gnovm/tests/files/types/26a0_runtime_filetest.gno new file mode 100644 index 00000000000..47ad2aaaf3f --- /dev/null +++ b/gnovm/tests/files/types/26a0_runtime_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + m := map[string]bool{"foo": true} + m["foo"]++ +} + +// Error: +// main/files/types/26a0_runtime_filetest.gno:5: operator ++ not defined on: bool diff --git a/gnovm/tests/files/types/26a0a_runtime_filetest.gno b/gnovm/tests/files/types/26a0a_runtime_filetest.gno new file mode 100644 index 00000000000..fecce01817e --- /dev/null +++ b/gnovm/tests/files/types/26a0a_runtime_filetest.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(map[string]bool{"foo": true}["foo"] == true) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/26a1_filetest.gno b/gnovm/tests/files/types/26a1_filetest.gno index 0eba81f4a9c..3705dee7d99 100644 --- a/gnovm/tests/files/types/26a1_filetest.gno +++ b/gnovm/tests/files/types/26a1_filetest.gno @@ -2,9 +2,9 @@ package main func main() { a := 1 - r := a << 1.0 // NOTE: go vet would fail, but still process - println(r) + b := 1 + (a == b)++ // LHS is untyped bool, determined in preprocess } -// Output: -// 2 +// Error: +// main/files/types/26a1_filetest.gno:6: operator ++ not defined on: bool diff --git a/gnovm/tests/files/types/26a2_filetest.gno b/gnovm/tests/files/types/26a2_filetest.gno index 753ed909aae..d53c9c4d970 100644 --- a/gnovm/tests/files/types/26a2_filetest.gno +++ b/gnovm/tests/files/types/26a2_filetest.gno @@ -1,10 +1,15 @@ package main +import "fmt" + +func gen() interface{} { + return false +} + func main() { - a := 1 - r := a << "hello" // NOTE: go vet would fail, but still process - println(r) + r := gen() + fmt.Printf("%T \n", r) } -// Error: -// main/files/types/26a2_filetest.gno:3: cannot convert StringKind to UintKind +// Output: +// bool diff --git a/gnovm/tests/files/types/26a3_filetest.gno b/gnovm/tests/files/types/26a3_filetest.gno index 5735854d684..2364a18a031 100644 --- a/gnovm/tests/files/types/26a3_filetest.gno +++ b/gnovm/tests/files/types/26a3_filetest.gno @@ -1,14 +1,9 @@ package main -import "fmt" +func gen() interface{} { + return false +} func main() { - a := uint(1) - r := uint64(1) << a - println(r) - fmt.Printf("%T \n", r) + gen()++ } - -// Output: -// 2 -// uint64 diff --git a/gnovm/tests/files/types/26a7_filetest.gno b/gnovm/tests/files/types/26a7_filetest.gno deleted file mode 100644 index 67fdc8b9d12..00000000000 --- a/gnovm/tests/files/types/26a7_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - r := "hello" << 1 - println(r) -} - -// Error: -// main/files/types/26a7_filetest.gno:4: operator << not defined on: string diff --git a/gnovm/tests/files/types/28a0_filetest.gno b/gnovm/tests/files/types/28a0_filetest.gno deleted file mode 100644 index 43b3ea3667c..00000000000 --- a/gnovm/tests/files/types/28a0_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - a := 1 - println(a / 0) -} - -// Error: -// main/files/types/28a0_filetest.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/28a1_filetest.gno b/gnovm/tests/files/types/28a1_filetest.gno deleted file mode 100644 index 9f13276c132..00000000000 --- a/gnovm/tests/files/types/28a1_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - a := 1 - println(a % 0) -} - -// Error: -// main/files/types/28a1_filetest.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/2a0_filetest.gno b/gnovm/tests/files/types/2a0_SUB_filetest.gno similarity index 51% rename from gnovm/tests/files/types/2a0_filetest.gno rename to gnovm/tests/files/types/2a0_SUB_filetest.gno index 156fe844751..e3793e0d36a 100644 --- a/gnovm/tests/files/types/2a0_filetest.gno +++ b/gnovm/tests/files/types/2a0_SUB_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/2a0_SUB_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/30a1_LAND_filetest.gno b/gnovm/tests/files/types/30a1_LAND_filetest.gno deleted file mode 100644 index ada74750bad..00000000000 --- a/gnovm/tests/files/types/30a1_LAND_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(true && 0) -} - -// Error: -// main/files/types/30a1_LAND_filetest.gno:4: operator && not defined on: bigint \ No newline at end of file diff --git a/gnovm/tests/files/types/3a0_filetest.gno b/gnovm/tests/files/types/3a0_MUL_filetest.gno similarity index 51% rename from gnovm/tests/files/types/3a0_filetest.gno rename to gnovm/tests/files/types/3a0_MUL_filetest.gno index 42fc593c685..2a38ffa48f4 100644 --- a/gnovm/tests/files/types/3a0_filetest.gno +++ b/gnovm/tests/files/types/3a0_MUL_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/3a0_MUL_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/4a0_filetest.gno b/gnovm/tests/files/types/4a0_QUO_filetest.gno similarity index 51% rename from gnovm/tests/files/types/4a0_filetest.gno rename to gnovm/tests/files/types/4a0_QUO_filetest.gno index e357bf749fc..d7e69d7f10c 100644 --- a/gnovm/tests/files/types/4a0_filetest.gno +++ b/gnovm/tests/files/types/4a0_QUO_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/4a0_QUO_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/4f0_filetest.gno b/gnovm/tests/files/types/4f0_filetest.gno new file mode 100644 index 00000000000..7db1773913e --- /dev/null +++ b/gnovm/tests/files/types/4f0_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := 1 + println(a / 0) +} + +// Error: +// main/files/types/4f0_filetest.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/5a0_filetest.gno b/gnovm/tests/files/types/5a0_REM_filetest.gno similarity index 51% rename from gnovm/tests/files/types/5a0_filetest.gno rename to gnovm/tests/files/types/5a0_REM_filetest.gno index 6fa8e3dcbda..b2199a69489 100644 --- a/gnovm/tests/files/types/5a0_filetest.gno +++ b/gnovm/tests/files/types/5a0_REM_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/5a0_REM_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/5f3_filetest.gno b/gnovm/tests/files/types/5f3_filetest.gno new file mode 100644 index 00000000000..d203e9ecffc --- /dev/null +++ b/gnovm/tests/files/types/5f3_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := 1 + println(a % 0) +} + +// Error: +// main/files/types/5f3_filetest.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/6a0_filetest.gno b/gnovm/tests/files/types/6a0_AND_filetest.gno similarity index 51% rename from gnovm/tests/files/types/6a0_filetest.gno rename to gnovm/tests/files/types/6a0_AND_filetest.gno index 6c90121daeb..9b8d7590c56 100644 --- a/gnovm/tests/files/types/6a0_filetest.gno +++ b/gnovm/tests/files/types/6a0_AND_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/6a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/6a0_AND_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/7a0_filetest.gno b/gnovm/tests/files/types/7a0_OR_filetest.gno similarity index 51% rename from gnovm/tests/files/types/7a0_filetest.gno rename to gnovm/tests/files/types/7a0_OR_filetest.gno index 45a7cdf4bdc..01c82fc0b4d 100644 --- a/gnovm/tests/files/types/7a0_filetest.gno +++ b/gnovm/tests/files/types/7a0_OR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/7a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/7a0_OR_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/8a0_filetest.gno b/gnovm/tests/files/types/8a0_XOR_filetest.gno similarity index 51% rename from gnovm/tests/files/types/8a0_filetest.gno rename to gnovm/tests/files/types/8a0_XOR_filetest.gno index 0d58e905d7c..cfd863e9992 100644 --- a/gnovm/tests/files/types/8a0_filetest.gno +++ b/gnovm/tests/files/types/8a0_XOR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/8a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/8a0_XOR_filetest.gno:5: invalid operation: mismatched types int8 and int diff --git a/gnovm/tests/files/types/9a0_filetest.gno b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno similarity index 51% rename from gnovm/tests/files/types/9a0_filetest.gno rename to gnovm/tests/files/types/9a0_ANDNOT_filetest.gno index 87701d56e40..27c053d46cd 100644 --- a/gnovm/tests/files/types/9a0_filetest.gno +++ b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/9a0_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/9a0_ANDNOT_filetest.gno:5: invalid operation: mismatched types int8 and int From fe2cb7d6a79520f897928aeddbbfb3be601e19cc Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Dec 2023 16:14:32 +0800 Subject: [PATCH 056/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 234 ++++++++++----------- gnovm/pkg/gnolang/types.go | 92 ++------ gnovm/tests/files/types/0a1a0_filetest.gno | 1 - gnovm/tests/files/types/0a1a1_filetest.gno | 9 + gnovm/tests/files/types/0f2_filetest.gno | 2 +- 5 files changed, 133 insertions(+), 205 deletions(-) create mode 100644 gnovm/tests/files/types/0a1a1_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index fd7752e7860..0ede71b59b0 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -797,11 +797,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: + // TODO: improve readability debugPP.Println("---binaryExpr---, op: ", n.Op) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR + //special case of shift if isShift { checkOp(store, last, &n.Left, lt, n.Op, Binary) if baseOf(rt) != UintType { @@ -823,7 +825,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) debugPP.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) - // TODO: improve readibility if lic { if ric { // Left const, Right const ---------------------- @@ -832,15 +833,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // refer to 0a0_filetest if !isShift { cmp := cmpSpecificity(lcx.T, rcx.T) - if cmp < 0 { // this always implies untyped>? + if cmp < 0 { debugPP.Println("cmp < 0, ->") // convert n.Left to right type. checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false) } else if cmp == 0 { debugPP.Println("cmp == 0") - // TODO: consider check dir in here checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) + // XXX check left -> right would be same in reverse dir, since we are checking compatibility + // XXX if only check compatibility, checkOp has done the work? checkOrConvertType(store, last, &n.Left, rcx.T, false) } else { debugPP.Println("cmp > 0, <-") @@ -848,20 +850,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false) } - } - // check special case: zero divisor - if isQuoOrRem(n.Op) { - checkOperand(rcx) + // check special case: zero divisor + if isQuoOrRem(n.Op) { + checkOperand(rcx) + } } // Then, evaluate the expression. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE - } else if isUntyped(lcx.T) { // untyped -> not const, e.g. var a int = 1 + } else if isUntyped(lcx.T) { // untyped -> not const debugPP.Printf("left: %v is untyped const, right: %v is not const \n", lt, rt) // Left untyped const, Right not const ---------------- - if rnt, ok := rt.(*NativeType); ok { // typed <- untyped, native TODO: check this case - debugPP.Println("right is native type") - if isShift { + if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native) TODO: check this case + if isShift { // RHS of shift should not be native panic("should not happen") } // get concrete native base type. @@ -869,7 +870,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to pt type, checkOp(store, last, &n.Left, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, pt, false) - // convert n.Right to (gno) pt type, + // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. tx := constType(n, rnt) @@ -898,14 +899,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if !isUntyped(lcx.T) { // left is typed const, right is not const(also typed) - checkOp(store, last, &n.Left, rt, n.Op, Binary) - // if n.Op == SHR || n.Op == SHL { + // XXX, does this always imply typed on both sides? if isShift { - debugPP.Println("-----shift-----") // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check } else { checkOp(store, last, &n.Left, rt, n.Op, Binary) + // the other way round should work too checkOrConvertType(store, last, &n.Left, rt, false) } } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable @@ -918,14 +918,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isUntyped(rcx.T) { // Left not, Right untyped const ---------------- if isShift { - if baseOf(rt) != UintType { - // convert n.Right to (gno) uint type. - // checkOp(store, last, &n.Right, UintType, n.Op, true) - // checkOrConvertType(store, last, &n.Right, UintType, false) - convertConstType(store, last, &n.Right, UintType, false) // bypass check - } else { - // leave n.Left as is and baseOf(n.Right) as UintType. - } + // do nothing } else { if lnt, ok := lt.(*NativeType); ok { // get concrete native base type. @@ -960,79 +953,80 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Right to typed-nil type. checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) - } else if !isShift { // left not const(typed), right is typed const + } else if !isShift { // left not const(typed), right is typed const, both typed checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) } + // check special case first if isQuoOrRem(n.Op) { checkOperand(rcx) } } else { // ---both not const--- - if n.Op == SHL || n.Op == SHR { - } else if lnt, ok := lt.(*NativeType); ok { - if debug { - if !isShift { - assertSameTypes(lt, rt) // TODO: what is this for? possible untyped? - } - } - // If left and right are native type, - // convert left and right to gno, then - // convert result back to native. - // - // get concrete native base type. - pt := go2GnoBaseType(lnt.Type).(PrimitiveType) - // convert n.Left to (gno) pt type, - ln := Expr(Call(pt.String(), n.Left)) - // convert n.Right to pt or uint type, - rn := n.Right - if isShift { - if baseOf(rt) != UintType { - rn = Expr(Call("uint", n.Right)) + if !isShift { + if lnt, ok := lt.(*NativeType); ok { + if debug { + if !isShift { + assertSameTypes(lt, rt) // TODO: what is this for? possible untyped? + } } - } else { - rn = Expr(Call(pt.String(), n.Right)) - } - // and convert result back. - tx := constType(n, lnt) - // reset/create n2 to preprocess - // children. - n2 := &BinaryExpr{ - Left: ln, - Op: n.Op, - Right: rn, - } - resn := Node(Call(tx, n2)) - resn = Preprocess(store, last, resn) - return resn, TRANS_CONTINUE - // NOTE: binary operations are always - // computed in gno, never with - // reflect. - } else { - debugPP.Println("lt not native") - // non-shift non-const binary operator. - liu, riu := isUntyped(lt), isUntyped(rt) - if liu { - if riu { - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf( - "incompatible types in binary expression: %v %v %v", - n.Left, n.Op, n.Right)) + // If left and right are native type, + // convert left and right to gno, then + // convert result back to native. + // + // get concrete native base type. + pt := go2GnoBaseType(lnt.Type).(PrimitiveType) + // convert n.Left to (gno) pt type, + ln := Expr(Call(pt.String(), n.Left)) + // convert n.Right to pt or uint type, + rn := n.Right + if isShift { + if baseOf(rt) != UintType { + rn = Expr(Call("uint", n.Right)) } - } else { // left untyped, right typed - debugPP.Println("left untyped, right is typed") - checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) + } else { + rn = Expr(Call(pt.String(), n.Right)) } - } else if riu { // left typed, right untyped - if !isShift { - checkOp(store, last, &n.Right, lt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lt, false) + // and convert result back. + tx := constType(n, lnt) + // reset/create n2 to preprocess + // children. + n2 := &BinaryExpr{ + Left: ln, + Op: n.Op, + Right: rn, } - } else { // both typed vars, refer to 0a1f_filetest - debugPP.Printf("else, is lt untyped: %t, is rt untyped: %t \n", liu, riu) - if !isShift { - checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) + resn := Node(Call(tx, n2)) + resn = Preprocess(store, last, resn) + return resn, TRANS_CONTINUE + // NOTE: binary operations are always + // computed in gno, never with + // reflect. + } else { + debugPP.Println("lt not native") + // non-shift non-const binary operator. + liu, riu := isUntyped(lt), isUntyped(rt) + if liu { + if riu { + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf( + "incompatible types in binary expression: %v %v %v", + n.Left, n.Op, n.Right)) + } + } else { // left untyped, right typed + debugPP.Println("left untyped, right is typed") + checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false) + } + } else if riu { // left typed, right untyped + if !isShift { + checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOrConvertType(store, last, &n.Right, lt, false) + } + } else { // both typed vars, refer to 0a1f_filetest + if !isShift { + checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false) + } } } } @@ -2492,6 +2486,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // default: } } + // general case cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx @@ -2515,14 +2510,12 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { debugPP.Printf("convertConst, cx:%v, t:%v \n", cx, t) if t != nil && t.Kind() == InterfaceKind { - debugPP.Println("set t to nil, if its kind is interface") t = nil // signifies to convert to default type. } if isUntyped(cx.T) { debugPP.Println("convert untyped const") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) - debug.Printf("after conversion: cx: %v \n", cx) } else if t != nil { debugPP.Println("convert typed const for indexing") // e.g. a named type or uint8 type to int for indexing. @@ -2541,13 +2534,8 @@ func isQuoOrRem(op Word) bool { } func checkOperand(cx *ConstExpr) { - if cx.TypedValue.T != nil { - debugPP.Println("check operand, kind is: ", cx.TypedValue.T.Kind()) - } if cx.TypedValue.Sign() == 0 { panic("invalid operation: division by zero") - } else { - debugPP.Println("sign is: ", cx.TypedValue.Sign()) } } @@ -2560,7 +2548,7 @@ func isComparison(op Word) bool { } } -type checkMode int +type nodeType int const ( Binary = iota @@ -2570,10 +2558,10 @@ const ( ) // check operand types with operators -func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, mode checkMode) { - debugPP.Printf("checkOp, dt: %v, op: %v, mode: %v \n", dt, op, mode) - if mode == Unary || mode == IncDec { - switch mode { +func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { + debugPP.Printf("checkOp, dt: %v, op: %v, nt: %v \n", dt, op, nt) + if nt == Unary || nt == IncDec { + switch nt { case Unary: // unary if pred, ok := unaryPredicates[op]; ok { @@ -2597,15 +2585,14 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, mode checkM } else if *x != nil { xt = evalStaticTypeOf(store, last, *x) } - switch mode { + switch nt { case Binary: if isComparison(op) { switch op { case EQL, NEQ: // check maybeIdenticalType - // 1. first, check specific types can be compared, like binaryPredicates for ADD, etc - // 2. maybeIdenticalType requires one is assignable to another - // 3. handle nil - // TODO: is xt is nil + // NOTE: not checking types strict identical here, unlike ADD, etc + // this will pass the case one is interface and the other implements this interface + // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertable -> assignable if ok, code := maybeIdenticalType(xt, dt); !ok { panic(code) } @@ -2618,34 +2605,33 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, mode checkM default: panic("invalid comparison operator") } - } - debugPP.Println("binary---") - // two steps of check: - // first, check is the dt type satisfies op, the switch logic - // second, xt can be converted to dt, this is done below this - // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt - if pred, ok := binaryPredicates[op]; ok { - if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } else { + // two steps of check: + // first, check is the dt type satisfies op, the switch logic + // second, xt can be converted to dt, this is done below this + // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt + if pred, ok := binaryPredicates[op]; ok { + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } - } - switch op { - case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: - // if both typed - if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if xt != nil && dt != nil { - if xt.TypeID() != dt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + switch op { + case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: + // if both typed + if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped + if xt != nil && dt != nil { + if xt.TypeID() != dt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) + } } + debugPP.Println("typed and identical as maybeIdenticalType") } - debugPP.Println("typed and identical as maybeIdenticalType") + case SHL, SHR: + default: + // Note: others no check, assign will be check in assignable } - case SHL, SHR: - default: - // Note: others no check, assign will be check in assignable } case Assign: - debugPP.Println("assign---") if pred, ok := AssignStmtPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 974dd873434..dfd210f3aeb 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -277,8 +277,8 @@ const ( // IsConstType = IsBoolean | IsNumeric | IsString ) -// this is more convenient than compare with types -func (pt PrimitiveType) Predicate() predicate { +// predicate makes it more convenient than compare with types +func (pt PrimitiveType) predicate() predicate { switch pt { case InvalidType: return IsInvalid @@ -334,7 +334,7 @@ func (pt PrimitiveType) Predicate() predicate { func isOrdered(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsOrdered != 0 || t.Predicate()&IsRune != 0 { + if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { return true } return false @@ -346,7 +346,7 @@ func isOrdered(t Type) bool { func isBoolean(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsBoolean != 0 { + if t.predicate() != IsInvalid && t.predicate()&IsBoolean != 0 { return true } return false @@ -359,7 +359,7 @@ func isBoolean(t Type) bool { func isNumeric(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate()&IsRune != 0 { + if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsRune != 0 { return true } return false @@ -372,7 +372,7 @@ func isNumeric(t Type) bool { func isIntNum(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate()&IsUnsigned != 0 || t.Predicate()&IsBigInt != 0 || t.Predicate()&IsRune != 0 { + if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsBigInt != 0 || t.predicate()&IsRune != 0 { return true } return false @@ -384,7 +384,7 @@ func isIntNum(t Type) bool { //func isIntOrUint(t Type) bool { // switch t := baseOf(t).(type) { // case PrimitiveType: -// if t.Predicate() != IsInvalid && t.Predicate()&IsInteger != 0 || t.Predicate()&IsUnsigned != 0 || t.Predicate()&IsRune != 0 { +// if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsRune != 0 { // return true // } // return false @@ -396,7 +396,7 @@ func isIntNum(t Type) bool { func isNumericOrString(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.Predicate() != IsInvalid && t.Predicate()&IsNumeric != 0 || t.Predicate()&IsString != 0 || t.Predicate()&IsRune != 0 { + if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsString != 0 || t.predicate()&IsRune != 0 { return true } return false @@ -1138,7 +1138,6 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // field is embedded interface... im2 := baseOf(im.Type).(*InterfaceType) if !im2.IsImplementedBy(ot) { - debugPP.Println("first false") return false } else { continue @@ -1147,7 +1146,6 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // find method in field. tr, hp, rt, ft, _ := findEmbeddedFieldType(it.PkgPath, ot, im.Name, nil) if tr == nil { // not found. - debugPP.Println("second false") return false } if nft, ok := ft.(*NativeType); ok { @@ -1158,7 +1156,6 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { // ie, if each of ft's arg types can match // against the desired arg types in im.Types. if !gno2GoTypeMatches(im.Type, nft.Type) { - debugPP.Println("third false") return false } } else if mt, ok := ft.(*FuncType); ok { @@ -2654,23 +2651,23 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := checkConvertable(pt.Elt, cdt.Elt, false) + cdt := assignable(pt.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := checkConvertable(at.Elt, cdt.Elt, false) + cdt := assignable(at.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := checkConvertable(st.Elt, cdt.Elt, false) + cdt := assignable(st.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := checkConvertable(mt.Key, cdt.Key, false) - cn2 := checkConvertable(mt.Value, cdt.Value, false) + cn1 := assignable(mt.Key, cdt.Key, false) + cn2 := assignable(mt.Value, cdt.Value, false) return cn1 || cn2 || conversionNeeded } case *FuncType: @@ -2719,69 +2716,6 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { //} } -// type-check rules: -// 1. this happens in binary expressions, assign stmt, call to a func(args and return values) -// 2. cases: (typed/untyped)const op not const, not const op (typed/untyped)const, not const/not const -// 3. steps: first check legal operands of an Op, requires operands on left and right are typed, and both legal with the Op, -// or if one of the operand is not legal with the Op(while the other is) but can be converted into the corresponding one. -// e.g. : 1 + "a" is illegal, or int(1) + 0 is legal after convert -// untyped 0 to int(0) implicitly(no cast), this is because "a" cannot be converted to 1, is untyped 0, which is -// untyped bigint can be converted to int(0). -// special case in here is declared types, is A is declared type of B, and baseOf(A) == B, A and B is assignable in both direction -// NOTE: Op like + - * / % ,etc. have a more strict constrain than equality == or != -// NOTE: if both a typed, but not in the rule of declared type, no conversion. just check if they match. - -// 2. if one of LHS or RHS is constExpr(typed or untyped), it would be converted to the type of its -// corresponding side(using checkOrConvertType, iff it's assignable, using checkConvertable), e.g. int-> int8, int-> (type Error int), -// 3. if both LHS and RHS are not const, assertTypeMatchStrict - -// 4. Operators. need one place in asset* or checkConvertable, to switch operators - -// TODO: merge this with checkConvertable -//func assertTypeMatchStrict(lt, rt Type, op Word) { -// if lt == nil && rt == nil { -// println("1") -// // both are nil. -// } else if lt == nil || rt == nil { -// println("2") -// // one is nil. see function comment. -// } else if lt.Kind() == rt.Kind() && -// isUntyped(lt) || isUntyped(rt) { -// println("3") -// // one is untyped of same kind. -// } else if lt.Kind() == InterfaceKind && -// IsImplementedBy(lt, rt) { -// println("4") -// // one is untyped of same kind. -// // rt implements lt (and lt is nil interface). -// } else if rt.Kind() == InterfaceKind && -// IsImplementedBy(rt, lt) { -// println("5") -// // lt implements rt (and rt is nil interface). -// } else if lt.TypeID() == rt.TypeID() { -// println("6") -// // non-nil types are identical. -// } else { -// println("7") -// panic("7, incompatible operands") -// //debug.Errorf( -// // "incompatible operands in binary (eql/neq) expression: %s and %s", -// // lt.String(), -// // rt.String(), -// //) -// } -// // check special case, + - & / % -// switch op { -// case ADD: // assume untyped has been converted -// if lt.TypeID() != rt.TypeID() { -// panic("+ has mismatched operands") -// } -// if !isTypedNumber(lt) || !isTypedString(lt) { -// panic(fmt.Sprintf("+ should have operand number or string, while have: %v", lt)) -// } -// } -//} - // ---------------------------------------- // misc diff --git a/gnovm/tests/files/types/0a1a0_filetest.gno b/gnovm/tests/files/types/0a1a0_filetest.gno index 2ab23e5d8f3..f10b0cf599a 100644 --- a/gnovm/tests/files/types/0a1a0_filetest.gno +++ b/gnovm/tests/files/types/0a1a0_filetest.gno @@ -3,7 +3,6 @@ package main func main() { a := uint(1) println(uint64(1) == a) - println(r) } // Error: diff --git a/gnovm/tests/files/types/0a1a1_filetest.gno b/gnovm/tests/files/types/0a1a1_filetest.gno new file mode 100644 index 00000000000..996950e6092 --- /dev/null +++ b/gnovm/tests/files/types/0a1a1_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := uint(1) + println(a == uint64(1)) +} + +// Error: +// main/files/types/0a1a1_filetest.gno:5: cannot use uint64 as uint diff --git a/gnovm/tests/files/types/0f2_filetest.gno b/gnovm/tests/files/types/0f2_filetest.gno index d963f28565f..7ded58b4ff0 100644 --- a/gnovm/tests/files/types/0f2_filetest.gno +++ b/gnovm/tests/files/types/0f2_filetest.gno @@ -16,7 +16,7 @@ var errCmp = errors.New("XXXX") // specil case: // one is interface func main() { - if Error(0) == errCmp { + if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 //if errCmp == 1 { println("what the firetruck?") } else { From 5f58979450e6142053c8405be430b91889b61d89 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Dec 2023 16:17:32 +0800 Subject: [PATCH 057/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0ede71b59b0..0d0faa6035a 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -803,7 +803,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR - //special case of shift + // special case of shift if isShift { checkOp(store, last, &n.Left, lt, n.Op, Binary) if baseOf(rt) != UintType { From c936fea17da531238ba1d4f7ae72f9acc01aeb3a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 18 Dec 2023 17:59:05 +0800 Subject: [PATCH 058/193] fix special case relate to nil type --- gnovm/pkg/gnolang/gonative.go | 12 +- gnovm/pkg/gnolang/op_binary.go | 9 +- gnovm/pkg/gnolang/preprocess.go | 182 ++++++++++++++---- gnovm/pkg/gnolang/types.go | 53 +++-- gnovm/pkg/gnolang/values_conversions.go | 14 +- gnovm/pkg/gnolang/values_string.go | 8 +- gnovm/tests/files/addr0b_stdlibs.gno | 2 +- gnovm/tests/files/interface27b.gno | 2 +- gnovm/tests/files/interface28b.gno | 2 +- gnovm/tests/files/types/0a01_filetest.gno | 2 +- gnovm/tests/files/types/0f30f_filetest.gno | 11 ++ gnovm/tests/files/types/0f30g_filetest.gno | 11 ++ gnovm/tests/files/types/0f32_filetest.gno | 3 +- .../files/types/0f43_hasNil_filetest.gno | 15 ++ gnovm/tests/files/types/0f43a_filetest.gno | 25 +++ gnovm/tests/files/types/0f44_filetest.gno | 16 ++ gnovm/tests/files/types/0f45_filetest.gno | 14 ++ gnovm/tests/files/types/0f46_filetest.gno | 18 ++ gnovm/tests/files/types/0f46a_filetest.gno | 18 ++ .../files/types/0f47_nilcast_filetest.gno | 18 ++ gnovm/tests/files/types/0f47a_filetest.gno | 10 + gnovm/tests/files/types/0f47b_filetest.gno | 11 ++ gnovm/tests/files/types/0f47c_filetest.gno | 20 ++ gnovm/tests/files/types/0f47d_filetest.gno | 17 ++ gnovm/tests/files/types/0f47e_filetest.gno | 17 ++ gnovm/tests/files/types/0f48_filetest.gno | 22 +++ gnovm/tests/files/zrealm1.gno | 16 +- 27 files changed, 472 insertions(+), 76 deletions(-) create mode 100644 gnovm/tests/files/types/0f30f_filetest.gno create mode 100644 gnovm/tests/files/types/0f30g_filetest.gno create mode 100644 gnovm/tests/files/types/0f43_hasNil_filetest.gno create mode 100644 gnovm/tests/files/types/0f43a_filetest.gno create mode 100644 gnovm/tests/files/types/0f44_filetest.gno create mode 100644 gnovm/tests/files/types/0f45_filetest.gno create mode 100644 gnovm/tests/files/types/0f46_filetest.gno create mode 100644 gnovm/tests/files/types/0f46a_filetest.gno create mode 100644 gnovm/tests/files/types/0f47_nilcast_filetest.gno create mode 100644 gnovm/tests/files/types/0f47a_filetest.gno create mode 100644 gnovm/tests/files/types/0f47b_filetest.gno create mode 100644 gnovm/tests/files/types/0f47c_filetest.gno create mode 100644 gnovm/tests/files/types/0f47d_filetest.gno create mode 100644 gnovm/tests/files/types/0f47e_filetest.gno create mode 100644 gnovm/tests/files/types/0f48_filetest.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 7e3992559e6..e84d67fe24b 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -359,12 +359,16 @@ func Gno2GoValue(tv *TypedValue, rv reflect.Value) (ret reflect.Value) { // ConvertTo(). // Unlike go2GnoValue2(), rv may be invalid. func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { + debugPP.Printf("go2GnoValue---, rv: %v \n", rv) if !rv.IsValid() { return } if rv.Kind() == reflect.Interface { - if rv.IsNil() { - return TypedValue{} + if rv.IsNil() { // special case, nil interface, interface(nil) differs nil in types, but equal + return TypedValue{ + T: (&InterfaceType{}), + } + //return TypedValue{} } else { rv = rv.Elem() } @@ -437,6 +441,7 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { // reflection, any child Gno declared types cannot change // types, and pointer values cannot change. func go2GnoValueUpdate(alloc *Allocator, rlm *Realm, lvl int, tv *TypedValue, rv reflect.Value) { + debugPP.Println("go2GnoValueUpdate---") // Special case if nil: if tv.IsUndefined() { return // do nothing @@ -901,7 +906,7 @@ func gno2GoType(t Type) reflect.Type { // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). -// This is called when autoNative is true in checkConvertable(). +// This is called when autoNative is true in checkConvertible(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { @@ -1405,6 +1410,7 @@ func (m *Machine) doOpStructLitGoNative() { // NOTE: Unlike doOpCall(), doOpCallGoNative() also handles // conversions, similarly to doOpConvert(). func (m *Machine) doOpCallGoNative() { + debugPP.Println("doOpCallGoNative---") fr := m.LastFrame() fv := fr.GoFunc ft := fv.Value.Type() diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 84de6411b57..8b67eb940c9 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -2,9 +2,8 @@ package gnolang import ( "fmt" - "math/big" - "github.com/cockroachdb/apd/v3" + "math/big" ) // ---------------------------------------- @@ -80,7 +79,7 @@ func (m *Machine) doOpLand() { } func (m *Machine) doOpEql() { - debugPP.Println("doOpEql") + debugPP.Println("doOpEql---") m.PopExpr() // get right and left operands. @@ -105,7 +104,7 @@ func (m *Machine) doOpEql() { } func (m *Machine) doOpNeq() { - debugPP.Println("doOpNeq") + debugPP.Println("doOpNeq---") m.PopExpr() // get right and left operands. @@ -123,6 +122,7 @@ func (m *Machine) doOpNeq() { debugPP.Println("-----type not identical------") res = true } + debugPP.Println("------res:-----", res) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -377,6 +377,7 @@ func (m *Machine) doOpBandn() { // TODO: can be much faster. func isEql(store Store, lv, rv *TypedValue) bool { + debugPP.Printf("isEql: lv: %v, rv: %v \n", lv, rv) // If one is undefined, the other must be as well. // Fields/items are set to defaultValue along the way. lvu := lv.IsUndefined() diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0d0faa6035a..7c8d4294fe0 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,10 +2,9 @@ package gnolang import ( "fmt" + "github.com/gnolang/gno/tm2/pkg/errors" "math/big" "reflect" - - "github.com/gnolang/gno/tm2/pkg/errors" ) type f func(t Type) bool @@ -19,29 +18,18 @@ var ( func init() { binaryPredicates[ADD] = isNumericOrString - AssignStmtPredicates[ADD_ASSIGN] = isNumericOrString binaryPredicates[SUB] = isNumeric - AssignStmtPredicates[SUB_ASSIGN] = isNumeric binaryPredicates[MUL] = isNumeric - AssignStmtPredicates[MUL_ASSIGN] = isNumeric binaryPredicates[QUO] = isNumeric - AssignStmtPredicates[QUO_ASSIGN] = isNumeric binaryPredicates[REM] = isIntNum - AssignStmtPredicates[REM_ASSIGN] = isIntNum binaryPredicates[SHL] = isNumeric - AssignStmtPredicates[SHL_ASSIGN] = isNumeric binaryPredicates[SHR] = isNumeric - AssignStmtPredicates[SHR_ASSIGN] = isNumeric // bit op binaryPredicates[BAND] = isIntNum - AssignStmtPredicates[BAND_ASSIGN] = isIntNum binaryPredicates[XOR] = isIntNum - AssignStmtPredicates[XOR_ASSIGN] = isIntNum binaryPredicates[BOR] = isIntNum - AssignStmtPredicates[BOR_ASSIGN] = isIntNum binaryPredicates[BAND_NOT] = isIntNum - AssignStmtPredicates[BAND_NOT_ASSIGN] = isIntNum // logic op binaryPredicates[LAND] = isBoolean binaryPredicates[LOR] = isBoolean @@ -59,9 +47,22 @@ func init() { unaryPredicates[NOT] = isBoolean // Inc Dec stmt - // NOTE: special case to be consistent with op_inc_dec, line3, no float support for now while go do. + // NOTE: special case to be consistent with op_inc_dec, line3, no float support for now while go does. IncDecStmtPredicates[INC] = isNumeric IncDecStmtPredicates[DEC] = isNumeric + + // assign stmt + AssignStmtPredicates[ADD_ASSIGN] = isNumericOrString + AssignStmtPredicates[SUB_ASSIGN] = isNumeric + AssignStmtPredicates[MUL_ASSIGN] = isNumeric + AssignStmtPredicates[QUO_ASSIGN] = isNumeric + AssignStmtPredicates[REM_ASSIGN] = isIntNum + AssignStmtPredicates[SHL_ASSIGN] = isNumeric + AssignStmtPredicates[SHR_ASSIGN] = isNumeric + AssignStmtPredicates[BAND_ASSIGN] = isIntNum + AssignStmtPredicates[XOR_ASSIGN] = isIntNum + AssignStmtPredicates[BOR_ASSIGN] = isIntNum + AssignStmtPredicates[BAND_NOT_ASSIGN] = isIntNum } // ------------------------------------------------------------------------------------------- @@ -235,6 +236,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if debug { debug.Printf("Preprocess %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } + debugPP.Printf("Preprocess %s, (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) switch stage { // ---------------------------------------- @@ -681,6 +683,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { switch n := n.(type) { // TRANS_LEAVE ----------------------- case *NameExpr: // e.g. var a int, a is NameExpr + debugPP.Println("NameExpr---") // Validity: check that name isn't reserved. if isReservedName(n.Name) { panic(fmt.Sprintf( @@ -791,6 +794,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BasicLitExpr: + debugPP.Println("basicLitExpr---") // Replace with *ConstExpr. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE @@ -840,10 +844,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rcx.T, false) } else if cmp == 0 { debugPP.Println("cmp == 0") - checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) - // XXX check left -> right would be same in reverse dir, since we are checking compatibility - // XXX if only check compatibility, checkOp has done the work? - checkOrConvertType(store, last, &n.Left, rcx.T, false) + // NOTE: nil manipulation + // NOTE: refer to 0f46, this logic convert nil to the corresponding type intentionally, rather than the other way round, + // to simplify the logic of comparing in runtime, isEql. + // otherwise need to compare undefined with nil value but have specific type in (sliceType, mapType, funcType, PointerType): + // lv: (nil main.m), rv: (undefined), this should be comparable and can be equal if the lv value is nil, but complicated + // now we have: lv: (nil main.m), rv: (nil main.m), would be simpler to compare. + if lcx.T == nil { + checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rcx.T, false) + } else if rcx.T == nil { + checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) + checkOrConvertType(store, last, &n.Right, lcx.T, false) + } else { // default case, choose -> or <- on convenience + checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rcx.T, false) + } } else { debugPP.Println("cmp > 0, <-") // convert n.Right to left type. @@ -898,21 +914,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false) } } - } else if !isUntyped(lcx.T) { // left is typed const, right is not const(also typed) - // XXX, does this always imply typed on both sides? + } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable + debugPP.Println("lcx.T is nil") + // convert n.Left to typed-nil type. + checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false) + } else { // left is typed const, right is not const(also typed), and not nil if isShift { // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check - } else { + } else { // dir makes sense here, since non-const(right) implies more dynamic(interface) checkOp(store, last, &n.Left, rt, n.Op, Binary) // the other way round should work too checkOrConvertType(store, last, &n.Left, rt, false) } - } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable - debugPP.Println("lcx.T is nil") - // convert n.Left to typed-nil type. - checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) } } else if ric { // right is const, left is not--- if isUntyped(rcx.T) { @@ -948,11 +963,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil + // TODO: check lt maybeIdentical debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest - // TODO: shift - // convert n.Right to typed-nil type. + //if lnt, ok := lt.(*NativeType); ok { + // if ilnt, ok := baseOf(lnt).(*InterfaceType); ok { + // checkOp(store, last, &n.Right, ilnt, n.Op, Binary) + // checkOrConvertType(store, last, &n.Right, ilnt, false) + // } + //} + // in case of rcx.T == nil(untyped nil), require lt is maybeNil checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) + //// TODO: shift + //// convert n.Right to typed-nil type. } else if !isShift { // left not const(typed), right is typed const, both typed checkOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false) @@ -1034,7 +1057,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *CallExpr: - debugPP.Println("---CallExpr---") + debugPP.Printf("---CallExpr---: %v \n", n) + //if debugPP { + // rd.PrintStack() + //} // Func type evaluation. var ft *FuncType ift := evalStaticTypeOf(store, last, n.Func) @@ -1042,14 +1068,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *FuncType: ft = cft case *NativeType: + debugPP.Println("native type") ft = store.Go2GnoType(cft.Type).(*FuncType) case *TypeType: + debugPP.Println("type type") if len(n.Args) != 1 { panic("type conversion requires single argument") } n.NumArgs = 1 + var dt Type if arg0, ok := n.Args[0].(*ConstExpr); ok { + debugPP.Println("const expr") ct := evalStaticType(store, last, n.Func) + if arg0.IsUndefined() { // nil is const + switch ct.Kind() { + case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind: + dt = ct + default: + panic(fmt.Sprintf( + "cannot convert %v to %v", + arg0, ct.Kind())) + } + } // As a special case, if a decimal cannot // be represented as an integer, it cannot be converted to one, // and the error is handled here. @@ -1068,7 +1108,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // (const) untyped decimal -> float64. // (const) untyped bigint -> int. - convertConst(store, last, arg0, nil) + convertConst(store, last, arg0, dt) // evaluate the new expression. cx := evalConst(store, last, n) // Though cx may be undefined if ct is interface, @@ -1076,7 +1116,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE } else { + debugPP.Println("else") ct := evalStaticType(store, last, n.Func) + debugPP.Printf("ct: %v \n", ct) n.SetAttribute(ATTR_TYPEOF_VALUE, ct) return n, TRANS_CONTINUE } @@ -1119,6 +1161,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } + debugPP.Println("general cases---") // Continue with general case. hasVarg := ft.HasVarg() isVarg := n.Varg @@ -1160,6 +1203,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if !hasVarg { + debugPP.Println("no varg") argTVs = evalStaticTypedValues(store, last, n.Args...) if len(n.Args) != len(ft.Params) { panic(fmt.Sprintf( @@ -1218,15 +1262,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, tv := range argTVs { if hasVarg { if (len(spts) - 1) <= i { - checkConvertable(tv.T, spts[len(spts)-1].Type.Elem(), true) + checkConvertible(tv.T, spts[len(spts)-1].Type.Elem(), true) } else { - checkConvertable(tv.T, spts[i].Type, true) + checkConvertible(tv.T, spts[i].Type, true) } } else { - checkConvertable(tv.T, spts[i].Type, true) + checkConvertible(tv.T, spts[i].Type, true) } } } else { + debugPP.Println("no embeded") for i := range n.Args { if hasVarg { if (len(spts) - 1) <= i { @@ -1234,15 +1279,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if len(spts) <= i { panic("expected final vargs slice but got many") } + debugPP.Println("1") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } else { + debugPP.Println("2") checkOrConvertType(store, last, &n.Args[i], spts[len(spts)-1].Type.Elem(), true) } } else { + debugPP.Println("3") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } else { + debugPP.Println("4") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true) } } @@ -1251,6 +1300,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *IndexExpr: + debugPP.Println("IndexExpr---") dt := evalStaticTypeOf(store, last, n.X) if dt.Kind() == PointerKind { // if a is a pointer to an array, @@ -1276,6 +1326,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SliceExpr: + debugPP.Println("SliceExpr---") // Replace const L/H/M with int *ConstExpr, // or if not const, assert integer type.. checkOrConvertIntegerType(store, last, n.Low) @@ -1284,6 +1335,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *TypeAssertExpr: + debugPP.Println("TypeAssertExpr---") if n.Type == nil { panic("should not happen") } @@ -1293,6 +1345,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: + debugPP.Println("UnaryExpr---") xt := evalStaticTypeOf(store, last, n.X) debugPP.Printf("---unaryExpr---, op: %v, xt: %v \n", n.Op, xt) if xnt, ok := xt.(*NativeType); ok { @@ -1399,11 +1452,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *KeyValueExpr: + debugPP.Println("KeyValueExpr---") // NOTE: For simplicity we just // use the *CompositeLitExpr. // TRANS_LEAVE ----------------------- case *SelectorExpr: + debugPP.Println("SelectorExpr---") xt := evalStaticTypeOf(store, last, n.X) // Set selector path based on xt's type. @@ -1552,11 +1607,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *FieldTypeExpr: + debugPP.Println("FieldTypeExpr---") // Replace const Tag with default *ConstExpr. convertIfConst(store, last, n.Tag) // TRANS_LEAVE ----------------------- case *ArrayTypeExpr: + debugPP.Println("ArrayTypeExpr---") if n.Len == nil { // Calculate length at *CompositeLitExpr:LEAVE } else { @@ -1572,22 +1629,27 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SliceTypeExpr: + debugPP.Println("SliceTypeExpr---") evalStaticType(store, last, n) // TRANS_LEAVE ----------------------- case *InterfaceTypeExpr: + debugPP.Println("InterfaceTypeExpr---") evalStaticType(store, last, n) // TRANS_LEAVE ----------------------- case *ChanTypeExpr: + debugPP.Println("ChanTypeExpr---") evalStaticType(store, last, n) // TRANS_LEAVE ----------------------- case *FuncTypeExpr: + debugPP.Println("FuncTypeExpr---") evalStaticType(store, last, n) // TRANS_LEAVE ----------------------- case *MapTypeExpr: + debugPP.Println("MapTypeExpr---") evalStaticType(store, last, n) // TRANS_LEAVE ----------------------- @@ -1600,12 +1662,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Printf("---AssignStmt---, Op: %v, LHS: %v, RHS:%v \n", n.Op, n.Lhs, n.Rhs) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { + debugPP.Println("define----") // Rhs consts become default *ConstExprs. for _, rx := range n.Rhs { // NOTE: does nothing if rx is "nil". convertIfConst(store, last, rx) } if len(n.Lhs) > len(n.Rhs) { + debugPP.Println("len lhs > len rhs") // Unpack n.Rhs[0] to n.Lhs[:] if len(n.Rhs) != 1 { panic("should not happen") @@ -1624,6 +1688,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, lx := range n.Lhs { ln := lx.(*NameExpr).Name rf := cft.Results[i] + debugPP.Printf("rf.Type: %v \n", rf.Type) // re-definition last.Define(ln, anyValue(rf.Type)) } @@ -1658,6 +1723,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } debugPP.Println("else") } else { + debugPP.Println("else---") // General case: a, b := x, y for i, lx := range n.Lhs { ln := lx.(*NameExpr).Name @@ -1740,6 +1806,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BranchStmt: + debugPP.Println("BranchStmt---") switch n.Op { case BREAK: case CONTINUE: @@ -1772,20 +1839,24 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ForStmt: + debugPP.Println("ForStmt---") // Cond consts become bool *ConstExprs. checkOrConvertType(store, last, &n.Cond, BoolType, false) // TRANS_LEAVE ----------------------- case *IfStmt: + debugPP.Println("ifStmt---") // Cond consts become bool *ConstExprs. checkOrConvertType(store, last, &n.Cond, BoolType, false) // TRANS_LEAVE ----------------------- case *RangeStmt: + debugPP.Println("RangeStmt---") // NOTE: k,v already defined @ TRANS_BLOCK. // TRANS_LEAVE ----------------------- case *ReturnStmt: + debugPP.Println("ReturnStmt---") fnode, ft := funcOf(last) // Check number of return arguments. if len(n.Results) != len(ft.Results) { @@ -1876,6 +1947,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ValueDecl: + debugPP.Println("ValueDecl---") // evaluate value if const expr. if n.Const { // NOTE: may or may not be a *ConstExpr, @@ -1966,6 +2038,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if nx.Name == "_" { nx.Path = NewValuePathBlock(0, 0, "_") } else { + debugPP.Println("define for valDecl---") pn.Define2(n.Const, nx.Name, sts[i], tvs[i]) nx.Path = last.GetPathForName(nil, nx.Name) } @@ -1987,6 +2060,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *TypeDecl: + debugPP.Println("TypeDecl---") // Construct new Type, where any recursive // references refer to the old Type declared // during *TypeDecl:ENTER. Then, copy over the @@ -2276,17 +2350,20 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { + //debugPP.Printf("evalConst, last: %v, x: %v \n", last, x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) tv := cv.EvalStatic(last, x) cv.Release() + //debugPP.Printf("result: %v \n", tv) cx := &ConstExpr{ Source: x, TypedValue: tv, } cx.SetAttribute(ATTR_PREPROCESSED, true) setConstAttrs(cx) + //debugPP.Printf("cx: %+v, source: %v, tv: %v \n", cx, cx.Source, cx.TypedValue) return cx } @@ -2410,6 +2487,7 @@ func isConstType(x Expr) bool { } func cmpSpecificity(t1, t2 Type) int { + debugPP.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { t1s = t1p.Specificity() @@ -2445,11 +2523,15 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative //if debugPP { // rd.PrintStack() //} - debugPP.Printf("checkOrConvertType, x: %v:, t:%v, \n", x, t) + debugPP.Printf("checkOrConvertType, x: %v:, t:%v \n", x, t) + if nt, ok := t.(*NativeType); ok { // not native type, refer to time4_native.gno + debugPP.Printf("gnoType: %v, typeId: %v \n", nt.gnoType, nt.typeid) + } + if cx, ok := (*x).(*ConstExpr); ok { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno - checkConvertable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args + checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { @@ -2462,10 +2544,11 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative debugPP.Printf("else, xt not nil, xt: %v \n", xt) var conversionNeeded bool if t != nil { - conversionNeeded = checkConvertable(xt, t, autoNative) + conversionNeeded = checkConvertible(xt, t, autoNative) } debugPP.Println("need conversion: ", conversionNeeded) if isUntyped(xt) { + debugPP.Println("xt untyped") if t == nil { t = defaultTypeOf(xt) } @@ -2508,16 +2591,28 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - debugPP.Printf("convertConst, cx:%v, t:%v \n", cx, t) + debugPP.Printf("------convertConst, cx:%v, t:%v \n", cx, t) if t != nil && t.Kind() == InterfaceKind { - t = nil // signifies to convert to default type. + debugPP.Println("convert const, t is interface kind") + if cx.IsUndefined() { + debugPP.Println("convert const, cx is undefined") + if _, ok := t.(*NativeType); !ok { // bypass native nil interface + debugPP.Println("special case for undefined to interface{}") + debugPP.Printf("before convert, cx: %v, cx.T: %v \n", cx, cx.T) + ConvertTo(nilAllocator, store, &cx.TypedValue, t) + setConstAttrs(cx) + debugPP.Printf("after convert, cx: %v, cx.T: %v \n", cx, cx.T) + return + } + } + t = nil } if isUntyped(cx.T) { debugPP.Println("convert untyped const") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) } else if t != nil { - debugPP.Println("convert typed const for indexing") + debugPP.Println("convert coerce, t != nil") // e.g. a named type or uint8 type to int for indexing. ConvertTo(nilAllocator, store, &cx.TypedValue, t) setConstAttrs(cx) @@ -2592,7 +2687,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType case EQL, NEQ: // check maybeIdenticalType // NOTE: not checking types strict identical here, unlike ADD, etc // this will pass the case one is interface and the other implements this interface - // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertable -> assignable + // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertible -> assignable if ok, code := maybeIdenticalType(xt, dt); !ok { panic(code) } @@ -2660,9 +2755,10 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func checkConvertable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { +// TODO: name. convertible is for value, not type, should be check assignable? +func checkConvertible(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno - debugPP.Println("checkConvertable, xt or dt is nil") + debugPP.Println("checkConvertible, xt or dt is nil") return } return assignable(xt, dt, autoNative) @@ -3110,6 +3206,8 @@ func tryPredefine(store Store, last BlockNode, d Decl) (un Name) { t = &MapType{} case *StructTypeExpr: t = &StructType{} + case *StarExpr: + t = &PointerType{} case *NameExpr: if tv := last.GetValueRef(store, tx.Name); tv != nil { // (file) block name diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index dfd210f3aeb..363caf49bfd 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -257,11 +257,11 @@ func (pt PrimitiveType) TypeID() TypeID { } } -type predicate int +type category int const ( - IsInvalid = 0 - IsBoolean predicate = 1 << iota + IsInvalid = 0 + IsBoolean category = 1 << iota IsInteger IsUnsigned IsFloat @@ -277,8 +277,8 @@ const ( // IsConstType = IsBoolean | IsNumeric | IsString ) -// predicate makes it more convenient than compare with types -func (pt PrimitiveType) predicate() predicate { +// category makes it more convenient than compare with types +func (pt PrimitiveType) predicate() category { switch pt { case InvalidType: return IsInvalid @@ -384,7 +384,7 @@ func isIntNum(t Type) bool { //func isIntOrUint(t Type) bool { // switch t := baseOf(t).(type) { // case PrimitiveType: -// if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsRune != 0 { +// if t.category() != IsInvalid && t.category()&IsInteger != 0 || t.category()&IsUnsigned != 0 || t.category()&IsRune != 0 { // return true // } // return false @@ -2289,13 +2289,21 @@ func isIdenticalType(lt, rt Type) bool { // // one is untyped of same kind. } else if lt.Kind() == rt.Kind() && isDataByte(lt) { - // left is databyte of same kind, + // left is databyteinvalide operation of same kind, // specifically for assignments. // TODO: make another function // and remove this case? } else if lt.TypeID() == rt.TypeID() { debugPP.Println("typeID equal") // non-nil types are identical. + } else if ilt, ok := baseOf(lt).(*InterfaceType); ok { + if ilt.IsEmptyInterface() { + return true + } + } else if irt, ok := baseOf(rt).(*InterfaceType); ok { + if irt.IsEmptyInterface() { + return true + } } else { return false } @@ -2330,8 +2338,7 @@ func assertEqualityTypes(lt, rt Type) { } } -// XXX: maybeIdenticalType is a more strict check than assertSameTypes, refer to 0f20_filetest.gno, -// maybeIdenticalType is relaxed than isIdentical in preprocess. +// maybeIdenticalType is more relaxed than isIdentical, it's used in preprocess. // The logic here is, when != or == shows up, check if t is maybeIdenticalType, if yes, // then check the corresponding type(the other side of the operator) is convertable to t. func maybeIdenticalType(xt, dt Type) (bool, string) { @@ -2345,7 +2352,15 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { // TODO: check at least length here switch baseOf(cdt.Elem()).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? - return true, "" + switch cxt := baseOf(xt).(type) { + case *ArrayType: + if cxt.Len != cdt.Len { + return false, fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt) + } + return true, "" + default: + return false, fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt) + } default: return false, fmt.Sprintf("%v cannot be compared \n", cdt) } @@ -2363,7 +2378,7 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { return true, "" case *InterfaceType: return true, "" - case *SliceType, *FuncType, *MapType: // TODO: check only comparable with nil + case *SliceType, *FuncType, *MapType: if xt != nil { return false, fmt.Sprintf("%v can only be compared to nil \n", dt) } else { @@ -2372,17 +2387,23 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { } case *NativeType: if cdt.Type.Comparable() { + debugPP.Printf("cdt type: %v \n", cdt.Type) return true, "" } + debugPP.Printf("not comparable, cdt type: %v \n", cdt.Type) return false, fmt.Sprintf("%v is not comparable \n", dt) - case nil: // TODO: have this case? targe type is nil? + case nil: // refer to 0a01_filetest, 0f32_filetest. + debugPP.Println("dt is nil") switch cxt := baseOf(xt).(type) { - case *SliceType, *FuncType, *MapType, *InterfaceType: + case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer + debugPP.Printf("dt is nil, cxt: %v \n", cxt) return true, "" default: - return false, fmt.Sprintf("invalide operation, %v can only be compared to hasNil \n", cxt) + debugPP.Printf("default, dt is nil, cxt: %v \n", cxt) + return false, fmt.Sprintf("invalid operation, nil can not be compared to nil \n") } default: + debugPP.Printf("default: cdt: %v \n", cdt) return false, fmt.Sprintf("%v is not comparable \n", dt) } } @@ -2955,7 +2976,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkConvertable(spec, match.Elem(), false) + checkConvertible(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -2969,7 +2990,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkConvertable(spec, match, false) + checkConvertible(spec, match, false) return // ok } else { if isUntyped(spec) { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 60274e67693..0b94866015d 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -14,6 +14,7 @@ import ( // the conversion is forced and overflow/underflow is ignored. // TODO: return error, and let caller also print the file and line. func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { + debugPP.Printf("--------------ConvertTo, tv: %v, t: %v \n", tv, t) if debug { if t == nil { panic("ConvertTo() requires non-nil type") @@ -32,7 +33,9 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { ntv, tvIsNat := tv.T.(*NativeType) nt, tIsNat := t.(*NativeType) if tvIsNat { + debugPP.Println("tvIsNat") if tIsNat { + debugPP.Println("t IsNat") // both NativeType, use reflect to assert. if debug { if !ntv.Type.ConvertibleTo(nt.Type) { @@ -44,6 +47,8 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { tv.T = t return } else { + debugPP.Println("t not IsNat") + // both NativeType, use reflect to assert. // convert go-native to gno type (shallow). *tv = go2GnoValue2(alloc, store, tv.V.(*NativeValue).Value, false) ConvertTo(alloc, store, tv, t) @@ -73,10 +78,17 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { GNO_CASE: // special case for interface target if t.Kind() == InterfaceKind { + if tv.IsUndefined() { // set interface type + if _, ok := t.(*NativeType); !ok { + debugPP.Println("t is interface and not native") + tv.T = t + } + } return } // special case for undefined/nil source if tv.IsUndefined() { + debugPP.Println("case of undefined") tv.T = t return } @@ -877,7 +889,7 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { - debugPP.Printf("ConvertUntypedTo, tv:%v, t:%v \n", tv, t) + debugPP.Printf("------ConvertUntypedTo, tv:%v, t:%v \n", tv, t) if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index b64b491cbb8..16b91a1d197 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -278,7 +278,13 @@ func printNilOrValue(tv *TypedValue, valueType interface{}) string { // For gno debugging/testing. func (tv TypedValue) String() string { if tv.IsUndefined() { - return "(undefined)" + var n string + if tv.T == nil { + n = "nil" + } else { + n = tv.T.String() + } + return "(undefined)" + " " + n } vs := "" if tv.V == nil { diff --git a/gnovm/tests/files/addr0b_stdlibs.gno b/gnovm/tests/files/addr0b_stdlibs.gno index 2ec6782c7f0..324a30f8140 100644 --- a/gnovm/tests/files/addr0b_stdlibs.gno +++ b/gnovm/tests/files/addr0b_stdlibs.gno @@ -20,4 +20,4 @@ func main() { } // Output: -// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined),(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) +// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined) nil,(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) diff --git a/gnovm/tests/files/interface27b.gno b/gnovm/tests/files/interface27b.gno index 97c7127e315..7022b934b9f 100644 --- a/gnovm/tests/files/interface27b.gno +++ b/gnovm/tests/files/interface27b.gno @@ -7,4 +7,4 @@ func main() { } // Output: -// map{(0 int):(undefined)} +// map{(0 int):(undefined) .uverse.error} diff --git a/gnovm/tests/files/interface28b.gno b/gnovm/tests/files/interface28b.gno index 1fdcab58905..1a372943c09 100644 --- a/gnovm/tests/files/interface28b.gno +++ b/gnovm/tests/files/interface28b.gno @@ -7,4 +7,4 @@ func main() { } // Output: -// slice[(undefined)] +// slice[(undefined) .uverse.error] diff --git a/gnovm/tests/files/types/0a01_filetest.gno b/gnovm/tests/files/types/0a01_filetest.gno index 3a37fa86ce8..37d4f381901 100644 --- a/gnovm/tests/files/types/0a01_filetest.gno +++ b/gnovm/tests/files/types/0a01_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/0a01_filetest.gno:4: invalide operation, can only be compared to hasNil +// main/files/types/0a01_filetest.gno:4: invalid operation, nil can not be compared to nil diff --git a/gnovm/tests/files/types/0f30f_filetest.gno b/gnovm/tests/files/types/0f30f_filetest.gno new file mode 100644 index 00000000000..62cf24182df --- /dev/null +++ b/gnovm/tests/files/types/0f30f_filetest.gno @@ -0,0 +1,11 @@ +package main + +var a = [2]int{1, 1} +var b = [3]int{1, 1} + +func main() { + println(a == b) +} + +// Error: +// main/files/types/0f30f_filetest.gno:7: [2]int and [3]int cannot be compared diff --git a/gnovm/tests/files/types/0f30g_filetest.gno b/gnovm/tests/files/types/0f30g_filetest.gno new file mode 100644 index 00000000000..1a2518dfdf0 --- /dev/null +++ b/gnovm/tests/files/types/0f30g_filetest.gno @@ -0,0 +1,11 @@ +package main + +var a = [2]int{1, 1} +var b = []int{1, 1} + +func main() { + println(a == b) +} + +// Error: +// main/files/types/0f30g_filetest.gno:7: []int can only be compared to nil diff --git a/gnovm/tests/files/types/0f32_filetest.gno b/gnovm/tests/files/types/0f32_filetest.gno index c9d65acd3d7..321824566cb 100644 --- a/gnovm/tests/files/types/0f32_filetest.gno +++ b/gnovm/tests/files/types/0f32_filetest.gno @@ -1,8 +1,7 @@ package main -// both not const, and both interface func main() { - println([]byte("a") == nil) + println([]byte("a") == nil) // lx: (const (slice[0x61] []uint8)), rx: (const (undefined)), cmp = 0 } // Output: diff --git a/gnovm/tests/files/types/0f43_hasNil_filetest.gno b/gnovm/tests/files/types/0f43_hasNil_filetest.gno new file mode 100644 index 00000000000..c336aa92ef6 --- /dev/null +++ b/gnovm/tests/files/types/0f43_hasNil_filetest.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + var myPointer *int + if myPointer == nil { // rcx.T == nil, <-, after conversion lv: (nil *int), rv: (nil *int) + fmt.Println("Pointer is nil") + } else { + fmt.Println("Pointer is not nil") + } +} + +// Output: +// Pointer is nil diff --git a/gnovm/tests/files/types/0f43a_filetest.gno b/gnovm/tests/files/types/0f43a_filetest.gno new file mode 100644 index 00000000000..c3d275afc0c --- /dev/null +++ b/gnovm/tests/files/types/0f43a_filetest.gno @@ -0,0 +1,25 @@ +package main + +import "fmt" + +type myPointer *int + +func main() { + // NOTE: this is deprecated logic. + // rhs nil is not converted to left, it's undefined + // flow. left and right are both const: + // DEBUG: ---BinaryExpr---, OP: EQL, lx: (const (nil main.myPointer)), rx: (const (undefined)), lt: main.myPointer, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false + // the have same specificity of 0 (neither is primitive) + // so the conversion dir is ->, it won't convert since dt is nil(type and value of nil are both nil), refer to convertConst logic + // so it results in runtime: "isEql, lv: (nil main.myPointer), rv: (undefined), lvu: false, rvc: true" + // so, as a special case, they are actually equal when: one is undefined, and one is defined with specific type(slice, map, pointer, func) and nil value + // or, think, we should convert from type-nil(nil) to typed(nil)->typed, value is nil + if myPointer(nil) == nil { + fmt.Println("Pointer is nil") + } else { + fmt.Println("Pointer is not nil") + } +} + +// Output: +// Pointer is nil diff --git a/gnovm/tests/files/types/0f44_filetest.gno b/gnovm/tests/files/types/0f44_filetest.gno new file mode 100644 index 00000000000..e23e6c07aba --- /dev/null +++ b/gnovm/tests/files/types/0f44_filetest.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +type f func() + +func main() { + if f(nil) == nil { // rcx.T == nil + fmt.Println("func is nil") + } else { + fmt.Println("func is not nil") + } +} + +// Output: +// func is nil diff --git a/gnovm/tests/files/types/0f45_filetest.gno b/gnovm/tests/files/types/0f45_filetest.gno new file mode 100644 index 00000000000..7707136b82e --- /dev/null +++ b/gnovm/tests/files/types/0f45_filetest.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + if func() {} == nil { + fmt.Println("func is nil") + } else { + fmt.Println("func is not nil") + } +} + +// Output: +// func is not nil diff --git a/gnovm/tests/files/types/0f46_filetest.gno b/gnovm/tests/files/types/0f46_filetest.gno new file mode 100644 index 00000000000..3a65bd18b3b --- /dev/null +++ b/gnovm/tests/files/types/0f46_filetest.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +type m map[string]int + +func main() { + // m(nil) is a conversion from nil to m, whose underlying type is map[string]int + // lv: (nil main.m), rv: (undefined) + if m(nil) == nil { + fmt.Println("m is nil") + } else { + fmt.Println("m is not nil") + } +} + +// Output: +// m is nil diff --git a/gnovm/tests/files/types/0f46a_filetest.gno b/gnovm/tests/files/types/0f46a_filetest.gno new file mode 100644 index 00000000000..9476b1f22ef --- /dev/null +++ b/gnovm/tests/files/types/0f46a_filetest.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +type s []int + +func main() { + // s(nil) is a conversion from nil to s, whose underlying type is []int + // lv: (nil main.s), rv: (undefined) + if s(nil) == nil { + fmt.Println("s is nil") + } else { + fmt.Println("s is not nil") + } +} + +// Output: +// s is nil diff --git a/gnovm/tests/files/types/0f47_nilcast_filetest.gno b/gnovm/tests/files/types/0f47_nilcast_filetest.gno new file mode 100644 index 00000000000..ba5715d6382 --- /dev/null +++ b/gnovm/tests/files/types/0f47_nilcast_filetest.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +type integer int + +func main() { // TODO: refer to 47a, this shoul be solved + // m(nil) is a conversion from nil to m, whose underlying type is map[string]int + // lv: (nil main.m), rv: (undefined) + if integer(nil) == nil { + fmt.Println("integer is nil") + } else { + fmt.Println("integer is not nil") + } +} + +// Error: +// main/files/types/0f47_nilcast_filetest.gno:10: cannot convert (const (undefined) nil) to IntKind diff --git a/gnovm/tests/files/types/0f47a_filetest.gno b/gnovm/tests/files/types/0f47a_filetest.gno new file mode 100644 index 00000000000..e307adf6f64 --- /dev/null +++ b/gnovm/tests/files/types/0f47a_filetest.gno @@ -0,0 +1,10 @@ +package main + +type integer int + +func main() { + println(integer(nil)) // TODO: this should be a conversion error: cannot convert nil to type integer +} + +// Error: +// main/files/types/0f47a_filetest.gno:6: cannot convert (const (undefined) nil) to IntKind diff --git a/gnovm/tests/files/types/0f47b_filetest.gno b/gnovm/tests/files/types/0f47b_filetest.gno new file mode 100644 index 00000000000..e8228c622e6 --- /dev/null +++ b/gnovm/tests/files/types/0f47b_filetest.gno @@ -0,0 +1,11 @@ +package main + +type integer *int + +// nil can be cast to pointer +func main() { + println(integer(nil) == nil) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f47c_filetest.gno b/gnovm/tests/files/types/0f47c_filetest.gno new file mode 100644 index 00000000000..410bbff23f8 --- /dev/null +++ b/gnovm/tests/files/types/0f47c_filetest.gno @@ -0,0 +1,20 @@ +package main + +import "fmt" + +type integer *int + +// TODO: this is go outputs, should check println and fmt.Printf +// 0x0 +// +// main.integer +func main() { + println(integer(nil)) + fmt.Println(integer(nil)) + fmt.Printf("%T \n", integer(nil)) +} + +// Output: +// (nil main.integer) +// +// *int diff --git a/gnovm/tests/files/types/0f47d_filetest.gno b/gnovm/tests/files/types/0f47d_filetest.gno new file mode 100644 index 00000000000..5ec984bed2f --- /dev/null +++ b/gnovm/tests/files/types/0f47d_filetest.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +type integer interface{} + +// note, cast untyped nil to interface{}, hence comparable, special case +// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false +func main() { + //println(integer(nil) == nil) + println(interface{}(nil) == nil) + fmt.Printf("%T \n", interface{}(nil)) +} + +// Output: +// true +// diff --git a/gnovm/tests/files/types/0f47e_filetest.gno b/gnovm/tests/files/types/0f47e_filetest.gno new file mode 100644 index 00000000000..d195aed98d9 --- /dev/null +++ b/gnovm/tests/files/types/0f47e_filetest.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +type integer interface{} + +// note, cast untyped nil to interface{}, hence comparable, special case +// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false +func main() { + //println(integer(nil) == nil) + println(integer(nil) == nil) + fmt.Printf("%T \n", integer(nil)) +} + +// Output: +// true +// diff --git a/gnovm/tests/files/types/0f48_filetest.gno b/gnovm/tests/files/types/0f48_filetest.gno new file mode 100644 index 00000000000..8576159a0db --- /dev/null +++ b/gnovm/tests/files/types/0f48_filetest.gno @@ -0,0 +1,22 @@ +package main + +func testEql(want, got interface{}) { + if want != got { + println(false) + } else { + println(true) + } +} + +// return var of error nil +func gen() error { + return nil +} + +func main() { + r := gen() + testEql(r, error(nil)) +} + +// Output: +// true diff --git a/gnovm/tests/files/zrealm1.gno b/gnovm/tests/files/zrealm1.gno index 1dea983a49d..d93bf82c62e 100644 --- a/gnovm/tests/files/zrealm1.gno +++ b/gnovm/tests/files/zrealm1.gno @@ -37,8 +37,18 @@ func main() { // "value": "somekey" // } // }, -// {}, -// {} +// { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.Node" +// } +// }, +// { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.Node" +// } +// } // ], // "ObjectInfo": { // "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4", @@ -195,7 +205,7 @@ func main() { // }, // "V": { // "@type": "/gno.RefValue", -// "Hash": "ae4e9e2d205cc0081d4ee249e1d188ebe270b220", +// "Hash": "5684cb2d35e7da2ec67cf7a389db879a44bb4d30", // "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4" // } // } From ee408c264e0af03e3fd412461608a5c4d7a6888e Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 19 Dec 2023 10:36:04 +0800 Subject: [PATCH 059/193] fixup --- gnovm/pkg/gnolang/gonative.go | 3 +-- gnovm/pkg/gnolang/op_binary.go | 3 ++- gnovm/pkg/gnolang/preprocess.go | 11 ++++++----- gnovm/pkg/gnolang/values.go | 10 +++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index e84d67fe24b..3cefc32ea18 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -366,9 +366,8 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { if rv.Kind() == reflect.Interface { if rv.IsNil() { // special case, nil interface, interface(nil) differs nil in types, but equal return TypedValue{ - T: (&InterfaceType{}), + T: &InterfaceType{}, } - //return TypedValue{} } else { rv = rv.Elem() } diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 8b67eb940c9..15d9b39db75 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -2,8 +2,9 @@ package gnolang import ( "fmt" - "github.com/cockroachdb/apd/v3" "math/big" + + "github.com/cockroachdb/apd/v3" ) // ---------------------------------------- diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 7c8d4294fe0..10ad16cd66e 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,9 +2,10 @@ package gnolang import ( "fmt" - "github.com/gnolang/gno/tm2/pkg/errors" "math/big" "reflect" + + "github.com/gnolang/gno/tm2/pkg/errors" ) type f func(t Type) bool @@ -47,7 +48,7 @@ func init() { unaryPredicates[NOT] = isBoolean // Inc Dec stmt - // NOTE: special case to be consistent with op_inc_dec, line3, no float support for now while go does. + // NOTE: special case to be consistent with op_inc_dec.go, line3, no float support for now(while go does). IncDecStmtPredicates[INC] = isNumeric IncDecStmtPredicates[DEC] = isNumeric @@ -2350,20 +2351,20 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { - //debugPP.Printf("evalConst, last: %v, x: %v \n", last, x) + // debugPP.Printf("evalConst, last: %v, x: %v \n", last, x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) tv := cv.EvalStatic(last, x) cv.Release() - //debugPP.Printf("result: %v \n", tv) + // debugPP.Printf("result: %v \n", tv) cx := &ConstExpr{ Source: x, TypedValue: tv, } cx.SetAttribute(ATTR_PREPROCESSED, true) setConstAttrs(cx) - //debugPP.Printf("cx: %+v, source: %v, tv: %v \n", cx, cx.Source, cx.TypedValue) + // debugPP.Printf("cx: %+v, source: %v, tv: %v \n", cx, cx.Source, cx.TypedValue) return cx } diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 747cfc98971..65b20dd8304 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -1506,7 +1506,7 @@ func (tv *TypedValue) Sign() int { return 1 } case UintKind: - v := tv.GetInt() + v := tv.GetUint() if v < 0 { return -1 } else if v == 0 { @@ -1515,7 +1515,7 @@ func (tv *TypedValue) Sign() int { return 1 } case Uint8Kind: - v := tv.GetInt8() + v := tv.GetUint8() if v < 0 { return -1 } else if v == 0 { @@ -1524,7 +1524,7 @@ func (tv *TypedValue) Sign() int { return 1 } case Uint16Kind: - v := tv.GetInt16() + v := tv.GetUint16() if v < 0 { return -1 } else if v == 0 { @@ -1533,7 +1533,7 @@ func (tv *TypedValue) Sign() int { return 1 } case Uint32Kind: - v := tv.GetInt32() + v := tv.GetUint32() if v < 0 { return -1 } else if v == 0 { @@ -1542,7 +1542,7 @@ func (tv *TypedValue) Sign() int { return 1 } case Uint64Kind: - v := tv.GetInt64() + v := tv.GetUint64() if v < 0 { return -1 } else if v == 0 { From 277164954e0807a5b7b6c560613e9dc26bc9323a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 20 Dec 2023 22:13:44 +0800 Subject: [PATCH 060/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 344 +++++++++++++----- gnovm/pkg/gnolang/types.go | 2 +- gnovm/pkg/gnolang/values_conversions.go | 4 + .../files/debug/10a01_native_filetest.gnoa | 19 + gnovm/tests/files/debug/10a0_filetest.gno | 13 + gnovm/tests/files/debug/10a10_filetest.gno | 10 + gnovm/tests/files/debug/10a11_filetest.gno | 13 + gnovm/tests/files/debug/10a17.gno | 10 + gnovm/tests/files/debug/10a17a.gno | 21 ++ gnovm/tests/files/debug/10a17b.gno | 16 + gnovm/tests/files/debug/10a18.gno | 10 + gnovm/tests/files/debug/10a19.gno | 10 + gnovm/tests/files/debug/10a20.gno | 10 + gnovm/tests/files/debug/10a21.gno | 10 + gnovm/tests/files/debug/10a21a.gno | 10 + gnovm/tests/files/debug/10a22.gno | 10 + gnovm/tests/files/debug/10a23.gno | 9 + gnovm/tests/files/debug/10a24.gno | 10 + gnovm/tests/files/debug/10a25.gno | 10 + gnovm/tests/files/debug/10a25a.gno | 10 + gnovm/tests/files/debug/10a25b.gno | 11 + gnovm/tests/files/debug/10a25c.gno | 11 + gnovm/tests/files/debug/10a26.gno | 11 + gnovm/tests/files/debug/10a27.gno | 14 + gnovm/tests/files/debug/debug.gnoa | 19 + gnovm/tests/files/types/27_filetest.gno | 10 + gnovm/tests/files/types/27a_filetest.gno | 10 + 27 files changed, 537 insertions(+), 100 deletions(-) create mode 100644 gnovm/tests/files/debug/10a01_native_filetest.gnoa create mode 100644 gnovm/tests/files/debug/10a0_filetest.gno create mode 100644 gnovm/tests/files/debug/10a10_filetest.gno create mode 100644 gnovm/tests/files/debug/10a11_filetest.gno create mode 100644 gnovm/tests/files/debug/10a17.gno create mode 100644 gnovm/tests/files/debug/10a17a.gno create mode 100644 gnovm/tests/files/debug/10a17b.gno create mode 100644 gnovm/tests/files/debug/10a18.gno create mode 100644 gnovm/tests/files/debug/10a19.gno create mode 100644 gnovm/tests/files/debug/10a20.gno create mode 100644 gnovm/tests/files/debug/10a21.gno create mode 100644 gnovm/tests/files/debug/10a21a.gno create mode 100644 gnovm/tests/files/debug/10a22.gno create mode 100644 gnovm/tests/files/debug/10a23.gno create mode 100644 gnovm/tests/files/debug/10a24.gno create mode 100644 gnovm/tests/files/debug/10a25.gno create mode 100644 gnovm/tests/files/debug/10a25a.gno create mode 100644 gnovm/tests/files/debug/10a25b.gno create mode 100644 gnovm/tests/files/debug/10a25c.gno create mode 100644 gnovm/tests/files/debug/10a26.gno create mode 100644 gnovm/tests/files/debug/10a27.gno create mode 100644 gnovm/tests/files/debug/debug.gnoa create mode 100644 gnovm/tests/files/types/27_filetest.gno create mode 100644 gnovm/tests/files/types/27a_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 10ad16cd66e..786f2beaee3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -214,12 +214,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { defer func() { if r := recover(); r != nil { - fmt.Println("--- preprocess stack ---") - for i := len(stack) - 1; i >= 0; i-- { - sbn := stack[i] - fmt.Printf("stack %d: %s\n", i, sbn.String()) + if debugPP { + fmt.Println("--- preprocess stack ---") + for i := len(stack) - 1; i >= 0; i-- { + sbn := stack[i] + fmt.Printf("stack %d: %s\n", i, sbn.String()) + } + fmt.Println("------------------------") } - fmt.Println("------------------------") // before re-throwing the error, append location information to message. loc := last.GetLocation() if nline := n.GetLine(); nline > 0 { @@ -237,7 +239,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if debug { debug.Printf("Preprocess %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } - debugPP.Printf("Preprocess %s, (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + //debugPP.Printf("Preprocess %s, (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) switch stage { // ---------------------------------------- @@ -511,7 +513,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, cx := range n.Cases { cx = Preprocess( store, last, cx).(Expr) - checkOrConvertType(store, last, &cx, tt, false) // #nosec G601 + checkOrConvertType(store, last, &cx, tt, false, false) // #nosec G601 n.Cases[i] = cx } } @@ -803,13 +805,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: // TODO: improve readability - debugPP.Println("---binaryExpr---, op: ", n.Op) + debugPP.Printf("---binaryExpr---:%v \n", n) + //if t, ok := n.GetAttribute(ATTR_TYPEOF_VALUE).(Type); ok { + // debugPP.Printf("t is: %v \n", t) + //} + //debugPP.Printf("len of ns: %d \n", len(ns)) + lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR // special case of shift if isShift { + // if resumeType is set checkOp(store, last, &n.Left, lt, n.Op, Binary) if baseOf(rt) != UintType { // checkOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* @@ -822,6 +830,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { Right: rn, } resn := Preprocess(store, last, n2) + //resn.SetAttribute(ATTR_TYPEOF_VALUE, "untyped shift expr") + //if isUntyped(lt) { + // debugPP.Println("fire resume---") + // return resn, TRANS_RESUME + //} else { + // return resn, TRANS_CONTINUE + //} return resn, TRANS_CONTINUE } } @@ -842,7 +857,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("cmp < 0, ->") // convert n.Left to right type. checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rcx.T, false) + checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { debugPP.Println("cmp == 0") // NOTE: nil manipulation @@ -853,19 +868,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // now we have: lv: (nil main.m), rv: (nil main.m), would be simpler to compare. if lcx.T == nil { checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rcx.T, false) + checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lcx.T, false) + checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } else { // default case, choose -> or <- on convenience checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rcx.T, false) + checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } } else { debugPP.Println("cmp > 0, <-") // convert n.Right to left type. checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lcx.T, false) + checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } // check special case: zero divisor if isQuoOrRem(n.Op) { @@ -886,7 +901,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, checkOp(store, last, &n.Left, pt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, pt, false) + checkOrConvertType(store, last, &n.Left, pt, false, false) // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. @@ -912,14 +927,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // not shift // convert n.Left to right type. checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, false, false) } } } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, false, false) } else { // left is typed const, right is not const(also typed), and not nil if isShift { // do nothing, final type is bind to left @@ -927,7 +942,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // dir makes sense here, since non-const(right) implies more dynamic(interface) checkOp(store, last, &n.Left, rt, n.Op, Binary) // the other way round should work too - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, false, false) } } } else if ric { // right is const, left is not--- @@ -943,7 +958,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, checkOp(store, last, &n.Right, pt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, pt, false) + checkOrConvertType(store, last, &n.Right, pt, false, false) // and convert result back. tx := constType(n, lnt) // reset/create n2 to preprocess left child. @@ -960,7 +975,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // convert n.Right to left type. checkOp(store, last, &n.Right, lt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lt, false) + checkOrConvertType(store, last, &n.Right, lt, false, false) } } } else if rcx.T == nil { // RHS is nil @@ -974,12 +989,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { //} // in case of rcx.T == nil(untyped nil), require lt is maybeNil checkOp(store, last, &n.Right, lt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lt, false) + checkOrConvertType(store, last, &n.Right, lt, false, false) //// TODO: shift //// convert n.Right to typed-nil type. } else if !isShift { // left not const(typed), right is typed const, both typed checkOp(store, last, &n.Right, lt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lt, false) + checkOrConvertType(store, last, &n.Right, lt, false, false) } // check special case first if isQuoOrRem(n.Op) { @@ -1039,34 +1054,34 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // left untyped, right typed debugPP.Println("left untyped, right is typed") checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, false, false) } } else if riu { // left typed, right untyped if !isShift { checkOp(store, last, &n.Right, lt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lt, false) + checkOrConvertType(store, last, &n.Right, lt, false, false) } } else { // both typed vars, refer to 0a1f_filetest if !isShift { checkOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false) + checkOrConvertType(store, last, &n.Left, rt, false, false) } } } } } + debugPP.Printf("len of ns after preprocess binary: %d \n", len(ns)) // TRANS_LEAVE ----------------------- case *CallExpr: debugPP.Printf("---CallExpr---: %v \n", n) - //if debugPP { - // rd.PrintStack() - //} + // Func type evaluation. var ft *FuncType ift := evalStaticTypeOf(store, last, n.Func) switch cft := baseOf(ift).(type) { case *FuncType: + debugPP.Println("funcType----") ft = cft case *NativeType: debugPP.Println("native type") @@ -1116,13 +1131,48 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // the ATTR_TYPEOF_VALUE is still interface. cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE - } else { - debugPP.Println("else") - ct := evalStaticType(store, last, n.Func) - debugPP.Printf("ct: %v \n", ct) - n.SetAttribute(ATTR_TYPEOF_VALUE, ct) - return n, TRANS_CONTINUE + } else if bx, ok := n.Args[0].(*BinaryExpr); ok { + debugPP.Printf("callExpr---, arg is binary expr, bx: %v \n", bx) + // only untyped. + // cases: legal: r := float64(int(1) << s) + // illegal: r := float64(1 << s) + // legal r := float64(1< a conversion checkOp(store, last, &n.Rhs[0], lt, n.Op, Assign) - checkOrConvertType(store, last, &n.Rhs[0], lt, true) + checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) } else { // all else, like BAND_ASSIGN, etc debugPP.Println("case like: a, b = x, y") // General case: a, b = x, y. for i, lx := range n.Lhs { + debugPP.Printf("lx: %v \n", lx) lt := evalStaticTypeOf(store, last, lx) - // is x or y is untyped, convert, else check type - // rt := evalStaticTypeOf(store, last, n.Rhs[i]) - // all else check - checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) - checkOrConvertType(store, last, &n.Rhs[i], lt, true) + debugPP.Printf("lt: %v \n", lt) + + // update rhs if needed, special case + if _, ok := n.Rhs[i].(*BinaryExpr); ok { + debugPP.Println("is binrary expr-----") + rt := evalStaticTypeOf(store, last, n.Rhs[i]) + // only untyped + if isUntyped(rt) { + debugPP.Println("------rt untyped, update--------") + checkOrConvertType(store, last, &n.Rhs[i], lt, false, true) + } else { + checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) + } + } else if rux, ok := n.Rhs[i].(*UnaryExpr); ok { + checkOrConvertType(store, last, &rux.X, lt, false, true) + } else { + debugPP.Println("-------------else cases-----------------") + checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) + } } } } @@ -1842,13 +1924,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *ForStmt: debugPP.Println("ForStmt---") // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, false) + checkOrConvertType(store, last, &n.Cond, BoolType, false, false) // TRANS_LEAVE ----------------------- case *IfStmt: debugPP.Println("ifStmt---") // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, false) + checkOrConvertType(store, last, &n.Cond, BoolType, false, false) // TRANS_LEAVE ----------------------- case *RangeStmt: @@ -1905,7 +1987,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // XXX how to deal? panic("not yet implemented") } else { - checkOrConvertType(store, last, &n.Results[i], rt, false) + checkOrConvertType(store, last, &n.Results[i], rt, false, false) } } } @@ -1913,7 +1995,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SendStmt: // Value consts become default *ConstExprs. - checkOrConvertType(store, last, &n.Value, nil, false) + checkOrConvertType(store, last, &n.Value, nil, false, false) // TRANS_LEAVE ----------------------- case *SelectCaseStmt: @@ -2002,7 +2084,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // convert if const to nt. for i := range n.Values { - checkOrConvertType(store, last, &n.Values[i], nt, false) + checkOrConvertType(store, last, &n.Values[i], nt, false, false) } } else if n.Const { // derive static type from values. @@ -2520,66 +2602,123 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() -func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { - //if debugPP { - // rd.PrintStack() - //} +func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, isUpdate bool) { debugPP.Printf("checkOrConvertType, x: %v:, t:%v \n", x, t) - if nt, ok := t.(*NativeType); ok { // not native type, refer to time4_native.gno - debugPP.Printf("gnoType: %v, typeId: %v \n", nt.gnoType, nt.typeid) - } + if !isUpdate { + debugPP.Println("not update---") + if nt, ok := t.(*NativeType); ok { // not native type, refer to time4_native.gno + debugPP.Printf("gnoType: %v, typeId: %v \n", nt.gnoType, nt.typeid) + } + if cx, ok := (*x).(*ConstExpr); ok { + // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint + if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno + checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args + } + convertConst(store, last, cx, t) + } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + // TODO: check this + debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) + xt := evalStaticTypeOf(store, last, *x) + if t == nil { + t = defaultTypeOf(xt) + debugPP.Println("default type of t: %v \n", t) + } + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) + } else if *x != nil { // XXX if x != nil && t != nil { + xt := evalStaticTypeOf(store, last, *x) + debugPP.Printf("else, xt not nil, xt: %v \n", xt) + var conversionNeeded bool + if t != nil { + conversionNeeded = checkConvertible(xt, t, autoNative) + } + if isUntyped(xt) { + debugPP.Println("xt untyped") + if t == nil { + t = defaultTypeOf(xt) + debugPP.Println("default type of t: %v \n", t) + } + // Push type into expr if qualifying binary expr. + if bx, ok := (*x).(*BinaryExpr); ok { + switch bx.Op { + case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, + BAND_NOT, LAND, LOR: + // push t into bx.Left and bx.Right, recursively + checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) + checkOrConvertType(store, last, &bx.Right, t, autoNative, isUpdate) + return + case SHL, SHR: + debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) + if t.Kind() == Float32Kind { + panic("float not compatible with shift") + } + // push t into bx.Left + checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) + return + // case EQL, LSS, GTR, NEQ, LEQ, GEQ: + // default: + } + } + // general case + cx := Expr(Call(constType(nil, t), *x)) + cx = Preprocess(store, last, cx).(Expr) + *x = cx + } - if cx, ok := (*x).(*ConstExpr); ok { - // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint - if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno - checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args + debugPP.Println("need conversion: ", conversionNeeded) + // cover all declared type case + if conversionNeeded { + cx := Expr(Call(constType(nil, t), *x)) + cx = Preprocess(store, last, cx).(Expr) + *x = cx + } + } + } else { + debugPP.Printf("is update---, x: %v, t: %v \n", *x, t) + if cx, ok := (*x).(*ConstExpr); ok { // initiates from inner + convertConst(store, last, cx, t) } - convertConst(store, last, cx, t) - } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // TODO: check this - debugPP.Println("SHL or SHR") - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative) - } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("else, xt not nil, xt: %v \n", xt) - var conversionNeeded bool - if t != nil { - conversionNeeded = checkConvertible(xt, t, autoNative) - } - debugPP.Println("need conversion: ", conversionNeeded) - if isUntyped(xt) { - debugPP.Println("xt untyped") - if t == nil { + // limit to shl and shr + if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + // TODO: check this + // whitelist operand for shift caster + debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) + debugPP.Printf("xt: %v \n", xt) + if t == nil { // or we should return t = defaultTypeOf(xt) + debugPP.Println("default type of t: %v \n", t) + } + + if t.Kind() == Float32Kind { + panic("float not compatible with shift") } - // Push type into expr if qualifying binary expr. + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) + } else { // other binary expr other than shl and shr + debugPP.Printf("other binary exprs, x: %v \n", *x) + debugPP.Printf("xt: %v \n", xt) if bx, ok := (*x).(*BinaryExpr); ok { + debugPP.Println("op: ", bx.Op) switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: - // push t into bx.Left and bx.Right - checkOrConvertType(store, last, &bx.Left, t, autoNative) - checkOrConvertType(store, last, &bx.Right, t, autoNative) + // push t into bx.Left and bx.Right, recursively + checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) + checkOrConvertType(store, last, &bx.Right, t, autoNative, isUpdate) return case SHL, SHR: + debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) + if t.Kind() == Float32Kind { + panic("float not compatible with shift") + } // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) return // case EQL, LSS, GTR, NEQ, LEQ, GEQ: // default: } } - // general case - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx - } - // cover all declared type case - if conversionNeeded { - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx } } } @@ -2594,9 +2733,7 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { debugPP.Printf("------convertConst, cx:%v, t:%v \n", cx, t) if t != nil && t.Kind() == InterfaceKind { - debugPP.Println("convert const, t is interface kind") if cx.IsUndefined() { - debugPP.Println("convert const, cx is undefined") if _, ok := t.(*NativeType); !ok { // bypass native nil interface debugPP.Println("special case for undefined to interface{}") debugPP.Printf("before convert, cx: %v, cx.T: %v \n", cx, cx.T) @@ -2686,6 +2823,14 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType if isComparison(op) { switch op { case EQL, NEQ: // check maybeIdenticalType + // check typed primitives + //if !isUntyped(xt) && !isUntyped(dt) { + // if xt != nil && dt != nil { + // if xt.TypeID() != dt.TypeID() { + // panic(fmt.Sprintf("incompatible type of, xt: %v, dt: %v \n", xt, dt)) + // } + // } + //} // NOTE: not checking types strict identical here, unlike ADD, etc // this will pass the case one is interface and the other implements this interface // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertible -> assignable @@ -2758,6 +2903,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType // a target native dt type, if and only if dt is a native type. // TODO: name. convertible is for value, not type, should be check assignable? func checkConvertible(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { + debugPP.Printf("checkConvertible, xt: %v, dt: %v \n", xt, dt) if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno debugPP.Println("checkConvertible, xt or dt is nil") return diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 363caf49bfd..1e76bf64408 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2346,7 +2346,7 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { // primitive is maybeIdenticalType switch cdt := baseOf(dt).(type) { case PrimitiveType: - debugPP.Println("primitive type, return true") + debugPP.Println("primitive type, return true, fallthrough") return true, "" case *ArrayType: // NOTE: no recursive allowed // TODO: check at least length here diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 0b94866015d..3ef991a752e 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -52,6 +52,7 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { // convert go-native to gno type (shallow). *tv = go2GnoValue2(alloc, store, tv.V.(*NativeValue).Value, false) ConvertTo(alloc, store, tv, t) + debugPP.Printf("tv after conversion: %v \n", tv) return } } else { @@ -876,6 +877,9 @@ GNO_CASE: "cannot convert %s to %s", tv.T.String(), k.String())) } + case BigintKind: + debugPP.Println("---bigIntKind---") + ConvertUntypedBigintTo(tv, tv.V.(BigintValue), t) default: panic(fmt.Sprintf( "cannot convert %s to %s", diff --git a/gnovm/tests/files/debug/10a01_native_filetest.gnoa b/gnovm/tests/files/debug/10a01_native_filetest.gnoa new file mode 100644 index 00000000000..42faa57634d --- /dev/null +++ b/gnovm/tests/files/debug/10a01_native_filetest.gnoa @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "time" + + "github.com/gnolang/gno/_test/net/http" +) + +func main() { + http.DefaultClient.Timeout = time.Second * 10 + fmt.Println(http.DefaultClient) + http.DefaultClient = &http.Client{} + fmt.Println(http.DefaultClient) +} + +// Output: +// &{ 10s} +// &{ 0s} diff --git a/gnovm/tests/files/debug/10a0_filetest.gno b/gnovm/tests/files/debug/10a0_filetest.gno new file mode 100644 index 00000000000..2ac7ba6d674 --- /dev/null +++ b/gnovm/tests/files/debug/10a0_filetest.gno @@ -0,0 +1,13 @@ +package main + +func gen() []int { + return nil +} + +func main() { + r := gen() == nil + println(r) +} + +// Output: +// true diff --git a/gnovm/tests/files/debug/10a10_filetest.gno b/gnovm/tests/files/debug/10a10_filetest.gno new file mode 100644 index 00000000000..0eba81f4a9c --- /dev/null +++ b/gnovm/tests/files/debug/10a10_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << 1.0 // NOTE: go vet would fail, but still process + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/debug/10a11_filetest.gno b/gnovm/tests/files/debug/10a11_filetest.gno new file mode 100644 index 00000000000..bcb62dc76c3 --- /dev/null +++ b/gnovm/tests/files/debug/10a11_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "bytes" + +// both not const, and both interface +func main() { + // lv.T: * uint8, rv.T: * uint8 + cmp := bytes.Compare([]byte("a"), []byte("b")) + println(cmp) +} + +// Output: +// -1 diff --git a/gnovm/tests/files/debug/10a17.gno b/gnovm/tests/files/debug/10a17.gno new file mode 100644 index 00000000000..5c504d7d616 --- /dev/null +++ b/gnovm/tests/files/debug/10a17.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/debug/10a17a.gno b/gnovm/tests/files/debug/10a17a.gno new file mode 100644 index 00000000000..254c36e613f --- /dev/null +++ b/gnovm/tests/files/debug/10a17a.gno @@ -0,0 +1,21 @@ +package main + +import "fmt" + +func foo(a uint64, b int64) { + fmt.Printf("%T \n", a) + fmt.Printf("%T \n", b) + println(a) + println(b) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Output: +// uint64 +// int64 +// 2048 +// 0 diff --git a/gnovm/tests/files/debug/10a17b.gno b/gnovm/tests/files/debug/10a17b.gno new file mode 100644 index 00000000000..88d8af99b68 --- /dev/null +++ b/gnovm/tests/files/debug/10a17b.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// operators >> and >>= not defined for float32 diff --git a/gnovm/tests/files/debug/10a18.gno b/gnovm/tests/files/debug/10a18.gno new file mode 100644 index 00000000000..a29108aef5a --- /dev/null +++ b/gnovm/tests/files/debug/10a18.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1 << x) + println(y) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/debug/10a19.gno b/gnovm/tests/files/debug/10a19.gno new file mode 100644 index 00000000000..3b7fb0aec50 --- /dev/null +++ b/gnovm/tests/files/debug/10a19.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1<> 8) + println(b) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/debug/10a23.gno b/gnovm/tests/files/debug/10a23.gno new file mode 100644 index 00000000000..44aa5a95561 --- /dev/null +++ b/gnovm/tests/files/debug/10a23.gno @@ -0,0 +1,9 @@ +package main + +func main() { + b := uint64(1 + 1) + println(b) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/debug/10a24.gno b/gnovm/tests/files/debug/10a24.gno new file mode 100644 index 00000000000..d118c422845 --- /dev/null +++ b/gnovm/tests/files/debug/10a24.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := 1 << x + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/debug/10a25.gno b/gnovm/tests/files/debug/10a25.gno new file mode 100644 index 00000000000..c29c8e2813f --- /dev/null +++ b/gnovm/tests/files/debug/10a25.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := -(1 << x) + println(y) +} + +// Output: +// -2048 diff --git a/gnovm/tests/files/debug/10a25a.gno b/gnovm/tests/files/debug/10a25a.gno new file mode 100644 index 00000000000..da008b9b5a1 --- /dev/null +++ b/gnovm/tests/files/debug/10a25a.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := -(1 + 1< bigint)) + (const (1 bigint)) << (const-type uint)(x) is not a type diff --git a/gnovm/tests/files/debug/debug.gnoa b/gnovm/tests/files/debug/debug.gnoa new file mode 100644 index 00000000000..380a6711abc --- /dev/null +++ b/gnovm/tests/files/debug/debug.gnoa @@ -0,0 +1,19 @@ +package main + +import ( + "errors" +) + +//func gen() error { +// return errors.New("xxx") +//} + +func main() { + r := errors.New("xxx") + if r != nil { + println("error: ", r.Error()) + } +} + +// Output: +// error: xxx diff --git a/gnovm/tests/files/types/27_filetest.gno b/gnovm/tests/files/types/27_filetest.gno new file mode 100644 index 00000000000..5c504d7d616 --- /dev/null +++ b/gnovm/tests/files/types/27_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/27a_filetest.gno b/gnovm/tests/files/types/27a_filetest.gno new file mode 100644 index 00000000000..8490c751c88 --- /dev/null +++ b/gnovm/tests/files/types/27a_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1.0 << x) + println(y) +} + +// Output: +// 2048 From 005b370b214a6c8459b365af8b1cd0a9cd3c1625 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 22 Dec 2023 11:31:27 +0800 Subject: [PATCH 061/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 508 +++++++++++------- gnovm/pkg/gnolang/types.go | 18 +- gnovm/tests/files/debug/0.gno | 23 + gnovm/tests/files/debug/0_a.gno | 22 + gnovm/tests/files/debug/0_a_1.gno | 22 + gnovm/tests/files/debug/0_b.gno | 21 + gnovm/tests/files/debug/0_c.gno | 22 + gnovm/tests/files/debug/0_d.gno | 22 + gnovm/tests/files/debug/0_e.gno | 22 + gnovm/tests/files/debug/0_f.gno | 22 + gnovm/tests/files/debug/1.gno | 21 + gnovm/tests/files/debug/10a000_filetest.gno | 9 + gnovm/tests/files/debug/10a00_filetest.gno | 9 + gnovm/tests/files/debug/10a01_filetest.gno | 18 + gnovm/tests/files/debug/10a02_filetest.gno | 15 + gnovm/tests/files/debug/10a03_filetest.gno | 18 + gnovm/tests/files/debug/10a10_filetest.gno | 2 +- ...10a11_filetest.gno => 10a11_filetest.gnoa} | 0 gnovm/tests/files/debug/10a17b.gno | 3 +- gnovm/tests/files/debug/10a17b1.gno | 17 + gnovm/tests/files/debug/10a21.gno | 2 +- gnovm/tests/files/debug/10a21a.gno | 2 +- gnovm/tests/files/debug/10a25c.gno | 2 +- gnovm/tests/files/debug/10a26.gno | 2 +- gnovm/tests/files/debug/10a27.gno | 9 +- gnovm/tests/files/debug/10a27a.gno | 14 + gnovm/tests/files/debug/10a27b.gno | 14 + gnovm/tests/files/debug/10a27c.gno | 13 + gnovm/tests/files/debug/1_a.gno | 20 + gnovm/tests/files/debug/3.gno | 14 + gnovm/tests/files/debug/3_a.gno | 14 + gnovm/tests/files/debug/3_b.gno | 14 + gnovm/tests/files/debug/4.gno | 22 + gnovm/tests/files/debug/4_a.gno | 22 + gnovm/tests/files/debug/4_b.gno | 22 + gnovm/tests/files/debug/4_c.gno | 22 + gnovm/tests/files/debug/5.gno | 20 + gnovm/tests/files/debug/a46.gno | 26 + gnovm/tests/files/debug/addr0b_stdlibs.gno | 23 + gnovm/tests/files/debug/comp3.gno | 14 + .../files/debug3/10a01_native_filetest.gnoa | 19 + gnovm/tests/files/debug3/10a0_filetest.gno | 13 + gnovm/tests/files/debug3/10a10_filetest.gno | 10 + gnovm/tests/files/debug3/10a11_filetest.gno | 13 + gnovm/tests/files/debug3/10a17.gno | 10 + gnovm/tests/files/debug3/10a17a.gno | 21 + gnovm/tests/files/debug3/10a17b.gno | 17 + gnovm/tests/files/debug3/10a18.gno | 10 + gnovm/tests/files/debug3/10a19.gno | 10 + gnovm/tests/files/debug3/10a20.gno | 10 + gnovm/tests/files/debug3/10a21.gno | 10 + gnovm/tests/files/debug3/10a21a.gno | 10 + gnovm/tests/files/debug3/10a22.gno | 10 + gnovm/tests/files/debug3/10a23.gno | 9 + gnovm/tests/files/debug3/10a24.gno | 10 + gnovm/tests/files/debug3/10a25.gno | 10 + gnovm/tests/files/debug3/10a25a.gno | 10 + gnovm/tests/files/debug3/10a25b.gno | 11 + gnovm/tests/files/debug3/10a25c.gno | 11 + gnovm/tests/files/debug3/10a26.gno | 12 + gnovm/tests/files/debug3/10a27.gno | 15 + .../tests/files/{debug => debug3}/debug.gnoa | 0 gnovm/tests/files/types/10a14_filetest.gno | 2 +- gnovm/tests/files/types/10a16_filetest.gno | 2 +- gnovm/tests/files/types/10a5_filetest.gno | 2 +- gnovm/tests/files/types/27a_filetest.gno | 4 +- 66 files changed, 1159 insertions(+), 207 deletions(-) create mode 100644 gnovm/tests/files/debug/0.gno create mode 100644 gnovm/tests/files/debug/0_a.gno create mode 100644 gnovm/tests/files/debug/0_a_1.gno create mode 100644 gnovm/tests/files/debug/0_b.gno create mode 100644 gnovm/tests/files/debug/0_c.gno create mode 100644 gnovm/tests/files/debug/0_d.gno create mode 100644 gnovm/tests/files/debug/0_e.gno create mode 100644 gnovm/tests/files/debug/0_f.gno create mode 100644 gnovm/tests/files/debug/1.gno create mode 100644 gnovm/tests/files/debug/10a000_filetest.gno create mode 100644 gnovm/tests/files/debug/10a00_filetest.gno create mode 100644 gnovm/tests/files/debug/10a01_filetest.gno create mode 100644 gnovm/tests/files/debug/10a02_filetest.gno create mode 100644 gnovm/tests/files/debug/10a03_filetest.gno rename gnovm/tests/files/debug/{10a11_filetest.gno => 10a11_filetest.gnoa} (100%) create mode 100644 gnovm/tests/files/debug/10a17b1.gno create mode 100644 gnovm/tests/files/debug/10a27a.gno create mode 100644 gnovm/tests/files/debug/10a27b.gno create mode 100644 gnovm/tests/files/debug/10a27c.gno create mode 100644 gnovm/tests/files/debug/1_a.gno create mode 100644 gnovm/tests/files/debug/3.gno create mode 100644 gnovm/tests/files/debug/3_a.gno create mode 100644 gnovm/tests/files/debug/3_b.gno create mode 100644 gnovm/tests/files/debug/4.gno create mode 100644 gnovm/tests/files/debug/4_a.gno create mode 100644 gnovm/tests/files/debug/4_b.gno create mode 100644 gnovm/tests/files/debug/4_c.gno create mode 100644 gnovm/tests/files/debug/5.gno create mode 100644 gnovm/tests/files/debug/a46.gno create mode 100644 gnovm/tests/files/debug/addr0b_stdlibs.gno create mode 100644 gnovm/tests/files/debug/comp3.gno create mode 100644 gnovm/tests/files/debug3/10a01_native_filetest.gnoa create mode 100644 gnovm/tests/files/debug3/10a0_filetest.gno create mode 100644 gnovm/tests/files/debug3/10a10_filetest.gno create mode 100644 gnovm/tests/files/debug3/10a11_filetest.gno create mode 100644 gnovm/tests/files/debug3/10a17.gno create mode 100644 gnovm/tests/files/debug3/10a17a.gno create mode 100644 gnovm/tests/files/debug3/10a17b.gno create mode 100644 gnovm/tests/files/debug3/10a18.gno create mode 100644 gnovm/tests/files/debug3/10a19.gno create mode 100644 gnovm/tests/files/debug3/10a20.gno create mode 100644 gnovm/tests/files/debug3/10a21.gno create mode 100644 gnovm/tests/files/debug3/10a21a.gno create mode 100644 gnovm/tests/files/debug3/10a22.gno create mode 100644 gnovm/tests/files/debug3/10a23.gno create mode 100644 gnovm/tests/files/debug3/10a24.gno create mode 100644 gnovm/tests/files/debug3/10a25.gno create mode 100644 gnovm/tests/files/debug3/10a25a.gno create mode 100644 gnovm/tests/files/debug3/10a25b.gno create mode 100644 gnovm/tests/files/debug3/10a25c.gno create mode 100644 gnovm/tests/files/debug3/10a26.gno create mode 100644 gnovm/tests/files/debug3/10a27.gno rename gnovm/tests/files/{debug => debug3}/debug.gnoa (100%) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 786f2beaee3..09d13f779e5 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -23,8 +23,11 @@ func init() { binaryPredicates[MUL] = isNumeric binaryPredicates[QUO] = isNumeric binaryPredicates[REM] = isIntNum - binaryPredicates[SHL] = isNumeric - binaryPredicates[SHR] = isNumeric + //binaryPredicates[SHL] = isIntOrFloat // NOTE: 1.0 << 1 is legal + //binaryPredicates[SHR] = isIntOrFloat + + binaryPredicates[SHL] = isIntNum // NOTE: consistent with op_binary for now + binaryPredicates[SHR] = isIntNum // bit op binaryPredicates[BAND] = isIntNum @@ -686,7 +689,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { switch n := n.(type) { // TRANS_LEAVE ----------------------- case *NameExpr: // e.g. var a int, a is NameExpr - debugPP.Println("NameExpr---") + debugPP.Printf("---NameExpr---: %v \n", n) // Validity: check that name isn't reserved. if isReservedName(n.Name) { panic(fmt.Sprintf( @@ -806,19 +809,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *BinaryExpr: // TODO: improve readability debugPP.Printf("---binaryExpr---:%v \n", n) - //if t, ok := n.GetAttribute(ATTR_TYPEOF_VALUE).(Type); ok { - // debugPP.Printf("t is: %v \n", t) - //} - //debugPP.Printf("len of ns: %d \n", len(ns)) - lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR // special case of shift if isShift { - // if resumeType is set - checkOp(store, last, &n.Left, lt, n.Op, Binary) if baseOf(rt) != UintType { // checkOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* // convert n.Right to (gno) uint type, @@ -830,13 +826,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { Right: rn, } resn := Preprocess(store, last, n2) - //resn.SetAttribute(ATTR_TYPEOF_VALUE, "untyped shift expr") - //if isUntyped(lt) { - // debugPP.Println("fire resume---") - // return resn, TRANS_RESUME - //} else { - // return resn, TRANS_CONTINUE - //} return resn, TRANS_CONTINUE } } @@ -886,9 +875,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isQuoOrRem(n.Op) { checkOperand(rcx) } + } else { // is shift, and assume RHS is uint + // here we don't need to check rt, it must be right + // we should check lt instead + // NOTE: + // it's complicated. + // type of shift can be determined by some cases: + // 1. lhs of shift expr is already typed with type name, e.g. int(1) << 1. + // 2. type gained from further expr, e.g. 1.0< not const debugPP.Printf("left: %v is untyped const, right: %v is not const \n", lt, rt) @@ -920,6 +920,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { debugPP.Println("right not native") if isShift { + checkOp(store, last, &n.Left, lt, n.Op, Binary) + debugPP.Println("shift checkOp pass, postpone processing when assign or type cast") // nothing to do, right type is (already) uint type. // we don't yet know what this type should be, // but another checkOrConvertType() later does. @@ -937,12 +939,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false, false) } else { // left is typed const, right is not const(also typed), and not nil if isShift { + checkOp(store, last, &n.Left, lt, n.Op, Binary) // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check - } else { // dir makes sense here, since non-const(right) implies more dynamic(interface) - checkOp(store, last, &n.Left, rt, n.Op, Binary) - // the other way round should work too - checkOrConvertType(store, last, &n.Left, rt, false, false) + } else { // ? dir makes sense here, since non-const(right) implies more dynamic(interface) + // TODO: check if right untyped + if isUntyped(rt) { + checkOp(store, last, &n.Right, lt, n.Op, Binary) + // the other way round should work too + checkOrConvertType(store, last, &n.Right, lt, false, false) + } else { + checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false, false) + } } } } else if ric { // right is const, left is not--- @@ -950,6 +959,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Left not, Right untyped const ---------------- if isShift { // do nothing + checkOp(store, last, &n.Left, lt, n.Op, Binary) } else { if lnt, ok := lt.(*NativeType); ok { // get concrete native base type. @@ -993,8 +1003,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { //// TODO: shift //// convert n.Right to typed-nil type. } else if !isShift { // left not const(typed), right is typed const, both typed - checkOp(store, last, &n.Right, lt, n.Op, Binary) - checkOrConvertType(store, last, &n.Right, lt, false, false) + // TODO: if left untyped? + if isUntyped(lt) { + checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false, false) + } else { + checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOrConvertType(store, last, &n.Right, lt, false, false) + } + } else if isShift { + // check if LHS is valid + checkOp(store, last, &n.Left, lt, n.Op, Binary) } // check special case first if isQuoOrRem(n.Op) { @@ -1068,10 +1087,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } + } else { + checkOp(store, last, &n.Left, lt, n.Op, Binary) } } - debugPP.Printf("len of ns after preprocess binary: %d \n", len(ns)) - // TRANS_LEAVE ----------------------- case *CallExpr: debugPP.Printf("---CallExpr---: %v \n", n) @@ -1079,15 +1098,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Func type evaluation. var ft *FuncType ift := evalStaticTypeOf(store, last, n.Func) + debugPP.Printf("---func type: %v \n", ift) switch cft := baseOf(ift).(type) { case *FuncType: - debugPP.Println("funcType----") ft = cft case *NativeType: - debugPP.Println("native type") ft = store.Go2GnoType(cft.Type).(*FuncType) case *TypeType: - debugPP.Println("type type") if len(n.Args) != 1 { panic("type conversion requires single argument") } @@ -1096,8 +1113,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if arg0, ok := n.Args[0].(*ConstExpr); ok { debugPP.Println("const expr") ct := evalStaticType(store, last, n.Func) - if arg0.IsUndefined() { // nil is const - switch ct.Kind() { + if arg0.IsUndefined() { + switch ct.Kind() { // special case for nil conversion check, TODO: refer to case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind: dt = ct default: @@ -1122,6 +1139,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } + // TODO: consider this, need check? // (const) untyped decimal -> float64. // (const) untyped bigint -> int. convertConst(store, last, arg0, dt) @@ -1131,43 +1149,58 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // the ATTR_TYPEOF_VALUE is still interface. cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE - } else if bx, ok := n.Args[0].(*BinaryExpr); ok { - debugPP.Printf("callExpr---, arg is binary expr, bx: %v \n", bx) - // only untyped. - // cases: legal: r := float64(int(1) << s) - // illegal: r := float64(1 << s) - // legal r := float64(1< len(n.Rhs) { // TODO dry code w/ above. @@ -1860,29 +1898,36 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("case like: a, b = x, y") // General case: a, b = x, y. for i, lx := range n.Lhs { - debugPP.Printf("lx: %v \n", lx) lt := evalStaticTypeOf(store, last, lx) + + debugPP.Printf("lx: %v \n", lx) debugPP.Printf("lt: %v \n", lt) + //rt := evalStaticTypeOf(store, last, n.Rhs[i]) // update rhs if needed, special case - if _, ok := n.Rhs[i].(*BinaryExpr); ok { - debugPP.Println("is binrary expr-----") - rt := evalStaticTypeOf(store, last, n.Rhs[i]) - // only untyped - if isUntyped(rt) { - debugPP.Println("------rt untyped, update--------") - checkOrConvertType(store, last, &n.Rhs[i], lt, false, true) - } else { - checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) - checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) - } - } else if rux, ok := n.Rhs[i].(*UnaryExpr); ok { - checkOrConvertType(store, last, &rux.X, lt, false, true) - } else { - debugPP.Println("-------------else cases-----------------") - checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) - checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) - } + //if _, ok := n.Rhs[i].(*BinaryExpr); ok { + // debugPP.Println("is binary expr-----") + // // only untyped + // if isUntyped(rt) { // not coerce, so should be untyped, and not skip + // debugPP.Println("------rt untyped, regular convert routine") + // checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + // checkOrConvertType(store, last, &n.Rhs[i], lt, false, false) // + // } else if rux, ok := n.Rhs[i].(*UnaryExpr); ok { + // if isUntyped(rt) { + // debugPP.Println("------rt untyped, regular convert routine") + // checkOp(store, last, &rux.X, lt, n.Op, Assign) + // checkOrConvertType(store, last, &rux.X, lt, false, false) + // } + // } else { + // debugPP.Println("-------------else cases-----------------") + // checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + // checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) + // } + //} + //if isUntyped(rt) { + checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) + //} } } } @@ -2433,7 +2478,7 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { - // debugPP.Printf("evalConst, last: %v, x: %v \n", last, x) + debugPP.Printf("evalConst, last: %v, x: %v \n", last, x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) @@ -2602,127 +2647,208 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() -func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, isUpdate bool) { - debugPP.Printf("checkOrConvertType, x: %v:, t:%v \n", x, t) - if !isUpdate { - debugPP.Println("not update---") - if nt, ok := t.(*NativeType); ok { // not native type, refer to time4_native.gno - debugPP.Printf("gnoType: %v, typeId: %v \n", nt.gnoType, nt.typeid) - } - if cx, ok := (*x).(*ConstExpr); ok { - // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint + +// TODO: use opts instead +func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { + debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) + if cx, ok := (*x).(*ConstExpr); ok { + // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint + // TODO: other bypass situations like cast + if !coerce { if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } - convertConst(store, last, cx, t) - } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // TODO: check this - debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) - xt := evalStaticTypeOf(store, last, *x) - if t == nil { - t = defaultTypeOf(xt) - debugPP.Println("default type of t: %v \n", t) - } - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) - } else if *x != nil { // XXX if x != nil && t != nil { - xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("else, xt not nil, xt: %v \n", xt) - var conversionNeeded bool - if t != nil { - conversionNeeded = checkConvertible(xt, t, autoNative) - } + } + convertConst(store, last, cx, t) + } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) + xt := evalStaticTypeOf(store, last, *x) + debugPP.Printf("xt: %v \n", xt) + if t == nil { if isUntyped(xt) { - debugPP.Println("xt untyped") - if t == nil { - t = defaultTypeOf(xt) - debugPP.Println("default type of t: %v \n", t) - } - // Push type into expr if qualifying binary expr. - if bx, ok := (*x).(*BinaryExpr); ok { - switch bx.Op { - case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, - BAND_NOT, LAND, LOR: - // push t into bx.Left and bx.Right, recursively - checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) - checkOrConvertType(store, last, &bx.Right, t, autoNative, isUpdate) - return - case SHL, SHR: - debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) - if t.Kind() == Float32Kind { - panic("float not compatible with shift") - } - // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) - return - // case EQL, LSS, GTR, NEQ, LEQ, GEQ: - // default: - } - } - // general case - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx + t = defaultTypeOf(xt) + } else { + t = xt } + } - debugPP.Println("need conversion: ", conversionNeeded) - // cover all declared type case - if conversionNeeded { - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx + if coerce { + checkOp(store, last, &bx.Left, t, bx.Op, Binary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + } else if !coerce && isUntyped(xt) { + if _, ok := t.(*InterfaceType); !ok { // concrete type + checkOp(store, last, &bx.Left, t, bx.Op, Binary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + } else { + checkConvertible(xt, t, false) } + } else { + checkConvertible(xt, t, false) } - } else { - debugPP.Printf("is update---, x: %v, t: %v \n", *x, t) - if cx, ok := (*x).(*ConstExpr); ok { // initiates from inner - convertConst(store, last, cx, t) - } + + } else if ux, ok := (*x).(*UnaryExpr); ok { + debugPP.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) xt := evalStaticTypeOf(store, last, *x) - // limit to shl and shr - if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // TODO: check this - // whitelist operand for shift caster - debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) - debugPP.Printf("xt: %v \n", xt) - if t == nil { // or we should return + if t == nil { + if isUntyped(xt) { t = defaultTypeOf(xt) - debugPP.Println("default type of t: %v \n", t) + } else { + t = xt } + } + // "push" expected type into shift unary's operand + checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) + } else if *x != nil { // XXX if x != nil && t != nil { + xt := evalStaticTypeOf(store, last, *x) + debugPP.Printf("else expr, xt not nil,x: %v, xt: %v \n", *x, xt) - if t.Kind() == Float32Kind { - panic("float not compatible with shift") + // check convertible prior + var isUnamed bool + if t != nil && !coerce { + isUnamed = checkConvertible(xt, t, autoNative) + } + if isUntyped(xt) { + debugPP.Println("xt untyped") + if t == nil { + t = defaultTypeOf(xt) + debugPP.Printf("default type of t: %v \n", t) } - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) - } else { // other binary expr other than shl and shr - debugPP.Printf("other binary exprs, x: %v \n", *x) - debugPP.Printf("xt: %v \n", xt) + // Push type into expr if qualifying binary expr. if bx, ok := (*x).(*BinaryExpr); ok { - debugPP.Println("op: ", bx.Op) switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: + debugPP.Println("binary, going recursive call") // push t into bx.Left and bx.Right, recursively - checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) - checkOrConvertType(store, last, &bx.Right, t, autoNative, isUpdate) + checkOp(store, last, &bx.Left, t, bx.Op, Binary) + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + checkOp(store, last, &bx.Right, t, bx.Op, Binary) + checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return case SHL, SHR: debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) - if t.Kind() == Float32Kind { - panic("float not compatible with shift") - } // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, autoNative, isUpdate) + if coerce { + checkOp(store, last, &bx.Left, t, bx.Op, Binary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + } else if !coerce && isUntyped(xt) { + if _, ok := t.(*InterfaceType); !ok { // concrete type + checkOp(store, last, &bx.Left, t, bx.Op, Binary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + } else { + checkConvertible(xt, t, false) + } + } else { + checkConvertible(xt, t, false) + } return - // case EQL, LSS, GTR, NEQ, LEQ, GEQ: + case EQL, LSS, GTR, NEQ, LEQ, GEQ: + debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) + //checkOp(store, last, &bx.Left, t, bx.Op, Binary) + ////checkOrConvertType(store, last, x, t, autoNative, coerce) + //(*x).SetAttribute(ATTR_TYPEOF_VALUE, t) + //return // default: } } + // general case + cx := Expr(Call(constType(nil, t), *x)) + cx.SetAttribute(ATTR_TYPEOF_VALUE, t) + cx = Preprocess(store, last, cx).(Expr) + *x = cx + } + + debugPP.Println("is Unamed: ", isUnamed) + // cover all declared type case + if isUnamed { + cx := Expr(Call(constType(nil, t), *x)) + cx = Preprocess(store, last, cx).(Expr) + *x = cx } } } +// focus on update type to specific scenarios +// call, assign type to postponed untyped expr, e.g. shift, unary +// first, checkOrConvert to do the immediate convert +// use updateType to handle postponed case +// only for typetype(callExpr), assign, so println(1< native. it's reasonable for gno is a superset of go type, e.g. bigint +// // TODO: other bypass situations like cast +// if !skip { +// if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno +// checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args +// } +// } +// convertConst(store, last, cx, t) +// } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { +// debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) +// xt := evalStaticTypeOf(store, last, *x) +// if t == nil { +// t = defaultTypeOf(xt) +// } +// checkOp(store, last, &bx.Left, t, bx.Op, Binary) +// updateType(store, last, &bx.Left, t, autoNative, false) +// } else if *x != nil { // XXX if x != nil && t != nil { +// xt := evalStaticTypeOf(store, last, *x) +// debugPP.Printf("else expr, xt not nil, x: %v, xt: %v \n", *x, xt) +// +// // check convertible prior +// // TODO: check this logic +// //var isUnamed bool +// if t != nil && !skip { +// checkConvertible(xt, t, autoNative) +// } +// if isUntyped(xt) { +// debugPP.Println("xt untyped") +// if t == nil { +// t = defaultTypeOf(xt) +// debugPP.Println("default type of t: %v \n", t) +// } +// // Push type into expr if qualifying binary expr. +// if bx, ok := (*x).(*BinaryExpr); ok { +// switch bx.Op { +// case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, +// BAND_NOT, LAND, LOR: +// // push t into bx.Left and bx.Right, recursively +// checkOp(store, last, &bx.Left, t, bx.Op, Binary) +// updateType(store, last, &bx.Left, t, autoNative, skip) +// checkOp(store, last, &bx.Right, t, bx.Op, Binary) +// updateType(store, last, &bx.Right, t, autoNative, skip) +// return +// case SHL, SHR: +// debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) +// checkOp(store, last, &bx.Left, t, bx.Op, Binary) +// // push t into bx.Left +// updateType(store, last, &bx.Left, t, autoNative, skip) +// return +// // case EQL, LSS, GTR, NEQ, LEQ, GEQ: +// // default: +// } +// } else if ux, ok := (*x).(*UnaryExpr); ok { +// checkOp(store, last, &ux.X, t, ux.Op, Unary) +// updateType(store, last, &ux.X, t, autoNative, skip) +// return +// } +// } +// +// //debugPP.Println("is Unamed: ", isUnamed) +// //// cover all declared type case +// //if isUnamed { +// // cx := Expr(Call(constType(nil, t), *x)) +// // cx = Preprocess(store, last, cx).(Expr) +// // *x = cx +// //} +// } +//} + // like checkOrConvertType(last, x, nil) func convertIfConst(store Store, last BlockNode, x Expr) { if cx, ok := x.(*ConstExpr); ok { @@ -2868,6 +2994,8 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType debugPP.Println("typed and identical as maybeIdenticalType") } case SHL, SHR: + // TODO: check float like 1.0 would work, 1.2 won't + // Currently, the check is relaxed(with runtime strict, to be consistent) default: // Note: others no check, assign will be check in assignable } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 1e76bf64408..90414a69712 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -272,8 +272,9 @@ const ( IsBigDec IsRune - IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned - IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec + IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned + IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec + IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec // IsConstType = IsBoolean | IsNumeric | IsString ) @@ -356,6 +357,7 @@ func isBoolean(t Type) bool { } // rune can be numeric and string +// TODO: consider, do we need complex? func isNumeric(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: @@ -368,6 +370,18 @@ func isNumeric(t Type) bool { } } +func isIntOrFloat(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsIntOrFloat != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + // signed or unsigned int func isIntNum(t Type) bool { switch t := baseOf(t).(type) { diff --git a/gnovm/tests/files/debug/0.gno b/gnovm/tests/files/debug/0.gno new file mode 100644 index 00000000000..551269541dd --- /dev/null +++ b/gnovm/tests/files/debug/0.gno @@ -0,0 +1,23 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +// case of expr in type call +func main() { + //println(1 << 2) + x := 2 + r := uint64(1 << x) // 2 step. first binary, second call type + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 4 +// uint64 diff --git a/gnovm/tests/files/debug/0_a.gno b/gnovm/tests/files/debug/0_a.gno new file mode 100644 index 00000000000..0f78a9c141f --- /dev/null +++ b/gnovm/tests/files/debug/0_a.gno @@ -0,0 +1,22 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +// case of expr in type call +func main() { + x := 2 + r := uint64(1< bigdec diff --git a/gnovm/tests/files/debug/10a02_filetest.gno b/gnovm/tests/files/debug/10a02_filetest.gno new file mode 100644 index 00000000000..173770f6a93 --- /dev/null +++ b/gnovm/tests/files/debug/10a02_filetest.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := 1.0 << x + println(y) + fmt.Printf("%T \n", y) + fmt.Printf("%T \n", 1) + fmt.Printf("%T \n", x) +} + +// Error: +// main/files/debug/10a02_filetest.gno:5: operator << not defined on: bigdec diff --git a/gnovm/tests/files/debug/10a03_filetest.gno b/gnovm/tests/files/debug/10a03_filetest.gno new file mode 100644 index 00000000000..1ebbf69e67b --- /dev/null +++ b/gnovm/tests/files/debug/10a03_filetest.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := 1 << x + println(y) + fmt.Printf("%T \n", y) + fmt.Printf("%T \n", 1) + fmt.Printf("%T \n", x) +} + +// Output: +// 2048 +// int +// int +// int diff --git a/gnovm/tests/files/debug/10a10_filetest.gno b/gnovm/tests/files/debug/10a10_filetest.gno index 0eba81f4a9c..165307a6477 100644 --- a/gnovm/tests/files/debug/10a10_filetest.gno +++ b/gnovm/tests/files/debug/10a10_filetest.gno @@ -2,7 +2,7 @@ package main func main() { a := 1 - r := a << 1.0 // NOTE: go vet would fail, but still process + r := a << 1 // NOTE: go vet would fail, but still process println(r) } diff --git a/gnovm/tests/files/debug/10a11_filetest.gno b/gnovm/tests/files/debug/10a11_filetest.gnoa similarity index 100% rename from gnovm/tests/files/debug/10a11_filetest.gno rename to gnovm/tests/files/debug/10a11_filetest.gnoa diff --git a/gnovm/tests/files/debug/10a17b.gno b/gnovm/tests/files/debug/10a17b.gno index 88d8af99b68..a92284f01da 100644 --- a/gnovm/tests/files/debug/10a17b.gno +++ b/gnovm/tests/files/debug/10a17b.gno @@ -2,6 +2,7 @@ package main import "fmt" +// TODO: the log is runtime log, implies it escape preprocess check func foo(a uint64, b float32) { fmt.Printf("%T \n", a) println(a) @@ -13,4 +14,4 @@ func main() { } // Error: -// operators >> and >>= not defined for float32 +// main/files/debug/10a17b.gno:13: operator >> not defined on: float32 diff --git a/gnovm/tests/files/debug/10a17b1.gno b/gnovm/tests/files/debug/10a17b1.gno new file mode 100644 index 00000000000..c4c3538a65f --- /dev/null +++ b/gnovm/tests/files/debug/10a17b1.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +// it's like assign +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// main/files/debug/10a17b1.gno:13: cannot use int as float32 diff --git a/gnovm/tests/files/debug/10a21.gno b/gnovm/tests/files/debug/10a21.gno index 6f9744fef30..ea9caace97b 100644 --- a/gnovm/tests/files/debug/10a21.gno +++ b/gnovm/tests/files/debug/10a21.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/debug/10a21.gno:5: float not compatible with shift +// main/files/debug/10a21.gno:5: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a21a.gno b/gnovm/tests/files/debug/10a21a.gno index 557ac867bec..209394386c0 100644 --- a/gnovm/tests/files/debug/10a21a.gno +++ b/gnovm/tests/files/debug/10a21a.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/debug/10a21a.gno:5: float not compatible with shift +// main/files/debug/10a21a.gno:5: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a25c.gno b/gnovm/tests/files/debug/10a25c.gno index b237519537d..ebe2deac1d6 100644 --- a/gnovm/tests/files/debug/10a25c.gno +++ b/gnovm/tests/files/debug/10a25c.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/debug/10a25c.gno:6: float not compatible with shift +// main/files/debug/10a25c.gno:6: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a26.gno b/gnovm/tests/files/debug/10a26.gno index 65445e8d52a..ea1c2a2ef32 100644 --- a/gnovm/tests/files/debug/10a26.gno +++ b/gnovm/tests/files/debug/10a26.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/debug/10a26.gno:6: float not compatible with shift +// main/files/debug/10a26.gno:6: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a27.gno b/gnovm/tests/files/debug/10a27.gno index 6f1fb6d8fd6..4269a713c7c 100644 --- a/gnovm/tests/files/debug/10a27.gno +++ b/gnovm/tests/files/debug/10a27.gno @@ -2,13 +2,14 @@ package main import "fmt" -// TODO: no support for this expr for now, should fix in another context func main() { x := 11 - y := uint64(-(1 + 1< bigint)) + (const (1 bigint)) << (const-type uint)(x) is not a type +// Output: +// 18446744073709549568 +// uint64 diff --git a/gnovm/tests/files/debug/10a27a.gno b/gnovm/tests/files/debug/10a27a.gno new file mode 100644 index 00000000000..62c6435a591 --- /dev/null +++ b/gnovm/tests/files/debug/10a27a.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64(-(1 + 1< bigdec diff --git a/gnovm/tests/files/debug/1_a.gno b/gnovm/tests/files/debug/1_a.gno new file mode 100644 index 00000000000..40e595eecc3 --- /dev/null +++ b/gnovm/tests/files/debug/1_a.gno @@ -0,0 +1,20 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +// case of const in type call +func main() { + r := int(uint(string("hello"))) + println(r) + fmt.Printf("%T \n", r) +} + +// Error: +// main/files/debug/1_a.gno:14: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/debug/3.gno b/gnovm/tests/files/debug/3.gno new file mode 100644 index 00000000000..f932a970a9a --- /dev/null +++ b/gnovm/tests/files/debug/3.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 1 + r := uint(+x) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 1 +// uint diff --git a/gnovm/tests/files/debug/3_a.gno b/gnovm/tests/files/debug/3_a.gno new file mode 100644 index 00000000000..6ca9a8b7cc2 --- /dev/null +++ b/gnovm/tests/files/debug/3_a.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 1 + r := uint(+(1 << x)) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 2 +// uint diff --git a/gnovm/tests/files/debug/3_b.gno b/gnovm/tests/files/debug/3_b.gno new file mode 100644 index 00000000000..55b5fa782d7 --- /dev/null +++ b/gnovm/tests/files/debug/3_b.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 63 + r := int32(+(1<>2) +} + +// Output: +// 4 0 diff --git a/gnovm/tests/files/debug/a46.gno b/gnovm/tests/files/debug/a46.gno new file mode 100644 index 00000000000..d50c3944e90 --- /dev/null +++ b/gnovm/tests/files/debug/a46.gno @@ -0,0 +1,26 @@ +package main + +var specialBytes [16]byte + +func main() { + for i, b := range []byte(`\.+*?()|[]{}^$`) { + specialBytes[b%16] |= 1 << (b / 16) + println(i, (1 << (b / 16)), specialBytes[b%16]) + } +} + +// Output: +// 0 32 32 +// 1 4 4 +// 2 4 4 +// 3 4 4 +// 4 8 8 +// 5 4 4 +// 6 4 4 +// 7 128 160 +// 8 32 36 +// 9 32 32 +// 10 128 164 +// 11 128 160 +// 12 32 36 +// 13 4 4 diff --git a/gnovm/tests/files/debug/addr0b_stdlibs.gno b/gnovm/tests/files/debug/addr0b_stdlibs.gno new file mode 100644 index 00000000000..324a30f8140 --- /dev/null +++ b/gnovm/tests/files/debug/addr0b_stdlibs.gno @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/gnolang/gno/_test/net/http" +) + +type extendedRequest struct { + Request http.Request + + Data string +} + +func main() { + r := extendedRequest{} + // req := &r.Request + + println(r) + // XXX removed temporarily until recursion detection implemented for sprintString(). + // println(req) +} + +// Output: +// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined) nil,(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) diff --git a/gnovm/tests/files/debug/comp3.gno b/gnovm/tests/files/debug/comp3.gno new file mode 100644 index 00000000000..bd926979844 --- /dev/null +++ b/gnovm/tests/files/debug/comp3.gno @@ -0,0 +1,14 @@ +package main + +func main() { + // test against uninitialized value: https://github.com/gnolang/gno/pull/1132 + var x string + y := "Hello" + results := [...]bool{ + x < y, + } + println(results) +} + +// Output: +// array[(true bool)] diff --git a/gnovm/tests/files/debug3/10a01_native_filetest.gnoa b/gnovm/tests/files/debug3/10a01_native_filetest.gnoa new file mode 100644 index 00000000000..42faa57634d --- /dev/null +++ b/gnovm/tests/files/debug3/10a01_native_filetest.gnoa @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "time" + + "github.com/gnolang/gno/_test/net/http" +) + +func main() { + http.DefaultClient.Timeout = time.Second * 10 + fmt.Println(http.DefaultClient) + http.DefaultClient = &http.Client{} + fmt.Println(http.DefaultClient) +} + +// Output: +// &{ 10s} +// &{ 0s} diff --git a/gnovm/tests/files/debug3/10a0_filetest.gno b/gnovm/tests/files/debug3/10a0_filetest.gno new file mode 100644 index 00000000000..2ac7ba6d674 --- /dev/null +++ b/gnovm/tests/files/debug3/10a0_filetest.gno @@ -0,0 +1,13 @@ +package main + +func gen() []int { + return nil +} + +func main() { + r := gen() == nil + println(r) +} + +// Output: +// true diff --git a/gnovm/tests/files/debug3/10a10_filetest.gno b/gnovm/tests/files/debug3/10a10_filetest.gno new file mode 100644 index 00000000000..0eba81f4a9c --- /dev/null +++ b/gnovm/tests/files/debug3/10a10_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << 1.0 // NOTE: go vet would fail, but still process + println(r) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/debug3/10a11_filetest.gno b/gnovm/tests/files/debug3/10a11_filetest.gno new file mode 100644 index 00000000000..bcb62dc76c3 --- /dev/null +++ b/gnovm/tests/files/debug3/10a11_filetest.gno @@ -0,0 +1,13 @@ +package main + +import "bytes" + +// both not const, and both interface +func main() { + // lv.T: * uint8, rv.T: * uint8 + cmp := bytes.Compare([]byte("a"), []byte("b")) + println(cmp) +} + +// Output: +// -1 diff --git a/gnovm/tests/files/debug3/10a17.gno b/gnovm/tests/files/debug3/10a17.gno new file mode 100644 index 00000000000..5c504d7d616 --- /dev/null +++ b/gnovm/tests/files/debug3/10a17.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/debug3/10a17a.gno b/gnovm/tests/files/debug3/10a17a.gno new file mode 100644 index 00000000000..254c36e613f --- /dev/null +++ b/gnovm/tests/files/debug3/10a17a.gno @@ -0,0 +1,21 @@ +package main + +import "fmt" + +func foo(a uint64, b int64) { + fmt.Printf("%T \n", a) + fmt.Printf("%T \n", b) + println(a) + println(b) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Output: +// uint64 +// int64 +// 2048 +// 0 diff --git a/gnovm/tests/files/debug3/10a17b.gno b/gnovm/tests/files/debug3/10a17b.gno new file mode 100644 index 00000000000..82ddf971e01 --- /dev/null +++ b/gnovm/tests/files/debug3/10a17b.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +// TODO: the log is runtime log, implies it escape preprocess check +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// operators >> and >>= not defined for float32 diff --git a/gnovm/tests/files/debug3/10a18.gno b/gnovm/tests/files/debug3/10a18.gno new file mode 100644 index 00000000000..a29108aef5a --- /dev/null +++ b/gnovm/tests/files/debug3/10a18.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1 << x) + println(y) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/debug3/10a19.gno b/gnovm/tests/files/debug3/10a19.gno new file mode 100644 index 00000000000..3b7fb0aec50 --- /dev/null +++ b/gnovm/tests/files/debug3/10a19.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1<> 8) + println(b) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/debug3/10a23.gno b/gnovm/tests/files/debug3/10a23.gno new file mode 100644 index 00000000000..44aa5a95561 --- /dev/null +++ b/gnovm/tests/files/debug3/10a23.gno @@ -0,0 +1,9 @@ +package main + +func main() { + b := uint64(1 + 1) + println(b) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/debug3/10a24.gno b/gnovm/tests/files/debug3/10a24.gno new file mode 100644 index 00000000000..d118c422845 --- /dev/null +++ b/gnovm/tests/files/debug3/10a24.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := 1 << x + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/debug3/10a25.gno b/gnovm/tests/files/debug3/10a25.gno new file mode 100644 index 00000000000..c29c8e2813f --- /dev/null +++ b/gnovm/tests/files/debug3/10a25.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := -(1 << x) + println(y) +} + +// Output: +// -2048 diff --git a/gnovm/tests/files/debug3/10a25a.gno b/gnovm/tests/files/debug3/10a25a.gno new file mode 100644 index 00000000000..da008b9b5a1 --- /dev/null +++ b/gnovm/tests/files/debug3/10a25a.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := -(1 + 1< string +// main/files/types/10a16_filetest.gno:3: operator << not defined on: string diff --git a/gnovm/tests/files/types/10a5_filetest.gno b/gnovm/tests/files/types/10a5_filetest.gno index 7538b2f4b10..af55d1b5cdc 100644 --- a/gnovm/tests/files/types/10a5_filetest.gno +++ b/gnovm/tests/files/types/10a5_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/10a5_filetest.gno:4: operators << and <<= not defined for bigdec +// main/files/types/10a5_filetest.gno:4: operator << not defined on: bigdec diff --git a/gnovm/tests/files/types/27a_filetest.gno b/gnovm/tests/files/types/27a_filetest.gno index 8490c751c88..d3d314d3685 100644 --- a/gnovm/tests/files/types/27a_filetest.gno +++ b/gnovm/tests/files/types/27a_filetest.gno @@ -6,5 +6,5 @@ func main() { println(y) } -// Output: -// 2048 +// Error: +// main/files/types/27a_filetest.gno:3: operator << not defined on: bigdec From c1f4dda22a924333ea6451d7ebccf2dd23a64b3d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 22 Dec 2023 15:48:29 +0800 Subject: [PATCH 062/193] fixup --- gnovm/Makefile | 4 +- gnovm/pkg/gnolang/op_expressions.go | 1 + gnovm/pkg/gnolang/preprocess.go | 250 +++--------------- gnovm/pkg/gnolang/types.go | 17 +- gnovm/pkg/gnolang/values_conversions.go | 5 +- gnovm/pkg/gnolang/values_string.go | 2 + gnovm/tests/file_test.go | 5 + gnovm/tests/files/debug/10a17b.gno | 17 -- gnovm/tests/files/debug/10a21.gno | 10 - gnovm/tests/files/debug/10a25c.gno | 11 - .../files/debug3/10a01_native_filetest.gnoa | 19 -- gnovm/tests/files/debug3/10a0_filetest.gno | 13 - gnovm/tests/files/debug3/10a10_filetest.gno | 10 - gnovm/tests/files/debug3/10a11_filetest.gno | 13 - gnovm/tests/files/debug3/10a17.gno | 10 - gnovm/tests/files/debug3/10a17a.gno | 21 -- gnovm/tests/files/debug3/10a18.gno | 10 - gnovm/tests/files/debug3/10a19.gno | 10 - gnovm/tests/files/debug3/10a20.gno | 10 - gnovm/tests/files/debug3/10a21a.gno | 10 - gnovm/tests/files/debug3/10a22.gno | 10 - gnovm/tests/files/debug3/10a23.gno | 9 - gnovm/tests/files/debug3/10a24.gno | 10 - gnovm/tests/files/debug3/10a25.gno | 10 - gnovm/tests/files/debug3/10a25a.gno | 10 - gnovm/tests/files/debug3/10a25b.gno | 11 - gnovm/tests/files/debug3/10a26.gno | 12 - gnovm/tests/files/debug3/10a27.gno | 15 -- gnovm/tests/files/debug3/debug.gnoa | 19 -- gnovm/tests/files/{debug => types2}/0.gno | 0 gnovm/tests/files/{debug => types2}/0_a.gno | 0 gnovm/tests/files/{debug => types2}/0_a_1.gno | 0 gnovm/tests/files/{debug => types2}/0_b.gno | 2 +- gnovm/tests/files/{debug => types2}/0_c.gno | 0 gnovm/tests/files/{debug => types2}/0_d.gno | 0 gnovm/tests/files/{debug => types2}/0_e.gno | 0 gnovm/tests/files/{debug => types2}/0_f.gno | 0 gnovm/tests/files/{debug => types2}/1.gno | 0 .../{debug => types2}/10a000_filetest.gno | 0 .../{debug => types2}/10a00_filetest.gno | 0 .../{debug => types2}/10a01_filetest.gno | 2 +- .../10a01_native_filetest.gnoa | 0 .../{debug => types2}/10a02_filetest.gno | 2 +- .../{debug => types2}/10a03_filetest.gno | 0 .../files/{debug => types2}/10a0_filetest.gno | 0 .../{debug => types2}/10a10_filetest.gno | 0 .../{debug => types2}/10a11_filetest.gnoa | 0 gnovm/tests/files/{debug => types2}/10a17.gno | 0 .../tests/files/{debug => types2}/10a17a.gno | 0 .../tests/files/{debug3 => types2}/10a17b.gno | 2 +- .../tests/files/{debug => types2}/10a17b1.gno | 2 +- gnovm/tests/files/{debug => types2}/10a18.gno | 0 gnovm/tests/files/{debug => types2}/10a19.gno | 0 gnovm/tests/files/{debug => types2}/10a20.gno | 0 .../tests/files/{debug3 => types2}/10a21.gno | 2 +- .../tests/files/{debug => types2}/10a21a.gno | 2 +- gnovm/tests/files/{debug => types2}/10a22.gno | 0 gnovm/tests/files/{debug => types2}/10a23.gno | 0 gnovm/tests/files/{debug => types2}/10a24.gno | 0 gnovm/tests/files/{debug => types2}/10a25.gno | 0 .../tests/files/{debug => types2}/10a25a.gno | 0 .../tests/files/{debug => types2}/10a25b.gno | 0 .../tests/files/{debug3 => types2}/10a25c.gno | 2 +- gnovm/tests/files/{debug => types2}/10a26.gno | 2 +- gnovm/tests/files/{debug => types2}/10a27.gno | 0 .../tests/files/{debug => types2}/10a27a.gno | 0 .../tests/files/{debug => types2}/10a27b.gno | 0 .../tests/files/{debug => types2}/10a27c.gno | 2 +- gnovm/tests/files/{debug => types2}/1_a.gno | 2 +- gnovm/tests/files/{debug => types2}/3.gno | 0 gnovm/tests/files/{debug => types2}/3_a.gno | 0 gnovm/tests/files/{debug => types2}/3_b.gno | 0 gnovm/tests/files/{debug => types2}/4.gno | 2 +- gnovm/tests/files/{debug => types2}/4_a.gno | 2 +- gnovm/tests/files/{debug => types2}/4_b.gno | 2 +- gnovm/tests/files/{debug => types2}/4_c.gno | 0 gnovm/tests/files/{debug => types2}/5.gno | 0 gnovm/tests/files/{debug => types2}/a46.gno | 0 .../{debug => types2}/addr0b_stdlibs.gno | 0 gnovm/tests/files/{debug => types2}/comp3.gno | 0 80 files changed, 77 insertions(+), 505 deletions(-) delete mode 100644 gnovm/tests/files/debug/10a17b.gno delete mode 100644 gnovm/tests/files/debug/10a21.gno delete mode 100644 gnovm/tests/files/debug/10a25c.gno delete mode 100644 gnovm/tests/files/debug3/10a01_native_filetest.gnoa delete mode 100644 gnovm/tests/files/debug3/10a0_filetest.gno delete mode 100644 gnovm/tests/files/debug3/10a10_filetest.gno delete mode 100644 gnovm/tests/files/debug3/10a11_filetest.gno delete mode 100644 gnovm/tests/files/debug3/10a17.gno delete mode 100644 gnovm/tests/files/debug3/10a17a.gno delete mode 100644 gnovm/tests/files/debug3/10a18.gno delete mode 100644 gnovm/tests/files/debug3/10a19.gno delete mode 100644 gnovm/tests/files/debug3/10a20.gno delete mode 100644 gnovm/tests/files/debug3/10a21a.gno delete mode 100644 gnovm/tests/files/debug3/10a22.gno delete mode 100644 gnovm/tests/files/debug3/10a23.gno delete mode 100644 gnovm/tests/files/debug3/10a24.gno delete mode 100644 gnovm/tests/files/debug3/10a25.gno delete mode 100644 gnovm/tests/files/debug3/10a25a.gno delete mode 100644 gnovm/tests/files/debug3/10a25b.gno delete mode 100644 gnovm/tests/files/debug3/10a26.gno delete mode 100644 gnovm/tests/files/debug3/10a27.gno delete mode 100644 gnovm/tests/files/debug3/debug.gnoa rename gnovm/tests/files/{debug => types2}/0.gno (100%) rename gnovm/tests/files/{debug => types2}/0_a.gno (100%) rename gnovm/tests/files/{debug => types2}/0_a_1.gno (100%) rename gnovm/tests/files/{debug => types2}/0_b.gno (90%) rename gnovm/tests/files/{debug => types2}/0_c.gno (100%) rename gnovm/tests/files/{debug => types2}/0_d.gno (100%) rename gnovm/tests/files/{debug => types2}/0_e.gno (100%) rename gnovm/tests/files/{debug => types2}/0_f.gno (100%) rename gnovm/tests/files/{debug => types2}/1.gno (100%) rename gnovm/tests/files/{debug => types2}/10a000_filetest.gno (100%) rename gnovm/tests/files/{debug => types2}/10a00_filetest.gno (100%) rename gnovm/tests/files/{debug => types2}/10a01_filetest.gno (71%) rename gnovm/tests/files/{debug => types2}/10a01_native_filetest.gnoa (100%) rename gnovm/tests/files/{debug => types2}/10a02_filetest.gno (64%) rename gnovm/tests/files/{debug => types2}/10a03_filetest.gno (100%) rename gnovm/tests/files/{debug => types2}/10a0_filetest.gno (100%) rename gnovm/tests/files/{debug => types2}/10a10_filetest.gno (100%) rename gnovm/tests/files/{debug => types2}/10a11_filetest.gnoa (100%) rename gnovm/tests/files/{debug => types2}/10a17.gno (100%) rename gnovm/tests/files/{debug => types2}/10a17a.gno (100%) rename gnovm/tests/files/{debug3 => types2}/10a17b.gno (75%) rename gnovm/tests/files/{debug => types2}/10a17b1.gno (73%) rename gnovm/tests/files/{debug => types2}/10a18.gno (100%) rename gnovm/tests/files/{debug => types2}/10a19.gno (100%) rename gnovm/tests/files/{debug => types2}/10a20.gno (100%) rename gnovm/tests/files/{debug3 => types2}/10a21.gno (54%) rename gnovm/tests/files/{debug => types2}/10a21a.gno (54%) rename gnovm/tests/files/{debug => types2}/10a22.gno (100%) rename gnovm/tests/files/{debug => types2}/10a23.gno (100%) rename gnovm/tests/files/{debug => types2}/10a24.gno (100%) rename gnovm/tests/files/{debug => types2}/10a25.gno (100%) rename gnovm/tests/files/{debug => types2}/10a25a.gno (100%) rename gnovm/tests/files/{debug => types2}/10a25b.gno (100%) rename gnovm/tests/files/{debug3 => types2}/10a25c.gno (56%) rename gnovm/tests/files/{debug => types2}/10a26.gno (57%) rename gnovm/tests/files/{debug => types2}/10a27.gno (100%) rename gnovm/tests/files/{debug => types2}/10a27a.gno (100%) rename gnovm/tests/files/{debug => types2}/10a27b.gno (100%) rename gnovm/tests/files/{debug => types2}/10a27c.gno (61%) rename gnovm/tests/files/{debug => types2}/1_a.gno (89%) rename gnovm/tests/files/{debug => types2}/3.gno (100%) rename gnovm/tests/files/{debug => types2}/3_a.gno (100%) rename gnovm/tests/files/{debug => types2}/3_b.gno (100%) rename gnovm/tests/files/{debug => types2}/4.gno (89%) rename gnovm/tests/files/{debug => types2}/4_a.gno (89%) rename gnovm/tests/files/{debug => types2}/4_b.gno (91%) rename gnovm/tests/files/{debug => types2}/4_c.gno (100%) rename gnovm/tests/files/{debug => types2}/5.gno (100%) rename gnovm/tests/files/{debug => types2}/a46.gno (100%) rename gnovm/tests/files/{debug => types2}/addr0b_stdlibs.gno (100%) rename gnovm/tests/files/{debug => types2}/comp3.gno (100%) diff --git a/gnovm/Makefile b/gnovm/Makefile index f258081145a..ca1ef8e5340 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -50,7 +50,7 @@ _test.pkg: go test ./pkg/... $(GOTEST_FLAGS) .PHONY: _test.gnolang -_test.gnolang: _test.gnolang.types _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other +_test.gnolang: _test.gnolang.types _test.gnolang.types2 _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other _test.gnolang.other:; go test tests/*.go -run "(TestFileStr|TestSelectors)" $(GOTEST_FLAGS) _test.gnolang.realm:; go test tests/*.go -run "TestFiles/^zrealm" $(GOTEST_FLAGS) _test.gnolang.pkg0:; go test tests/*.go -run "TestPackages/(bufio|crypto|encoding|errors|internal|io|math|sort|std|stdshim|strconv|strings|testing|unicode)" $(GOTEST_FLAGS) @@ -64,6 +64,8 @@ _test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallen _test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.debug:; go test tests/*.go -test.short -run 'TestDebug$$/' --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.debug.native:; go test tests/*.go -test.short -run 'TestDebugNative$$/' --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.types2:; go test tests/*.go -test.short -run 'TestTypes2$$/' --update-golden-tests $(GOTEST_FLAGS) ######################################## # Code gen diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 967541c6e8f..6a16506d6d1 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -703,6 +703,7 @@ func (m *Machine) doOpFuncLit() { } func (m *Machine) doOpConvert() { + debugPP.Println("---doOpConvert---") xv := m.PopValue() t := m.PopValue().GetType() ConvertTo(m.Alloc, m.Store, xv, t) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 09d13f779e5..6fdf8b9f7f2 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -875,15 +875,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isQuoOrRem(n.Op) { checkOperand(rcx) } - } else { // is shift, and assume RHS is uint - // here we don't need to check rt, it must be right - // we should check lt instead - // NOTE: - // it's complicated. - // type of shift can be determined by some cases: - // 1. lhs of shift expr is already typed with type name, e.g. int(1) << 1. - // 2. type gained from further expr, e.g. 1.0< len(n.Rhs) { - debugPP.Println("len lhs > len rhs") // Unpack n.Rhs[0] to n.Lhs[:] if len(n.Rhs) != 1 { panic("should not happen") @@ -1810,7 +1762,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { default: panic("should not happen") } - debugPP.Println("else") } else { debugPP.Println("else---") // General case: a, b := x, y @@ -1826,24 +1777,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(ln, anyValue(rt)) } checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) - - //// handle untyped rhs - //if _, ok := rx.(*BinaryExpr); ok { - // rt := evalStaticTypeOf(store, last, rx) - // // only untyped - // if isUntyped(rt) { - // debugPP.Println("------rt untyped, update--------") - // updateType(store, last, &n.Rhs[i], nil, false, false) - // } else { - // // do nothing - // } - //} else if rux, ok := rx.(*UnaryExpr); ok { - // updateType(store, last, &rux.X, nil, false, true) - //} } } } else { // ASSIGN. - debugPP.Println("---assign---") // NOTE: Keep in sync with DEFINE above. if len(n.Lhs) > len(n.Rhs) { // TODO dry code w/ above. @@ -1895,46 +1831,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOp(store, last, &n.Rhs[0], lt, n.Op, Assign) checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) } else { // all else, like BAND_ASSIGN, etc - debugPP.Println("case like: a, b = x, y") // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) - - debugPP.Printf("lx: %v \n", lx) - debugPP.Printf("lt: %v \n", lt) - //rt := evalStaticTypeOf(store, last, n.Rhs[i]) - - // update rhs if needed, special case - //if _, ok := n.Rhs[i].(*BinaryExpr); ok { - // debugPP.Println("is binary expr-----") - // // only untyped - // if isUntyped(rt) { // not coerce, so should be untyped, and not skip - // debugPP.Println("------rt untyped, regular convert routine") - // checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) - // checkOrConvertType(store, last, &n.Rhs[i], lt, false, false) // - // } else if rux, ok := n.Rhs[i].(*UnaryExpr); ok { - // if isUntyped(rt) { - // debugPP.Println("------rt untyped, regular convert routine") - // checkOp(store, last, &rux.X, lt, n.Op, Assign) - // checkOrConvertType(store, last, &rux.X, lt, false, false) - // } - // } else { - // debugPP.Println("-------------else cases-----------------") - // checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) - // checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) - // } - //} - //if isUntyped(rt) { checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) - //} } } } // TRANS_LEAVE ----------------------- case *BranchStmt: - debugPP.Println("BranchStmt---") switch n.Op { case BREAK: case CONTINUE: @@ -1961,30 +1868,25 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *IncDecStmt: - debugPP.Println("---IncDecStmt---") xt := evalStaticTypeOf(store, last, n.X) checkOp(store, last, nil, xt, n.Op, IncDec) // TRANS_LEAVE ----------------------- case *ForStmt: - debugPP.Println("ForStmt---") // Cond consts become bool *ConstExprs. checkOrConvertType(store, last, &n.Cond, BoolType, false, false) // TRANS_LEAVE ----------------------- case *IfStmt: - debugPP.Println("ifStmt---") // Cond consts become bool *ConstExprs. checkOrConvertType(store, last, &n.Cond, BoolType, false, false) // TRANS_LEAVE ----------------------- case *RangeStmt: - debugPP.Println("RangeStmt---") // NOTE: k,v already defined @ TRANS_BLOCK. // TRANS_LEAVE ----------------------- case *ReturnStmt: - debugPP.Println("ReturnStmt---") fnode, ft := funcOf(last) // Check number of return arguments. if len(n.Results) != len(ft.Results) { @@ -2075,7 +1977,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ValueDecl: - debugPP.Println("ValueDecl---") // evaluate value if const expr. if n.Const { // NOTE: may or may not be a *ConstExpr, @@ -2188,7 +2089,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *TypeDecl: - debugPP.Println("TypeDecl---") // Construct new Type, where any recursive // references refer to the old Type declared // during *TypeDecl:ENTER. Then, copy over the @@ -2647,8 +2547,7 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() - -// TODO: use opts instead +// TODO: use opts instead? func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) if cx, ok := (*x).(*ConstExpr); ok { @@ -2656,28 +2555,27 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // TODO: other bypass situations like cast if !coerce { if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno + // TODO: make it flag checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } } convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("xt: %v \n", xt) + debugPP.Printf("shift,xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) if t == nil { if isUntyped(xt) { t = defaultTypeOf(xt) } else { - t = xt + t = xt // xt maybe typed while assign, with t is the type of LHS } } - - if coerce { + if coerce { // mostly when explicitly conversion, type call checkOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else if !coerce && isUntyped(xt) { - if _, ok := t.(*InterfaceType); !ok { // concrete type + } else if !coerce && isUntyped(xt) { // assign, func call + if _, ok := t.(*InterfaceType); !ok { // TODO: consider this checkOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) @@ -2698,8 +2596,23 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative t = xt } } + if coerce { // mostly when explicitly conversion, type call + checkOp(store, last, &ux.X, t, ux.Op, Unary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) + } else if !coerce && isUntyped(xt) { // assign, func call + if _, ok := t.(*InterfaceType); !ok { // TODO: consider this + checkOp(store, last, &ux.X, t, ux.Op, Unary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) + } else { + checkConvertible(xt, t, false) + } + } else { + checkConvertible(xt, t, false) + } // "push" expected type into shift unary's operand - checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) + //checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("else expr, xt not nil,x: %v, xt: %v \n", *x, xt) @@ -2748,21 +2661,15 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative return case EQL, LSS, GTR, NEQ, LEQ, GEQ: debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) - //checkOp(store, last, &bx.Left, t, bx.Op, Binary) - ////checkOrConvertType(store, last, x, t, autoNative, coerce) - //(*x).SetAttribute(ATTR_TYPEOF_VALUE, t) - //return - // default: } } // general case cx := Expr(Call(constType(nil, t), *x)) - cx.SetAttribute(ATTR_TYPEOF_VALUE, t) + cx.SetAttribute(ATTR_TYPEOF_VALUE, t) // as a flag for processor cx = Preprocess(store, last, cx).(Expr) *x = cx } - debugPP.Println("is Unamed: ", isUnamed) // cover all declared type case if isUnamed { cx := Expr(Call(constType(nil, t), *x)) @@ -2772,83 +2679,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } -// focus on update type to specific scenarios -// call, assign type to postponed untyped expr, e.g. shift, unary -// first, checkOrConvert to do the immediate convert -// use updateType to handle postponed case -// only for typetype(callExpr), assign, so println(1< native. it's reasonable for gno is a superset of go type, e.g. bigint -// // TODO: other bypass situations like cast -// if !skip { -// if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno -// checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args -// } -// } -// convertConst(store, last, cx, t) -// } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { -// debugPP.Printf("shift, Op: %v, t: %v \n", bx.Op, t) -// xt := evalStaticTypeOf(store, last, *x) -// if t == nil { -// t = defaultTypeOf(xt) -// } -// checkOp(store, last, &bx.Left, t, bx.Op, Binary) -// updateType(store, last, &bx.Left, t, autoNative, false) -// } else if *x != nil { // XXX if x != nil && t != nil { -// xt := evalStaticTypeOf(store, last, *x) -// debugPP.Printf("else expr, xt not nil, x: %v, xt: %v \n", *x, xt) -// -// // check convertible prior -// // TODO: check this logic -// //var isUnamed bool -// if t != nil && !skip { -// checkConvertible(xt, t, autoNative) -// } -// if isUntyped(xt) { -// debugPP.Println("xt untyped") -// if t == nil { -// t = defaultTypeOf(xt) -// debugPP.Println("default type of t: %v \n", t) -// } -// // Push type into expr if qualifying binary expr. -// if bx, ok := (*x).(*BinaryExpr); ok { -// switch bx.Op { -// case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, -// BAND_NOT, LAND, LOR: -// // push t into bx.Left and bx.Right, recursively -// checkOp(store, last, &bx.Left, t, bx.Op, Binary) -// updateType(store, last, &bx.Left, t, autoNative, skip) -// checkOp(store, last, &bx.Right, t, bx.Op, Binary) -// updateType(store, last, &bx.Right, t, autoNative, skip) -// return -// case SHL, SHR: -// debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) -// checkOp(store, last, &bx.Left, t, bx.Op, Binary) -// // push t into bx.Left -// updateType(store, last, &bx.Left, t, autoNative, skip) -// return -// // case EQL, LSS, GTR, NEQ, LEQ, GEQ: -// // default: -// } -// } else if ux, ok := (*x).(*UnaryExpr); ok { -// checkOp(store, last, &ux.X, t, ux.Op, Unary) -// updateType(store, last, &ux.X, t, autoNative, skip) -// return -// } -// } -// -// //debugPP.Println("is Unamed: ", isUnamed) -// //// cover all declared type case -// //if isUnamed { -// // cx := Expr(Call(constType(nil, t), *x)) -// // cx = Preprocess(store, last, cx).(Expr) -// // *x = cx -// //} -// } -//} - // like checkOrConvertType(last, x, nil) func convertIfConst(store Store, last BlockNode, x Expr) { if cx, ok := x.(*ConstExpr); ok { @@ -2857,7 +2687,7 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - debugPP.Printf("------convertConst, cx:%v, t:%v \n", cx, t) + debugPP.Printf("---convertConst---, cx:%v, t:%v \n", cx, t) if t != nil && t.Kind() == InterfaceKind { if cx.IsUndefined() { if _, ok := t.(*NativeType); !ok { // bypass native nil interface @@ -2872,11 +2702,9 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { t = nil } if isUntyped(cx.T) { - debugPP.Println("convert untyped const") ConvertUntypedTo(&cx.TypedValue, t) setConstAttrs(cx) } else if t != nil { - debugPP.Println("convert coerce, t != nil") // e.g. a named type or uint8 type to int for indexing. ConvertTo(nilAllocator, store, &cx.TypedValue, t) setConstAttrs(cx) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 90414a69712..af774d6a933 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2356,10 +2356,10 @@ func assertEqualityTypes(lt, rt Type) { // The logic here is, when != or == shows up, check if t is maybeIdenticalType, if yes, // then check the corresponding type(the other side of the operator) is convertable to t. func maybeIdenticalType(xt, dt Type) (bool, string) { - debugPP.Printf("check maybeIdenticalType, xt: %v, dt: %v \n", xt, dt) + debugPP.Printf("---check maybeIdenticalType---, xt: %v, dt: %v \n", xt, dt) // primitive is maybeIdenticalType switch cdt := baseOf(dt).(type) { - case PrimitiveType: + case PrimitiveType: // TODO: more strict when both typed primitive debugPP.Println("primitive type, return true, fallthrough") return true, "" case *ArrayType: // NOTE: no recursive allowed @@ -2401,23 +2401,24 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { } case *NativeType: if cdt.Type.Comparable() { - debugPP.Printf("cdt type: %v \n", cdt.Type) return true, "" } - debugPP.Printf("not comparable, cdt type: %v \n", cdt.Type) return false, fmt.Sprintf("%v is not comparable \n", dt) case nil: // refer to 0a01_filetest, 0f32_filetest. - debugPP.Println("dt is nil") switch cxt := baseOf(xt).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer - debugPP.Printf("dt is nil, cxt: %v \n", cxt) return true, "" + case *NativeType: + switch nk := cxt.Type.Kind(); nk { + case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: + return true, "" + default: + return false, fmt.Sprintf("invalid operation, nil can not be compared to %v \n", nk) + } default: - debugPP.Printf("default, dt is nil, cxt: %v \n", cxt) return false, fmt.Sprintf("invalid operation, nil can not be compared to nil \n") } default: - debugPP.Printf("default: cdt: %v \n", cdt) return false, fmt.Sprintf("%v is not comparable \n", dt) } } diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 3ef991a752e..0dc06fbc2a0 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -893,7 +893,10 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { - debugPP.Printf("------ConvertUntypedTo, tv:%v, t:%v \n", tv, t) + debugPP.Printf("---ConvertUntypedTo---, tv:%v, t:%v \n", tv, t) + defer func() { + debugPP.Printf("---after ConvertUntypedTo---, tv:%v \n", tv) + }() if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index 16b91a1d197..669c8067787 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -162,6 +162,7 @@ func (v RefValue) String() string { // for print() and println(). func (tv *TypedValue) Sprint(m *Machine) string { + debugPP.Println("sprint") // if undefined, just "undefined". if tv == nil || tv.T == nil { return undefinedStr @@ -266,6 +267,7 @@ func (tv *TypedValue) Sprint(m *Machine) string { } func printNilOrValue(tv *TypedValue, valueType interface{}) string { + debugPP.Printf("printNilOrValue: tv: %v, T:%v, V:%v \n", *tv, (*tv).T, (*tv).V) if tv.V == nil { return nilStr + " " + tv.T.String() } diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index 402728d6902..ff9bb5431bb 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -47,6 +47,11 @@ func TestTypesNative(t *testing.T) { runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) } +func TestTypes2(t *testing.T) { + baseDir := filepath.Join(".", "files/types2") + runFileTests(t, baseDir, nil) +} + func TestDebug(t *testing.T) { baseDir := filepath.Join(".", "files/debug") runFileTests(t, baseDir, nil) diff --git a/gnovm/tests/files/debug/10a17b.gno b/gnovm/tests/files/debug/10a17b.gno deleted file mode 100644 index a92284f01da..00000000000 --- a/gnovm/tests/files/debug/10a17b.gno +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import "fmt" - -// TODO: the log is runtime log, implies it escape preprocess check -func foo(a uint64, b float32) { - fmt.Printf("%T \n", a) - println(a) -} - -func main() { - x := 11 - foo(1<>x) -} - -// Error: -// main/files/debug/10a17b.gno:13: operator >> not defined on: float32 diff --git a/gnovm/tests/files/debug/10a21.gno b/gnovm/tests/files/debug/10a21.gno deleted file mode 100644 index ea9caace97b..00000000000 --- a/gnovm/tests/files/debug/10a21.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := float32(1 << x) - println(y) -} - -// Error: -// main/files/debug/10a21.gno:5: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a25c.gno b/gnovm/tests/files/debug/10a25c.gno deleted file mode 100644 index ebe2deac1d6..00000000000 --- a/gnovm/tests/files/debug/10a25c.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -func main() { - x := 11 - var y float32 - y = -(1 << x) - println(y) -} - -// Error: -// main/files/debug/10a25c.gno:6: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug3/10a01_native_filetest.gnoa b/gnovm/tests/files/debug3/10a01_native_filetest.gnoa deleted file mode 100644 index 42faa57634d..00000000000 --- a/gnovm/tests/files/debug3/10a01_native_filetest.gnoa +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/gnolang/gno/_test/net/http" -) - -func main() { - http.DefaultClient.Timeout = time.Second * 10 - fmt.Println(http.DefaultClient) - http.DefaultClient = &http.Client{} - fmt.Println(http.DefaultClient) -} - -// Output: -// &{ 10s} -// &{ 0s} diff --git a/gnovm/tests/files/debug3/10a0_filetest.gno b/gnovm/tests/files/debug3/10a0_filetest.gno deleted file mode 100644 index 2ac7ba6d674..00000000000 --- a/gnovm/tests/files/debug3/10a0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -func gen() []int { - return nil -} - -func main() { - r := gen() == nil - println(r) -} - -// Output: -// true diff --git a/gnovm/tests/files/debug3/10a10_filetest.gno b/gnovm/tests/files/debug3/10a10_filetest.gno deleted file mode 100644 index 0eba81f4a9c..00000000000 --- a/gnovm/tests/files/debug3/10a10_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 1 - r := a << 1.0 // NOTE: go vet would fail, but still process - println(r) -} - -// Output: -// 2 diff --git a/gnovm/tests/files/debug3/10a11_filetest.gno b/gnovm/tests/files/debug3/10a11_filetest.gno deleted file mode 100644 index bcb62dc76c3..00000000000 --- a/gnovm/tests/files/debug3/10a11_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import "bytes" - -// both not const, and both interface -func main() { - // lv.T: * uint8, rv.T: * uint8 - cmp := bytes.Compare([]byte("a"), []byte("b")) - println(cmp) -} - -// Output: -// -1 diff --git a/gnovm/tests/files/debug3/10a17.gno b/gnovm/tests/files/debug3/10a17.gno deleted file mode 100644 index 5c504d7d616..00000000000 --- a/gnovm/tests/files/debug3/10a17.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := uint64(1 << x) - println(y) -} - -// Output: -// 2048 diff --git a/gnovm/tests/files/debug3/10a17a.gno b/gnovm/tests/files/debug3/10a17a.gno deleted file mode 100644 index 254c36e613f..00000000000 --- a/gnovm/tests/files/debug3/10a17a.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import "fmt" - -func foo(a uint64, b int64) { - fmt.Printf("%T \n", a) - fmt.Printf("%T \n", b) - println(a) - println(b) -} - -func main() { - x := 11 - foo(1<>x) -} - -// Output: -// uint64 -// int64 -// 2048 -// 0 diff --git a/gnovm/tests/files/debug3/10a18.gno b/gnovm/tests/files/debug3/10a18.gno deleted file mode 100644 index a29108aef5a..00000000000 --- a/gnovm/tests/files/debug3/10a18.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 64 - y := uint64(1 << x) - println(y) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/debug3/10a19.gno b/gnovm/tests/files/debug3/10a19.gno deleted file mode 100644 index 3b7fb0aec50..00000000000 --- a/gnovm/tests/files/debug3/10a19.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 64 - y := uint64(1<> 8) - println(b) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/debug3/10a23.gno b/gnovm/tests/files/debug3/10a23.gno deleted file mode 100644 index 44aa5a95561..00000000000 --- a/gnovm/tests/files/debug3/10a23.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - b := uint64(1 + 1) - println(b) -} - -// Output: -// 2 diff --git a/gnovm/tests/files/debug3/10a24.gno b/gnovm/tests/files/debug3/10a24.gno deleted file mode 100644 index d118c422845..00000000000 --- a/gnovm/tests/files/debug3/10a24.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := 1 << x - println(y) -} - -// Output: -// 2048 diff --git a/gnovm/tests/files/debug3/10a25.gno b/gnovm/tests/files/debug3/10a25.gno deleted file mode 100644 index c29c8e2813f..00000000000 --- a/gnovm/tests/files/debug3/10a25.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := -(1 << x) - println(y) -} - -// Output: -// -2048 diff --git a/gnovm/tests/files/debug3/10a25a.gno b/gnovm/tests/files/debug3/10a25a.gno deleted file mode 100644 index da008b9b5a1..00000000000 --- a/gnovm/tests/files/debug3/10a25a.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := -(1 + 1< bigdec +// main/files/types2/10a01_filetest.gno:7: operator << not defined on: bigdec diff --git a/gnovm/tests/files/debug/10a01_native_filetest.gnoa b/gnovm/tests/files/types2/10a01_native_filetest.gnoa similarity index 100% rename from gnovm/tests/files/debug/10a01_native_filetest.gnoa rename to gnovm/tests/files/types2/10a01_native_filetest.gnoa diff --git a/gnovm/tests/files/debug/10a02_filetest.gno b/gnovm/tests/files/types2/10a02_filetest.gno similarity index 64% rename from gnovm/tests/files/debug/10a02_filetest.gno rename to gnovm/tests/files/types2/10a02_filetest.gno index 173770f6a93..fa8e0bfec19 100644 --- a/gnovm/tests/files/debug/10a02_filetest.gno +++ b/gnovm/tests/files/types2/10a02_filetest.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/debug/10a02_filetest.gno:5: operator << not defined on: bigdec +// main/files/types2/10a02_filetest.gno:5: operator << not defined on: bigdec diff --git a/gnovm/tests/files/debug/10a03_filetest.gno b/gnovm/tests/files/types2/10a03_filetest.gno similarity index 100% rename from gnovm/tests/files/debug/10a03_filetest.gno rename to gnovm/tests/files/types2/10a03_filetest.gno diff --git a/gnovm/tests/files/debug/10a0_filetest.gno b/gnovm/tests/files/types2/10a0_filetest.gno similarity index 100% rename from gnovm/tests/files/debug/10a0_filetest.gno rename to gnovm/tests/files/types2/10a0_filetest.gno diff --git a/gnovm/tests/files/debug/10a10_filetest.gno b/gnovm/tests/files/types2/10a10_filetest.gno similarity index 100% rename from gnovm/tests/files/debug/10a10_filetest.gno rename to gnovm/tests/files/types2/10a10_filetest.gno diff --git a/gnovm/tests/files/debug/10a11_filetest.gnoa b/gnovm/tests/files/types2/10a11_filetest.gnoa similarity index 100% rename from gnovm/tests/files/debug/10a11_filetest.gnoa rename to gnovm/tests/files/types2/10a11_filetest.gnoa diff --git a/gnovm/tests/files/debug/10a17.gno b/gnovm/tests/files/types2/10a17.gno similarity index 100% rename from gnovm/tests/files/debug/10a17.gno rename to gnovm/tests/files/types2/10a17.gno diff --git a/gnovm/tests/files/debug/10a17a.gno b/gnovm/tests/files/types2/10a17a.gno similarity index 100% rename from gnovm/tests/files/debug/10a17a.gno rename to gnovm/tests/files/types2/10a17a.gno diff --git a/gnovm/tests/files/debug3/10a17b.gno b/gnovm/tests/files/types2/10a17b.gno similarity index 75% rename from gnovm/tests/files/debug3/10a17b.gno rename to gnovm/tests/files/types2/10a17b.gno index 82ddf971e01..b8084da9e30 100644 --- a/gnovm/tests/files/debug3/10a17b.gno +++ b/gnovm/tests/files/types2/10a17b.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// operators >> and >>= not defined for float32 +// main/files/types2/10a17b.gno:13: operator >> not defined on: float32 diff --git a/gnovm/tests/files/debug/10a17b1.gno b/gnovm/tests/files/types2/10a17b1.gno similarity index 73% rename from gnovm/tests/files/debug/10a17b1.gno rename to gnovm/tests/files/types2/10a17b1.gno index c4c3538a65f..d747ba8a617 100644 --- a/gnovm/tests/files/debug/10a17b1.gno +++ b/gnovm/tests/files/types2/10a17b1.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/debug/10a17b1.gno:13: cannot use int as float32 +// main/files/types2/10a17b1.gno:13: cannot use int as float32 diff --git a/gnovm/tests/files/debug/10a18.gno b/gnovm/tests/files/types2/10a18.gno similarity index 100% rename from gnovm/tests/files/debug/10a18.gno rename to gnovm/tests/files/types2/10a18.gno diff --git a/gnovm/tests/files/debug/10a19.gno b/gnovm/tests/files/types2/10a19.gno similarity index 100% rename from gnovm/tests/files/debug/10a19.gno rename to gnovm/tests/files/types2/10a19.gno diff --git a/gnovm/tests/files/debug/10a20.gno b/gnovm/tests/files/types2/10a20.gno similarity index 100% rename from gnovm/tests/files/debug/10a20.gno rename to gnovm/tests/files/types2/10a20.gno diff --git a/gnovm/tests/files/debug3/10a21.gno b/gnovm/tests/files/types2/10a21.gno similarity index 54% rename from gnovm/tests/files/debug3/10a21.gno rename to gnovm/tests/files/types2/10a21.gno index ea9caace97b..e4a6ec223eb 100644 --- a/gnovm/tests/files/debug3/10a21.gno +++ b/gnovm/tests/files/types2/10a21.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/debug/10a21.gno:5: operator << not defined on: float32 +// main/files/types2/10a21.gno:5: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a21a.gno b/gnovm/tests/files/types2/10a21a.gno similarity index 54% rename from gnovm/tests/files/debug/10a21a.gno rename to gnovm/tests/files/types2/10a21a.gno index 209394386c0..c29d8b14896 100644 --- a/gnovm/tests/files/debug/10a21a.gno +++ b/gnovm/tests/files/types2/10a21a.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/debug/10a21a.gno:5: operator << not defined on: float32 +// main/files/types2/10a21a.gno:5: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a22.gno b/gnovm/tests/files/types2/10a22.gno similarity index 100% rename from gnovm/tests/files/debug/10a22.gno rename to gnovm/tests/files/types2/10a22.gno diff --git a/gnovm/tests/files/debug/10a23.gno b/gnovm/tests/files/types2/10a23.gno similarity index 100% rename from gnovm/tests/files/debug/10a23.gno rename to gnovm/tests/files/types2/10a23.gno diff --git a/gnovm/tests/files/debug/10a24.gno b/gnovm/tests/files/types2/10a24.gno similarity index 100% rename from gnovm/tests/files/debug/10a24.gno rename to gnovm/tests/files/types2/10a24.gno diff --git a/gnovm/tests/files/debug/10a25.gno b/gnovm/tests/files/types2/10a25.gno similarity index 100% rename from gnovm/tests/files/debug/10a25.gno rename to gnovm/tests/files/types2/10a25.gno diff --git a/gnovm/tests/files/debug/10a25a.gno b/gnovm/tests/files/types2/10a25a.gno similarity index 100% rename from gnovm/tests/files/debug/10a25a.gno rename to gnovm/tests/files/types2/10a25a.gno diff --git a/gnovm/tests/files/debug/10a25b.gno b/gnovm/tests/files/types2/10a25b.gno similarity index 100% rename from gnovm/tests/files/debug/10a25b.gno rename to gnovm/tests/files/types2/10a25b.gno diff --git a/gnovm/tests/files/debug3/10a25c.gno b/gnovm/tests/files/types2/10a25c.gno similarity index 56% rename from gnovm/tests/files/debug3/10a25c.gno rename to gnovm/tests/files/types2/10a25c.gno index 6283e9f0938..c69dafc7d37 100644 --- a/gnovm/tests/files/debug3/10a25c.gno +++ b/gnovm/tests/files/types2/10a25c.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// operators << and <<= not defined for float32 +// main/files/types2/10a25c.gno:6: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a26.gno b/gnovm/tests/files/types2/10a26.gno similarity index 57% rename from gnovm/tests/files/debug/10a26.gno rename to gnovm/tests/files/types2/10a26.gno index ea1c2a2ef32..4c02fd979c8 100644 --- a/gnovm/tests/files/debug/10a26.gno +++ b/gnovm/tests/files/types2/10a26.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/debug/10a26.gno:6: operator << not defined on: float32 +// main/files/types2/10a26.gno:6: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/10a27.gno b/gnovm/tests/files/types2/10a27.gno similarity index 100% rename from gnovm/tests/files/debug/10a27.gno rename to gnovm/tests/files/types2/10a27.gno diff --git a/gnovm/tests/files/debug/10a27a.gno b/gnovm/tests/files/types2/10a27a.gno similarity index 100% rename from gnovm/tests/files/debug/10a27a.gno rename to gnovm/tests/files/types2/10a27a.gno diff --git a/gnovm/tests/files/debug/10a27b.gno b/gnovm/tests/files/types2/10a27b.gno similarity index 100% rename from gnovm/tests/files/debug/10a27b.gno rename to gnovm/tests/files/types2/10a27b.gno diff --git a/gnovm/tests/files/debug/10a27c.gno b/gnovm/tests/files/types2/10a27c.gno similarity index 61% rename from gnovm/tests/files/debug/10a27c.gno rename to gnovm/tests/files/types2/10a27c.gno index 936a29823d7..6740de32892 100644 --- a/gnovm/tests/files/debug/10a27c.gno +++ b/gnovm/tests/files/types2/10a27c.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/debug/10a27c.gno:5: operator << not defined on: bigdec +// main/files/types2/10a27c.gno:5: operator << not defined on: bigdec diff --git a/gnovm/tests/files/debug/1_a.gno b/gnovm/tests/files/types2/1_a.gno similarity index 89% rename from gnovm/tests/files/debug/1_a.gno rename to gnovm/tests/files/types2/1_a.gno index 40e595eecc3..dcda35a078e 100644 --- a/gnovm/tests/files/debug/1_a.gno +++ b/gnovm/tests/files/types2/1_a.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/debug/1_a.gno:14: cannot convert StringKind to UintKind +// main/files/types2/1_a.gno:14: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/debug/3.gno b/gnovm/tests/files/types2/3.gno similarity index 100% rename from gnovm/tests/files/debug/3.gno rename to gnovm/tests/files/types2/3.gno diff --git a/gnovm/tests/files/debug/3_a.gno b/gnovm/tests/files/types2/3_a.gno similarity index 100% rename from gnovm/tests/files/debug/3_a.gno rename to gnovm/tests/files/types2/3_a.gno diff --git a/gnovm/tests/files/debug/3_b.gno b/gnovm/tests/files/types2/3_b.gno similarity index 100% rename from gnovm/tests/files/debug/3_b.gno rename to gnovm/tests/files/types2/3_b.gno diff --git a/gnovm/tests/files/debug/4.gno b/gnovm/tests/files/types2/4.gno similarity index 89% rename from gnovm/tests/files/debug/4.gno rename to gnovm/tests/files/types2/4.gno index 8469ddc7d1e..bcc2903c10b 100644 --- a/gnovm/tests/files/debug/4.gno +++ b/gnovm/tests/files/types2/4.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/debug/4.gno:16: operator << not defined on: float32 +// main/files/types2/4.gno:16: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/4_a.gno b/gnovm/tests/files/types2/4_a.gno similarity index 89% rename from gnovm/tests/files/debug/4_a.gno rename to gnovm/tests/files/types2/4_a.gno index 99602928e69..db98074eebd 100644 --- a/gnovm/tests/files/debug/4_a.gno +++ b/gnovm/tests/files/types2/4_a.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/debug/4_a.gno:16: operator << not defined on: float32 \ No newline at end of file +// main/files/types2/4_a.gno:16: operator << not defined on: float32 diff --git a/gnovm/tests/files/debug/4_b.gno b/gnovm/tests/files/types2/4_b.gno similarity index 91% rename from gnovm/tests/files/debug/4_b.gno rename to gnovm/tests/files/types2/4_b.gno index 302427603ca..7f7374caaab 100644 --- a/gnovm/tests/files/debug/4_b.gno +++ b/gnovm/tests/files/types2/4_b.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/debug/4_b.gno:16: cannot use int as float32 +// main/files/types2/4_b.gno:16: cannot use int as float32 diff --git a/gnovm/tests/files/debug/4_c.gno b/gnovm/tests/files/types2/4_c.gno similarity index 100% rename from gnovm/tests/files/debug/4_c.gno rename to gnovm/tests/files/types2/4_c.gno diff --git a/gnovm/tests/files/debug/5.gno b/gnovm/tests/files/types2/5.gno similarity index 100% rename from gnovm/tests/files/debug/5.gno rename to gnovm/tests/files/types2/5.gno diff --git a/gnovm/tests/files/debug/a46.gno b/gnovm/tests/files/types2/a46.gno similarity index 100% rename from gnovm/tests/files/debug/a46.gno rename to gnovm/tests/files/types2/a46.gno diff --git a/gnovm/tests/files/debug/addr0b_stdlibs.gno b/gnovm/tests/files/types2/addr0b_stdlibs.gno similarity index 100% rename from gnovm/tests/files/debug/addr0b_stdlibs.gno rename to gnovm/tests/files/types2/addr0b_stdlibs.gno diff --git a/gnovm/tests/files/debug/comp3.gno b/gnovm/tests/files/types2/comp3.gno similarity index 100% rename from gnovm/tests/files/debug/comp3.gno rename to gnovm/tests/files/types2/comp3.gno From f94e4fd5d3086197e3bf098640630ebe6945d690 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 22 Dec 2023 18:01:47 +0800 Subject: [PATCH 063/193] add test --- gnovm/pkg/gnolang/preprocess.go | 4 +++- gnovm/tests/files/types2/10a0012_filetest.gno | 9 +++++++++ gnovm/tests/files/types2/10a001_filetest.gno | 9 +++++++++ .../files/types2/10a01_native_filetest.gnoa | 19 ------------------- ...10a11_filetest.gnoa => 10a11_filetest.gno} | 0 gnovm/tests/files/types2/3_c.gno | 10 ++++++++++ 6 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 gnovm/tests/files/types2/10a0012_filetest.gno create mode 100644 gnovm/tests/files/types2/10a001_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a01_native_filetest.gnoa rename gnovm/tests/files/types2/{10a11_filetest.gnoa => 10a11_filetest.gno} (100%) create mode 100644 gnovm/tests/files/types2/3_c.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 6fdf8b9f7f2..04b3ab112e3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2640,7 +2640,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOp(store, last, &bx.Right, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return - case SHL, SHR: + case SHL, SHR: // is this duplicated? debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) // push t into bx.Left if coerce { @@ -2661,6 +2661,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative return case EQL, LSS, GTR, NEQ, LEQ, GEQ: debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) + default: + // } } // general case diff --git a/gnovm/tests/files/types2/10a0012_filetest.gno b/gnovm/tests/files/types2/10a0012_filetest.gno new file mode 100644 index 00000000000..e766e5e218d --- /dev/null +++ b/gnovm/tests/files/types2/10a0012_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := bool(1<<2+1 == 1>>2) + println(r) +} + +// Output: +// false diff --git a/gnovm/tests/files/types2/10a001_filetest.gno b/gnovm/tests/files/types2/10a001_filetest.gno new file mode 100644 index 00000000000..3af624a1d2f --- /dev/null +++ b/gnovm/tests/files/types2/10a001_filetest.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := uint64(1<<2 == 1>>2) + println(r) +} + +// Error: +// main/files/types2/10a001_filetest.gno:4: cannot convert BoolKind to Uint64Kind \ No newline at end of file diff --git a/gnovm/tests/files/types2/10a01_native_filetest.gnoa b/gnovm/tests/files/types2/10a01_native_filetest.gnoa deleted file mode 100644 index 42faa57634d..00000000000 --- a/gnovm/tests/files/types2/10a01_native_filetest.gnoa +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/gnolang/gno/_test/net/http" -) - -func main() { - http.DefaultClient.Timeout = time.Second * 10 - fmt.Println(http.DefaultClient) - http.DefaultClient = &http.Client{} - fmt.Println(http.DefaultClient) -} - -// Output: -// &{ 10s} -// &{ 0s} diff --git a/gnovm/tests/files/types2/10a11_filetest.gnoa b/gnovm/tests/files/types2/10a11_filetest.gno similarity index 100% rename from gnovm/tests/files/types2/10a11_filetest.gnoa rename to gnovm/tests/files/types2/10a11_filetest.gno diff --git a/gnovm/tests/files/types2/3_c.gno b/gnovm/tests/files/types2/3_c.gno new file mode 100644 index 00000000000..0d4a8e4dbe9 --- /dev/null +++ b/gnovm/tests/files/types2/3_c.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(uint64(1) << x) + println(y) +} + +// Output: +// 2048 From 635decdef158852b0635a33f0cc98bd36c1f2902 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 24 Dec 2023 20:30:49 +0800 Subject: [PATCH 064/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 04b3ab112e3..95ec6021349 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1776,7 +1776,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { last.Define(ln, anyValue(rt)) } - checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) + checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 } } } else { // ASSIGN. From 95214af8ecee492f7010ad6b88244ab2d9580f46 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 9 Jan 2024 08:13:25 +0800 Subject: [PATCH 065/193] add new test --- gnovm/tests/files/types2/11.gno | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gnovm/tests/files/types2/11.gno diff --git a/gnovm/tests/files/types2/11.gno b/gnovm/tests/files/types2/11.gno new file mode 100644 index 00000000000..e2b37bc8e75 --- /dev/null +++ b/gnovm/tests/files/types2/11.gno @@ -0,0 +1,14 @@ +package main + +func main() { + x := 1024 + p := 10 + if x != 1<

Date: Thu, 11 Jan 2024 14:29:53 +0800 Subject: [PATCH 066/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 69 +++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 95ec6021349..dc7ac002550 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -23,8 +23,8 @@ func init() { binaryPredicates[MUL] = isNumeric binaryPredicates[QUO] = isNumeric binaryPredicates[REM] = isIntNum - //binaryPredicates[SHL] = isIntOrFloat // NOTE: 1.0 << 1 is legal - //binaryPredicates[SHR] = isIntOrFloat + // binaryPredicates[SHL] = isIntOrFloat // NOTE: 1.0 << 1 is legal + // binaryPredicates[SHR] = isIntOrFloat binaryPredicates[SHL] = isIntNum // NOTE: consistent with op_binary for now binaryPredicates[SHR] = isIntNum @@ -242,7 +242,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if debug { debug.Printf("Preprocess %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } - //debugPP.Printf("Preprocess %s, (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + // debugPP.Printf("Preprocess %s, (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) switch stage { // ---------------------------------------- @@ -1142,27 +1142,56 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // the ATTR_TYPEOF_VALUE is still interface. cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE - case *BinaryExpr, *UnaryExpr: + case *BinaryExpr: debugPP.Printf("---callExpr, arg is binary expr, bx: %v \n", arg0) - - xt := n.GetAttribute(ATTR_TYPEOF_VALUE) - debugPP.Printf("pt: %v \n", xt) - ct := evalStaticType(store, last, n.Func) debugPP.Printf("ct: %v \n", ct) - if ppt, ok := xt.(Type); ok { - if cct, ok := ct.(Type); ok { - if ppt.TypeID() == cct.TypeID() { - debugPP.Printf("---------equal, avoid reentry: %v \n", ct) - //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) - //return n, TRANS_CONTINUE - break - } - } + switch arg0.Op { + case EQL, NEQ, LSS, GTR, LEQ, GEQ: + break // quick forward + default: + checkOrConvertType(store, last, &n.Args[0], ct, false, true) } + + //xt := n.GetAttribute(ATTR_TYPEOF_VALUE) + //debugPP.Printf("pt: %v \n", xt) + // + //ct := evalStaticType(store, last, n.Func) + //debugPP.Printf("ct: %v \n", ct) + // + //if ppt, ok := xt.(Type); ok { + // if cct, ok := ct.(Type); ok { + // if ppt.TypeID() == cct.TypeID() { + // debugPP.Printf("---------equal, avoid reentry: %v \n", ct) + // //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) + // //return n, TRANS_CONTINUE + // break + // } + // } + //} + case *UnaryExpr: + debugPP.Printf("---callExpr, arg is unary expr, bx: %v \n", arg0) + + //xt := n.GetAttribute(ATTR_TYPEOF_VALUE) + //debugPP.Printf("pt: %v \n", xt) + // + ct := evalStaticType(store, last, n.Func) + debugPP.Printf("ct: %v \n", ct) + // + //if ppt, ok := xt.(Type); ok { + // if cct, ok := ct.(Type); ok { + // if ppt.TypeID() == cct.TypeID() { + // debugPP.Printf("---------equal, avoid reentry: %v \n", ct) + // //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) + // //return n, TRANS_CONTINUE + // break + // } + // } + //} checkOrConvertType(store, last, &n.Args[0], ct, false, true) default: + // do nothing } debugPP.Println("else") ct := evalStaticType(store, last, n.Func) @@ -1427,7 +1456,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return cx, TRANS_CONTINUE } checkOp(store, last, nil, xt, n.Op, Unary) - //checkOrConvertType(store, last, &n.X, nil, false) + // checkOrConvertType(store, last, &n.X, nil, false) // TRANS_LEAVE ----------------------- case *CompositeLitExpr: @@ -2612,7 +2641,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkConvertible(xt, t, false) } // "push" expected type into shift unary's operand - //checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) + // checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("else expr, xt not nil,x: %v, xt: %v \n", *x, xt) @@ -2667,7 +2696,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } // general case cx := Expr(Call(constType(nil, t), *x)) - cx.SetAttribute(ATTR_TYPEOF_VALUE, t) // as a flag for processor + // cx.SetAttribute(ATTR_TYPEOF_VALUE, t) // as a flag for processor cx = Preprocess(store, last, cx).(Expr) *x = cx } From 4f370a2bdda2510ea243a9a964bd2a68f7f8580f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Jan 2024 17:08:02 +0800 Subject: [PATCH 067/193] clean --- gnovm/pkg/gnolang/preprocess.go | 54 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index dc7ac002550..cc553a9e10f 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2576,22 +2576,21 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() -// TODO: use opts instead? +// TODO: replace all ConvertConst with this +// TODO: more doc func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) if cx, ok := (*x).(*ConstExpr); ok { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint - // TODO: other bypass situations like cast if !coerce { - if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno - // TODO: make it flag + if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno, TODO: make it !coerced checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } } convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("shift,xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) + debugPP.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) if t == nil { if isUntyped(xt) { t = defaultTypeOf(xt) @@ -2599,11 +2598,11 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative t = xt // xt maybe typed while assign, with t is the type of LHS } } - if coerce { // mostly when explicitly conversion, type call - checkOp(store, last, &bx.Left, t, bx.Op, Binary) + if coerce { // mostly when explicitly conversion, type call, while arg is binary expr + checkOp(store, last, &bx.Left, t, bx.Op, Binary) // left is the target operand // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else if !coerce && isUntyped(xt) { // assign, func call + } else if !coerce && isUntyped(xt) { // assign, func call(param) if _, ok := t.(*InterfaceType); !ok { // TODO: consider this checkOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. @@ -2669,26 +2668,27 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOp(store, last, &bx.Right, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return - case SHL, SHR: // is this duplicated? - debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) - // push t into bx.Left - if coerce { - checkOp(store, last, &bx.Left, t, bx.Op, Binary) - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else if !coerce && isUntyped(xt) { - if _, ok := t.(*InterfaceType); !ok { // concrete type - checkOp(store, last, &bx.Left, t, bx.Op, Binary) - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else { - checkConvertible(xt, t, false) - } - } else { - checkConvertible(xt, t, false) - } - return + //case SHL, SHR: // is this duplicated? + // debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) + // // push t into bx.Left + // if coerce { + // checkOp(store, last, &bx.Left, t, bx.Op, Binary) + // // "push" expected type into shift binary's left operand. + // checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + // } else if !coerce && isUntyped(xt) { + // if _, ok := t.(*InterfaceType); !ok { // concrete type + // checkOp(store, last, &bx.Left, t, bx.Op, Binary) + // // "push" expected type into shift binary's left operand. + // checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + // } else { + // checkConvertible(xt, t, false) + // } + // } else { + // checkConvertible(xt, t, false) + // } + // return case EQL, LSS, GTR, NEQ, LEQ, GEQ: + // nothing to do, quick forward debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) default: // From 54b255d69cf8fb5fbcee66d8eef9abea51a1301b Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Jan 2024 17:52:30 +0800 Subject: [PATCH 068/193] add comments --- gnovm/pkg/gnolang/nodes_string.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 70 ++++------------------------ gnovm/pkg/gnolang/types.go | 8 ++-- gnovm/tests/file_test.go | 4 +- gnovm/tests/files/types2/10a17b2.gno | 18 +++++++ 5 files changed, 35 insertions(+), 67 deletions(-) create mode 100644 gnovm/tests/files/types2/10a17b2.gno diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index 353fd1e5127..c6e47f9dcff 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -13,7 +13,7 @@ var wordTokenStrings = map[Word]string{ SUB: "-", MUL: "*", QUO: "/", - REM: "%%", + REM: "%%", // escape to be rendered correctly BAND: "&", BOR: "|", XOR: "^", diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index cc553a9e10f..94444b9f125 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1146,49 +1146,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Printf("---callExpr, arg is binary expr, bx: %v \n", arg0) ct := evalStaticType(store, last, n.Func) debugPP.Printf("ct: %v \n", ct) - switch arg0.Op { case EQL, NEQ, LSS, GTR, LEQ, GEQ: break // quick forward default: checkOrConvertType(store, last, &n.Args[0], ct, false, true) } - - //xt := n.GetAttribute(ATTR_TYPEOF_VALUE) - //debugPP.Printf("pt: %v \n", xt) - // - //ct := evalStaticType(store, last, n.Func) - //debugPP.Printf("ct: %v \n", ct) - // - //if ppt, ok := xt.(Type); ok { - // if cct, ok := ct.(Type); ok { - // if ppt.TypeID() == cct.TypeID() { - // debugPP.Printf("---------equal, avoid reentry: %v \n", ct) - // //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) - // //return n, TRANS_CONTINUE - // break - // } - // } - //} case *UnaryExpr: debugPP.Printf("---callExpr, arg is unary expr, bx: %v \n", arg0) - - //xt := n.GetAttribute(ATTR_TYPEOF_VALUE) - //debugPP.Printf("pt: %v \n", xt) - // ct := evalStaticType(store, last, n.Func) debugPP.Printf("ct: %v \n", ct) - // - //if ppt, ok := xt.(Type); ok { - // if cct, ok := ct.(Type); ok { - // if ppt.TypeID() == cct.TypeID() { - // debugPP.Printf("---------equal, avoid reentry: %v \n", ct) - // //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) - // //return n, TRANS_CONTINUE - // break - // } - // } - //} checkOrConvertType(store, last, &n.Args[0], ct, false, true) default: // do nothing @@ -2577,7 +2544,7 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() // TODO: replace all ConvertConst with this -// TODO: more doc +// TODO: more docs func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) if cx, ok := (*x).(*ConstExpr); ok { @@ -2598,19 +2565,22 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative t = xt // xt maybe typed while assign, with t is the type of LHS } } + // deal with binary expr(bx.Left), determine its type if coerce { // mostly when explicitly conversion, type call, while arg is binary expr checkOp(store, last, &bx.Left, t, bx.Op, Binary) // left is the target operand // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else if !coerce && isUntyped(xt) { // assign, func call(param) - if _, ok := t.(*InterfaceType); !ok { // TODO: consider this + } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 + // TODO: consider this: one example for interface type, println(x), where target t is interface + // can this special case expanded? + if _, ok := t.(*InterfaceType); !ok { checkOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { - checkConvertible(xt, t, false) + // checkConvertible(xt, t, false) // XXX, seems unreachable } - } else { + } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable checkConvertible(xt, t, false) } @@ -2668,35 +2638,15 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOp(store, last, &bx.Right, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return - //case SHL, SHR: // is this duplicated? - // debugPP.Printf("xt not nil, shift, Op: %v, t: %v, t.kind: %v \n", bx.Op, t, t.Kind()) - // // push t into bx.Left - // if coerce { - // checkOp(store, last, &bx.Left, t, bx.Op, Binary) - // // "push" expected type into shift binary's left operand. - // checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - // } else if !coerce && isUntyped(xt) { - // if _, ok := t.(*InterfaceType); !ok { // concrete type - // checkOp(store, last, &bx.Left, t, bx.Op, Binary) - // // "push" expected type into shift binary's left operand. - // checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - // } else { - // checkConvertible(xt, t, false) - // } - // } else { - // checkConvertible(xt, t, false) - // } - // return case EQL, LSS, GTR, NEQ, LEQ, GEQ: // nothing to do, quick forward debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) default: - // + // do nothing } } // general case cx := Expr(Call(constType(nil, t), *x)) - // cx.SetAttribute(ATTR_TYPEOF_VALUE, t) // as a flag for processor cx = Preprocess(store, last, cx).(Expr) *x = cx } @@ -2888,7 +2838,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -// TODO: name. convertible is for value, not type, should be check assignable? +// TODO: proper name func checkConvertible(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Printf("checkConvertible, xt: %v, dt: %v \n", xt, dt) if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index af774d6a933..4f4270da338 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2423,13 +2423,13 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { } } -// check if xt can be converted to dt, conversionNeeded indicates further conversion needed from unnamed -> named +// check if xt can be assigned to dt, conversionNeeded indicates further conversion needed from unnamed -> named // case 1. untyped const to typed const with same kind // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general convert, for composite types check // XXX. the name of assignable should be considered, or convertable? -// they have same function but implies different application scenarios +// seems they have same function but implies different application scenarios func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Printf("assignable, xt: %v dt: %v \n", xt, dt) // case3 @@ -2438,7 +2438,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { if dt.Kind() == InterfaceKind { debugPP.Println("dt is interface") if idt, ok := baseOf(dt).(*InterfaceType); ok { - if idt.IsEmptyInterface() { + if idt.IsEmptyInterface() { // XXX, can this be merged with IsImplementedBy? debugPP.Println("dt is empty interface") // if dt is an empty Gno interface, any x ok. return // ok @@ -2446,7 +2446,7 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok - } else if iot, ok := xt.(*InterfaceType); ok { // case 0f38_stdlibs_filetest.gno + } else if iot, ok := xt.(*InterfaceType); ok { // XXX. case 0f38_stdlibs_filetest.gno debugPP.Println("xt is empty interface: ", iot) if iot.IsEmptyInterface() { return // ok diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index ff9bb5431bb..49fd4f5efbd 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -53,8 +53,8 @@ func TestTypes2(t *testing.T) { } func TestDebug(t *testing.T) { - baseDir := filepath.Join(".", "files/debug") - runFileTests(t, baseDir, nil) + baseDir := filepath.Join(".", "debug") + runFileTests(t, baseDir, []string{"*_native*"}) } func filterFileTests(t *testing.T, files []fs.DirEntry, ignore []string) []fs.DirEntry { diff --git a/gnovm/tests/files/types2/10a17b2.gno b/gnovm/tests/files/types2/10a17b2.gno new file mode 100644 index 00000000000..cfeb643e291 --- /dev/null +++ b/gnovm/tests/files/types2/10a17b2.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +// it's like assign +func foo(a uint64, b int64) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Output: +// uint64 +// 2048 From 184f526dfdcc1d245b4153bbe15e42b123d19b9f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Jan 2024 18:07:29 +0800 Subject: [PATCH 069/193] add comment --- gnovm/pkg/gnolang/preprocess.go | 2 +- gnovm/pkg/gnolang/types.go | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 94444b9f125..a84ca2064a8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2784,7 +2784,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType } else { // two steps of check: // first, check is the dt type satisfies op, the switch logic - // second, xt can be converted to dt, this is done below this + // second, xt can be converted to dt, this is done after checkOp, in checkOrConvert stage // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 4f4270da338..75328fce339 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2353,13 +2353,17 @@ func assertEqualityTypes(lt, rt Type) { } // maybeIdenticalType is more relaxed than isIdentical, it's used in preprocess. -// The logic here is, when != or == shows up, check if t is maybeIdenticalType, if yes, +// The logic here is, when != or == shows up, check if `dt` is maybeIdenticalType(TODO: a better name +// indicates operand with dt can be used as with == or !=). if this check pass, // then check the corresponding type(the other side of the operator) is convertable to t. +// this is located in checkOrConvertType->checkConvertable stage. +// so, checkOp is working as a pre-check. +// TODO: just panic func maybeIdenticalType(xt, dt Type) (bool, string) { debugPP.Printf("---check maybeIdenticalType---, xt: %v, dt: %v \n", xt, dt) // primitive is maybeIdenticalType switch cdt := baseOf(dt).(type) { - case PrimitiveType: // TODO: more strict when both typed primitive + case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage debugPP.Println("primitive type, return true, fallthrough") return true, "" case *ArrayType: // NOTE: no recursive allowed From 6aa1c046647d7ef36e0c8e3c5051cebe7b3b354c Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Jan 2024 18:13:18 +0800 Subject: [PATCH 070/193] add comments --- gnovm/pkg/gnolang/types.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 75328fce339..0d3ffef27b6 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2244,6 +2244,7 @@ func KindOf(t Type) Kind { // One of them can be nil, and this lets uninitialized primitives // and others serve as empty values. See doOpAdd() // usage: if debug { assertSameTypes() } +// TODO: consider use mayeIdenticalType and isIdentical instead func assertSameTypes(lt, rt Type) { debugPP.Println("assert same types") if lt == nil && rt == nil { @@ -2262,7 +2263,7 @@ func assertSameTypes(lt, rt Type) { } else if lt.TypeID() == rt.TypeID() { // non-nil types are identical. } else { - panic("panic assertSameTypes") + //panic("panic assertSameTypes") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -2271,10 +2272,10 @@ func assertSameTypes(lt, rt Type) { } } +// only used in runtime. this assume all operands are typed after prerocess and doOpConvert +// TODO: consider. is untyped 100% excluded? this is major difference from assertSameTypes // both typed, or one is nil, or data byte(special case) -// only for runtime type checks, op_binary // any implicit identical check is in preprocess stage and excluded from here -// TODO: is untyped 100% excluded? this is major difference from assertSameTypes func isIdenticalType(lt, rt Type) bool { debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID @@ -2298,7 +2299,7 @@ func isIdenticalType(lt, rt Type) bool { // both are nil. } else if lt == nil || rt == nil { // one is nil. see function comment. - //} else if lt.Kind() == rt.Kind() && // TODO: this should not be right. keep untyped, there would be runtime untyped, e.g. `hello`[1:0] will create a runtime untype string, and + //} else if lt.Kind() == rt.Kind() && // isUntyped(lt) || isUntyped(rt) { // // one is untyped of same kind. } else if lt.Kind() == rt.Kind() && From 46ced4730080486505d58d114e415909898d2232 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Jan 2024 21:42:51 +0800 Subject: [PATCH 071/193] add test --- gnovm/pkg/gnolang/preprocess.go | 7 +++--- gnovm/pkg/gnolang/types.go | 2 +- gnovm/tests/files/types2/0_a_2.gno | 40 ++++++++++++++++++++++++++++++ gnovm/tests/files/types2/0_a_3.gno | 40 ++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 gnovm/tests/files/types2/0_a_2.gno create mode 100644 gnovm/tests/files/types2/0_a_3.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a84ca2064a8..765adad5ae5 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2571,14 +2571,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 - // TODO: consider this: one example for interface type, println(x), where target t is interface - // can this special case expanded? - if _, ok := t.(*InterfaceType); !ok { + // dt not interface type + if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil checkOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { - // checkConvertible(xt, t, false) // XXX, seems unreachable + checkConvertible(xt, t, false) // XXX, left is interface, refer to 0_a_2.gno, 0_a_3.gno } } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable checkConvertible(xt, t, false) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 0d3ffef27b6..e9afc9d952d 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2263,7 +2263,7 @@ func assertSameTypes(lt, rt Type) { } else if lt.TypeID() == rt.TypeID() { // non-nil types are identical. } else { - //panic("panic assertSameTypes") + // panic("panic assertSameTypes") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), diff --git a/gnovm/tests/files/types2/0_a_2.gno b/gnovm/tests/files/types2/0_a_2.gno new file mode 100644 index 00000000000..49460665277 --- /dev/null +++ b/gnovm/tests/files/types2/0_a_2.gno @@ -0,0 +1,40 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +// case of expr in type call +func main() { + x := 2 + var r U64 + r = U64(1< Date: Thu, 11 Jan 2024 22:52:45 +0800 Subject: [PATCH 072/193] add test --- gnovm/pkg/gnolang/preprocess.go | 4 +-- gnovm/tests/files/types2/0_a_3a.gno | 40 +++++++++++++++++++++++++++++ gnovm/tests/files/types2/0_a_3b.gno | 39 ++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 gnovm/tests/files/types2/0_a_3a.gno create mode 100644 gnovm/tests/files/types2/0_a_3b.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 765adad5ae5..0c6e8278fe8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2577,10 +2577,10 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { - checkConvertible(xt, t, false) // XXX, left is interface, refer to 0_a_2.gno, 0_a_3.gno + checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno } } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable - checkConvertible(xt, t, false) + checkConvertible(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno } } else if ux, ok := (*x).(*UnaryExpr); ok { diff --git a/gnovm/tests/files/types2/0_a_3a.gno b/gnovm/tests/files/types2/0_a_3a.gno new file mode 100644 index 00000000000..d083b4c6ca0 --- /dev/null +++ b/gnovm/tests/files/types2/0_a_3a.gno @@ -0,0 +1,40 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +// case of expr in type call +func main() { + x := 2 + var r U64 + // assign to type conform and interface + r = 1 << x // 2 step. first binary, second call type + + r.foo() + + fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type +} + +// Output: +// bar +// uint64 diff --git a/gnovm/tests/files/types2/0_a_3b.gno b/gnovm/tests/files/types2/0_a_3b.gno new file mode 100644 index 00000000000..a497d2a17b9 --- /dev/null +++ b/gnovm/tests/files/types2/0_a_3b.gno @@ -0,0 +1,39 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +// case of expr in type call +func main() { + x := 2 + var r R + // assign to interface + r = 1 << x // 2 step. first binary, second call type + + r.foo() + + fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type +} + +// Error: +// main/files/types2/0_a_3b.gno:31: operator << not defined on: main.R From 9e47ced574cbf9041877e737d9e66aedcfc964a5 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Jan 2024 23:07:37 +0800 Subject: [PATCH 073/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0c6e8278fe8..0a82dfdcf37 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2577,7 +2577,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { - checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno + // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOp + // checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno } } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable checkConvertible(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno From 937a725a480a9648270e774ff6b3fd23b5e9c2a2 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sat, 13 Jan 2024 00:08:45 +0800 Subject: [PATCH 074/193] update --- gnovm/pkg/gnolang/gonative.go | 4 +- gnovm/pkg/gnolang/preprocess.go | 142 +++++++----------- gnovm/pkg/gnolang/types.go | 29 ++-- gnovm/tests/files/types/0f2_native.gno | 28 ++++ .../{0f2b_filetest.gno => 0f2b_native.gno} | 2 +- gnovm/tests/files/types/0f2b_stdlibs.gno | 28 ++++ .../{0f2c_filetest.gno => 0f2c_native.gno} | 2 +- gnovm/tests/files/types/0f2c_stdlibs.gno | 28 ++++ gnovm/tests/files/types/0f2d_filetest.gno | 32 ++++ 9 files changed, 194 insertions(+), 101 deletions(-) create mode 100644 gnovm/tests/files/types/0f2_native.gno rename gnovm/tests/files/types/{0f2b_filetest.gno => 0f2b_native.gno} (80%) create mode 100644 gnovm/tests/files/types/0f2b_stdlibs.gno rename gnovm/tests/files/types/{0f2c_filetest.gno => 0f2c_native.gno} (81%) create mode 100644 gnovm/tests/files/types/0f2c_stdlibs.gno create mode 100644 gnovm/tests/files/types/0f2d_filetest.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 3cefc32ea18..5ab2014ddb2 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -364,8 +364,8 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { return } if rv.Kind() == reflect.Interface { - if rv.IsNil() { // special case, nil interface, interface(nil) differs nil in types, but equal - return TypedValue{ + if rv.IsNil() { + return TypedValue{ // should not have untyped nil T: &InterfaceType{}, } } else { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0a82dfdcf37..88941520cc6 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -8,69 +8,51 @@ import ( "github.com/gnolang/gno/tm2/pkg/errors" ) -type f func(t Type) bool - var ( - binaryPredicates = make(map[Word]f) - unaryPredicates = make(map[Word]f) - IncDecStmtPredicates = make(map[Word]f) - AssignStmtPredicates = make(map[Word]f) + binaryPredicates = map[Word]func(t Type) bool{ + ADD: isNumericOrString, + SUB: isNumeric, + MUL: isNumeric, + QUO: isNumeric, + REM: isIntNum, + SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. + SHR: isIntNum, + BAND: isIntNum, // bit ops + XOR: isIntNum, + BOR: isIntNum, + BAND_NOT: isIntNum, + LAND: isBoolean, // logic + LOR: isBoolean, + LSS: isOrdered, // compare + LEQ: isOrdered, + GTR: isOrdered, + GEQ: isOrdered, + } + unaryPredicates = map[Word]func(t Type) bool{ + ADD: isNumeric, + SUB: isNumeric, + XOR: isIntNum, + NOT: isBoolean, + } + IncDecStmtPredicates = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). + INC: isNumeric, + DEC: isNumeric, + } + AssignStmtPredicates = map[Word]func(t Type) bool{ + ADD_ASSIGN: isNumericOrString, + SUB_ASSIGN: isNumeric, + MUL_ASSIGN: isNumeric, + QUO_ASSIGN: isNumeric, + REM_ASSIGN: isIntNum, + SHL_ASSIGN: isNumeric, + SHR_ASSIGN: isNumeric, + BAND_ASSIGN: isIntNum, + XOR_ASSIGN: isIntNum, + BOR_ASSIGN: isIntNum, + BAND_NOT_ASSIGN: isIntNum, + } ) -func init() { - binaryPredicates[ADD] = isNumericOrString - binaryPredicates[SUB] = isNumeric - binaryPredicates[MUL] = isNumeric - binaryPredicates[QUO] = isNumeric - binaryPredicates[REM] = isIntNum - // binaryPredicates[SHL] = isIntOrFloat // NOTE: 1.0 << 1 is legal - // binaryPredicates[SHR] = isIntOrFloat - - binaryPredicates[SHL] = isIntNum // NOTE: consistent with op_binary for now - binaryPredicates[SHR] = isIntNum - - // bit op - binaryPredicates[BAND] = isIntNum - binaryPredicates[XOR] = isIntNum - binaryPredicates[BOR] = isIntNum - binaryPredicates[BAND_NOT] = isIntNum - // logic op - binaryPredicates[LAND] = isBoolean - binaryPredicates[LOR] = isBoolean - - // compare - binaryPredicates[LSS] = isOrdered - binaryPredicates[LEQ] = isOrdered - binaryPredicates[GTR] = isOrdered - binaryPredicates[GEQ] = isOrdered - - // unary - unaryPredicates[ADD] = isNumeric - unaryPredicates[SUB] = isNumeric - unaryPredicates[XOR] = isIntNum - unaryPredicates[NOT] = isBoolean - - // Inc Dec stmt - // NOTE: special case to be consistent with op_inc_dec.go, line3, no float support for now(while go does). - IncDecStmtPredicates[INC] = isNumeric - IncDecStmtPredicates[DEC] = isNumeric - - // assign stmt - AssignStmtPredicates[ADD_ASSIGN] = isNumericOrString - AssignStmtPredicates[SUB_ASSIGN] = isNumeric - AssignStmtPredicates[MUL_ASSIGN] = isNumeric - AssignStmtPredicates[QUO_ASSIGN] = isNumeric - AssignStmtPredicates[REM_ASSIGN] = isIntNum - AssignStmtPredicates[SHL_ASSIGN] = isNumeric - AssignStmtPredicates[SHR_ASSIGN] = isNumeric - AssignStmtPredicates[BAND_ASSIGN] = isIntNum - AssignStmtPredicates[XOR_ASSIGN] = isIntNum - AssignStmtPredicates[BOR_ASSIGN] = isIntNum - AssignStmtPredicates[BAND_NOT_ASSIGN] = isIntNum -} - -// ------------------------------------------------------------------------------------------- - // In the case of a *FileSet, some declaration steps have to happen // in a restricted parallel way across all the files. // Anything predefined or preprocessed here get skipped during the Preprocess @@ -1831,6 +1813,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + // if lt is interface, nothing will happen checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) } } @@ -2680,6 +2663,7 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { return } } + debugPP.Println(("set interface to nil, nothing else happens")) t = nil } if isUntyped(cx.T) { @@ -2725,13 +2709,20 @@ const ( Assign ) -// check operand types with operators +// checkOp works as a pre-check prior to checkOrConvertType() +// It checks expressions to ensure the compatibility between operands and operators. +// e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. +// Overall,it efficiently filters out incompatible expressions, stopping before the next +// checkOrConvertType() operation to optimize performance. + +// there are two steps of check: +// first, check is the dt type satisfies op; +// second, check if xt can be converted to dt, this is done after checkOp, in checkOrConvertType(), func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { debugPP.Printf("checkOp, dt: %v, op: %v, nt: %v \n", dt, op, nt) if nt == Unary || nt == IncDec { switch nt { case Unary: - // unary if pred, ok := unaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2758,21 +2749,13 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType if isComparison(op) { switch op { case EQL, NEQ: // check maybeIdenticalType - // check typed primitives - //if !isUntyped(xt) && !isUntyped(dt) { - // if xt != nil && dt != nil { - // if xt.TypeID() != dt.TypeID() { - // panic(fmt.Sprintf("incompatible type of, xt: %v, dt: %v \n", xt, dt)) - // } - // } - //} - // NOTE: not checking types strict identical here, unlike ADD, etc - // this will pass the case one is interface and the other implements this interface + // NOTE: not checking types strict identical here, unlike ADD, etc. + // this will pass the case of lhs is interface and rhs implements this interface, vice versa. // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertible -> assignable if ok, code := maybeIdenticalType(xt, dt); !ok { panic(code) } - case LSS, LEQ, GTR, GEQ: // check if is ordered, primitive && numericOrString + case LSS, LEQ, GTR, GEQ: if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2782,10 +2765,6 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType panic("invalid comparison operator") } } else { - // two steps of check: - // first, check is the dt type satisfies op, the switch logic - // second, xt can be converted to dt, this is done after checkOp, in checkOrConvert stage - // NOTE: dt has a higher precedence, which means it would be the type of xt after conversion, that used for evaluation, so only check dt if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) @@ -2802,11 +2781,8 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType } debugPP.Println("typed and identical as maybeIdenticalType") } - case SHL, SHR: - // TODO: check float like 1.0 would work, 1.2 won't - // Currently, the check is relaxed(with runtime strict, to be consistent) default: - // Note: others no check, assign will be check in assignable + // do nothing } } case Assign: @@ -2826,7 +2802,7 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType debugPP.Println("typed and identical as maybeIdenticalType") } default: - // Note: others no check, assign will be check in assignable + // do nothing } } default: @@ -2838,11 +2814,9 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -// TODO: proper name func checkConvertible(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Printf("checkConvertible, xt: %v, dt: %v \n", xt, dt) if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno - debugPP.Println("checkConvertible, xt or dt is nil") return } return assignable(xt, dt, autoNative) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index e9afc9d952d..6c70ac50f06 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -260,22 +260,19 @@ func (pt PrimitiveType) TypeID() TypeID { type category int const ( - IsInvalid = 0 + IsInvalid category = 0 IsBoolean category = 1 << iota IsInteger IsUnsigned IsFloat - IsComplex // no use for now IsString - IsUntyped IsBigInt IsBigDec IsRune - IsOrdered = IsInteger | IsFloat | IsString | IsBigInt | IsBigDec | IsUnsigned - IsNumeric = IsInteger | IsUnsigned | IsFloat | IsComplex | IsBigInt | IsBigDec + IsNumeric = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec + IsOrdered = IsNumeric | IsString IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec - // IsConstType = IsBoolean | IsNumeric | IsString ) // category makes it more convenient than compare with types @@ -2272,15 +2269,21 @@ func assertSameTypes(lt, rt Type) { } } -// only used in runtime. this assume all operands are typed after prerocess and doOpConvert -// TODO: consider. is untyped 100% excluded? this is major difference from assertSameTypes -// both typed, or one is nil, or data byte(special case) -// any implicit identical check is in preprocess stage and excluded from here +// Only used in runtime. this implies all operands are typed after preprocess and doOpConvert. +// This check has narrow conditions compared to assertEqualityTypes(), it's used to replace assertEqualityTypes() + +// the key difference with assertEqualityTypes() is that here excludes untyped == typed(we assume +// all types are typed), and Foo_interface == Foo_xxx case(refer to 0f_2d), since in preprocess stage, +// if Foo_xxx does not satisfy Foo_interface, the checkConvertible() will fail, otherwise, Foo_xxx will +// still remain its type since target type in interface, this logic is located in convertConst(). + +// Cases checked here consists: +// both typed, or one/both is nil, or data byte(special case) TODO: link test case func isIdenticalType(lt, rt Type) bool { debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID if lpt, ok := lt.(*PointerType); ok { - if isDataByte(lpt.Elt) { + if isDataByte(lpt.Elt) { // refer to 0f31 debugPP.Println("lt is pointer type and base type is data byte") return true } @@ -2311,7 +2314,7 @@ func isIdenticalType(lt, rt Type) bool { } else if lt.TypeID() == rt.TypeID() { debugPP.Println("typeID equal") // non-nil types are identical. - } else if ilt, ok := baseOf(lt).(*InterfaceType); ok { + } else if ilt, ok := baseOf(lt).(*InterfaceType); ok { // refer to 0f48 if ilt.IsEmptyInterface() { return true } @@ -2432,7 +2435,7 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { // case 1. untyped const to typed const with same kind // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt -// case 4. general convert, for composite types check +// case 4. general cases. // XXX. the name of assignable should be considered, or convertable? // seems they have same function but implies different application scenarios func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { diff --git a/gnovm/tests/files/types/0f2_native.gno b/gnovm/tests/files/types/0f2_native.gno new file mode 100644 index 00000000000..7ded58b4ff0 --- /dev/null +++ b/gnovm/tests/files/types/0f2_native.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/0f2b_filetest.gno b/gnovm/tests/files/types/0f2b_native.gno similarity index 80% rename from gnovm/tests/files/types/0f2b_filetest.gno rename to gnovm/tests/files/types/0f2b_native.gno index 5e548ab0d65..1f66c6cb5fa 100644 --- a/gnovm/tests/files/types/0f2b_filetest.gno +++ b/gnovm/tests/files/types/0f2b_native.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f2b_filetest.gno:19: operator <= not defined on: .uverse.error +// main/files/types/0f2b_native.gno:19: operator <= not defined on: gonative{error} diff --git a/gnovm/tests/files/types/0f2b_stdlibs.gno b/gnovm/tests/files/types/0f2b_stdlibs.gno new file mode 100644 index 00000000000..9eb42188153 --- /dev/null +++ b/gnovm/tests/files/types/0f2b_stdlibs.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) <= errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f2b_stdlibs.gno:19: operator <= not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f2c_filetest.gno b/gnovm/tests/files/types/0f2c_native.gno similarity index 81% rename from gnovm/tests/files/types/0f2c_filetest.gno rename to gnovm/tests/files/types/0f2c_native.gno index 2b7ef210041..9bef65aeeb2 100644 --- a/gnovm/tests/files/types/0f2c_filetest.gno +++ b/gnovm/tests/files/types/0f2c_native.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f2c_filetest.gno:19: operator < not defined on: .uverse.error +// main/files/types/0f2c_native.gno:19: operator < not defined on: gonative{error} diff --git a/gnovm/tests/files/types/0f2c_stdlibs.gno b/gnovm/tests/files/types/0f2c_stdlibs.gno new file mode 100644 index 00000000000..10ea7379fa9 --- /dev/null +++ b/gnovm/tests/files/types/0f2c_stdlibs.gno @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) < errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/0f2c_stdlibs.gno:19: operator < not defined on: .uverse.error diff --git a/gnovm/tests/files/types/0f2d_filetest.gno b/gnovm/tests/files/types/0f2d_filetest.gno new file mode 100644 index 00000000000..fca12f7f938 --- /dev/null +++ b/gnovm/tests/files/types/0f2d_filetest.gno @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "strconv" +) + +type E interface { + Error() string +} +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// specil case: +// one is interface +func main() { + var e0 E + e0 = Error(0) + fmt.Printf("%T \n", e0) + if e0 == Error(0) { // this would not convert, errCmp is interface, refer to preprocess, line2526 + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// int64 +// what the firetruck? From 57bd72445a70f405d3dba5eb6a6fb3c1caa5da78 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sat, 13 Jan 2024 09:41:23 +0800 Subject: [PATCH 075/193] update --- gnovm/pkg/gnolang/preprocess.go | 20 ++---- gnovm/pkg/gnolang/values.go | 113 +++++++++++--------------------- 2 files changed, 43 insertions(+), 90 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 88941520cc6..e4c879d8092 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1124,12 +1124,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // the ATTR_TYPEOF_VALUE is still interface. cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE - case *BinaryExpr: + case *BinaryExpr: // when arg is untyped expression and contains SHL/SHR expression, call type convert explicitly to give it type debugPP.Printf("---callExpr, arg is binary expr, bx: %v \n", arg0) ct := evalStaticType(store, last, n.Func) debugPP.Printf("ct: %v \n", ct) switch arg0.Op { - case EQL, NEQ, LSS, GTR, LEQ, GEQ: + case EQL, NEQ, LSS, GTR, LEQ, GEQ: // refer to 10a0012 break // quick forward default: checkOrConvertType(store, last, &n.Args[0], ct, false, true) @@ -1142,7 +1142,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { default: // do nothing } - debugPP.Println("else") + debugPP.Println("general case") ct := evalStaticType(store, last, n.Func) debugPP.Printf("ct: %v \n", ct) n.SetAttribute(ATTR_TYPEOF_VALUE, ct) @@ -1228,7 +1228,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if !hasVarg { - debugPP.Println("no varg") argTVs = evalStaticTypedValues(store, last, n.Args...) if len(n.Args) != len(ft.Params) { panic(fmt.Sprintf( @@ -1296,7 +1295,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { - debugPP.Println("no embeded") for i := range n.Args { // iterate args if hasVarg { if (len(spts) - 1) <= i { @@ -1304,21 +1302,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if len(spts) <= i { panic("expected final vargs slice but got many") } - debugPP.Println("1") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true, false) } else { - debugPP.Println("2") - at := evalStaticTypeOf(store, last, n.Args[i]) - debugPP.Printf("at: %v \n", at) checkOrConvertType(store, last, &n.Args[i], spts[len(spts)-1].Type.Elem(), true, false) } } else { - debugPP.Println("3") checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true, false) } } else { - debugPP.Println("4") // TODO: check if type bx checkOrConvertType(store, last, &n.Args[i], spts[i].Type, true, false) } @@ -1754,6 +1746,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { last.Define(ln, anyValue(rt)) } + // in define, when RHS is untyped and contains SHR/SHL expression, explicitly + // call this, to give the SHR/SHL a type checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 } } @@ -1796,8 +1790,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } // Special case if shift assign <<= or >>=. - // TODO: no need here, like index convert - // checkOrConvertType(store, last, &n.Rhs[0], UintType, false) convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check lt := evalStaticTypeOf(store, last, n.Lhs[0]) checkOp(store, last, &n.Lhs[0], lt, n.Op, Assign) @@ -2686,7 +2678,7 @@ func isQuoOrRem(op Word) bool { } func checkOperand(cx *ConstExpr) { - if cx.TypedValue.Sign() == 0 { + if cx.TypedValue.isZero() { panic("invalid operation: division by zero") } } diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 65b20dd8304..7b9884a970d 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -1454,129 +1454,86 @@ func (tv *TypedValue) GetBigDec() *apd.Decimal { return tv.V.(BigdecValue).V } -// Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0; -func (tv *TypedValue) Sign() int { +// returns true if tv is zero +func (tv *TypedValue) isZero() bool { if tv.T == nil { panic("type should not be nil") } switch tv.T.Kind() { case IntKind: v := tv.GetInt() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Int8Kind: v := tv.GetInt8() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Int16Kind: v := tv.GetInt16() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Int32Kind: v := tv.GetInt32() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Int64Kind: v := tv.GetInt64() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case UintKind: v := tv.GetUint() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Uint8Kind: v := tv.GetUint8() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Uint16Kind: v := tv.GetUint16() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Uint32Kind: v := tv.GetUint32() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Uint64Kind: v := tv.GetUint64() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Float32Kind: v := tv.GetFloat32() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case Float64Kind: v := tv.GetFloat64() - if v < 0 { - return -1 - } else if v == 0 { - return 0 - } else { - return 1 + if v == 0 { + return true } case BigintKind: v := tv.GetBigInt() - return v.Sign() + if v.Sign() == 0 { + return true + } case BigdecKind: v := tv.GetBigDec() - return v.Sign() + if v.Sign() == 0 { + return true + } default: panic("not numeric") } + return false } func (tv *TypedValue) ComputeMapKey(store Store, omitType bool) MapKey { @@ -2419,6 +2376,8 @@ func (b *Block) GetParent(store Store) *Block { } func (b *Block) GetPointerToInt(store Store, index int) PointerValue { + debugPP.Printf("---GetPointerToInt, path: %v \n", index) + debugPP.Printf("---GetPointerToInt, b: %v \n", b) vv := fillValueTV(store, &b.Values[index]) return PointerValue{ TV: vv, @@ -2428,6 +2387,8 @@ func (b *Block) GetPointerToInt(store Store, index int) PointerValue { } func (b *Block) GetPointerTo(store Store, path ValuePath) PointerValue { + debugPP.Printf("---GetPointerTo, path: %v \n", path) + debugPP.Printf("---GetPointerTo, b: %v \n", b) if path.IsBlockBlankPath() { if debug { if path.Name != "_" { From e9a3a0aea4d8cdeadc30985c3cae35d938a2d2d2 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sat, 13 Jan 2024 10:46:32 +0800 Subject: [PATCH 076/193] fixup --- gnovm/pkg/gnolang/op_assign.go | 18 ++++++++--------- gnovm/pkg/gnolang/op_binary.go | 34 ++++++++++++++++----------------- gnovm/pkg/gnolang/preprocess.go | 1 - gnovm/pkg/gnolang/types.go | 32 +++++++++++++++++++++++-------- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index 8d15669f7de..90661fdf941 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -52,7 +52,7 @@ func (m *Machine) doOpAddAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -77,7 +77,7 @@ func (m *Machine) doOpSubAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -101,7 +101,7 @@ func (m *Machine) doOpMulAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -125,7 +125,7 @@ func (m *Machine) doOpQuoAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -149,7 +149,7 @@ func (m *Machine) doOpRemAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -173,7 +173,7 @@ func (m *Machine) doOpBandAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -197,7 +197,7 @@ func (m *Machine) doOpBandnAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -221,7 +221,7 @@ func (m *Machine) doOpBorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -245,7 +245,7 @@ func (m *Machine) doOpXorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isIdenticalType(lv.TV.T, rv.T) { + if !isSameType(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 15d9b39db75..8aef5626e4d 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -52,7 +52,7 @@ func (m *Machine) doOpLor() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -68,7 +68,7 @@ func (m *Machine) doOpLand() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -92,7 +92,7 @@ func (m *Machine) doOpEql() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isIdenticalType(lv.T, rv.T) { + if isEqualityType(lv.T, rv.T) { res = isEql(m.Store, lv, rv) } else { debugPP.Println("-----type not identical------") @@ -117,7 +117,7 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isIdenticalType(lv.T, rv.T) { + if isEqualityType(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { debugPP.Println("-----type not identical------") @@ -136,7 +136,7 @@ func (m *Machine) doOpLss() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -154,7 +154,7 @@ func (m *Machine) doOpLeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -172,7 +172,7 @@ func (m *Machine) doOpGtr() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -190,7 +190,7 @@ func (m *Machine) doOpGeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -208,7 +208,7 @@ func (m *Machine) doOpAdd() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -223,7 +223,7 @@ func (m *Machine) doOpSub() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -238,7 +238,7 @@ func (m *Machine) doOpBor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -253,7 +253,7 @@ func (m *Machine) doOpXor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -268,7 +268,7 @@ func (m *Machine) doOpMul() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -284,7 +284,7 @@ func (m *Machine) doOpQuo() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -300,7 +300,7 @@ func (m *Machine) doOpRem() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -348,7 +348,7 @@ func (m *Machine) doOpBand() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -364,7 +364,7 @@ func (m *Machine) doOpBandn() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isIdenticalType(lv.T, rv.T) { + if !isSameType(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e4c879d8092..83182601044 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2349,7 +2349,6 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { - debugPP.Printf("evalConst, last: %v, x: %v \n", last, x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 6c70ac50f06..fdcecc7bc87 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2279,9 +2279,10 @@ func assertSameTypes(lt, rt Type) { // Cases checked here consists: // both typed, or one/both is nil, or data byte(special case) TODO: link test case -func isIdenticalType(lt, rt Type) bool { +func isEqualityType(lt, rt Type) bool { debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID + // XXX consider, is it the only case of runtime untyped? if lpt, ok := lt.(*PointerType); ok { if isDataByte(lpt.Elt) { // refer to 0f31 debugPP.Println("lt is pointer type and base type is data byte") @@ -2294,20 +2295,14 @@ func isIdenticalType(lt, rt Type) bool { return true } } - if isDataByte(lt) || isDataByte(rt) { - return true - } // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { // both are nil. } else if lt == nil || rt == nil { // one is nil. see function comment. - //} else if lt.Kind() == rt.Kind() && - // isUntyped(lt) || isUntyped(rt) { - // // one is untyped of same kind. } else if lt.Kind() == rt.Kind() && isDataByte(lt) { - // left is databyteinvalide operation of same kind, + // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? @@ -2328,6 +2323,27 @@ func isIdenticalType(lt, rt Type) bool { return true } +// similar with isEqualityType +func isSameType(lt, rt Type) bool { + debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + if lt == nil && rt == nil { + // both are nil. + } else if lt == nil || rt == nil { + // one is nil. see function comment. + } else if lt.Kind() == rt.Kind() && + isDataByte(lt) { + // left is databyte of same kind, + // specifically for assignments. + // TODO: make another function + // and remove this case? + } else if lt.TypeID() == rt.TypeID() { + debugPP.Println("typeID equal") + } else { + return false + } + return true +} + // Like assertSameTypes(), but more relaxed, for == and !=. func assertEqualityTypes(lt, rt Type) { if lt == nil && rt == nil { From ef2110309adff2d0372219b519f7bdf5971e3f5d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sat, 13 Jan 2024 20:14:02 +0800 Subject: [PATCH 077/193] fixup --- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/op_assign.go | 18 +++++----- gnovm/pkg/gnolang/op_binary.go | 36 ++++++++++--------- gnovm/pkg/gnolang/types.go | 64 ++++++++++++++++++---------------- 4 files changed, 62 insertions(+), 58 deletions(-) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 5ab2014ddb2..185856c8a54 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -359,7 +359,7 @@ func Gno2GoValue(tv *TypedValue, rv reflect.Value) (ret reflect.Value) { // ConvertTo(). // Unlike go2GnoValue2(), rv may be invalid. func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { - debugPP.Printf("go2GnoValue---, rv: %v \n", rv) + debugPP.Printf("go2GnoValue---, rv: %v \n", rv.Kind()) if !rv.IsValid() { return } diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index 90661fdf941..f227ecc681b 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -52,7 +52,7 @@ func (m *Machine) doOpAddAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -77,7 +77,7 @@ func (m *Machine) doOpSubAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -101,7 +101,7 @@ func (m *Machine) doOpMulAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -125,7 +125,7 @@ func (m *Machine) doOpQuoAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -149,7 +149,7 @@ func (m *Machine) doOpRemAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -173,7 +173,7 @@ func (m *Machine) doOpBandAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -197,7 +197,7 @@ func (m *Machine) doOpBandnAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -221,7 +221,7 @@ func (m *Machine) doOpBorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } @@ -245,7 +245,7 @@ func (m *Machine) doOpXorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameType(lv.TV.T, rv.T) { + if !isSameTypes(lv.TV.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) } } diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 8aef5626e4d..780a316285e 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -52,7 +52,7 @@ func (m *Machine) doOpLor() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -68,7 +68,7 @@ func (m *Machine) doOpLand() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -92,7 +92,8 @@ func (m *Machine) doOpEql() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isEqualityType(lv.T, rv.T) { + if isEqualityTypes(lv.T, rv.T) { + debugPP.Println("-----type identical------") res = isEql(m.Store, lv, rv) } else { debugPP.Println("-----type not identical------") @@ -117,7 +118,7 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isEqualityType(lv.T, rv.T) { + if isEqualityTypes(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { debugPP.Println("-----type not identical------") @@ -136,7 +137,7 @@ func (m *Machine) doOpLss() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -154,7 +155,7 @@ func (m *Machine) doOpLeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -172,7 +173,7 @@ func (m *Machine) doOpGtr() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -190,7 +191,7 @@ func (m *Machine) doOpGeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -208,7 +209,7 @@ func (m *Machine) doOpAdd() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -223,7 +224,7 @@ func (m *Machine) doOpSub() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -238,7 +239,7 @@ func (m *Machine) doOpBor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -253,7 +254,7 @@ func (m *Machine) doOpXor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -268,7 +269,7 @@ func (m *Machine) doOpMul() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -284,7 +285,7 @@ func (m *Machine) doOpQuo() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -300,7 +301,7 @@ func (m *Machine) doOpRem() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -348,7 +349,7 @@ func (m *Machine) doOpBand() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -364,7 +365,7 @@ func (m *Machine) doOpBandn() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameType(lv.T, rv.T) { + if !isSameTypes(lv.T, rv.T) { panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) } } @@ -1127,6 +1128,7 @@ func xorAssign(lv, rv *TypedValue) { // for doOpShl and doOpShlAssign. func shlAssign(lv, rv *TypedValue) { + debugPP.Println("---shl Assign") // set the result in lv. // NOTE: baseOf(rv.T) is always UintType. switch baseOf(lv.T) { diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index fdcecc7bc87..1608c395e1d 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2241,7 +2241,6 @@ func KindOf(t Type) Kind { // One of them can be nil, and this lets uninitialized primitives // and others serve as empty values. See doOpAdd() // usage: if debug { assertSameTypes() } -// TODO: consider use mayeIdenticalType and isIdentical instead func assertSameTypes(lt, rt Type) { debugPP.Println("assert same types") if lt == nil && rt == nil { @@ -2269,20 +2268,10 @@ func assertSameTypes(lt, rt Type) { } } -// Only used in runtime. this implies all operands are typed after preprocess and doOpConvert. -// This check has narrow conditions compared to assertEqualityTypes(), it's used to replace assertEqualityTypes() - -// the key difference with assertEqualityTypes() is that here excludes untyped == typed(we assume -// all types are typed), and Foo_interface == Foo_xxx case(refer to 0f_2d), since in preprocess stage, -// if Foo_xxx does not satisfy Foo_interface, the checkConvertible() will fail, otherwise, Foo_xxx will -// still remain its type since target type in interface, this logic is located in convertConst(). - -// Cases checked here consists: -// both typed, or one/both is nil, or data byte(special case) TODO: link test case -func isEqualityType(lt, rt Type) bool { +func isEqualityTypes(lt, rt Type) bool { debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) // refer to std3.gno, untyped byte has no typeID - // XXX consider, is it the only case of runtime untyped? + // quich pick if lpt, ok := lt.(*PointerType); ok { if isDataByte(lpt.Elt) { // refer to 0f31 debugPP.Println("lt is pointer type and base type is data byte") @@ -2297,51 +2286,64 @@ func isEqualityType(lt, rt Type) bool { } // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { + return true // both are nil. } else if lt == nil || rt == nil { // one is nil. see function comment. + return true } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + return true + } else if lt.Kind() == rt.Kind() && + isDataByte(lt) { // XXX, what hit this // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? - } else if lt.TypeID() == rt.TypeID() { + return true + } else if lt.TypeID() == rt.TypeID() { // order matters debugPP.Println("typeID equal") // non-nil types are identical. - } else if ilt, ok := baseOf(lt).(*InterfaceType); ok { // refer to 0f48 - if ilt.IsEmptyInterface() { - return true - } - } else if irt, ok := baseOf(rt).(*InterfaceType); ok { - if irt.IsEmptyInterface() { - return true - } - } else { - return false + return true + } else if lt.Kind() == InterfaceKind && + IsImplementedBy(lt, rt) { + // one is untyped of same kind. + // rt implements lt (and lt is nil interface). + return true + } else if rt.Kind() == InterfaceKind && + IsImplementedBy(rt, lt) { + // lt implements rt (and rt is nil interface). + return true } - return true + return false } -// similar with isEqualityType -func isSameType(lt, rt Type) bool { +// similar with isEqualityTypes +func isSameTypes(lt, rt Type) bool { debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) if lt == nil && rt == nil { // both are nil. + return true } else if lt == nil || rt == nil { // one is nil. see function comment. + return true + } else if lt.Kind() == rt.Kind() && + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + return true } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? + return true } else if lt.TypeID() == rt.TypeID() { debugPP.Println("typeID equal") - } else { - return false + return true } - return true + return false } // Like assertSameTypes(), but more relaxed, for == and !=. From 37f00df14e419f59bd9dcc6a31cdb8303320100e Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sat, 13 Jan 2024 23:55:00 +0800 Subject: [PATCH 078/193] improve name --- gnovm/pkg/gnolang/preprocess.go | 127 +++++++++++++++----------------- gnovm/pkg/gnolang/types.go | 51 ++++++------- 2 files changed, 83 insertions(+), 95 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 83182601044..b8785037899 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -782,7 +782,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BasicLitExpr: - debugPP.Println("basicLitExpr---") + debugPP.Printf("basicLitExpr---, %v \n", n) // Replace with *ConstExpr. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE @@ -798,7 +798,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // special case of shift if isShift { if baseOf(rt) != UintType { - // checkOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* + // checkOperandWithOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* // convert n.Right to (gno) uint type, rn := Expr(Call("uint", n.Right)) // reset/create n2 to preprocess right child. @@ -827,38 +827,35 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cmp < 0 { debugPP.Println("cmp < 0, ->") // convert n.Left to right type. - checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { debugPP.Println("cmp == 0") - // NOTE: nil manipulation - // NOTE: refer to 0f46, this logic convert nil to the corresponding type intentionally, rather than the other way round, - // to simplify the logic of comparing in runtime, isEql. - // otherwise need to compare undefined with nil value but have specific type in (sliceType, mapType, funcType, PointerType): - // lv: (nil main.m), rv: (undefined), this should be comparable and can be equal if the lv value is nil, but complicated - // now we have: lv: (nil main.m), rv: (nil main.m), would be simpler to compare. + // to typed-nil. refer to 0f46 if lcx.T == nil { - checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { - checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) - } else { // default case, choose -> or <- on convenience - checkOp(store, last, &n.Left, rcx.T, n.Op, Binary) + } else { // default case + checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } } else { debugPP.Println("cmp > 0, <-") // convert n.Right to left type. - checkOp(store, last, &n.Right, lcx.T, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } // check special case: zero divisor if isQuoOrRem(n.Op) { - checkOperand(rcx) + if rcx.TypedValue.isZero() { + panic("invalid operation: division by zero") + } } } else { - checkOp(store, last, &n.Left, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } // Then, evaluate the expression. cx := evalConst(store, last, n) @@ -874,7 +871,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOp(store, last, &n.Left, pt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, pt, false, false) // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) @@ -894,36 +891,36 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { debugPP.Println("right not native") if isShift { - checkOp(store, last, &n.Left, lt, n.Op, Binary) - debugPP.Println("shift checkOp pass, postpone processing when assign or type cast") + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) + debugPP.Println("shift checkOperandWithOp pass, postpone processing when assign or type cast") // nothing to do, right type is (already) uint type. // we don't yet know what this type should be, // but another checkOrConvertType() later does. // (e.g. from AssignStmt or other). } else { // not shift // convert n.Left to right type. - checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable debugPP.Println("lcx.T is nil") // convert n.Left to typed-nil type. - checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else { // left is typed const, right is not const(also typed), and not nil if isShift { - checkOp(store, last, &n.Left, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) // do nothing, final type is bind to left // convertConstType(store, last, &n.Left, lt, false) // bypass check } else { // ? dir makes sense here, since non-const(right) implies more dynamic(interface) // TODO: check if right untyped if isUntyped(rt) { - checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) // the other way round should work too checkOrConvertType(store, last, &n.Right, lt, false, false) } else { - checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } @@ -933,7 +930,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Left not, Right untyped const ---------------- if isShift { // do nothing - checkOp(store, last, &n.Left, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } else { if lnt, ok := lt.(*NativeType); ok { // get concrete native base type. @@ -941,7 +938,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOp(store, last, &n.Right, pt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, pt, false, false) // and convert result back. tx := constType(n, lnt) @@ -958,7 +955,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } @@ -967,31 +964,33 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest //if lnt, ok := lt.(*NativeType); ok { // if ilnt, ok := baseOf(lnt).(*InterfaceType); ok { - // checkOp(store, last, &n.Right, ilnt, n.Op, Binary) + // checkOperandWithOp(store, last, &n.Right, ilnt, n.Op, Binary) // checkOrConvertType(store, last, &n.Right, ilnt, false) // } //} // in case of rcx.T == nil(untyped nil), require lt is maybeNil - checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) //// TODO: shift //// convert n.Right to typed-nil type. } else if !isShift { // left not const(typed), right is typed const, both typed // TODO: if left untyped? if isUntyped(lt) { - checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else { - checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } else if isShift { // check if LHS is valid - checkOp(store, last, &n.Left, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } // check special case first if isQuoOrRem(n.Op) { - checkOperand(rcx) + if rcx.TypedValue.isZero() { + panic("invalid operation: division by zero") + } } } else { // ---both not const--- if !isShift { @@ -1046,23 +1045,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // left untyped, right typed debugPP.Println("left untyped, right is typed") - checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } else if riu { // left typed, right untyped if !isShift { - checkOp(store, last, &n.Right, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } else { // both typed vars, refer to 0a1f_filetest if !isShift { - checkOp(store, last, &n.Left, rt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } } } else { - checkOp(store, last, &n.Left, lt, n.Op, Binary) + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } } // TRANS_LEAVE ----------------------- @@ -1388,15 +1387,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // always computed in gno, never with reflect. } // Replace with *ConstExpr if const X. - // checkOp, like +a, while a should be numeric + // checkOperandWithOp, like +a, while a should be numeric if cx, ok := n.X.(*ConstExpr); ok { debugPP.Println("not native, ConstExpr") - // checkOp, e.g. +a while a should be numeric - checkOp(store, last, nil, cx.T, n.Op, Unary) + // checkOperandWithOp, e.g. +a while a should be numeric + checkOperandWithOp(store, last, nil, cx.T, n.Op, Unary) cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } - checkOp(store, last, nil, xt, n.Op, Unary) + checkOperandWithOp(store, last, nil, xt, n.Op, Unary) // checkOrConvertType(store, last, &n.X, nil, false) // TRANS_LEAVE ----------------------- @@ -1792,19 +1791,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Special case if shift assign <<= or >>=. convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check lt := evalStaticTypeOf(store, last, n.Lhs[0]) - checkOp(store, last, &n.Lhs[0], lt, n.Op, Assign) + checkOperandWithOp(store, last, &n.Lhs[0], lt, n.Op, Assign) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, // TODO: assert length lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion - checkOp(store, last, &n.Rhs[0], lt, n.Op, Assign) + checkOperandWithOp(store, last, &n.Rhs[0], lt, n.Op, Assign) checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) } else { // all else, like BAND_ASSIGN, etc // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) - checkOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + checkOperandWithOp(store, last, &n.Rhs[i], lt, n.Op, Assign) // if lt is interface, nothing will happen checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) } @@ -1840,7 +1839,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *IncDecStmt: xt := evalStaticTypeOf(store, last, n.X) - checkOp(store, last, nil, xt, n.Op, IncDec) + checkOperandWithOp(store, last, nil, xt, n.Op, IncDec) // TRANS_LEAVE ----------------------- case *ForStmt: @@ -1948,6 +1947,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ValueDecl: + debugPP.Printf("---valueDecl: %v \n", n) // evaluate value if const expr. if n.Const { // NOTE: may or may not be a *ConstExpr, @@ -2038,7 +2038,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if nx.Name == "_" { nx.Path = NewValuePathBlock(0, 0, "_") } else { - debugPP.Println("define for valDecl---") pn.Define2(n.Const, nx.Name, sts[i], tvs[i]) nx.Path = last.GetPathForName(nil, nx.Name) } @@ -2169,6 +2168,7 @@ func pushRealBlock(bn BlockNode, last *BlockNode, stack *[]BlockNode) { // To discourage mis-use, expects x to already be // preprocessed. func evalStaticType(store Store, last BlockNode, x Expr) Type { + debugPP.Printf("---evalStaticType of: %v \n", x) if t, ok := x.GetAttribute(ATTR_TYPE_VALUE).(Type); ok { return t } else if ctx, ok := x.(*constTypeExpr); ok { @@ -2349,6 +2349,7 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { + debugPP.Printf("evalConst: %v \n", x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) @@ -2541,17 +2542,17 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } // deal with binary expr(bx.Left), determine its type if coerce { // mostly when explicitly conversion, type call, while arg is binary expr - checkOp(store, last, &bx.Left, t, bx.Op, Binary) // left is the target operand + checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) // left is the target operand // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 // dt not interface type if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil - checkOp(store, last, &bx.Left, t, bx.Op, Binary) + checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { - // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOp + // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOperandWithOp // checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno } } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable @@ -2569,12 +2570,12 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } if coerce { // mostly when explicitly conversion, type call - checkOp(store, last, &ux.X, t, ux.Op, Unary) + checkOperandWithOp(store, last, &ux.X, t, ux.Op, Unary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else if !coerce && isUntyped(xt) { // assign, func call if _, ok := t.(*InterfaceType); !ok { // TODO: consider this - checkOp(store, last, &ux.X, t, ux.Op, Unary) + checkOperandWithOp(store, last, &ux.X, t, ux.Op, Unary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else { @@ -2607,9 +2608,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative BAND_NOT, LAND, LOR: debugPP.Println("binary, going recursive call") // push t into bx.Left and bx.Right, recursively - checkOp(store, last, &bx.Left, t, bx.Op, Binary) + checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - checkOp(store, last, &bx.Right, t, bx.Op, Binary) + checkOperandWithOp(store, last, &bx.Right, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return case EQL, LSS, GTR, NEQ, LEQ, GEQ: @@ -2676,12 +2677,6 @@ func isQuoOrRem(op Word) bool { } } -func checkOperand(cx *ConstExpr) { - if cx.TypedValue.isZero() { - panic("invalid operation: division by zero") - } -} - func isComparison(op Word) bool { switch op { case EQL, NEQ, LSS, LEQ, GTR, GEQ: @@ -2700,7 +2695,7 @@ const ( Assign ) -// checkOp works as a pre-check prior to checkOrConvertType() +// checkOperandWithOp works as a pre-check prior to checkOrConvertType() // It checks expressions to ensure the compatibility between operands and operators. // e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. // Overall,it efficiently filters out incompatible expressions, stopping before the next @@ -2708,9 +2703,9 @@ const ( // there are two steps of check: // first, check is the dt type satisfies op; -// second, check if xt can be converted to dt, this is done after checkOp, in checkOrConvertType(), -func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { - debugPP.Printf("checkOp, dt: %v, op: %v, nt: %v \n", dt, op, nt) +// second, check if xt can be converted to dt, this is done after checkOperandWithOp, in checkOrConvertType(), +func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { + debugPP.Printf("checkOperandWithOp, dt: %v, op: %v, nt: %v \n", dt, op, nt) if nt == Unary || nt == IncDec { switch nt { case Unary: @@ -2739,13 +2734,11 @@ func checkOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType case Binary: if isComparison(op) { switch op { - case EQL, NEQ: // check maybeIdenticalType + case EQL, NEQ: // NOTE: not checking types strict identical here, unlike ADD, etc. // this will pass the case of lhs is interface and rhs implements this interface, vice versa. // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertible -> assignable - if ok, code := maybeIdenticalType(xt, dt); !ok { - panic(code) - } + assertEqualityCompatible(xt, dt) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 1608c395e1d..945dfcceb1d 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2269,7 +2269,13 @@ func assertSameTypes(lt, rt Type) { } func isEqualityTypes(lt, rt Type) bool { - debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + debugPP.Printf("check isEqualityTypes, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + if lt != nil { + debugPP.Printf("lt.Kind: %v \n", lt.Kind()) + } + if rt != nil { + debugPP.Printf("rt.Kind: %v \n", rt.Kind()) + } // refer to std3.gno, untyped byte has no typeID // quich pick if lpt, ok := lt.(*PointerType); ok { @@ -2374,20 +2380,18 @@ func assertEqualityTypes(lt, rt Type) { } } -// maybeIdenticalType is more relaxed than isIdentical, it's used in preprocess. -// The logic here is, when != or == shows up, check if `dt` is maybeIdenticalType(TODO: a better name +// assertEqualityCompatible is used in preprocess. +// The logic here is, when != or == shows up, check if `dt` is equalilty eval compatible. // indicates operand with dt can be used as with == or !=). if this check pass, // then check the corresponding type(the other side of the operator) is convertable to t. // this is located in checkOrConvertType->checkConvertable stage. -// so, checkOp is working as a pre-check. +// so, checkOperandWithOp is working as a pre-check. // TODO: just panic -func maybeIdenticalType(xt, dt Type) (bool, string) { - debugPP.Printf("---check maybeIdenticalType---, xt: %v, dt: %v \n", xt, dt) - // primitive is maybeIdenticalType +func assertEqualityCompatible(xt, dt Type) { + debugPP.Printf("--- assertEqualityCompatible---, xt: %v, dt: %v \n", xt, dt) switch cdt := baseOf(dt).(type) { case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage debugPP.Println("primitive type, return true, fallthrough") - return true, "" case *ArrayType: // NOTE: no recursive allowed // TODO: check at least length here switch baseOf(cdt.Elem()).(type) { @@ -2395,57 +2399,48 @@ func maybeIdenticalType(xt, dt Type) (bool, string) { switch cxt := baseOf(xt).(type) { case *ArrayType: if cxt.Len != cdt.Len { - return false, fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt) + panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) } - return true, "" default: - return false, fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt) + panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) } default: - return false, fmt.Sprintf("%v cannot be compared \n", cdt) + panic(fmt.Sprintf("%v cannot be compared \n", cdt)) } case *StructType: for _, f := range cdt.Fields { switch baseOf(f.Type).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: - return true, "" default: - return false, fmt.Sprintf("%v cannot be compared \n", cdt) + panic(fmt.Sprintf("%v cannot be compared \n", cdt)) } } - return true, "" case *PointerType: - return true, "" case *InterfaceType: - return true, "" case *SliceType, *FuncType, *MapType: if xt != nil { - return false, fmt.Sprintf("%v can only be compared to nil \n", dt) + panic(fmt.Sprintf("%v can only be compared to nil \n", dt)) } else { - // only maybeIdenticalType with nil, runtime check - return true, "" + // do nothing } case *NativeType: - if cdt.Type.Comparable() { - return true, "" + if !cdt.Type.Comparable() { + panic(fmt.Sprintf("%v is not comparable \n", dt)) } - return false, fmt.Sprintf("%v is not comparable \n", dt) case nil: // refer to 0a01_filetest, 0f32_filetest. switch cxt := baseOf(xt).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer - return true, "" case *NativeType: switch nk := cxt.Type.Kind(); nk { case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: - return true, "" default: - return false, fmt.Sprintf("invalid operation, nil can not be compared to %v \n", nk) + panic(fmt.Sprintf("invalid operation, nil can not be compared to %v \n", nk)) } default: - return false, fmt.Sprintf("invalid operation, nil can not be compared to nil \n") + panic(fmt.Sprintf("invalid operation, nil can not be compared to nil \n")) } default: - return false, fmt.Sprintf("%v is not comparable \n", dt) + panic(fmt.Sprintf("%v is not comparable \n", dt)) } } From 1791a34c2805a010e3825439fbd51b293d594cfa Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 14 Jan 2024 11:11:15 +0800 Subject: [PATCH 079/193] fixup --- gnovm/pkg/gnolang/op_assign.go | 38 ++++---------- gnovm/pkg/gnolang/op_binary.go | 66 ++++++------------------ gnovm/pkg/gnolang/preprocess.go | 29 ++++++++++- gnovm/pkg/gnolang/types.go | 30 +---------- gnovm/tests/files/op7.gno | 2 +- gnovm/tests/files/types/1d4_filetest.gno | 2 +- 6 files changed, 54 insertions(+), 113 deletions(-) diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index f227ecc681b..198813e8d29 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -1,7 +1,5 @@ package gnolang -import "fmt" - func (m *Machine) doOpDefine() { s := m.PopStmt().(*AssignStmt) // Define each value evaluated for Lhs. @@ -52,9 +50,7 @@ func (m *Machine) doOpAddAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -77,9 +73,7 @@ func (m *Machine) doOpSubAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -101,9 +95,7 @@ func (m *Machine) doOpMulAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -125,9 +117,7 @@ func (m *Machine) doOpQuoAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -149,9 +139,7 @@ func (m *Machine) doOpRemAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -173,9 +161,7 @@ func (m *Machine) doOpBandAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -197,9 +183,7 @@ func (m *Machine) doOpBandnAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -221,9 +205,7 @@ func (m *Machine) doOpBorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { @@ -245,9 +227,7 @@ func (m *Machine) doOpXorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - if !isSameTypes(lv.TV.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.TV.T.String(), rv.T.String())) - } + assertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) if m.ReadOnly { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 780a316285e..cee12bada65 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -52,9 +52,7 @@ func (m *Machine) doOpLor() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // set result in lv. if isUntyped(lv.T) { @@ -68,9 +66,7 @@ func (m *Machine) doOpLand() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // set result in lv. if isUntyped(lv.T) { @@ -86,9 +82,6 @@ func (m *Machine) doOpEql() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - //if debug { - // assertEqualityTypes(lv.T, rv.T) - //} debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool @@ -112,9 +105,6 @@ func (m *Machine) doOpNeq() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - //if debug { - // assertEqualityTypes(lv.T, rv.T) - //} debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool @@ -137,9 +127,7 @@ func (m *Machine) doOpLss() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // set the result in lv. res := isLss(lv, rv) @@ -155,9 +143,7 @@ func (m *Machine) doOpLeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // set the result in lv. res := isLeq(lv, rv) @@ -173,9 +159,7 @@ func (m *Machine) doOpGtr() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // set the result in lv. res := isGtr(lv, rv) @@ -191,9 +175,7 @@ func (m *Machine) doOpGeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // set the result in lv. res := isGeq(lv, rv) @@ -209,9 +191,7 @@ func (m *Machine) doOpAdd() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // add rv to lv. addAssign(m.Alloc, lv, rv) @@ -224,9 +204,7 @@ func (m *Machine) doOpSub() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // sub rv from lv. subAssign(lv, rv) @@ -239,9 +217,7 @@ func (m *Machine) doOpBor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv | rv borAssign(lv, rv) @@ -254,9 +230,7 @@ func (m *Machine) doOpXor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv ^ rv xorAssign(lv, rv) @@ -269,9 +243,7 @@ func (m *Machine) doOpMul() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv * rv @@ -285,9 +257,7 @@ func (m *Machine) doOpQuo() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv / rv @@ -301,9 +271,7 @@ func (m *Machine) doOpRem() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv % rv @@ -349,9 +317,7 @@ func (m *Machine) doOpBand() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv & rv @@ -365,9 +331,7 @@ func (m *Machine) doOpBandn() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - if !isSameTypes(lv.T, rv.T) { - panic(fmt.Sprintf("incompatible operands in binary expression: %s and %s", lv.T.String(), rv.T.String())) - } + assertSameTypes(lv.T, rv.T) } // lv &^ rv diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index b8785037899..e5a8f9a0898 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1055,8 +1055,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // both typed vars, refer to 0a1f_filetest if !isShift { - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false, false) + debugPP.Println("---both typed") + cmp := cmpSpecificity(lt, rt) + debugPP.Println("cmp: ", cmp) + if cmp == -1 { + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false, false) + } else if cmp == 1 { + checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + checkOrConvertType(store, last, &n.Right, lt, false, false) + } else { + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false, false) + } } } } @@ -2487,6 +2498,20 @@ func isConstType(x Expr) bool { func cmpSpecificity(t1, t2 Type) int { debugPP.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) + // debugPP.Printf("comSpecificity, t1: %T, t2: %T \n", t1, t2) + // debugPP.Printf("comSpecificity, t1.kind: %v, t2.kind: %v \n", t1.Kind(), t2.Kind()) + if it1, ok := baseOf(t1).(*InterfaceType); ok { + debugPP.Printf("it1: %v: \n", it1) + if it2, ok := baseOf(t2).(*InterfaceType); ok { + debugPP.Printf("it1: %v: \n", it2) + return 0 + } else { + return 1 + } + } else if _, ok := t2.(*InterfaceType); ok { + return -1 + } + t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { t1s = t1p.Specificity() diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 945dfcceb1d..c1078211587 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2242,7 +2242,6 @@ func KindOf(t Type) Kind { // and others serve as empty values. See doOpAdd() // usage: if debug { assertSameTypes() } func assertSameTypes(lt, rt Type) { - debugPP.Println("assert same types") if lt == nil && rt == nil { // both are nil. } else if lt == nil || rt == nil { @@ -2298,7 +2297,7 @@ func isEqualityTypes(lt, rt Type) bool { // one is nil. see function comment. return true } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { + isUntyped(lt) || isUntyped(rt) { // XXX, is this necessary? // one is untyped of same kind. return true } else if lt.Kind() == rt.Kind() && @@ -2325,33 +2324,6 @@ func isEqualityTypes(lt, rt Type) bool { return false } -// similar with isEqualityTypes -func isSameTypes(lt, rt Type) bool { - debugPP.Printf("check isIdenticalType, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) - if lt == nil && rt == nil { - // both are nil. - return true - } else if lt == nil || rt == nil { - // one is nil. see function comment. - return true - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. - return true - } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { - // left is databyte of same kind, - // specifically for assignments. - // TODO: make another function - // and remove this case? - return true - } else if lt.TypeID() == rt.TypeID() { - debugPP.Println("typeID equal") - return true - } - return false -} - // Like assertSameTypes(), but more relaxed, for == and !=. func assertEqualityTypes(lt, rt Type) { if lt == nil && rt == nil { diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files/op7.gno index 519b69299d5..d2a21e414fa 100644 --- a/gnovm/tests/files/op7.gno +++ b/gnovm/tests/files/op7.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// comparison operator > not defined for InterfaceKind +// main/files/op7.gno:11: operator > not defined on: .uverse.error diff --git a/gnovm/tests/files/types/1d4_filetest.gno b/gnovm/tests/files/types/1d4_filetest.gno index 2ecaabe8424..556fccf2171 100644 --- a/gnovm/tests/files/types/1d4_filetest.gno +++ b/gnovm/tests/files/types/1d4_filetest.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/1d4_filetest.gno:7: invalid operation: mismatched types int and interface{} +// main/files/types/1d4_filetest.gno:7: operator + not defined on: interface{} From 073bd48cf968ba25f36306b7d74eba2237b44c3b Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 14 Jan 2024 11:37:01 +0800 Subject: [PATCH 080/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 17 ++++++++++------- gnovm/tests/files/types2/12.gno | 9 +++++++++ gnovm/tests/files/types2/13.gno | 8 ++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 gnovm/tests/files/types2/12.gno create mode 100644 gnovm/tests/files/types2/13.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e5a8f9a0898..93546f8e662 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -903,11 +903,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false, false) } } - } else if lcx.T == nil { // LHS is nil // TODO: this seems unreachable + } else if lcx.T == nil { // LHS is nil debugPP.Println("lcx.T is nil") - // convert n.Left to typed-nil type. - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) - checkOrConvertType(store, last, &n.Left, rt, false, false) + if !isShift { + // convert n.Left to typed-nil type. + checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + checkOrConvertType(store, last, &n.Left, rt, false, false) + } else { + // check lhs of shift + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) + } } else { // left is typed const, right is not const(also typed), and not nil if isShift { checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) @@ -960,7 +965,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil - // TODO: check lt maybeIdentical + // no need to check lhs here since if rhs type is nil, it would fail earlier debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest //if lnt, ok := lt.(*NativeType); ok { // if ilnt, ok := baseOf(lnt).(*InterfaceType); ok { @@ -971,8 +976,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // in case of rcx.T == nil(untyped nil), require lt is maybeNil checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) - //// TODO: shift - //// convert n.Right to typed-nil type. } else if !isShift { // left not const(typed), right is typed const, both typed // TODO: if left untyped? if isUntyped(lt) { diff --git a/gnovm/tests/files/types2/12.gno b/gnovm/tests/files/types2/12.gno new file mode 100644 index 00000000000..347605a98af --- /dev/null +++ b/gnovm/tests/files/types2/12.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var a = int(1) + 1 + println(nil << a) +} + +// Error: +// main/files/types2/12.gno:3: operator << not defined on: \ No newline at end of file diff --git a/gnovm/tests/files/types2/13.gno b/gnovm/tests/files/types2/13.gno new file mode 100644 index 00000000000..47dc53cc6af --- /dev/null +++ b/gnovm/tests/files/types2/13.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << nil) +} + +// Error: +// main/files/types2/13.gno:3: cannot convert (const (undefined) nil) to UintKind From df4d4c70f4ec0d553b82aa6f3c4c43156979ada2 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 15 Jan 2024 11:44:06 +0800 Subject: [PATCH 081/193] fixup --- gnovm/pkg/gnolang/op_compatibility.go | 195 ++++++++++++++++++ gnovm/pkg/gnolang/preprocess.go | 111 +++------- gnovm/pkg/gnolang/types.go | 159 -------------- gnovm/tests/files/op7.gno | 2 +- .../files/types/0f26_stdlibs_filetest.gno | 2 +- .../files/types/0f27_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/0f28_filetest.gno | 2 +- gnovm/tests/files/types/0f29_filetest.gno | 2 +- gnovm/tests/files/types/0f2b_stdlibs.gno | 2 +- gnovm/tests/files/types/0f2c_stdlibs.gno | 2 +- gnovm/tests/files/types/10a14_filetest.gno | 2 +- gnovm/tests/files/types/10a15_filetest.gno | 2 +- gnovm/tests/files/types/10a16_filetest.gno | 2 +- gnovm/tests/files/types/10a5_filetest.gno | 2 +- .../tests/files/types/11a0_LAND_filetest.gno | 2 +- gnovm/tests/files/types/11a1_filetest.gno | 2 +- gnovm/tests/files/types/11a2_filetest.gno | 2 +- .../tests/files/types/11a5_LAND_filetest.gno | 2 +- .../tests/files/types/11a6_LAND_filetest.gno | 2 +- .../tests/files/types/11a7_LAND_filetest.gno | 2 +- gnovm/tests/files/types/12a0_LOR_filetest.gno | 2 +- gnovm/tests/files/types/12a1_filetest.gno | 2 +- gnovm/tests/files/types/12a2_filetest.gno | 2 +- .../files/types/13f2_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/13f3_filetest.gno | 2 +- .../files/types/14f2_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/14f3_filetest.gno | 2 +- gnovm/tests/files/types/14f4_filetest.gno | 2 +- gnovm/tests/files/types/14f5_filetest.gno | 2 +- gnovm/tests/files/types/15a02_filetest.gno | 2 +- gnovm/tests/files/types/15a04_filetest.gno | 2 +- gnovm/tests/files/types/1d4_filetest.gno | 2 +- .../files/types/1f0_stdlibs_filetest.gno | 2 +- .../files/types/1f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/1f2_filetest.gno | 2 +- gnovm/tests/files/types/23a0c_filetest.gno | 2 +- gnovm/tests/files/types/23a2a_filetest.gno | 2 +- gnovm/tests/files/types/23a6_filetest.gno | 2 +- gnovm/tests/files/types/25a1_filetest.gno | 2 +- .../files/types/26a0_runtime_filetest.gno | 2 +- gnovm/tests/files/types/26a1_filetest.gno | 2 +- gnovm/tests/files/types/27a_filetest.gno | 2 +- gnovm/tests/files/types/2b2_filetest.gno | 2 +- gnovm/tests/files/types/2b3_filetest.gno | 2 +- .../files/types/2f0_stdlibs_filetest.gno | 2 +- .../files/types/2f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/2f2_filetest.gno | 2 +- gnovm/tests/files/types/3b2_filetest.gno | 2 +- gnovm/tests/files/types/3b3_filetest.gno | 2 +- .../files/types/3f0_stdlibs_filetest.gno | 2 +- .../files/types/3f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/3f2_filetest.gno | 2 +- gnovm/tests/files/types/4b2_filetest.gno | 2 +- gnovm/tests/files/types/4b3_filetest.gno | 2 +- .../files/types/4f0_stdlibs_filetest.gno | 2 +- .../files/types/4f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/4f2_filetest.gno | 2 +- gnovm/tests/files/types/5b2_filetest.gno | 2 +- gnovm/tests/files/types/5b3_filetest.gno | 2 +- gnovm/tests/files/types/5d0_filetest.gno | 2 +- gnovm/tests/files/types/5d4_filetest.gno | 2 +- .../files/types/5f0_stdlibs_filetest.gno | 2 +- .../files/types/5f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/5f2_filetest.gno | 2 +- gnovm/tests/files/types/6b2_filetest.gno | 2 +- gnovm/tests/files/types/6b3_filetest.gno | 2 +- gnovm/tests/files/types/6d0_filetest.gno | 2 +- gnovm/tests/files/types/6d4_filetest.gno | 2 +- .../files/types/6f0_stdlibs_filetest.gno | 2 +- .../files/types/6f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/6f2_filetest.gno | 2 +- gnovm/tests/files/types/7b2_filetest.gno | 2 +- gnovm/tests/files/types/7b3_filetest.gno | 2 +- gnovm/tests/files/types/7d0_filetest.gno | 2 +- gnovm/tests/files/types/7d4_filetest.gno | 2 +- .../files/types/7f0_stdlibs_filetest.gno | 2 +- .../files/types/7f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/7f2_filetest.gno | 2 +- gnovm/tests/files/types/8b2_filetest.gno | 2 +- gnovm/tests/files/types/8b3_filetest.gno | 2 +- gnovm/tests/files/types/8d0_filetest.gno | 2 +- gnovm/tests/files/types/8d4_filetest.gno | 2 +- .../files/types/8f0_stdlibs_filetest.gno | 2 +- .../files/types/8f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/8f2_filetest.gno | 2 +- gnovm/tests/files/types/9b2_filetest.gno | 2 +- gnovm/tests/files/types/9b3_filetest.gno | 2 +- gnovm/tests/files/types/9d0_filetest.gno | 2 +- gnovm/tests/files/types/9d4_filetest.gno | 2 +- .../files/types/9f0_stdlibs_filetest.gno | 2 +- .../files/types/9f1_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/9f2_filetest.gno | 2 +- gnovm/tests/files/types2/0_a_3b.gno | 2 +- gnovm/tests/files/types2/0_b.gno | 2 +- gnovm/tests/files/types2/10a01_filetest.gno | 2 +- gnovm/tests/files/types2/10a02_filetest.gno | 2 +- gnovm/tests/files/types2/10a17b.gno | 2 +- gnovm/tests/files/types2/10a21.gno | 2 +- gnovm/tests/files/types2/10a21a.gno | 2 +- gnovm/tests/files/types2/10a25c.gno | 2 +- gnovm/tests/files/types2/10a26.gno | 2 +- gnovm/tests/files/types2/10a27c.gno | 2 +- gnovm/tests/files/types2/12.gno | 2 +- gnovm/tests/files/types2/4.gno | 2 +- gnovm/tests/files/types2/4_a.gno | 2 +- 105 files changed, 329 insertions(+), 340 deletions(-) create mode 100644 gnovm/pkg/gnolang/op_compatibility.go diff --git a/gnovm/pkg/gnolang/op_compatibility.go b/gnovm/pkg/gnolang/op_compatibility.go new file mode 100644 index 00000000000..8a65fa2397d --- /dev/null +++ b/gnovm/pkg/gnolang/op_compatibility.go @@ -0,0 +1,195 @@ +package gnolang + +import "fmt" + +var ( + binaryPredicates = map[Word]func(t Type) bool{ + ADD: isNumericOrString, + SUB: isNumeric, + MUL: isNumeric, + QUO: isNumeric, + REM: isIntNum, + SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. + SHR: isIntNum, + BAND: isIntNum, // bit ops + XOR: isIntNum, + BOR: isIntNum, + BAND_NOT: isIntNum, + LAND: isBoolean, // logic + LOR: isBoolean, + LSS: isOrdered, // compare + LEQ: isOrdered, + GTR: isOrdered, + GEQ: isOrdered, + } + unaryPredicates = map[Word]func(t Type) bool{ + ADD: isNumeric, + SUB: isNumeric, + XOR: isIntNum, + NOT: isBoolean, + } + IncDecStmtPredicates = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). + INC: isNumeric, + DEC: isNumeric, + } + AssignStmtPredicates = map[Word]func(t Type) bool{ + ADD_ASSIGN: isNumericOrString, + SUB_ASSIGN: isNumeric, + MUL_ASSIGN: isNumeric, + QUO_ASSIGN: isNumeric, + REM_ASSIGN: isIntNum, + SHL_ASSIGN: isNumeric, + SHR_ASSIGN: isNumeric, + BAND_ASSIGN: isIntNum, + XOR_ASSIGN: isIntNum, + BOR_ASSIGN: isIntNum, + BAND_NOT_ASSIGN: isIntNum, + } +) + +type category int + +const ( + IsInvalid category = 0 + IsBoolean category = 1 << iota + IsInteger + IsUnsigned + IsFloat + IsString + IsBigInt + IsBigDec + IsRune + + IsNumeric = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec + IsOrdered = IsNumeric | IsString + IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec +) + +// category makes it more convenient than compare with types +func (pt PrimitiveType) predicate() category { + switch pt { + case InvalidType: + return IsInvalid + case UntypedBoolType: + return IsBoolean + case BoolType: + return IsBoolean + case UntypedStringType: + return IsString + case StringType: + return IsString + case IntType: + return IsInteger + case Int8Type: + return IsInteger + case Int16Type: + return IsInteger + case UntypedRuneType: // TODO: this is treat as DataByteType, GUESS, refer to op_inc_dec + return IsRune + case Int32Type: + return IsInteger + case Int64Type: + return IsInteger + case UintType: + return IsUnsigned + case Uint8Type: + return IsUnsigned + case DataByteType: + return IsUnsigned // TODO: consider this + case Uint16Type: + return IsUnsigned + case Uint32Type: + return IsUnsigned + case Uint64Type: + return IsUnsigned + case Float32Type: + return IsFloat + case Float64Type: + return IsFloat + case UntypedBigintType: + return IsBigInt + case BigintType: + return IsBigInt + case UntypedBigdecType: + return IsBigDec + case BigdecType: + return IsBigDec + default: + panic(fmt.Sprintf("unexpected primitive type %d", pt)) + } +} + +func isOrdered(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +func isBoolean(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsBoolean != 0 { + return true + } + return false + default: + return false + } +} + +// rune can be numeric and string +// TODO: consider, do we need complex? +func isNumeric(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +func isIntOrFloat(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsIntOrFloat != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +// signed or unsigned int +func isIntNum(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsBigInt != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +func isNumericOrString(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsString != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 93546f8e662..9fd72385df5 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -8,51 +8,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/errors" ) -var ( - binaryPredicates = map[Word]func(t Type) bool{ - ADD: isNumericOrString, - SUB: isNumeric, - MUL: isNumeric, - QUO: isNumeric, - REM: isIntNum, - SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. - SHR: isIntNum, - BAND: isIntNum, // bit ops - XOR: isIntNum, - BOR: isIntNum, - BAND_NOT: isIntNum, - LAND: isBoolean, // logic - LOR: isBoolean, - LSS: isOrdered, // compare - LEQ: isOrdered, - GTR: isOrdered, - GEQ: isOrdered, - } - unaryPredicates = map[Word]func(t Type) bool{ - ADD: isNumeric, - SUB: isNumeric, - XOR: isIntNum, - NOT: isBoolean, - } - IncDecStmtPredicates = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). - INC: isNumeric, - DEC: isNumeric, - } - AssignStmtPredicates = map[Word]func(t Type) bool{ - ADD_ASSIGN: isNumericOrString, - SUB_ASSIGN: isNumeric, - MUL_ASSIGN: isNumeric, - QUO_ASSIGN: isNumeric, - REM_ASSIGN: isIntNum, - SHL_ASSIGN: isNumeric, - SHR_ASSIGN: isNumeric, - BAND_ASSIGN: isIntNum, - XOR_ASSIGN: isIntNum, - BOR_ASSIGN: isIntNum, - BAND_NOT_ASSIGN: isIntNum, - } -) - // In the case of a *FileSet, some declaration steps have to happen // in a restricted parallel way across all the files. // Anything predefined or preprocessed here get skipped during the Preprocess @@ -797,6 +752,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { isShift := n.Op == SHL || n.Op == SHR // special case of shift if isShift { + // check LHS type compatibility + checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) + // checkOrConvert RHS if baseOf(rt) != UintType { // checkOperandWithOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* // convert n.Right to (gno) uint type, @@ -854,10 +812,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("invalid operation: division by zero") } } - } else { - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } // Then, evaluate the expression. + // also for shift cx := evalConst(store, last, n) debugPP.Printf("const evaluated: %v \n", cx) return cx, TRANS_CONTINUE @@ -890,14 +847,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { debugPP.Println("right not native") - if isShift { - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) - debugPP.Println("shift checkOperandWithOp pass, postpone processing when assign or type cast") - // nothing to do, right type is (already) uint type. - // we don't yet know what this type should be, - // but another checkOrConvertType() later does. - // (e.g. from AssignStmt or other). - } else { // not shift + if !isShift { // convert n.Left to right type. checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) @@ -909,16 +859,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to typed-nil type. checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) - } else { - // check lhs of shift - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } } else { // left is typed const, right is not const(also typed), and not nil - if isShift { - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) - // do nothing, final type is bind to left - // convertConstType(store, last, &n.Left, lt, false) // bypass check - } else { // ? dir makes sense here, since non-const(right) implies more dynamic(interface) + if !isShift { // ? dir makes sense here, since non-const(right) implies more dynamic(interface) // TODO: check if right untyped if isUntyped(rt) { checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) @@ -933,10 +876,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if ric { // right is const, left is not--- if isUntyped(rcx.T) { // Left not, Right untyped const ---------------- - if isShift { - // do nothing - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) - } else { + if !isShift { if lnt, ok := lt.(*NativeType); ok { // get concrete native base type. pt := go2GnoBaseType(lnt.Type).(PrimitiveType) @@ -985,9 +925,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } - } else if isShift { - // check if LHS is valid - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } // check special case first if isQuoOrRem(n.Op) { @@ -1074,8 +1011,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } - } else { - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) } } // TRANS_LEAVE ----------------------- @@ -2739,13 +2674,21 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, case Unary: if pred, ok := unaryPredicates[op]; ok { if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + if dt != nil { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } } case IncDec: if pred, ok := IncDecStmtPredicates[op]; ok { if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + if dt != nil { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } } default: @@ -2770,7 +2713,11 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, case LSS, LEQ, GTR, GEQ: if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + if dt != nil { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } } default: @@ -2779,7 +2726,11 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, } else { if pred, ok := binaryPredicates[op]; ok { if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + if dt != nil { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } } switch op { @@ -2791,7 +2742,6 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } - debugPP.Println("typed and identical as maybeIdenticalType") } default: // do nothing @@ -2800,7 +2750,11 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, case Assign: if pred, ok := AssignStmtPredicates[op]; ok { if !pred(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + if dt != nil { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + } } switch op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: @@ -2811,7 +2765,6 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) } } - debugPP.Println("typed and identical as maybeIdenticalType") } default: // do nothing diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index c1078211587..743e6ec4781 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -257,165 +257,6 @@ func (pt PrimitiveType) TypeID() TypeID { } } -type category int - -const ( - IsInvalid category = 0 - IsBoolean category = 1 << iota - IsInteger - IsUnsigned - IsFloat - IsString - IsBigInt - IsBigDec - IsRune - - IsNumeric = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec - IsOrdered = IsNumeric | IsString - IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec -) - -// category makes it more convenient than compare with types -func (pt PrimitiveType) predicate() category { - switch pt { - case InvalidType: - return IsInvalid - case UntypedBoolType: - return IsBoolean - case BoolType: - return IsBoolean - case UntypedStringType: - return IsString - case StringType: - return IsString - case IntType: - return IsInteger - case Int8Type: - return IsInteger - case Int16Type: - return IsInteger - case UntypedRuneType: // TODO: this is treat as DataByteType, GUESS, refer to op_inc_dec - return IsRune - case Int32Type: - return IsInteger - case Int64Type: - return IsInteger - case UintType: - return IsUnsigned - case Uint8Type: - return IsUnsigned - case DataByteType: - return IsUnsigned // TODO: consider this - case Uint16Type: - return IsUnsigned - case Uint32Type: - return IsUnsigned - case Uint64Type: - return IsUnsigned - case Float32Type: - return IsFloat - case Float64Type: - return IsFloat - case UntypedBigintType: - return IsBigInt - case BigintType: - return IsBigInt - case UntypedBigdecType: - return IsBigDec - case BigdecType: - return IsBigDec - default: - panic(fmt.Sprintf("unexpected primitive type %d", pt)) - } -} - -func isOrdered(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -func isBoolean(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsBoolean != 0 { - return true - } - return false - default: - return false - } -} - -// rune can be numeric and string -// TODO: consider, do we need complex? -func isNumeric(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -func isIntOrFloat(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsIntOrFloat != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -// signed or unsigned int -func isIntNum(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsBigInt != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -//func isIntOrUint(t Type) bool { -// switch t := baseOf(t).(type) { -// case PrimitiveType: -// if t.category() != IsInvalid && t.category()&IsInteger != 0 || t.category()&IsUnsigned != 0 || t.category()&IsRune != 0 { -// return true -// } -// return false -// default: -// return false -// } -//} - -func isNumericOrString(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsString != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - func (pt PrimitiveType) String() string { switch pt { case InvalidType: diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files/op7.gno index d2a21e414fa..0c3f540600b 100644 --- a/gnovm/tests/files/op7.gno +++ b/gnovm/tests/files/op7.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/op7.gno:11: operator > not defined on: .uverse.error +// main/files/op7.gno:11: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f26_stdlibs_filetest.gno b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno index 5c4ed0646d2..83dd6d6af57 100644 --- a/gnovm/tests/files/types/0f26_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0f26_stdlibs_filetest.gno:19: operator > not defined on: .uverse.error +// main/files/types/0f26_stdlibs_filetest.gno:19: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f27_stdlibs_filetest.gno b/gnovm/tests/files/types/0f27_stdlibs_filetest.gno index 2115456eac1..c6d4b67d9bf 100644 --- a/gnovm/tests/files/types/0f27_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/0f27_stdlibs_filetest.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/types/0f27_stdlibs_filetest.gno:13: operator > not defined on: .uverse.error +// main/files/types/0f27_stdlibs_filetest.gno:13: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f28_filetest.gno b/gnovm/tests/files/types/0f28_filetest.gno index 907153db280..abc91cb4dd2 100644 --- a/gnovm/tests/files/types/0f28_filetest.gno +++ b/gnovm/tests/files/types/0f28_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/0f28_filetest.gno:27: operator > not defined on: main.E +// main/files/types/0f28_filetest.gno:27: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f29_filetest.gno b/gnovm/tests/files/types/0f29_filetest.gno index ec30b1f3901..e78a2324332 100644 --- a/gnovm/tests/files/types/0f29_filetest.gno +++ b/gnovm/tests/files/types/0f29_filetest.gno @@ -21,4 +21,4 @@ func main() { } // Error: -// main/files/types/0f29_filetest.gno:16: operator > not defined on: interface{} +// main/files/types/0f29_filetest.gno:16: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f2b_stdlibs.gno b/gnovm/tests/files/types/0f2b_stdlibs.gno index 9eb42188153..afc0ac13498 100644 --- a/gnovm/tests/files/types/0f2b_stdlibs.gno +++ b/gnovm/tests/files/types/0f2b_stdlibs.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f2b_stdlibs.gno:19: operator <= not defined on: .uverse.error +// main/files/types/0f2b_stdlibs.gno:19: operator <= not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f2c_stdlibs.gno b/gnovm/tests/files/types/0f2c_stdlibs.gno index 10ea7379fa9..7e47a9f1d3b 100644 --- a/gnovm/tests/files/types/0f2c_stdlibs.gno +++ b/gnovm/tests/files/types/0f2c_stdlibs.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f2c_stdlibs.gno:19: operator < not defined on: .uverse.error +// main/files/types/0f2c_stdlibs.gno:19: operator < not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/10a14_filetest.gno b/gnovm/tests/files/types/10a14_filetest.gno index 2b44d59b5c5..5856c253b65 100644 --- a/gnovm/tests/files/types/10a14_filetest.gno +++ b/gnovm/tests/files/types/10a14_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/10a14_filetest.gno:3: operator << not defined on: string +// main/files/types/10a14_filetest.gno:5: operator << not defined on: StringKind diff --git a/gnovm/tests/files/types/10a15_filetest.gno b/gnovm/tests/files/types/10a15_filetest.gno index eacc1897428..addc060947d 100644 --- a/gnovm/tests/files/types/10a15_filetest.gno +++ b/gnovm/tests/files/types/10a15_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/10a15_filetest.gno:6: operator <<= not defined on: string +// main/files/types/10a15_filetest.gno:6: operator <<= not defined on: StringKind diff --git a/gnovm/tests/files/types/10a16_filetest.gno b/gnovm/tests/files/types/10a16_filetest.gno index bf73e85ba23..0c934e82f92 100644 --- a/gnovm/tests/files/types/10a16_filetest.gno +++ b/gnovm/tests/files/types/10a16_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/10a16_filetest.gno:3: operator << not defined on: string +// main/files/types/10a16_filetest.gno:4: operator << not defined on: StringKind diff --git a/gnovm/tests/files/types/10a5_filetest.gno b/gnovm/tests/files/types/10a5_filetest.gno index af55d1b5cdc..74c839bad37 100644 --- a/gnovm/tests/files/types/10a5_filetest.gno +++ b/gnovm/tests/files/types/10a5_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/10a5_filetest.gno:4: operator << not defined on: bigdec +// main/files/types/10a5_filetest.gno:5: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types/11a0_LAND_filetest.gno b/gnovm/tests/files/types/11a0_LAND_filetest.gno index fad0c255443..abe396dd650 100644 --- a/gnovm/tests/files/types/11a0_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a0_LAND_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/11a0_LAND_filetest.gno:5: operator && not defined on: int +// main/files/types/11a0_LAND_filetest.gno:5: operator && not defined on: IntKind diff --git a/gnovm/tests/files/types/11a1_filetest.gno b/gnovm/tests/files/types/11a1_filetest.gno index 30a21fbb8e6..c04341a309e 100644 --- a/gnovm/tests/files/types/11a1_filetest.gno +++ b/gnovm/tests/files/types/11a1_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/11a1_filetest.gno:5: operator && not defined on: bigint +// main/files/types/11a1_filetest.gno:5: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a2_filetest.gno b/gnovm/tests/files/types/11a2_filetest.gno index fc8b1401304..a502575a27b 100644 --- a/gnovm/tests/files/types/11a2_filetest.gno +++ b/gnovm/tests/files/types/11a2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/11a2_filetest.gno:5: operator && not defined on: bigint \ No newline at end of file +// main/files/types/11a2_filetest.gno:5: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a5_LAND_filetest.gno b/gnovm/tests/files/types/11a5_LAND_filetest.gno index 363a98a8f1e..e2a8e10897c 100644 --- a/gnovm/tests/files/types/11a5_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a5_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/11a5_LAND_filetest.gno:4: operator && not defined on: bigint +// main/files/types/11a5_LAND_filetest.gno:4: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a6_LAND_filetest.gno b/gnovm/tests/files/types/11a6_LAND_filetest.gno index 156a7740c2e..d9b0702a5c7 100644 --- a/gnovm/tests/files/types/11a6_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a6_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/11a6_LAND_filetest.gno:4: operator && not defined on: bigint +// main/files/types/11a6_LAND_filetest.gno:4: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a7_LAND_filetest.gno b/gnovm/tests/files/types/11a7_LAND_filetest.gno index 7adac5f84d8..d27742cf32d 100644 --- a/gnovm/tests/files/types/11a7_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a7_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/11a7_LAND_filetest.gno:4: operator && not defined on: int +// main/files/types/11a7_LAND_filetest.gno:4: operator && not defined on: IntKind diff --git a/gnovm/tests/files/types/12a0_LOR_filetest.gno b/gnovm/tests/files/types/12a0_LOR_filetest.gno index be8bbba2529..f1be388ff6c 100644 --- a/gnovm/tests/files/types/12a0_LOR_filetest.gno +++ b/gnovm/tests/files/types/12a0_LOR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/12a0_LOR_filetest.gno:5: operator || not defined on: int +// main/files/types/12a0_LOR_filetest.gno:5: operator || not defined on: IntKind diff --git a/gnovm/tests/files/types/12a1_filetest.gno b/gnovm/tests/files/types/12a1_filetest.gno index 745ce998d57..367d8f98631 100644 --- a/gnovm/tests/files/types/12a1_filetest.gno +++ b/gnovm/tests/files/types/12a1_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/12a1_filetest.gno:5: operator || not defined on: bigint +// main/files/types/12a1_filetest.gno:5: operator || not defined on: BigintKind diff --git a/gnovm/tests/files/types/12a2_filetest.gno b/gnovm/tests/files/types/12a2_filetest.gno index 328758cf3fe..529639a2d54 100644 --- a/gnovm/tests/files/types/12a2_filetest.gno +++ b/gnovm/tests/files/types/12a2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/12a2_filetest.gno:5: operator || not defined on: bigint +// main/files/types/12a2_filetest.gno:5: operator || not defined on: BigintKind diff --git a/gnovm/tests/files/types/13f2_stdlibs_filetest.gno b/gnovm/tests/files/types/13f2_stdlibs_filetest.gno index f218300c53f..765aa172456 100644 --- a/gnovm/tests/files/types/13f2_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/13f2_stdlibs_filetest.gno @@ -42,4 +42,4 @@ func main() { } // Error: -// main/files/types/13f2_stdlibs_filetest.gno:40: operator += not defined on: .uverse.error +// main/files/types/13f2_stdlibs_filetest.gno:40: operator += not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/13f3_filetest.gno b/gnovm/tests/files/types/13f3_filetest.gno index 3b015e74b5d..25cb2f49953 100644 --- a/gnovm/tests/files/types/13f3_filetest.gno +++ b/gnovm/tests/files/types/13f3_filetest.gno @@ -29,4 +29,4 @@ func main() { } // Error: -// main/files/types/13f3_filetest.gno:27: operator += not defined on: main.E +// main/files/types/13f3_filetest.gno:27: operator += not defined on: InterfaceKind \ No newline at end of file diff --git a/gnovm/tests/files/types/14f2_stdlibs_filetest.gno b/gnovm/tests/files/types/14f2_stdlibs_filetest.gno index 7ccdebaadbd..29636e76aba 100644 --- a/gnovm/tests/files/types/14f2_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/14f2_stdlibs_filetest.gno @@ -42,4 +42,4 @@ func main() { } // Error: -// main/files/types/14f2_stdlibs_filetest.gno:40: operator -= not defined on: .uverse.error +// main/files/types/14f2_stdlibs_filetest.gno:40: operator -= not defined on: InterfaceKind \ No newline at end of file diff --git a/gnovm/tests/files/types/14f3_filetest.gno b/gnovm/tests/files/types/14f3_filetest.gno index 71eea3f78f8..60458f50050 100644 --- a/gnovm/tests/files/types/14f3_filetest.gno +++ b/gnovm/tests/files/types/14f3_filetest.gno @@ -29,4 +29,4 @@ func main() { } // Error: -// main/files/types/14f3_filetest.gno:27: operator -= not defined on: main.E \ No newline at end of file +// main/files/types/14f3_filetest.gno:27: operator -= not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/14f4_filetest.gno b/gnovm/tests/files/types/14f4_filetest.gno index 35558501b46..f847ac07805 100644 --- a/gnovm/tests/files/types/14f4_filetest.gno +++ b/gnovm/tests/files/types/14f4_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/14f4_filetest.gno:5: operator -= not defined on: string +// main/files/types/14f4_filetest.gno:5: operator -= not defined on: StringKind diff --git a/gnovm/tests/files/types/14f5_filetest.gno b/gnovm/tests/files/types/14f5_filetest.gno index facc612de18..787f2be03d8 100644 --- a/gnovm/tests/files/types/14f5_filetest.gno +++ b/gnovm/tests/files/types/14f5_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/14f5_filetest.gno:6: operator -= not defined on: string +// main/files/types/14f5_filetest.gno:6: operator -= not defined on: StringKind diff --git a/gnovm/tests/files/types/15a02_filetest.gno b/gnovm/tests/files/types/15a02_filetest.gno index 9637380913f..a401fd97cab 100644 --- a/gnovm/tests/files/types/15a02_filetest.gno +++ b/gnovm/tests/files/types/15a02_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/15a02_filetest.gno:5: operator %= not defined on: string +// main/files/types/15a02_filetest.gno:5: operator %= not defined on: StringKind diff --git a/gnovm/tests/files/types/15a04_filetest.gno b/gnovm/tests/files/types/15a04_filetest.gno index c5aaea85298..a465f75f1ac 100644 --- a/gnovm/tests/files/types/15a04_filetest.gno +++ b/gnovm/tests/files/types/15a04_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/15a04_filetest.gno:5: operator %= not defined on: float64 +// main/files/types/15a04_filetest.gno:5: operator %= not defined on: Float64Kind diff --git a/gnovm/tests/files/types/1d4_filetest.gno b/gnovm/tests/files/types/1d4_filetest.gno index 556fccf2171..8d44fe5ed75 100644 --- a/gnovm/tests/files/types/1d4_filetest.gno +++ b/gnovm/tests/files/types/1d4_filetest.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/1d4_filetest.gno:7: operator + not defined on: interface{} +// main/files/types/1d4_filetest.gno:7: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/1f0_stdlibs_filetest.gno b/gnovm/tests/files/types/1f0_stdlibs_filetest.gno index 06411f00584..a0cfe5b973d 100644 --- a/gnovm/tests/files/types/1f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/1f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/1f0_stdlibs_filetest.gno:19: operator + not defined on: .uverse.error +// main/files/types/1f0_stdlibs_filetest.gno:19: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/1f1_stdlibs_filetest.gno b/gnovm/tests/files/types/1f1_stdlibs_filetest.gno index 76a880f2c5d..b1d18f7605d 100644 --- a/gnovm/tests/files/types/1f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/1f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/1f1_stdlibs_filetest.gno:19: operator + not defined on: .uverse.error +// main/files/types/1f1_stdlibs_filetest.gno:19: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/1f2_filetest.gno b/gnovm/tests/files/types/1f2_filetest.gno index 6b54b409245..fd507a7d9ca 100644 --- a/gnovm/tests/files/types/1f2_filetest.gno +++ b/gnovm/tests/files/types/1f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/1f2_filetest.gno:27: operator + not defined on: main.E +// main/files/types/1f2_filetest.gno:27: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/23a0c_filetest.gno b/gnovm/tests/files/types/23a0c_filetest.gno index e6ead4453b0..2b74d51720b 100644 --- a/gnovm/tests/files/types/23a0c_filetest.gno +++ b/gnovm/tests/files/types/23a0c_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/types/23a0c_filetest.gno:7: operator + not defined on: string +// main/files/types/23a0c_filetest.gno:7: operator + not defined on: StringKind diff --git a/gnovm/tests/files/types/23a2a_filetest.gno b/gnovm/tests/files/types/23a2a_filetest.gno index 4aa51db913d..39d4769d680 100644 --- a/gnovm/tests/files/types/23a2a_filetest.gno +++ b/gnovm/tests/files/types/23a2a_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types/23a2a_filetest.gno:7: operator ! not defined on: int +// main/files/types/23a2a_filetest.gno:7: operator ! not defined on: IntKind diff --git a/gnovm/tests/files/types/23a6_filetest.gno b/gnovm/tests/files/types/23a6_filetest.gno index 455d7355a36..3f8dea36f12 100644 --- a/gnovm/tests/files/types/23a6_filetest.gno +++ b/gnovm/tests/files/types/23a6_filetest.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/types/23a6_filetest.gno:7: operator ^ not defined on: float64 +// main/files/types/23a6_filetest.gno:7: operator ^ not defined on: Float64Kind diff --git a/gnovm/tests/files/types/25a1_filetest.gno b/gnovm/tests/files/types/25a1_filetest.gno index 51046e36ed4..41db2511e51 100644 --- a/gnovm/tests/files/types/25a1_filetest.gno +++ b/gnovm/tests/files/types/25a1_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/25a1_filetest.gno:5: operator ++ not defined on: string +// main/files/types/25a1_filetest.gno:5: operator ++ not defined on: StringKind diff --git a/gnovm/tests/files/types/26a0_runtime_filetest.gno b/gnovm/tests/files/types/26a0_runtime_filetest.gno index 47ad2aaaf3f..92c2d987471 100644 --- a/gnovm/tests/files/types/26a0_runtime_filetest.gno +++ b/gnovm/tests/files/types/26a0_runtime_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/26a0_runtime_filetest.gno:5: operator ++ not defined on: bool +// main/files/types/26a0_runtime_filetest.gno:5: operator ++ not defined on: BoolKind diff --git a/gnovm/tests/files/types/26a1_filetest.gno b/gnovm/tests/files/types/26a1_filetest.gno index 3705dee7d99..ead8962aba0 100644 --- a/gnovm/tests/files/types/26a1_filetest.gno +++ b/gnovm/tests/files/types/26a1_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/26a1_filetest.gno:6: operator ++ not defined on: bool +// main/files/types/26a1_filetest.gno:6: operator ++ not defined on: BoolKind diff --git a/gnovm/tests/files/types/27a_filetest.gno b/gnovm/tests/files/types/27a_filetest.gno index d3d314d3685..3cc3c1f5e4c 100644 --- a/gnovm/tests/files/types/27a_filetest.gno +++ b/gnovm/tests/files/types/27a_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/27a_filetest.gno:3: operator << not defined on: bigdec +// main/files/types/27a_filetest.gno:5: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types/2b2_filetest.gno b/gnovm/tests/files/types/2b2_filetest.gno index a56d48a64b2..d5a0eff3c7b 100644 --- a/gnovm/tests/files/types/2b2_filetest.gno +++ b/gnovm/tests/files/types/2b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2b2_filetest.gno:5: operator - not defined on: string +// main/files/types/2b2_filetest.gno:5: operator - not defined on: StringKind diff --git a/gnovm/tests/files/types/2b3_filetest.gno b/gnovm/tests/files/types/2b3_filetest.gno index 092a8cfc067..2a040667102 100644 --- a/gnovm/tests/files/types/2b3_filetest.gno +++ b/gnovm/tests/files/types/2b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2b3_filetest.gno:5: operator - not defined on: string +// main/files/types/2b3_filetest.gno:5: operator - not defined on: StringKind diff --git a/gnovm/tests/files/types/2f0_stdlibs_filetest.gno b/gnovm/tests/files/types/2f0_stdlibs_filetest.gno index d56001a9b68..0d88cd45a58 100644 --- a/gnovm/tests/files/types/2f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/2f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/2f0_stdlibs_filetest.gno:19: operator - not defined on: .uverse.error +// main/files/types/2f0_stdlibs_filetest.gno:19: operator - not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/2f1_stdlibs_filetest.gno b/gnovm/tests/files/types/2f1_stdlibs_filetest.gno index 028a85b675b..5edb48288d0 100644 --- a/gnovm/tests/files/types/2f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/2f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/2f1_stdlibs_filetest.gno:19: operator - not defined on: .uverse.error +// main/files/types/2f1_stdlibs_filetest.gno:19: operator - not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/2f2_filetest.gno b/gnovm/tests/files/types/2f2_filetest.gno index a204e2be86d..895e3d5eb17 100644 --- a/gnovm/tests/files/types/2f2_filetest.gno +++ b/gnovm/tests/files/types/2f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/2f2_filetest.gno:27: operator - not defined on: main.E +// main/files/types/2f2_filetest.gno:27: operator - not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/3b2_filetest.gno b/gnovm/tests/files/types/3b2_filetest.gno index 7799f2e791e..2cf6d721528 100644 --- a/gnovm/tests/files/types/3b2_filetest.gno +++ b/gnovm/tests/files/types/3b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3b2_filetest.gno:5: operator * not defined on: string +// main/files/types/3b2_filetest.gno:5: operator * not defined on: StringKind diff --git a/gnovm/tests/files/types/3b3_filetest.gno b/gnovm/tests/files/types/3b3_filetest.gno index 839879870ff..cef4efb3c8a 100644 --- a/gnovm/tests/files/types/3b3_filetest.gno +++ b/gnovm/tests/files/types/3b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3b3_filetest.gno:5: operator * not defined on: string +// main/files/types/3b3_filetest.gno:5: operator * not defined on: StringKind diff --git a/gnovm/tests/files/types/3f0_stdlibs_filetest.gno b/gnovm/tests/files/types/3f0_stdlibs_filetest.gno index 540c1cd9476..c58261583aa 100644 --- a/gnovm/tests/files/types/3f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/3f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/3f0_stdlibs_filetest.gno:19: operator * not defined on: .uverse.error +// main/files/types/3f0_stdlibs_filetest.gno:19: operator * not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/3f1_stdlibs_filetest.gno b/gnovm/tests/files/types/3f1_stdlibs_filetest.gno index 56ff40457fd..708571493ac 100644 --- a/gnovm/tests/files/types/3f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/3f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/3f1_stdlibs_filetest.gno:19: operator * not defined on: .uverse.error +// main/files/types/3f1_stdlibs_filetest.gno:19: operator * not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/3f2_filetest.gno b/gnovm/tests/files/types/3f2_filetest.gno index a90d64a0328..229b7c89479 100644 --- a/gnovm/tests/files/types/3f2_filetest.gno +++ b/gnovm/tests/files/types/3f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/3f2_filetest.gno:27: operator * not defined on: main.E +// main/files/types/3f2_filetest.gno:27: operator * not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/4b2_filetest.gno b/gnovm/tests/files/types/4b2_filetest.gno index c0a7c118f0d..26568836778 100644 --- a/gnovm/tests/files/types/4b2_filetest.gno +++ b/gnovm/tests/files/types/4b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4b2_filetest.gno:5: operator / not defined on: string +// main/files/types/4b2_filetest.gno:5: operator / not defined on: StringKind diff --git a/gnovm/tests/files/types/4b3_filetest.gno b/gnovm/tests/files/types/4b3_filetest.gno index e8143b1ee10..2d3ce9b3656 100644 --- a/gnovm/tests/files/types/4b3_filetest.gno +++ b/gnovm/tests/files/types/4b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4b3_filetest.gno:5: operator / not defined on: string +// main/files/types/4b3_filetest.gno:5: operator / not defined on: StringKind diff --git a/gnovm/tests/files/types/4f0_stdlibs_filetest.gno b/gnovm/tests/files/types/4f0_stdlibs_filetest.gno index 03456e40d50..1ce0906baa9 100644 --- a/gnovm/tests/files/types/4f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/4f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/4f0_stdlibs_filetest.gno:19: operator / not defined on: .uverse.error +// main/files/types/4f0_stdlibs_filetest.gno:19: operator / not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/4f1_stdlibs_filetest.gno b/gnovm/tests/files/types/4f1_stdlibs_filetest.gno index cbd90a9d0e3..788ab7e312c 100644 --- a/gnovm/tests/files/types/4f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/4f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/4f1_stdlibs_filetest.gno:19: operator / not defined on: .uverse.error +// main/files/types/4f1_stdlibs_filetest.gno:19: operator / not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/4f2_filetest.gno b/gnovm/tests/files/types/4f2_filetest.gno index 95b09f068fc..45f176eca15 100644 --- a/gnovm/tests/files/types/4f2_filetest.gno +++ b/gnovm/tests/files/types/4f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/4f2_filetest.gno:27: operator / not defined on: main.E +// main/files/types/4f2_filetest.gno:27: operator / not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/5b2_filetest.gno b/gnovm/tests/files/types/5b2_filetest.gno index 4679f005cc0..928d24ce205 100644 --- a/gnovm/tests/files/types/5b2_filetest.gno +++ b/gnovm/tests/files/types/5b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5b2_filetest.gno:5: operator % not defined on: string +// main/files/types/5b2_filetest.gno:5: operator % not defined on: StringKind diff --git a/gnovm/tests/files/types/5b3_filetest.gno b/gnovm/tests/files/types/5b3_filetest.gno index ef990873c49..340291d63df 100644 --- a/gnovm/tests/files/types/5b3_filetest.gno +++ b/gnovm/tests/files/types/5b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5b3_filetest.gno:5: operator % not defined on: string +// main/files/types/5b3_filetest.gno:5: operator % not defined on: StringKind diff --git a/gnovm/tests/files/types/5d0_filetest.gno b/gnovm/tests/files/types/5d0_filetest.gno index 1f6ed065974..0077e6375e5 100644 --- a/gnovm/tests/files/types/5d0_filetest.gno +++ b/gnovm/tests/files/types/5d0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/5d0_filetest.gno:6: operator % not defined on: bigdec +// main/files/types/5d0_filetest.gno:6: operator % not defined on: BigdecKind diff --git a/gnovm/tests/files/types/5d4_filetest.gno b/gnovm/tests/files/types/5d4_filetest.gno index 703fc0aa8bf..cc010c97978 100644 --- a/gnovm/tests/files/types/5d4_filetest.gno +++ b/gnovm/tests/files/types/5d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/5d4_filetest.gno:6: operator % not defined on: bigdec +// main/files/types/5d4_filetest.gno:6: operator % not defined on: BigdecKind diff --git a/gnovm/tests/files/types/5f0_stdlibs_filetest.gno b/gnovm/tests/files/types/5f0_stdlibs_filetest.gno index 233ba6f64b3..8d934bc4d14 100644 --- a/gnovm/tests/files/types/5f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/5f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/5f0_stdlibs_filetest.gno:19: operator % not defined on: .uverse.error +// main/files/types/5f0_stdlibs_filetest.gno:19: operator % not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/5f1_stdlibs_filetest.gno b/gnovm/tests/files/types/5f1_stdlibs_filetest.gno index 91120567d40..ff841fefaa6 100644 --- a/gnovm/tests/files/types/5f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/5f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/5f1_stdlibs_filetest.gno:19: operator % not defined on: .uverse.error +// main/files/types/5f1_stdlibs_filetest.gno:19: operator % not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/5f2_filetest.gno b/gnovm/tests/files/types/5f2_filetest.gno index b8a5793d4ae..b982c34ebbd 100644 --- a/gnovm/tests/files/types/5f2_filetest.gno +++ b/gnovm/tests/files/types/5f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/5f2_filetest.gno:27: operator % not defined on: main.E +// main/files/types/5f2_filetest.gno:27: operator % not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/6b2_filetest.gno b/gnovm/tests/files/types/6b2_filetest.gno index 585772f2845..7fcfbdbacb0 100644 --- a/gnovm/tests/files/types/6b2_filetest.gno +++ b/gnovm/tests/files/types/6b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/6b2_filetest.gno:5: operator & not defined on: string +// main/files/types/6b2_filetest.gno:5: operator & not defined on: StringKind diff --git a/gnovm/tests/files/types/6b3_filetest.gno b/gnovm/tests/files/types/6b3_filetest.gno index eab5eb543b7..e2573f8a80f 100644 --- a/gnovm/tests/files/types/6b3_filetest.gno +++ b/gnovm/tests/files/types/6b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/6b3_filetest.gno:5: operator & not defined on: string +// main/files/types/6b3_filetest.gno:5: operator & not defined on: StringKind diff --git a/gnovm/tests/files/types/6d0_filetest.gno b/gnovm/tests/files/types/6d0_filetest.gno index 3f0e417adac..21067841348 100644 --- a/gnovm/tests/files/types/6d0_filetest.gno +++ b/gnovm/tests/files/types/6d0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/6d0_filetest.gno:6: operator & not defined on: bigdec +// main/files/types/6d0_filetest.gno:6: operator & not defined on: BigdecKind diff --git a/gnovm/tests/files/types/6d4_filetest.gno b/gnovm/tests/files/types/6d4_filetest.gno index 253dee86ed4..01be35e49b7 100644 --- a/gnovm/tests/files/types/6d4_filetest.gno +++ b/gnovm/tests/files/types/6d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/6d4_filetest.gno:6: operator & not defined on: bigdec +// main/files/types/6d4_filetest.gno:6: operator & not defined on: BigdecKind diff --git a/gnovm/tests/files/types/6f0_stdlibs_filetest.gno b/gnovm/tests/files/types/6f0_stdlibs_filetest.gno index 84171f05703..efb25f14b44 100644 --- a/gnovm/tests/files/types/6f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/6f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/6f0_stdlibs_filetest.gno:19: operator & not defined on: .uverse.error +// main/files/types/6f0_stdlibs_filetest.gno:19: operator & not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/6f1_stdlibs_filetest.gno b/gnovm/tests/files/types/6f1_stdlibs_filetest.gno index 824c1630a6a..21ff6fb5d43 100644 --- a/gnovm/tests/files/types/6f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/6f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/6f1_stdlibs_filetest.gno:19: operator & not defined on: .uverse.error +// main/files/types/6f1_stdlibs_filetest.gno:19: operator & not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/6f2_filetest.gno b/gnovm/tests/files/types/6f2_filetest.gno index 007d839bce7..174f2ea5d3b 100644 --- a/gnovm/tests/files/types/6f2_filetest.gno +++ b/gnovm/tests/files/types/6f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/6f2_filetest.gno:27: operator & not defined on: main.E +// main/files/types/6f2_filetest.gno:27: operator & not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/7b2_filetest.gno b/gnovm/tests/files/types/7b2_filetest.gno index 9a8d3af24d9..a63f9e055a1 100644 --- a/gnovm/tests/files/types/7b2_filetest.gno +++ b/gnovm/tests/files/types/7b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/7b2_filetest.gno:5: operator | not defined on: string +// main/files/types/7b2_filetest.gno:5: operator | not defined on: StringKind diff --git a/gnovm/tests/files/types/7b3_filetest.gno b/gnovm/tests/files/types/7b3_filetest.gno index 8ce21695e0b..07c74a1f916 100644 --- a/gnovm/tests/files/types/7b3_filetest.gno +++ b/gnovm/tests/files/types/7b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/7b3_filetest.gno:5: operator | not defined on: string +// main/files/types/7b3_filetest.gno:5: operator | not defined on: StringKind diff --git a/gnovm/tests/files/types/7d0_filetest.gno b/gnovm/tests/files/types/7d0_filetest.gno index 31a47cc066d..f14d45d3250 100644 --- a/gnovm/tests/files/types/7d0_filetest.gno +++ b/gnovm/tests/files/types/7d0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/7d0_filetest.gno:6: operator | not defined on: bigdec +// main/files/types/7d0_filetest.gno:6: operator | not defined on: BigdecKind diff --git a/gnovm/tests/files/types/7d4_filetest.gno b/gnovm/tests/files/types/7d4_filetest.gno index 87f4f6a7e1f..d0e1a227c03 100644 --- a/gnovm/tests/files/types/7d4_filetest.gno +++ b/gnovm/tests/files/types/7d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/7d4_filetest.gno:6: operator | not defined on: bigdec +// main/files/types/7d4_filetest.gno:6: operator | not defined on: BigdecKind diff --git a/gnovm/tests/files/types/7f0_stdlibs_filetest.gno b/gnovm/tests/files/types/7f0_stdlibs_filetest.gno index 5ea7e257e82..e9ba46148b0 100644 --- a/gnovm/tests/files/types/7f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/7f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/7f0_stdlibs_filetest.gno:19: operator | not defined on: .uverse.error +// main/files/types/7f0_stdlibs_filetest.gno:19: operator | not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/7f1_stdlibs_filetest.gno b/gnovm/tests/files/types/7f1_stdlibs_filetest.gno index 28f4a1483fc..ffe25f114d7 100644 --- a/gnovm/tests/files/types/7f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/7f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/7f1_stdlibs_filetest.gno:19: operator | not defined on: .uverse.error +// main/files/types/7f1_stdlibs_filetest.gno:19: operator | not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/7f2_filetest.gno b/gnovm/tests/files/types/7f2_filetest.gno index 3fb8c99496c..03fdb0f7621 100644 --- a/gnovm/tests/files/types/7f2_filetest.gno +++ b/gnovm/tests/files/types/7f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/7f2_filetest.gno:27: operator | not defined on: main.E +// main/files/types/7f2_filetest.gno:27: operator | not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/8b2_filetest.gno b/gnovm/tests/files/types/8b2_filetest.gno index cbeb942dd8a..f260a4b3078 100644 --- a/gnovm/tests/files/types/8b2_filetest.gno +++ b/gnovm/tests/files/types/8b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/8b2_filetest.gno:5: operator ^ not defined on: string +// main/files/types/8b2_filetest.gno:5: operator ^ not defined on: StringKind diff --git a/gnovm/tests/files/types/8b3_filetest.gno b/gnovm/tests/files/types/8b3_filetest.gno index 0cd6f8e5db6..70c3cb4af6d 100644 --- a/gnovm/tests/files/types/8b3_filetest.gno +++ b/gnovm/tests/files/types/8b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/8b3_filetest.gno:5: operator ^ not defined on: string +// main/files/types/8b3_filetest.gno:5: operator ^ not defined on: StringKind diff --git a/gnovm/tests/files/types/8d0_filetest.gno b/gnovm/tests/files/types/8d0_filetest.gno index 8758edf619d..3b4d4177df7 100644 --- a/gnovm/tests/files/types/8d0_filetest.gno +++ b/gnovm/tests/files/types/8d0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/8d0_filetest.gno:6: operator ^ not defined on: bigdec +// main/files/types/8d0_filetest.gno:6: operator ^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/8d4_filetest.gno b/gnovm/tests/files/types/8d4_filetest.gno index 7236bc12bb0..4b0e57515ea 100644 --- a/gnovm/tests/files/types/8d4_filetest.gno +++ b/gnovm/tests/files/types/8d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/8d4_filetest.gno:6: operator ^ not defined on: bigdec +// main/files/types/8d4_filetest.gno:6: operator ^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/8f0_stdlibs_filetest.gno b/gnovm/tests/files/types/8f0_stdlibs_filetest.gno index 5a37308ff4a..0a62300b46a 100644 --- a/gnovm/tests/files/types/8f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/8f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/8f0_stdlibs_filetest.gno:19: operator ^ not defined on: .uverse.error +// main/files/types/8f0_stdlibs_filetest.gno:19: operator ^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/8f1_stdlibs_filetest.gno b/gnovm/tests/files/types/8f1_stdlibs_filetest.gno index 8020e24f2fd..ab19520e10a 100644 --- a/gnovm/tests/files/types/8f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/8f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/8f1_stdlibs_filetest.gno:19: operator ^ not defined on: .uverse.error +// main/files/types/8f1_stdlibs_filetest.gno:19: operator ^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/8f2_filetest.gno b/gnovm/tests/files/types/8f2_filetest.gno index 2f80ff3840d..1ee42c37283 100644 --- a/gnovm/tests/files/types/8f2_filetest.gno +++ b/gnovm/tests/files/types/8f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/8f2_filetest.gno:27: operator ^ not defined on: main.E +// main/files/types/8f2_filetest.gno:27: operator ^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/9b2_filetest.gno b/gnovm/tests/files/types/9b2_filetest.gno index 2fb7afdf91e..b1dd347071b 100644 --- a/gnovm/tests/files/types/9b2_filetest.gno +++ b/gnovm/tests/files/types/9b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/9b2_filetest.gno:5: operator &^ not defined on: string +// main/files/types/9b2_filetest.gno:5: operator &^ not defined on: StringKind diff --git a/gnovm/tests/files/types/9b3_filetest.gno b/gnovm/tests/files/types/9b3_filetest.gno index b0fe7e24d60..65f64da6b25 100644 --- a/gnovm/tests/files/types/9b3_filetest.gno +++ b/gnovm/tests/files/types/9b3_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/9b3_filetest.gno:5: operator &^ not defined on: string +// main/files/types/9b3_filetest.gno:5: operator &^ not defined on: StringKind diff --git a/gnovm/tests/files/types/9d0_filetest.gno b/gnovm/tests/files/types/9d0_filetest.gno index 8499acea7e9..604252b0f46 100644 --- a/gnovm/tests/files/types/9d0_filetest.gno +++ b/gnovm/tests/files/types/9d0_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/9d0_filetest.gno:6: operator &^ not defined on: bigdec +// main/files/types/9d0_filetest.gno:6: operator &^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/9d4_filetest.gno b/gnovm/tests/files/types/9d4_filetest.gno index f44ece6fb12..c59d62ef1e2 100644 --- a/gnovm/tests/files/types/9d4_filetest.gno +++ b/gnovm/tests/files/types/9d4_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/9d4_filetest.gno:6: operator &^ not defined on: bigdec +// main/files/types/9d4_filetest.gno:6: operator &^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/9f0_stdlibs_filetest.gno b/gnovm/tests/files/types/9f0_stdlibs_filetest.gno index 7c97f2c37f1..b98b56900e5 100644 --- a/gnovm/tests/files/types/9f0_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/9f0_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/9f0_stdlibs_filetest.gno:19: operator &^ not defined on: .uverse.error +// main/files/types/9f0_stdlibs_filetest.gno:19: operator &^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/9f1_stdlibs_filetest.gno b/gnovm/tests/files/types/9f1_stdlibs_filetest.gno index 9124443e6e5..0233a763acb 100644 --- a/gnovm/tests/files/types/9f1_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/9f1_stdlibs_filetest.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/types/9f1_stdlibs_filetest.gno:19: operator &^ not defined on: .uverse.error +// main/files/types/9f1_stdlibs_filetest.gno:19: operator &^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/9f2_filetest.gno b/gnovm/tests/files/types/9f2_filetest.gno index 81092b6b3ff..aff0e9773cb 100644 --- a/gnovm/tests/files/types/9f2_filetest.gno +++ b/gnovm/tests/files/types/9f2_filetest.gno @@ -28,4 +28,4 @@ func main() { } // Error: -// main/files/types/9f2_filetest.gno:27: operator &^ not defined on: main.E +// main/files/types/9f2_filetest.gno:27: operator &^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types2/0_a_3b.gno b/gnovm/tests/files/types2/0_a_3b.gno index a497d2a17b9..ccc85747b98 100644 --- a/gnovm/tests/files/types2/0_a_3b.gno +++ b/gnovm/tests/files/types2/0_a_3b.gno @@ -36,4 +36,4 @@ func main() { } // Error: -// main/files/types2/0_a_3b.gno:31: operator << not defined on: main.R +// main/files/types2/0_a_3b.gno:31: operator << not defined on: InterfaceKind diff --git a/gnovm/tests/files/types2/0_b.gno b/gnovm/tests/files/types2/0_b.gno index b62f6f09f2c..d41ef81ae27 100644 --- a/gnovm/tests/files/types2/0_b.gno +++ b/gnovm/tests/files/types2/0_b.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/types2/0_b.gno:15: operator << not defined on: float32 +// main/files/types2/0_b.gno:15: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a01_filetest.gno b/gnovm/tests/files/types2/10a01_filetest.gno index cba3b5788df..9856d9cce7d 100644 --- a/gnovm/tests/files/types2/10a01_filetest.gno +++ b/gnovm/tests/files/types2/10a01_filetest.gno @@ -15,4 +15,4 @@ func main() { } // Error: -// main/files/types2/10a01_filetest.gno:7: operator << not defined on: bigdec +// main/files/types2/10a01_filetest.gno:9: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types2/10a02_filetest.gno b/gnovm/tests/files/types2/10a02_filetest.gno index fa8e0bfec19..703b0fc4dd5 100644 --- a/gnovm/tests/files/types2/10a02_filetest.gno +++ b/gnovm/tests/files/types2/10a02_filetest.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/types2/10a02_filetest.gno:5: operator << not defined on: bigdec +// main/files/types2/10a02_filetest.gno:7: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types2/10a17b.gno b/gnovm/tests/files/types2/10a17b.gno index b8084da9e30..e405f2504be 100644 --- a/gnovm/tests/files/types2/10a17b.gno +++ b/gnovm/tests/files/types2/10a17b.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/types2/10a17b.gno:13: operator >> not defined on: float32 +// main/files/types2/10a17b.gno:13: operator >> not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a21.gno b/gnovm/tests/files/types2/10a21.gno index e4a6ec223eb..9aca9605c9c 100644 --- a/gnovm/tests/files/types2/10a21.gno +++ b/gnovm/tests/files/types2/10a21.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types2/10a21.gno:5: operator << not defined on: float32 +// main/files/types2/10a21.gno:5: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a21a.gno b/gnovm/tests/files/types2/10a21a.gno index c29d8b14896..08345f04b50 100644 --- a/gnovm/tests/files/types2/10a21a.gno +++ b/gnovm/tests/files/types2/10a21a.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types2/10a21a.gno:5: operator << not defined on: float32 +// main/files/types2/10a21a.gno:5: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a25c.gno b/gnovm/tests/files/types2/10a25c.gno index c69dafc7d37..b2807a7d0b0 100644 --- a/gnovm/tests/files/types2/10a25c.gno +++ b/gnovm/tests/files/types2/10a25c.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types2/10a25c.gno:6: operator << not defined on: float32 +// main/files/types2/10a25c.gno:6: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a26.gno b/gnovm/tests/files/types2/10a26.gno index 4c02fd979c8..75bac65b1e1 100644 --- a/gnovm/tests/files/types2/10a26.gno +++ b/gnovm/tests/files/types2/10a26.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types2/10a26.gno:6: operator << not defined on: float32 +// main/files/types2/10a26.gno:6: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a27c.gno b/gnovm/tests/files/types2/10a27c.gno index 6740de32892..56de66d8caf 100644 --- a/gnovm/tests/files/types2/10a27c.gno +++ b/gnovm/tests/files/types2/10a27c.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types2/10a27c.gno:5: operator << not defined on: bigdec +// main/files/types2/10a27c.gno:7: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types2/12.gno b/gnovm/tests/files/types2/12.gno index 347605a98af..6869fb6cd47 100644 --- a/gnovm/tests/files/types2/12.gno +++ b/gnovm/tests/files/types2/12.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types2/12.gno:3: operator << not defined on: \ No newline at end of file +// main/files/types2/12.gno:5: operator << not defined on: diff --git a/gnovm/tests/files/types2/4.gno b/gnovm/tests/files/types2/4.gno index bcc2903c10b..110066a9145 100644 --- a/gnovm/tests/files/types2/4.gno +++ b/gnovm/tests/files/types2/4.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/types2/4.gno:16: operator << not defined on: float32 +// main/files/types2/4.gno:16: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/4_a.gno b/gnovm/tests/files/types2/4_a.gno index db98074eebd..1b18640d98f 100644 --- a/gnovm/tests/files/types2/4_a.gno +++ b/gnovm/tests/files/types2/4_a.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/types2/4_a.gno:16: operator << not defined on: float32 +// main/files/types2/4_a.gno:16: operator << not defined on: Float32Kind From ef25c1f29f26336fa7a9d35612a68f2abbb36e13 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 15 Jan 2024 15:04:58 +0800 Subject: [PATCH 082/193] fixup --- gnovm/pkg/gnolang/types.go | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 743e6ec4781..9b40900d38c 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2110,59 +2110,40 @@ func assertSameTypes(lt, rt Type) { func isEqualityTypes(lt, rt Type) bool { debugPP.Printf("check isEqualityTypes, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) - if lt != nil { - debugPP.Printf("lt.Kind: %v \n", lt.Kind()) - } - if rt != nil { - debugPP.Printf("rt.Kind: %v \n", rt.Kind()) - } - // refer to std3.gno, untyped byte has no typeID - // quich pick - if lpt, ok := lt.(*PointerType); ok { - if isDataByte(lpt.Elt) { // refer to 0f31 - debugPP.Println("lt is pointer type and base type is data byte") - return true - } + if lpt, ok := lt.(*PointerType); ok { // refer to 0f31 + lt = lpt.Elt } if rpt, ok := rt.(*PointerType); ok { - if isDataByte(rpt.Elt) { - debugPP.Println("rt is pointer type and base type is data byte") - return true - } + rt = rpt.Elt } // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { - return true // both are nil. } else if lt == nil || rt == nil { // one is nil. see function comment. - return true } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { // XXX, is this necessary? // one is untyped of same kind. - return true } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // XXX, what hit this // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? - return true - } else if lt.TypeID() == rt.TypeID() { // order matters - debugPP.Println("typeID equal") - // non-nil types are identical. - return true } else if lt.Kind() == InterfaceKind && IsImplementedBy(lt, rt) { // one is untyped of same kind. // rt implements lt (and lt is nil interface). - return true } else if rt.Kind() == InterfaceKind && IsImplementedBy(rt, lt) { // lt implements rt (and rt is nil interface). - return true + } else if lt.TypeID() == rt.TypeID() { // order matters + debugPP.Println("typeID equal") + // non-nil types are identical. + } else { + return false } - return false + return true } // Like assertSameTypes(), but more relaxed, for == and !=. From 6f591495aa4edef5290e2116783950867c77e036 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 16 Jan 2024 00:17:59 +0800 Subject: [PATCH 083/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 91 ++++++++++++++++++----------- gnovm/pkg/gnolang/values.go | 8 +-- gnovm/tests/files/types2/10a27d.gno | 14 +++++ gnovm/tests/files/types2/10a27e.gno | 13 +++++ gnovm/tests/files/types2/10a27f.gno | 14 +++++ gnovm/tests/files/types2/14.gno | 16 +++++ gnovm/tests/files/types2/15.gno | 26 +++++++++ gnovm/tests/files/types2/15a.gno | 26 +++++++++ gnovm/tests/files/types2/15b.gno | 30 ++++++++++ gnovm/tests/files/types2/15c.gno | 10 ++++ 10 files changed, 209 insertions(+), 39 deletions(-) create mode 100644 gnovm/tests/files/types2/10a27d.gno create mode 100644 gnovm/tests/files/types2/10a27e.gno create mode 100644 gnovm/tests/files/types2/10a27f.gno create mode 100644 gnovm/tests/files/types2/14.gno create mode 100644 gnovm/tests/files/types2/15.gno create mode 100644 gnovm/tests/files/types2/15a.gno create mode 100644 gnovm/tests/files/types2/15b.gno create mode 100644 gnovm/tests/files/types2/15c.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9fd72385df5..9eeb6573327 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1032,14 +1032,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } n.NumArgs = 1 var dt Type - + ct := evalStaticType(store, last, n.Func) + debugPP.Printf("ct: %v \n", ct) + at := evalStaticTypeOf(store, last, n.Args[0]) switch arg0 := n.Args[0].(type) { case *ConstExpr: - ct := evalStaticType(store, last, n.Func) if arg0.IsUndefined() { switch ct.Kind() { // special case for nil conversion check, TODO: refer to case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind: - dt = ct + dt = ct // convert nil to typed-nil default: panic(fmt.Sprintf( "cannot convert %v to %v", @@ -1065,34 +1066,35 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TODO: consider this, need check? // (const) untyped decimal -> float64. // (const) untyped bigint -> int. - convertConst(store, last, arg0, dt) + convertConst(store, last, arg0, dt) // convert to default type if dt is nil // evaluate the new expression. cx := evalConst(store, last, n) // Though cx may be undefined if ct is interface, // the ATTR_TYPEOF_VALUE is still interface. - cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) + cx.SetAttribute(ATTR_TYPEOF_VALUE, dt) return cx, TRANS_CONTINUE - case *BinaryExpr: // when arg is untyped expression and contains SHL/SHR expression, call type convert explicitly to give it type + case *BinaryExpr: // special case to evaluate type of binaryExpr/UnaryExpr which has untyped shift nested debugPP.Printf("---callExpr, arg is binary expr, bx: %v \n", arg0) - ct := evalStaticType(store, last, n.Func) - debugPP.Printf("ct: %v \n", ct) - switch arg0.Op { - case EQL, NEQ, LSS, GTR, LEQ, GEQ: // refer to 10a0012 - break // quick forward - default: - checkOrConvertType(store, last, &n.Args[0], ct, false, true) + if isUntyped(at) { // only when untyped, this is checked in checkOrConvertType too, but guard here + switch arg0.Op { + case EQL, NEQ, LSS, GTR, LEQ, GEQ: // refer to 10a0012. TODO: convert to typed too + break // quick forward + default: + checkOrConvertType(store, last, &n.Args[0], ct, false, true) + } } case *UnaryExpr: debugPP.Printf("---callExpr, arg is unary expr, bx: %v \n", arg0) - ct := evalStaticType(store, last, n.Func) - debugPP.Printf("ct: %v \n", ct) - checkOrConvertType(store, last, &n.Args[0], ct, false, true) + if isUntyped(at) { + checkOrConvertType(store, last, &n.Args[0], ct, false, true) + } default: - // do nothing + debugPP.Printf("default: arg type is: %T \n", arg0) } + // general case, for non-const untyped && no nested untyped shift + // after handling const, and special cases recursively, set the target node type debugPP.Println("general case") - ct := evalStaticType(store, last, n.Func) - debugPP.Printf("ct: %v \n", ct) + //ct := evalStaticType(store, last, n.Func) n.SetAttribute(ATTR_TYPEOF_VALUE, ct) return n, TRANS_CONTINUE default: @@ -1695,8 +1697,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(ln, anyValue(rt)) } // in define, when RHS is untyped and contains SHR/SHL expression, explicitly - // call this, to give the SHR/SHL a type - checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 + // call this, to give the SHR/SHL a type, the dest type is a faux type. + checkOrConvertType(store, last, &n.Rhs[i], &InterfaceType{}, false, false) // 10a03 } } } else { // ASSIGN. @@ -2168,6 +2170,7 @@ func gnoTypeOf(store Store, t Type) Type { // Unlike evalStaticType, x is not expected to be a typeval, // but rather computes the type OF x. func evalStaticTypeOf(store Store, last BlockNode, x Expr) Type { + debugPP.Printf("---evalStaticTypeOf: x : %v \n", x) t := evalStaticTypeOfRaw(store, last, x) if tt, ok := t.(*tupleType); ok { if len(tt.Elts) != 1 { @@ -2496,7 +2499,14 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) - if t == nil { + //if t == nil { + // if isUntyped(xt) { + // t = defaultTypeOf(xt) + // } else { + // t = xt // xt maybe typed while assign, with t is the type of LHS + // } + //} + if _, ok := t.(*InterfaceType); ok { if isUntyped(xt) { t = defaultTypeOf(xt) } else { @@ -2510,14 +2520,14 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 // dt not interface type - if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil - checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else { - // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOperandWithOp - // checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno - } + //if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil + checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + //} else { + // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOperandWithOp + // checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno + //} } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable checkConvertible(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno } @@ -2525,11 +2535,18 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if ux, ok := (*x).(*UnaryExpr); ok { debugPP.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) xt := evalStaticTypeOf(store, last, *x) - if t == nil { + //if t == nil { + // if isUntyped(xt) { + // t = defaultTypeOf(xt) + // } else { + // t = xt + // } + //} + if _, ok := t.(*InterfaceType); ok { if isUntyped(xt) { t = defaultTypeOf(xt) } else { - t = xt + t = xt // xt maybe typed while assign, with t is the type of LHS } } if coerce { // mostly when explicitly conversion, type call @@ -2551,7 +2568,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("else expr, xt not nil,x: %v, xt: %v \n", *x, xt) + debugPP.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v \n", *x, xt, t) // check convertible prior var isUnamed bool @@ -2560,10 +2577,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } if isUntyped(xt) { debugPP.Println("xt untyped") - if t == nil { + //if t == nil { + // t = defaultTypeOf(xt) + //} + if _, ok := t.(*InterfaceType); ok { t = defaultTypeOf(xt) - debugPP.Printf("default type of t: %v \n", t) } + debugPP.Printf("default type of t: %v \n", t) // Push type into expr if qualifying binary expr. if bx, ok := (*x).(*BinaryExpr); ok { switch bx.Op { @@ -2577,6 +2597,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return case EQL, LSS, GTR, NEQ, LEQ, GEQ: + // TODO: convert untyped to typed // nothing to do, quick forward debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) default: diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 7b9884a970d..f5357608528 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -2376,8 +2376,8 @@ func (b *Block) GetParent(store Store) *Block { } func (b *Block) GetPointerToInt(store Store, index int) PointerValue { - debugPP.Printf("---GetPointerToInt, path: %v \n", index) - debugPP.Printf("---GetPointerToInt, b: %v \n", b) + //debugPP.Printf("---GetPointerToInt, path: %v \n", index) + //debugPP.Printf("---GetPointerToInt, b: %v \n", b) vv := fillValueTV(store, &b.Values[index]) return PointerValue{ TV: vv, @@ -2387,8 +2387,8 @@ func (b *Block) GetPointerToInt(store Store, index int) PointerValue { } func (b *Block) GetPointerTo(store Store, path ValuePath) PointerValue { - debugPP.Printf("---GetPointerTo, path: %v \n", path) - debugPP.Printf("---GetPointerTo, b: %v \n", b) + //debugPP.Printf("---GetPointerTo, path: %v \n", path) + //debugPP.Printf("---GetPointerTo, b: %v \n", b) if path.IsBlockBlankPath() { if debug { if path.Name != "_" { diff --git a/gnovm/tests/files/types2/10a27d.gno b/gnovm/tests/files/types2/10a27d.gno new file mode 100644 index 00000000000..6a0325dee06 --- /dev/null +++ b/gnovm/tests/files/types2/10a27d.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64((1 << 2) << x) + println(y) + fmt.Printf("%T \n", y) +} + +// Output: +// 8192 +// uint64 diff --git a/gnovm/tests/files/types2/10a27e.gno b/gnovm/tests/files/types2/10a27e.gno new file mode 100644 index 00000000000..29c21b61553 --- /dev/null +++ b/gnovm/tests/files/types2/10a27e.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64(-(1 << 2) << x) + println(y) + fmt.Printf("%T \n", y) +} + +// Error: +// main/files/types2/10a27e.gno:7: bigint underflows target kind diff --git a/gnovm/tests/files/types2/10a27f.gno b/gnovm/tests/files/types2/10a27f.gno new file mode 100644 index 00000000000..daa6fa4a3ff --- /dev/null +++ b/gnovm/tests/files/types2/10a27f.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64((+(x + 1) << 1) << 2) + println(y) + fmt.Printf("%T \n", y) +} + +// Output: +// 96 +// uint64 diff --git a/gnovm/tests/files/types2/14.gno b/gnovm/tests/files/types2/14.gno new file mode 100644 index 00000000000..629175ebc19 --- /dev/null +++ b/gnovm/tests/files/types2/14.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func main() { + x := 1 + s := []int{1 << x} + + v := float32(s[0]) // type determined when indexed + println(v) + fmt.Printf("%T \n", v) +} + +// Output: +// 2 +// float32 diff --git a/gnovm/tests/files/types2/15.gno b/gnovm/tests/files/types2/15.gno new file mode 100644 index 00000000000..f6c249b8e46 --- /dev/null +++ b/gnovm/tests/files/types2/15.gno @@ -0,0 +1,26 @@ +package main + +// 1. find where shift expr is used +// a) type cast +// b) assign stmt +// c) composite literals + +// 2. get the dest type, if convert condition, convert +// condition: +// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get +// attr: HAS_SHIFT to determine if has shift. + +// 3. in type func, find termination condition when not const +// this condition should be the opposite of the convert condition + +// TODO: composite literal, checked, OK! +// TODO: simple print non-const untyped, checked, to typed if interface, OK! + +func main() { + a := 2 + s := []float32{1 << a} + println(s[0]) +} + +// Error: +// main/files/types2/15.gno:21: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/15a.gno b/gnovm/tests/files/types2/15a.gno new file mode 100644 index 00000000000..284da3b8748 --- /dev/null +++ b/gnovm/tests/files/types2/15a.gno @@ -0,0 +1,26 @@ +package main + +// 1. find where shift expr is used +// a) type cast +// b) assign stmt +// c) composite literals + +// 2. get the dest type, if convert condition, convert +// condition: +// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get +// attr: HAS_SHIFT to determine if has shift. + +// 3. in type func, find termination condition when not const +// this condition should be the opposite of the convert condition + +// TODO: composite literal +// TODO: simple print non-const untyped + +func main() { + a := 2 + s := map[string]float32{"k": 1 << a} + println(s[0]) +} + +// Error: +// main/files/types2/15a.gno:21: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/15b.gno b/gnovm/tests/files/types2/15b.gno new file mode 100644 index 00000000000..4cb0b57fb09 --- /dev/null +++ b/gnovm/tests/files/types2/15b.gno @@ -0,0 +1,30 @@ +package main + +// 1. find where shift expr is used +// a) type cast +// b) assign stmt +// c) composite literals + +// 2. get the dest type, if convert condition, convert +// condition: +// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get +// attr: HAS_SHIFT to determine if has shift. + +// 3. in type func, find termination condition when not const +// this condition should be the opposite of the convert condition + +// TODO: composite literal +// TODO: simple print non-const untyped + +func main() { + type S struct { + a float32 + } + s := S{ + a: 1 << 2, + } + println(s.a) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types2/15c.gno b/gnovm/tests/files/types2/15c.gno new file mode 100644 index 00000000000..e9b0032ac9a --- /dev/null +++ b/gnovm/tests/files/types2/15c.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := map[string]interface{}{"k": 1 << a} + println(s["k"]) +} + +// Output: +// 4 From 33ec34fb624d2abae9bdce77ef5b5ce8fadea690 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 16 Jan 2024 15:34:31 +0800 Subject: [PATCH 084/193] fixup --- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 4 +-- gnovm/pkg/gnolang/preprocess.go | 37 +++++++++++++------------ gnovm/pkg/gnolang/types.go | 23 +++++++-------- gnovm/pkg/gnolang/values_conversions.go | 13 +++++++-- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 185856c8a54..64d510461e9 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -366,7 +366,7 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { if rv.Kind() == reflect.Interface { if rv.IsNil() { return TypedValue{ // should not have untyped nil - T: &InterfaceType{}, + //T: &InterfaceType{}, } } else { rv = rv.Elem() diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index cee12bada65..0021db348ad 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -85,7 +85,7 @@ func (m *Machine) doOpEql() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isEqualityTypes(lv.T, rv.T) { + if maybeEqual(lv.T, rv.T) { debugPP.Println("-----type identical------") res = isEql(m.Store, lv, rv) } else { @@ -108,7 +108,7 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if isEqualityTypes(lv.T, rv.T) { + if maybeEqual(lv.T, rv.T) { res = !isEql(m.Store, lv, rv) } else { debugPP.Println("-----type not identical------") diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9eeb6573327..c9b34e8165c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1037,6 +1037,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { at := evalStaticTypeOf(store, last, n.Args[0]) switch arg0 := n.Args[0].(type) { case *ConstExpr: + // check legal type for nil if arg0.IsUndefined() { switch ct.Kind() { // special case for nil conversion check, TODO: refer to case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind: @@ -1698,7 +1699,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // in define, when RHS is untyped and contains SHR/SHL expression, explicitly // call this, to give the SHR/SHL a type, the dest type is a faux type. - checkOrConvertType(store, last, &n.Rhs[i], &InterfaceType{}, false, false) // 10a03 + checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 } } } else { // ASSIGN. @@ -2499,13 +2500,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) - //if t == nil { - // if isUntyped(xt) { - // t = defaultTypeOf(xt) - // } else { - // t = xt // xt maybe typed while assign, with t is the type of LHS - // } - //} + if t == nil { + if isUntyped(xt) { + t = defaultTypeOf(xt) + } else { + t = xt // xt maybe typed while assign, with t is the type of LHS + } + } if _, ok := t.(*InterfaceType); ok { if isUntyped(xt) { t = defaultTypeOf(xt) @@ -2535,13 +2536,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if ux, ok := (*x).(*UnaryExpr); ok { debugPP.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) xt := evalStaticTypeOf(store, last, *x) - //if t == nil { - // if isUntyped(xt) { - // t = defaultTypeOf(xt) - // } else { - // t = xt - // } - //} + if t == nil { + if isUntyped(xt) { + t = defaultTypeOf(xt) + } else { + t = xt + } + } if _, ok := t.(*InterfaceType); ok { if isUntyped(xt) { t = defaultTypeOf(xt) @@ -2577,9 +2578,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } if isUntyped(xt) { debugPP.Println("xt untyped") - //if t == nil { - // t = defaultTypeOf(xt) - //} + if t == nil { + t = defaultTypeOf(xt) + } if _, ok := t.(*InterfaceType); ok { t = defaultTypeOf(xt) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 9b40900d38c..1d5f74b257a 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2108,38 +2108,39 @@ func assertSameTypes(lt, rt Type) { } } -func isEqualityTypes(lt, rt Type) bool { - debugPP.Printf("check isEqualityTypes, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) +// TODO: break down this +func maybeEqual(lt, rt Type) bool { + debugPP.Printf("check maybeEqual, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) if lpt, ok := lt.(*PointerType); ok { // refer to 0f31 lt = lpt.Elt + maybeEqual(lt, rt) } if rpt, ok := rt.(*PointerType); ok { rt = rpt.Elt + maybeEqual(lt, rt) } // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil if lt == nil && rt == nil { + debugPP.Println("0") // both are nil. } else if lt == nil || rt == nil { - // one is nil. see function comment. + // one is nil. + debugPP.Println("1") } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { // XXX, is this necessary? // one is untyped of same kind. + debugPP.Println("2") } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // XXX, what hit this // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? - } else if lt.Kind() == InterfaceKind && - IsImplementedBy(lt, rt) { - // one is untyped of same kind. - // rt implements lt (and lt is nil interface). - } else if rt.Kind() == InterfaceKind && - IsImplementedBy(rt, lt) { - // lt implements rt (and rt is nil interface). - } else if lt.TypeID() == rt.TypeID() { // order matters + debugPP.Println("3") + } else if lt.TypeID() == rt.TypeID() { debugPP.Println("typeID equal") // non-nil types are identical. + debugPP.Println("6") } else { return false } diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 0dc06fbc2a0..43ba1e7e363 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -15,6 +15,9 @@ import ( // TODO: return error, and let caller also print the file and line. func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { debugPP.Printf("--------------ConvertTo, tv: %v, t: %v \n", tv, t) + //if t == nil { + // t = defaultTypeOf(tv.T) // TODO: check this on master + //} if debug { if t == nil { panic("ConvertTo() requires non-nil type") @@ -80,9 +83,13 @@ GNO_CASE: // special case for interface target if t.Kind() == InterfaceKind { if tv.IsUndefined() { // set interface type - if _, ok := t.(*NativeType); !ok { - debugPP.Println("t is interface and not native") - tv.T = t + debugPP.Printf("-----convertTo, tv: %v, tv.T: %v \n", tv, tv.T) + if tv.T == nil { // nil T and nil Value. not a nil interface but a nil + debugPP.Println("tv.T is nil") + if _, ok := t.(*NativeType); !ok { + debugPP.Printf("t is interface and not native, t: %v \n", t) + tv.T = t + } } } return From 836941dd8567e72117c4fbfd08918a585f6cc305 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 16 Jan 2024 17:20:56 +0800 Subject: [PATCH 085/193] sync and test --- gnovm/pkg/gnolang/gonative.go | 4 +- gnovm/pkg/gnolang/op_binary.go | 21 ++++---- gnovm/pkg/gnolang/op_exec.go | 2 +- gnovm/pkg/gnolang/op_expressions.go | 7 ++- gnovm/pkg/gnolang/types.go | 67 ++++++------------------- gnovm/tests/files/types/0f49.gno | 78 +++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 69 deletions(-) create mode 100644 gnovm/tests/files/types/0f49.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 64d510461e9..2c3eafa22aa 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -365,9 +365,7 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { } if rv.Kind() == reflect.Interface { if rv.IsNil() { - return TypedValue{ // should not have untyped nil - //T: &InterfaceType{}, - } + return TypedValue{} } else { rv = rv.Elem() } diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 0021db348ad..8344f8a3ac8 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -85,14 +85,10 @@ func (m *Machine) doOpEql() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if maybeEqual(lv.T, rv.T) { - debugPP.Println("-----type identical------") - res = isEql(m.Store, lv, rv) - } else { - debugPP.Println("-----type not identical------") - res = false + if debug { + assertAssignable(lv.T, rv.T) } - + res = isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -108,12 +104,10 @@ func (m *Machine) doOpNeq() { debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool - if maybeEqual(lv.T, rv.T) { - res = !isEql(m.Store, lv, rv) - } else { - debugPP.Println("-----type not identical------") - res = true + if debug { + assertAssignable(lv.T, rv.T) } + res = !isEql(m.Store, lv, rv) debugPP.Println("------res:-----", res) lv.T = UntypedBoolType lv.V = nil @@ -353,6 +347,9 @@ func isEql(store Store, lv, rv *TypedValue) bool { } else if rvu { return false } + if !isSameType(lv.T, rv.T) { + return false + } if lnt, ok := lv.T.(*NativeType); ok { if rnt, ok := rv.T.(*NativeType); ok { if lnt.Type != rnt.Type { diff --git a/gnovm/pkg/gnolang/op_exec.go b/gnovm/pkg/gnolang/op_exec.go index 300303135ad..5a7431799b3 100644 --- a/gnovm/pkg/gnolang/op_exec.go +++ b/gnovm/pkg/gnolang/op_exec.go @@ -957,7 +957,7 @@ func (m *Machine) doOpSwitchClauseCase() { // eval whether cv == tv. if debug { - assertEqualityTypes(cv.T, tv.T) + assertAssignable(cv.T, tv.T) } match := isEql(m.Store, cv, tv) if match { diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 6a16506d6d1..c68554cfab7 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -197,8 +197,13 @@ func (m *Machine) doOpRef() { nv.Value = rv2 } } + elt := xv.TV.T + if elt == DataByteType { + elt = xv.TV.V.(DataByteValue).ElemType + } m.PushValue(TypedValue{ - T: m.Alloc.NewType(&PointerType{Elt: xv.TV.T}), + //T: m.Alloc.NewType(&PointerType{Elt: xv.TV.T}), + T: m.Alloc.NewType(&PointerType{Elt: elt}), V: xv, }) } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 1d5f74b257a..5a4fa338040 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2108,67 +2108,30 @@ func assertSameTypes(lt, rt Type) { } } -// TODO: break down this -func maybeEqual(lt, rt Type) bool { - debugPP.Printf("check maybeEqual, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) - if lpt, ok := lt.(*PointerType); ok { // refer to 0f31 - lt = lpt.Elt - maybeEqual(lt, rt) - } - if rpt, ok := rt.(*PointerType); ok { - rt = rpt.Elt - maybeEqual(lt, rt) - } - // lt or rt could be nil in runtime, e.g. a == nil, type of RHS would be nil - if lt == nil && rt == nil { - debugPP.Println("0") - // both are nil. - } else if lt == nil || rt == nil { - // one is nil. - debugPP.Println("1") +func isSameType(lt, rt Type) bool { + return lt == nil && rt == nil || // both are nil/undefined + (lt != nil && rt != nil) && // both are defined + (lt.TypeID() == rt.TypeID()) // and identical. +} + +func assertAssignable(lt, rt Type) { + debugPP.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + if isSameType(lt, rt) { + // both are nil/undefined or same type. + } else if lt == nil || rt == nil { // TODO: consider this. files/context.gno + // LHS is undefined } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { // XXX, is this necessary? + isUntyped(lt) || isUntyped(rt) { // one is untyped of same kind. - debugPP.Println("2") } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { // XXX, what hit this + isDataByte(lt) { // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? - debugPP.Println("3") - } else if lt.TypeID() == rt.TypeID() { - debugPP.Println("typeID equal") - // non-nil types are identical. - debugPP.Println("6") - } else { - return false - } - return true -} - -// Like assertSameTypes(), but more relaxed, for == and !=. -func assertEqualityTypes(lt, rt Type) { - if lt == nil && rt == nil { - // both are nil. - } else if lt == nil || rt == nil { - // one is nil. see function comment. - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. - } else if lt.Kind() == InterfaceKind && - IsImplementedBy(lt, rt) { - // one is untyped of same kind. - // rt implements lt (and lt is nil interface). - } else if rt.Kind() == InterfaceKind && - IsImplementedBy(rt, lt) { - // lt implements rt (and rt is nil interface). - } else if lt.TypeID() == rt.TypeID() { - // non-nil types are identical. } else { - // panic("7, incompatible operands") debug.Errorf( - "incompatible operands in binary (eql/neq) expression: %s and %s", + "incompatible operands in binary expression: %s and %s", lt.String(), rt.String(), ) diff --git a/gnovm/tests/files/types/0f49.gno b/gnovm/tests/files/types/0f49.gno new file mode 100644 index 00000000000..7b8ab815003 --- /dev/null +++ b/gnovm/tests/files/types/0f49.gno @@ -0,0 +1,78 @@ +package main + +import ( + "fmt" +) + +// implicit type conversion and equality +// NOTE:, the output type is incorrect, but the == eval is right +func main() { + { // case 1 with slices + type X []byte + var x interface{} = []byte("foo") + var xx interface{} = X(x.([]byte)) + fmt.Printf("%T, %v \n", x, x) // []uint8 [102 111 111] + fmt.Printf("%T, %v \n", xx, xx) // main.X [102 111 111] + fmt.Println(x == xx) // false + } + + { // case 2 with arrays + type X [3]byte + var x interface{} = [3]byte{102, 111, 111} + var xx interface{} = X(x.([3]byte)) + fmt.Printf("%T, %v \n", x, x) // [3]uint8 [102 111 111] + fmt.Printf("%T, %v \n", xx, xx) // main.X [102 111 111] + fmt.Println(x == xx) // false still. + } + { // switch without conversion + type X [3]byte + var x interface{} = [3]byte{102, 111, 111} + switch x { + case [3]byte{102, 111, 111}: + fmt.Println("ok") // ok + case [3]byte{102, 111, 112}: + panic("should not happen") + default: + panic("should not happen") + } + } + + { // case 1 switch with conversion no match + type X [3]byte + var x interface{} = X([3]byte{102, 111, 111}) + switch x { + case [3]byte{102, 111, 111}: + panic("should not happen") + case [3]byte{102, 111, 112}: + panic("should not happen") + default: + fmt.Println("no match") // no match + } + } + + { // case 2 switch with conversion match + type X [3]byte + var x interface{} = X([3]byte{102, 111, 111}) + switch x { + case [3]byte{102, 111, 111}: + panic("should not happen") + case X([3]byte{102, 111, 111}): + fmt.Println("ok") // ok + case X([3]byte{102, 111, 112}): + panic("should not happen") + default: + panic("should not happen") + } + } +} + +// Output: +// []uint8, [102 111 111] +// []uint8, [102 111 111] +// false +// [3]uint8, [102 111 111] +// [3]uint8, [102 111 111] +// false +// ok +// no match +// ok From 8d3d8553930f64e71d1a7901286b1696db4b17ad Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Jan 2024 12:10:04 +0800 Subject: [PATCH 086/193] fixup --- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 5 +- gnovm/pkg/gnolang/op_expressions.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 43 ++++++------ gnovm/pkg/gnolang/types.go | 87 ++++--------------------- gnovm/pkg/gnolang/values.go | 8 +-- gnovm/pkg/gnolang/values_conversions.go | 15 ++--- gnovm/tests/files/types/0f49.gno | 2 +- 8 files changed, 53 insertions(+), 111 deletions(-) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 2c3eafa22aa..655517c3eb0 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -903,7 +903,7 @@ func gno2GoType(t Type) reflect.Type { // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). -// This is called when autoNative is true in checkConvertible(). +// This is called when autoNative is true in checkAssignable(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 8344f8a3ac8..7c07e87fa27 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -43,7 +43,7 @@ func (m *Machine) doOpBinary1() { // XXX. in preprocess stage, we have checked: // 1. if dt(type of lhs or rhs, depends on its convert dir); // 2. whether lt and rt is identical if they are typed(typeID ==); or if one is not typed, but is -// assignable to the other side. +// assignbaleTo to the other side. // so, logically, there's no need to check the type equivalence here. leave the check in debug mode. // NOTE: one exception is for == and !=, where there's a relaxed scope of operands for compare(maybeIdentical), // there might be cases lt and rt is not identical. e.g. two different types conform same interface. @@ -89,6 +89,7 @@ func (m *Machine) doOpEql() { assertAssignable(lv.T, rv.T) } res = isEql(m.Store, lv, rv) + debugPP.Println("------is EQL:-----", res) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -108,7 +109,7 @@ func (m *Machine) doOpNeq() { assertAssignable(lv.T, rv.T) } res = !isEql(m.Store, lv, rv) - debugPP.Println("------res:-----", res) + debugPP.Println("------is NEQ:-----", res) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index c68554cfab7..773f3339665 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -202,7 +202,7 @@ func (m *Machine) doOpRef() { elt = xv.TV.V.(DataByteValue).ElemType } m.PushValue(TypedValue{ - //T: m.Alloc.NewType(&PointerType{Elt: xv.TV.T}), + // T: m.Alloc.NewType(&PointerType{Elt: xv.TV.T}), T: m.Alloc.NewType(&PointerType{Elt: elt}), V: xv, }) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c9b34e8165c..fc2f2ae31a8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1095,7 +1095,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // general case, for non-const untyped && no nested untyped shift // after handling const, and special cases recursively, set the target node type debugPP.Println("general case") - //ct := evalStaticType(store, last, n.Func) + // ct := evalStaticType(store, last, n.Func) n.SetAttribute(ATTR_TYPEOF_VALUE, ct) return n, TRANS_CONTINUE default: @@ -1106,7 +1106,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Handle special cases. // NOTE: these appear to be actually special cases in go. - // In general, a string is not assignable to []bytes + // In general, a string is not assignbaleTo to []bytes // without conversion. if cx, ok := n.Func.(*ConstExpr); ok { fv := cx.GetFunc() @@ -1237,12 +1237,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, tv := range argTVs { if hasVarg { if (len(spts) - 1) <= i { - checkConvertible(tv.T, spts[len(spts)-1].Type.Elem(), true) + checkAssignable(tv.T, spts[len(spts)-1].Type.Elem(), true) } else { - checkConvertible(tv.T, spts[i].Type, true) + checkAssignable(tv.T, spts[i].Type, true) } } else { - checkConvertible(tv.T, spts[i].Type, true) + checkAssignable(tv.T, spts[i].Type, true) } } } else { @@ -2189,13 +2189,18 @@ func evalStaticTypeOf(store Store, last BlockNode, x Expr) Type { // like evalStaticTypeOf() but returns the raw *tupleType for *CallExpr. func evalStaticTypeOfRaw(store Store, last BlockNode, x Expr) (t Type) { + debugPP.Printf("---evalStaticTypeOfRaw: %v \n", x) if t, ok := x.GetAttribute(ATTR_TYPEOF_VALUE).(Type); ok { + debugPP.Printf("1, t: %v \n", t) return t } else if _, ok := x.(*constTypeExpr); ok { + debugPP.Println("2") return gTypeType } else if ctx, ok := x.(*ConstExpr); ok { + debugPP.Println("3") return ctx.T } else { + debugPP.Println("4") pn := packageOf(last) // NOTE: do not load the package value from store, // because we may be preprocessing in the middle of @@ -2493,7 +2498,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if !coerce { if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno, TODO: make it !coerced - checkConvertible(cx.T, t, autoNative) // refer to 22a17a_filetest, check args + checkAssignable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } } convertConst(store, last, cx, t) @@ -2521,16 +2526,16 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 // dt not interface type - //if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil + // if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) //} else { // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOperandWithOp - // checkConvertible(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno + // checkAssignable(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno //} } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable - checkConvertible(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno + checkAssignable(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno } } else if ux, ok := (*x).(*UnaryExpr); ok { @@ -2560,10 +2565,10 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else { - checkConvertible(xt, t, false) + checkAssignable(xt, t, false) } } else { - checkConvertible(xt, t, false) + checkAssignable(xt, t, false) } // "push" expected type into shift unary's operand // checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) @@ -2574,7 +2579,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // check convertible prior var isUnamed bool if t != nil && !coerce { - isUnamed = checkConvertible(xt, t, autoNative) + isUnamed = checkAssignable(xt, t, autoNative) } if isUntyped(xt) { debugPP.Println("xt untyped") @@ -2628,10 +2633,10 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - debugPP.Printf("---convertConst---, cx:%v, t:%v \n", cx, t) + debugPP.Printf("---convertConst---, cx:%v,cx.T: %v, t:%v \n", cx, cx.T, t) if t != nil && t.Kind() == InterfaceKind { - if cx.IsUndefined() { - if _, ok := t.(*NativeType); !ok { // bypass native nil interface + if cx.IsUndefined() && cx.T == nil { // if cx is nil, not undefined interface + if _, ok := t.(*NativeType); !ok { // bypass native nil interface, not support native interface(nil) now debugPP.Println("special case for undefined to interface{}") debugPP.Printf("before convert, cx: %v, cx.T: %v \n", cx, cx.T) ConvertTo(nilAllocator, store, &cx.TypedValue, t) @@ -2730,7 +2735,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, case EQL, NEQ: // NOTE: not checking types strict identical here, unlike ADD, etc. // this will pass the case of lhs is interface and rhs implements this interface, vice versa. - // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkConvertible -> assignable + // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkAssignable -> assignbaleTo assertEqualityCompatible(xt, dt) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryPredicates[op]; ok { @@ -2801,12 +2806,12 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func checkConvertible(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { - debugPP.Printf("checkConvertible, xt: %v, dt: %v \n", xt, dt) +func checkAssignable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { + debugPP.Printf("checkAssignable, xt: %v, dt: %v \n", xt, dt) if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno return } - return assignable(xt, dt, autoNative) + return assignbaleTo(xt, dt, autoNative) } // Returns any names not yet defined nor predefined in expr. These happen diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 5a4fa338040..89b0bda0336 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2114,6 +2114,7 @@ func isSameType(lt, rt Type) bool { (lt.TypeID() == rt.TypeID()) // and identical. } +// TODO: use another name to reduce confusion, we already have checkAssignableTo(or change this) func assertAssignable(lt, rt Type) { debugPP.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) if isSameType(lt, rt) { @@ -2202,17 +2203,16 @@ func assertEqualityCompatible(xt, dt Type) { } } -// check if xt can be assigned to dt, conversionNeeded indicates further conversion needed from unnamed -> named +// check if xt can be assigned to dt, conversionNeeded indicates further conversion needed especially from unnamed -> named // case 1. untyped const to typed const with same kind // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general cases. -// XXX. the name of assignable should be considered, or convertable? -// seems they have same function but implies different application scenarios -func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { - debugPP.Printf("assignable, xt: %v dt: %v \n", xt, dt) +// XXX. the name of assignbaleTo should be considered. +func assignbaleTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { + debugPP.Printf("assignbaleTo, xt: %v dt: %v \n", xt, dt) // case3 - // if xt or dt is empty interface, assignable + // if xt or dt is empty interface, assignbaleTo // if no empty interface, then check if xt satisfied dt if dt.Kind() == InterfaceKind { debugPP.Println("dt is interface") @@ -2277,64 +2277,6 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } else { panic("should not happen") } - } else if xt.Kind() == InterfaceKind { - debugPP.Println("xt is interface") - if ixt, ok := baseOf(xt).(*InterfaceType); ok { - if ixt.IsEmptyInterface() { - debugPP.Println("xt is empty interface") - // if dt is an empty Gno interface, any x ok. - return // ok - } else if ixt.IsImplementedBy(dt) { - debugPP.Println("xt is implemented by dt") - // if dt implements idt, ok. - return // ok - } else if idt, ok := dt.(*InterfaceType); ok { - if idt.IsEmptyInterface() { - return - } - } else { - panic(fmt.Sprintf( - "%s does not implement %s", - dt.String(), xt.String())) - } - } else if nxt, ok := baseOf(xt).(*NativeType); ok { - nixt := nxt.Type - if nixt.NumMethod() == 0 { - // if dt is an empty Go native interface, ditto. - return // ok - } else if ndt, ok := baseOf(dt).(*NativeType); ok { - // if xt has native base, do the naive native. - if nxt.Type.AssignableTo(nixt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nixt.String(), ndt.String())) - } - } else if pdt, ok := baseOf(dt).(*PointerType); ok { - nxt, ok := pdt.Elt.(*NativeType) - if !ok { - panic(fmt.Sprintf( - "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", - nixt.String(), pdt.String())) - } - // if xt has native base, do the naive native. - if reflect.PtrTo(nxt.Type).AssignableTo(nixt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nixt.String(), pdt.String())) - } - } else { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - xt.String(), - dt.String())) - } - } else { - panic("should not happen") - } } // case2 @@ -2466,23 +2408,23 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := assignable(pt.Elt, cdt.Elt, false) + cdt := assignbaleTo(pt.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := assignable(at.Elt, cdt.Elt, false) + cdt := assignbaleTo(at.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := assignable(st.Elt, cdt.Elt, false) + cdt := assignbaleTo(st.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := assignable(mt.Key, cdt.Key, false) - cn2 := assignable(mt.Value, cdt.Value, false) + cn1 := assignbaleTo(mt.Key, cdt.Key, false) + cn2 := assignbaleTo(mt.Value, cdt.Value, false) return cn1 || cn2 || conversionNeeded } case *FuncType: @@ -2528,7 +2470,6 @@ func assignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { "cannot use %s as %s", xt.String(), dt.String())) - //} } // ---------------------------------------- @@ -2635,7 +2576,7 @@ func fillEmbeddedName(ft *FieldType) { ft.Embedded = true } -// TODO: empty interface? refer to assignable +// TODO: empty interface? refer to assignbaleTo func IsImplementedBy(it Type, ot Type) bool { switch cbt := baseOf(it).(type) { case *InterfaceType: @@ -2770,7 +2711,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkConvertible(spec, match.Elem(), false) + checkAssignable(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -2784,7 +2725,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkConvertible(spec, match, false) + checkAssignable(spec, match, false) return // ok } else { if isUntyped(spec) { diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index f5357608528..cbd3fc69f73 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -2376,8 +2376,8 @@ func (b *Block) GetParent(store Store) *Block { } func (b *Block) GetPointerToInt(store Store, index int) PointerValue { - //debugPP.Printf("---GetPointerToInt, path: %v \n", index) - //debugPP.Printf("---GetPointerToInt, b: %v \n", b) + // debugPP.Printf("---GetPointerToInt, path: %v \n", index) + // debugPP.Printf("---GetPointerToInt, b: %v \n", b) vv := fillValueTV(store, &b.Values[index]) return PointerValue{ TV: vv, @@ -2387,8 +2387,8 @@ func (b *Block) GetPointerToInt(store Store, index int) PointerValue { } func (b *Block) GetPointerTo(store Store, path ValuePath) PointerValue { - //debugPP.Printf("---GetPointerTo, path: %v \n", path) - //debugPP.Printf("---GetPointerTo, b: %v \n", b) + // debugPP.Printf("---GetPointerTo, path: %v \n", path) + // debugPP.Printf("---GetPointerTo, b: %v \n", b) if path.IsBlockBlankPath() { if debug { if path.Name != "_" { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 43ba1e7e363..2acae558320 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -15,9 +15,6 @@ import ( // TODO: return error, and let caller also print the file and line. func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { debugPP.Printf("--------------ConvertTo, tv: %v, t: %v \n", tv, t) - //if t == nil { - // t = defaultTypeOf(tv.T) // TODO: check this on master - //} if debug { if t == nil { panic("ConvertTo() requires non-nil type") @@ -82,14 +79,12 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { GNO_CASE: // special case for interface target if t.Kind() == InterfaceKind { - if tv.IsUndefined() { // set interface type + if tv.IsUndefined() && tv.T == nil { // if tv.T == nil, nil T and nil Value. not a nil interface debugPP.Printf("-----convertTo, tv: %v, tv.T: %v \n", tv, tv.T) - if tv.T == nil { // nil T and nil Value. not a nil interface but a nil - debugPP.Println("tv.T is nil") - if _, ok := t.(*NativeType); !ok { - debugPP.Printf("t is interface and not native, t: %v \n", t) - tv.T = t - } + debugPP.Println("tv.T is nil") + if _, ok := t.(*NativeType); !ok { // no support for native now + debugPP.Printf("t is interface and not native, t: %v \n", t) + tv.T = t } } return diff --git a/gnovm/tests/files/types/0f49.gno b/gnovm/tests/files/types/0f49.gno index 7b8ab815003..1e930f65345 100644 --- a/gnovm/tests/files/types/0f49.gno +++ b/gnovm/tests/files/types/0f49.gno @@ -5,7 +5,7 @@ import ( ) // implicit type conversion and equality -// NOTE:, the output type is incorrect, but the == eval is right +// NOTE: the output type is incorrect, but the == eval is right func main() { { // case 1 with slices type X []byte From e4e5e2a82fbc1dad958114d3a85f8e3ed59f78ab Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Jan 2024 21:42:52 +0800 Subject: [PATCH 087/193] check nil --- gnovm/pkg/gnolang/op_binary.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 26 ++++++------- gnovm/pkg/gnolang/types.go | 68 +++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 7c07e87fa27..a51e1fd00b6 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -43,7 +43,7 @@ func (m *Machine) doOpBinary1() { // XXX. in preprocess stage, we have checked: // 1. if dt(type of lhs or rhs, depends on its convert dir); // 2. whether lt and rt is identical if they are typed(typeID ==); or if one is not typed, but is -// assignbaleTo to the other side. +// checkAssignable to the other side. // so, logically, there's no need to check the type equivalence here. leave the check in debug mode. // NOTE: one exception is for == and !=, where there's a relaxed scope of operands for compare(maybeIdentical), // there might be cases lt and rt is not identical. e.g. two different types conform same interface. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index fc2f2ae31a8..558b342784d 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1106,7 +1106,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Handle special cases. // NOTE: these appear to be actually special cases in go. - // In general, a string is not assignbaleTo to []bytes + // In general, a string is not checkAssignable to []bytes // without conversion. if cx, ok := n.Func.(*ConstExpr); ok { fv := cx.GetFunc() @@ -1699,7 +1699,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // in define, when RHS is untyped and contains SHR/SHL expression, explicitly // call this, to give the SHR/SHL a type, the dest type is a faux type. - checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 + switch n.Rhs[i].(type) { + case *BinaryExpr, *UnaryExpr: + checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 + default: + // do nothing + } } } } else { // ASSIGN. @@ -2498,6 +2503,10 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if !coerce { if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno, TODO: make it !coerced + // the reason why we need this is that the checkOperandWithOp can not filter out all mismatch case, + // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=, it's actually postponed to runtime check.) + // we still need a safe guard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). + // It does not guarantee convertible, e.g. s1{foo: 1} == 1), why this pass check? XXX. checkAssignable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } } @@ -2735,7 +2744,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, case EQL, NEQ: // NOTE: not checking types strict identical here, unlike ADD, etc. // this will pass the case of lhs is interface and rhs implements this interface, vice versa. - // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkAssignable -> assignbaleTo + // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkAssignable assertEqualityCompatible(xt, dt) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryPredicates[op]; ok { @@ -2803,17 +2812,6 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, } } -// Assert that xt can be assigned as dt (dest type). -// If autoNative is true, a broad range of xt can match against -// a target native dt type, if and only if dt is a native type. -func checkAssignable(xt Type, dt Type, autoNative bool) (conversionNeeded bool) { - debugPP.Printf("checkAssignable, xt: %v, dt: %v \n", xt, dt) - if xt == nil || dt == nil { // refer to 0f18_filetest, assign8.gno - return - } - return assignbaleTo(xt, dt, autoNative) -} - // Returns any names not yet defined nor predefined in expr. These happen // upon transcribe:enter from the top, so value paths cannot be used. If no // names are un and x is TypeExpr, evalStaticType(store,last, x) must not diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 89b0bda0336..907572a093b 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2145,7 +2145,6 @@ func assertAssignable(lt, rt Type) { // then check the corresponding type(the other side of the operator) is convertable to t. // this is located in checkOrConvertType->checkConvertable stage. // so, checkOperandWithOp is working as a pre-check. -// TODO: just panic func assertEqualityCompatible(xt, dt Type) { debugPP.Printf("--- assertEqualityCompatible---, xt: %v, dt: %v \n", xt, dt) switch cdt := baseOf(dt).(type) { @@ -2187,32 +2186,53 @@ func assertEqualityCompatible(xt, dt Type) { panic(fmt.Sprintf("%v is not comparable \n", dt)) } case nil: // refer to 0a01_filetest, 0f32_filetest. - switch cxt := baseOf(xt).(type) { - case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer - case *NativeType: - switch nk := cxt.Type.Kind(); nk { - case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: - default: - panic(fmt.Sprintf("invalid operation, nil can not be compared to %v \n", nk)) - } + assertMaybeNil(xt) + default: + panic(fmt.Sprintf("%v is not comparable \n", dt)) + } +} + +func assertMaybeNil(t Type) { + if t == nil { + panic(fmt.Sprintf("invalid operation, nil can not be compared to nil \n")) + } + switch cxt := baseOf(t).(type) { + case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer + case *NativeType: + switch nk := cxt.Type.Kind(); nk { + case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: default: - panic(fmt.Sprintf("invalid operation, nil can not be compared to nil \n")) + panic(fmt.Sprintf("invalid operation, nil can not be compared to %v \n", nk)) } default: - panic(fmt.Sprintf("%v is not comparable \n", dt)) + panic(fmt.Sprintf("invalid operation, nil can not be compared to %v \n", t)) } } -// check if xt can be assigned to dt, conversionNeeded indicates further conversion needed especially from unnamed -> named +// Assert that xt can be assigned as dt (dest type). +// If autoNative is true, a broad range of xt can match against +// a target native dt type, if and only if dt is a native type. + +// check if xt can be assigned to dt. conversionNeeded indicates further conversion needed especially from unnamed -> named +// case 0. nil check // case 1. untyped const to typed const with same kind // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt -// case 4. general cases. -// XXX. the name of assignbaleTo should be considered. -func assignbaleTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { - debugPP.Printf("assignbaleTo, xt: %v dt: %v \n", xt, dt) +// case 4. general cases for primitives and composite. +// XXX. the name of checkAssignable should be considered. +// we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime +func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { + debugPP.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) + // case0 + if xt == nil { // refer to 0f18_filetest + assertMaybeNil(dt) + return + } + if dt == nil { // refer to assign8.gno + return + } // case3 - // if xt or dt is empty interface, assignbaleTo + // if xt or dt is empty interface, checkAssignable // if no empty interface, then check if xt satisfied dt if dt.Kind() == InterfaceKind { debugPP.Println("dt is interface") @@ -2337,7 +2357,7 @@ func assignbaleTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // special case if implicitly named primitive type. // TODO simplify with .IsNamedType(). if _, ok := xt.(PrimitiveType); ok { - debugPP.Println("xt is primitiveType") + debugPP.Printf("xt is primitiveType: %v, ddt: %v \n", xt, ddt) // this is special when dt is the declared type of x if !isUntyped(xt) { panic(fmt.Sprintf( @@ -2408,23 +2428,23 @@ func assignbaleTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := assignbaleTo(pt.Elt, cdt.Elt, false) + cdt := checkAssignable(pt.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := assignbaleTo(at.Elt, cdt.Elt, false) + cdt := checkAssignable(at.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := assignbaleTo(st.Elt, cdt.Elt, false) + cdt := checkAssignable(st.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := assignbaleTo(mt.Key, cdt.Key, false) - cn2 := assignbaleTo(mt.Value, cdt.Value, false) + cn1 := checkAssignable(mt.Key, cdt.Key, false) + cn2 := checkAssignable(mt.Value, cdt.Value, false) return cn1 || cn2 || conversionNeeded } case *FuncType: @@ -2576,7 +2596,7 @@ func fillEmbeddedName(ft *FieldType) { ft.Embedded = true } -// TODO: empty interface? refer to assignbaleTo +// TODO: empty interface? refer to checkAssignable func IsImplementedBy(it Type, ot Type) bool { switch cbt := baseOf(it).(type) { case *InterfaceType: From 8ee97249b079ab0418a3a1e7c682613768d1a999 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Jan 2024 23:13:59 +0800 Subject: [PATCH 088/193] fixup --- gnovm/pkg/gnolang/types.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 907572a093b..f117791f517 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2145,6 +2145,7 @@ func assertAssignable(lt, rt Type) { // then check the corresponding type(the other side of the operator) is convertable to t. // this is located in checkOrConvertType->checkConvertable stage. // so, checkOperandWithOp is working as a pre-check. +// TODO: consider and tune log func assertEqualityCompatible(xt, dt Type) { debugPP.Printf("--- assertEqualityCompatible---, xt: %v, dt: %v \n", xt, dt) switch cdt := baseOf(dt).(type) { @@ -2186,15 +2187,15 @@ func assertEqualityCompatible(xt, dt Type) { panic(fmt.Sprintf("%v is not comparable \n", dt)) } case nil: // refer to 0a01_filetest, 0f32_filetest. - assertMaybeNil(xt) + assertMaybeNil("invalid operation, nil can not be compared to", xt) default: panic(fmt.Sprintf("%v is not comparable \n", dt)) } } -func assertMaybeNil(t Type) { +func assertMaybeNil(msg string, t Type) { if t == nil { - panic(fmt.Sprintf("invalid operation, nil can not be compared to nil \n")) + panic(fmt.Sprintf("%s %s \n", msg, "nil")) } switch cxt := baseOf(t).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer @@ -2202,10 +2203,10 @@ func assertMaybeNil(t Type) { switch nk := cxt.Type.Kind(); nk { case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: default: - panic(fmt.Sprintf("invalid operation, nil can not be compared to %v \n", nk)) + panic(fmt.Sprintf("%s %s \n", msg, nk)) } default: - panic(fmt.Sprintf("invalid operation, nil can not be compared to %v \n", t)) + panic(fmt.Sprintf("%s %s \n", msg, t)) } } @@ -2225,7 +2226,7 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) // case0 if xt == nil { // refer to 0f18_filetest - assertMaybeNil(dt) + assertMaybeNil("invalid operation, nil can not be compared to", dt) return } if dt == nil { // refer to assign8.gno @@ -2346,7 +2347,6 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { "cannot use %s as %s without explicit conversion", dxt.String(), dt.String())) - // xt = dxt.Base } else { // carry on with baseOf(dxt) xt = dxt.Base From 292b0380bf3cfd1736e14f009f14f275321cbf06 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Jan 2024 11:53:44 +0800 Subject: [PATCH 089/193] clear --- gnovm/pkg/gnolang/preprocess.go | 4 ++-- gnovm/pkg/gnolang/types.go | 7 +++---- gnovm/tests/file_test.go | 5 +++++ gnovm/tests/files/types/0b0_filetest.gno | 4 +--- gnovm/tests/files/types/0b2_filetest.gno | 6 +++--- gnovm/tests/files/types/0b3_filetest.gno | 12 ------------ gnovm/tests/files/types/0b5_native_filetest.gno | 11 ----------- gnovm/tests/files/types/0f15_filetest.gno | 1 - gnovm/tests/files/types/0f16_filetest.gno | 4 ++-- gnovm/tests/files/types/0f20_filetest.gno | 4 ++-- gnovm/tests/files/types/0f21_filetest.gno | 2 +- gnovm/tests/files/types/0f26_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/0f2b_native.gno | 4 ++-- gnovm/tests/files/types/0f2b_stdlibs.gno | 2 +- gnovm/tests/files/types/0f2c_native.gno | 4 ++-- gnovm/tests/files/types/0f2c_stdlibs.gno | 2 +- gnovm/tests/files/types/0f2d_filetest.gno | 4 ++-- gnovm/tests/files/types/0f3_filetest.gno | 3 +-- gnovm/tests/files/types/0f43a_filetest.gno | 9 --------- gnovm/tests/files/types/0f47_nilcast_filetest.gno | 6 +++--- gnovm/tests/files/types/0f47a_filetest.gno | 2 +- gnovm/tests/files/types/0f47d_filetest.gno | 2 +- gnovm/tests/files/types/0f48_filetest.gno | 2 +- gnovm/tests/files/types/0f4_filetest.gno | 3 +-- gnovm/tests/files/types/0f5_filetest.gno | 3 +-- gnovm/tests/files/types/0f7_filetest.gno | 3 +-- gnovm/tests/files/types/0f8_stdlibs_filetest.gno | 2 +- gnovm/tests/files/types/26a3_filetest.gno | 3 +++ gnovm/tests/files/{types => types2}/27_filetest.gno | 0 gnovm/tests/files/{types => types2}/27a_filetest.gno | 2 +- 30 files changed, 43 insertions(+), 75 deletions(-) delete mode 100644 gnovm/tests/files/types/0b5_native_filetest.gno rename gnovm/tests/files/{types => types2}/27_filetest.gno (100%) rename gnovm/tests/files/{types => types2}/27a_filetest.gno (51%) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 558b342784d..1269baa38ca 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1039,7 +1039,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *ConstExpr: // check legal type for nil if arg0.IsUndefined() { - switch ct.Kind() { // special case for nil conversion check, TODO: refer to + switch ct.Kind() { // special case for nil conversion check. refer to 0f47a case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind: dt = ct // convert nil to typed-nil default: @@ -2704,7 +2704,7 @@ const ( // first, check is the dt type satisfies op; // second, check if xt can be converted to dt, this is done after checkOperandWithOp, in checkOrConvertType(), func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { - debugPP.Printf("checkOperandWithOp, dt: %v, op: %v, nt: %v \n", dt, op, nt) + debugPP.Printf("checkOperandWithOp, dt: %v,op: %v, nt: %v \n", dt, op, nt) if nt == Unary || nt == IncDec { switch nt { case Unary: diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index f117791f517..2d1730fc749 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2152,26 +2152,25 @@ func assertEqualityCompatible(xt, dt Type) { case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage debugPP.Println("primitive type, return true, fallthrough") case *ArrayType: // NOTE: no recursive allowed - // TODO: check at least length here switch baseOf(cdt.Elem()).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? switch cxt := baseOf(xt).(type) { case *ArrayType: - if cxt.Len != cdt.Len { + if cxt.Len != cdt.Len { // check length panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) } default: panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) } default: - panic(fmt.Sprintf("%v cannot be compared \n", cdt)) + panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) } case *StructType: for _, f := range cdt.Fields { switch baseOf(f.Type).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: default: - panic(fmt.Sprintf("%v cannot be compared \n", cdt)) + panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) } } case *PointerType: diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index 49fd4f5efbd..dffd2210c63 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -57,6 +57,11 @@ func TestDebug(t *testing.T) { runFileTests(t, baseDir, []string{"*_native*"}) } +func TestDebugNative(t *testing.T) { + baseDir := filepath.Join(".", "debug") + runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) +} + func filterFileTests(t *testing.T, files []fs.DirEntry, ignore []string) []fs.DirEntry { t.Helper() diff --git a/gnovm/tests/files/types/0b0_filetest.gno b/gnovm/tests/files/types/0b0_filetest.gno index ee1b1c11ac0..2c968b5158f 100644 --- a/gnovm/tests/files/types/0b0_filetest.gno +++ b/gnovm/tests/files/types/0b0_filetest.gno @@ -11,9 +11,7 @@ func (e Error) Error() string { } // left is untyped const, right is typed const -// untyped value can be converted to its correspondence value when: -// a) it's (untyped) const -// b) it's declared type of value, like type Error int8, 0 will be able to converted to Error +// left is assignable to right func main() { if 1 == Error(1) { println("what the firetruck?") diff --git a/gnovm/tests/files/types/0b2_filetest.gno b/gnovm/tests/files/types/0b2_filetest.gno index 95544ef88ba..2f918d8d18c 100644 --- a/gnovm/tests/files/types/0b2_filetest.gno +++ b/gnovm/tests/files/types/0b2_filetest.gno @@ -7,9 +7,9 @@ func (e Error) Error() string { } // left is untyped const, right is typed const -// untyped value can be converted to its correspondence value when: -// a) it's (untyped) const -// b) it's declared type of value, like type Error int8, 0 will be able to converted to Error +// left is not assignable to right +// a) it's (untyped) bigint +// b) base type of right is string func main() { if 1 == Error(1) { println("what the firetruck?") diff --git a/gnovm/tests/files/types/0b3_filetest.gno b/gnovm/tests/files/types/0b3_filetest.gno index 86f2f4d3972..34c8a24cba2 100644 --- a/gnovm/tests/files/types/0b3_filetest.gno +++ b/gnovm/tests/files/types/0b3_filetest.gno @@ -1,17 +1,5 @@ package main -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is untyped const, right is not const - var a int8 func main() { diff --git a/gnovm/tests/files/types/0b5_native_filetest.gno b/gnovm/tests/files/types/0b5_native_filetest.gno deleted file mode 100644 index 7860292a6d2..00000000000 --- a/gnovm/tests/files/types/0b5_native_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import ( - "math/rand" -) - -func main() { - println(5 == rand.Uint32()) -} - -// Error: diff --git a/gnovm/tests/files/types/0f15_filetest.gno b/gnovm/tests/files/types/0f15_filetest.gno index d8089d198c9..36077127332 100644 --- a/gnovm/tests/files/types/0f15_filetest.gno +++ b/gnovm/tests/files/types/0f15_filetest.gno @@ -7,7 +7,6 @@ func gen() interface{} { return 1 } -// TODO: should stop at comparable check func main() { a = [2]interface{}{gen(), gen()} c = [2]interface{}{gen(), gen()} diff --git a/gnovm/tests/files/types/0f16_filetest.gno b/gnovm/tests/files/types/0f16_filetest.gno index a82590a7ae1..f4229190382 100644 --- a/gnovm/tests/files/types/0f16_filetest.gno +++ b/gnovm/tests/files/types/0f16_filetest.gno @@ -9,7 +9,7 @@ func gen() word { return []int{1} } -// TODO: should stop at comparable check +// TODO: consider log desc func main() { a = [2]word{gen(), gen()} c = [2]word{gen(), gen()} @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/types/0f16_filetest.gno:16: [2]main.word cannot be compared +// main/files/types/0f16_filetest.gno:16: [2]main.word and [2]main.word cannot be compared diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index 69230cb58a5..d42aceef7e4 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -2,12 +2,12 @@ package main type f func() bool +// slice would be comparable var a [2]f -var b [2]f func main() { println(a == nil) // rcx.T == nil } // Error: -// main/files/types/0f20_filetest.gno:9: [2]main.f cannot be compared +// main/files/types/0f20_filetest.gno:9: and [2]main.f cannot be compared diff --git a/gnovm/tests/files/types/0f21_filetest.gno b/gnovm/tests/files/types/0f21_filetest.gno index 7a607e09cab..fa6606b512d 100644 --- a/gnovm/tests/files/types/0f21_filetest.gno +++ b/gnovm/tests/files/types/0f21_filetest.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/types/0f21_filetest.gno:10: [2]main.f cannot be compared +// main/files/types/0f21_filetest.gno:10: [2]main.f and [2]main.f cannot be compared diff --git a/gnovm/tests/files/types/0f26_stdlibs_filetest.gno b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno index 83dd6d6af57..a786ee6563c 100644 --- a/gnovm/tests/files/types/0f26_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if 1 > errCmp { diff --git a/gnovm/tests/files/types/0f2b_native.gno b/gnovm/tests/files/types/0f2b_native.gno index 1f66c6cb5fa..acde29d336b 100644 --- a/gnovm/tests/files/types/0f2b_native.gno +++ b/gnovm/tests/files/types/0f2b_native.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(0) <= errCmp { @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f2b_native.gno:19: operator <= not defined on: gonative{error} +// main/files/types/0f2b_native.gno:19: operator <= not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f2b_stdlibs.gno b/gnovm/tests/files/types/0f2b_stdlibs.gno index afc0ac13498..6a95d4e61b1 100644 --- a/gnovm/tests/files/types/0f2b_stdlibs.gno +++ b/gnovm/tests/files/types/0f2b_stdlibs.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(0) <= errCmp { diff --git a/gnovm/tests/files/types/0f2c_native.gno b/gnovm/tests/files/types/0f2c_native.gno index 9bef65aeeb2..76f1c3de683 100644 --- a/gnovm/tests/files/types/0f2c_native.gno +++ b/gnovm/tests/files/types/0f2c_native.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(0) < errCmp { @@ -25,4 +25,4 @@ func main() { } // Error: -// main/files/types/0f2c_native.gno:19: operator < not defined on: gonative{error} +// main/files/types/0f2c_native.gno:19: operator < not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f2c_stdlibs.gno b/gnovm/tests/files/types/0f2c_stdlibs.gno index 7e47a9f1d3b..a729da89791 100644 --- a/gnovm/tests/files/types/0f2c_stdlibs.gno +++ b/gnovm/tests/files/types/0f2c_stdlibs.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(0) < errCmp { diff --git a/gnovm/tests/files/types/0f2d_filetest.gno b/gnovm/tests/files/types/0f2d_filetest.gno index fca12f7f938..5ad121f515b 100644 --- a/gnovm/tests/files/types/0f2d_filetest.gno +++ b/gnovm/tests/files/types/0f2d_filetest.gno @@ -14,13 +14,13 @@ func (e Error) Error() string { return "error: " + strconv.Itoa(int(e)) } -// specil case: +// special case: // one is interface func main() { var e0 E e0 = Error(0) fmt.Printf("%T \n", e0) - if e0 == Error(0) { // this would not convert, errCmp is interface, refer to preprocess, line2526 + if e0 == Error(0) { println("what the firetruck?") } else { println("something else") diff --git a/gnovm/tests/files/types/0f3_filetest.gno b/gnovm/tests/files/types/0f3_filetest.gno index 0e9b0987cb7..9c4cb0e5ea0 100644 --- a/gnovm/tests/files/types/0f3_filetest.gno +++ b/gnovm/tests/files/types/0f3_filetest.gno @@ -13,11 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(1) == errCmp { - //if errCmp == 1 { println("what the firetruck?") } else { println("something else") diff --git a/gnovm/tests/files/types/0f43a_filetest.gno b/gnovm/tests/files/types/0f43a_filetest.gno index c3d275afc0c..49bb000d951 100644 --- a/gnovm/tests/files/types/0f43a_filetest.gno +++ b/gnovm/tests/files/types/0f43a_filetest.gno @@ -5,15 +5,6 @@ import "fmt" type myPointer *int func main() { - // NOTE: this is deprecated logic. - // rhs nil is not converted to left, it's undefined - // flow. left and right are both const: - // DEBUG: ---BinaryExpr---, OP: EQL, lx: (const (nil main.myPointer)), rx: (const (undefined)), lt: main.myPointer, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false - // the have same specificity of 0 (neither is primitive) - // so the conversion dir is ->, it won't convert since dt is nil(type and value of nil are both nil), refer to convertConst logic - // so it results in runtime: "isEql, lv: (nil main.myPointer), rv: (undefined), lvu: false, rvc: true" - // so, as a special case, they are actually equal when: one is undefined, and one is defined with specific type(slice, map, pointer, func) and nil value - // or, think, we should convert from type-nil(nil) to typed(nil)->typed, value is nil if myPointer(nil) == nil { fmt.Println("Pointer is nil") } else { diff --git a/gnovm/tests/files/types/0f47_nilcast_filetest.gno b/gnovm/tests/files/types/0f47_nilcast_filetest.gno index ba5715d6382..2b850e53ce0 100644 --- a/gnovm/tests/files/types/0f47_nilcast_filetest.gno +++ b/gnovm/tests/files/types/0f47_nilcast_filetest.gno @@ -4,9 +4,9 @@ import "fmt" type integer int -func main() { // TODO: refer to 47a, this shoul be solved - // m(nil) is a conversion from nil to m, whose underlying type is map[string]int - // lv: (nil main.m), rv: (undefined) +func main() { // TODO: same with 47a + // illegal conversion + // should not work if integer(nil) == nil { fmt.Println("integer is nil") } else { diff --git a/gnovm/tests/files/types/0f47a_filetest.gno b/gnovm/tests/files/types/0f47a_filetest.gno index e307adf6f64..8faffefbee6 100644 --- a/gnovm/tests/files/types/0f47a_filetest.gno +++ b/gnovm/tests/files/types/0f47a_filetest.gno @@ -3,7 +3,7 @@ package main type integer int func main() { - println(integer(nil)) // TODO: this should be a conversion error: cannot convert nil to type integer + println(integer(nil)) // preprocess, 1042 } // Error: diff --git a/gnovm/tests/files/types/0f47d_filetest.gno b/gnovm/tests/files/types/0f47d_filetest.gno index 5ec984bed2f..22b8b5db220 100644 --- a/gnovm/tests/files/types/0f47d_filetest.gno +++ b/gnovm/tests/files/types/0f47d_filetest.gno @@ -8,7 +8,7 @@ type integer interface{} // ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false func main() { //println(integer(nil) == nil) - println(interface{}(nil) == nil) + println(interface{}(nil) == nil) // refer to convertConst and convertTo fmt.Printf("%T \n", interface{}(nil)) } diff --git a/gnovm/tests/files/types/0f48_filetest.gno b/gnovm/tests/files/types/0f48_filetest.gno index 8576159a0db..fbf4f164c9d 100644 --- a/gnovm/tests/files/types/0f48_filetest.gno +++ b/gnovm/tests/files/types/0f48_filetest.gno @@ -13,7 +13,7 @@ func gen() error { return nil } -func main() { +func main() { // about untyped nil to (interface{})typed-nil, no support for native for now. r := gen() testEql(r, error(nil)) } diff --git a/gnovm/tests/files/types/0f4_filetest.gno b/gnovm/tests/files/types/0f4_filetest.gno index d765b9640f1..e3f03cd76a2 100644 --- a/gnovm/tests/files/types/0f4_filetest.gno +++ b/gnovm/tests/files/types/0f4_filetest.gno @@ -13,11 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(0) != errCmp { - //if errCmp == 1 { println("what the firetruck?") } else { println("something else") diff --git a/gnovm/tests/files/types/0f5_filetest.gno b/gnovm/tests/files/types/0f5_filetest.gno index 75f022c240a..72e3eaac1b7 100644 --- a/gnovm/tests/files/types/0f5_filetest.gno +++ b/gnovm/tests/files/types/0f5_filetest.gno @@ -13,11 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if Error(1) != errCmp { - //if errCmp == 1 { println("what the firetruck?") } else { println("something else") diff --git a/gnovm/tests/files/types/0f7_filetest.gno b/gnovm/tests/files/types/0f7_filetest.gno index 174ca2bca90..29a6061cd77 100644 --- a/gnovm/tests/files/types/0f7_filetest.gno +++ b/gnovm/tests/files/types/0f7_filetest.gno @@ -13,11 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if errCmp == Error(1) { - //if errCmp == 1 { println("what the firetruck?") } else { println("something else") diff --git a/gnovm/tests/files/types/0f8_stdlibs_filetest.gno b/gnovm/tests/files/types/0f8_stdlibs_filetest.gno index 8282621df1d..89601f83910 100644 --- a/gnovm/tests/files/types/0f8_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/0f8_stdlibs_filetest.gno @@ -13,7 +13,7 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { if errCmp == int64(1) { diff --git a/gnovm/tests/files/types/26a3_filetest.gno b/gnovm/tests/files/types/26a3_filetest.gno index 2364a18a031..3b57f569ae1 100644 --- a/gnovm/tests/files/types/26a3_filetest.gno +++ b/gnovm/tests/files/types/26a3_filetest.gno @@ -7,3 +7,6 @@ func gen() interface{} { func main() { gen()++ } + +// Error: +// main/files/types/26a3_filetest.gno:8: operator ++ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/27_filetest.gno b/gnovm/tests/files/types2/27_filetest.gno similarity index 100% rename from gnovm/tests/files/types/27_filetest.gno rename to gnovm/tests/files/types2/27_filetest.gno diff --git a/gnovm/tests/files/types/27a_filetest.gno b/gnovm/tests/files/types2/27a_filetest.gno similarity index 51% rename from gnovm/tests/files/types/27a_filetest.gno rename to gnovm/tests/files/types2/27a_filetest.gno index 3cc3c1f5e4c..2f4394dc400 100644 --- a/gnovm/tests/files/types/27a_filetest.gno +++ b/gnovm/tests/files/types2/27a_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/27a_filetest.gno:5: operator << not defined on: BigdecKind +// main/files/types2/27a_filetest.gno:5: operator << not defined on: BigdecKind From cd8caa9210f6547bd7df64f045bc4d4ddaf86642 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Jan 2024 17:07:44 +0800 Subject: [PATCH 090/193] fixup --- gnovm/pkg/gnolang/op_compatibility.go | 11 ++-- gnovm/pkg/gnolang/preprocess.go | 85 +++++++++------------------ gnovm/pkg/gnolang/types.go | 35 +++-------- 3 files changed, 44 insertions(+), 87 deletions(-) diff --git a/gnovm/pkg/gnolang/op_compatibility.go b/gnovm/pkg/gnolang/op_compatibility.go index 8a65fa2397d..f296244489b 100644 --- a/gnovm/pkg/gnolang/op_compatibility.go +++ b/gnovm/pkg/gnolang/op_compatibility.go @@ -2,8 +2,11 @@ package gnolang import "fmt" +// here are a range of rules predefines for preprocessor to check the compatibility between operands and operators +// e,g. for binary expr x + y, x, y can only be numeric or string, 1+2, "a" + "b" +// this is used in checkOperandWithOp(). var ( - binaryPredicates = map[Word]func(t Type) bool{ + binaryChecker = map[Word]func(t Type) bool{ ADD: isNumericOrString, SUB: isNumeric, MUL: isNumeric, @@ -22,17 +25,17 @@ var ( GTR: isOrdered, GEQ: isOrdered, } - unaryPredicates = map[Word]func(t Type) bool{ + unaryChecker = map[Word]func(t Type) bool{ ADD: isNumeric, SUB: isNumeric, XOR: isIntNum, NOT: isBoolean, } - IncDecStmtPredicates = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). + IncDecStmtChecker = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). INC: isNumeric, DEC: isNumeric, } - AssignStmtPredicates = map[Word]func(t Type) bool{ + AssignStmtChecker = map[Word]func(t Type) bool{ ADD_ASSIGN: isNumericOrString, SUB_ASSIGN: isNumeric, MUL_ASSIGN: isNumeric, diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 1269baa38ca..d853f37deef 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2438,11 +2438,6 @@ func anyValue(t Type) TypedValue { } } -//func isConst(x Expr) bool { -// _, ok := x.(*ConstExpr) -// return ok -//} - func isConstType(x Expr) bool { _, ok := x.(*constTypeExpr) return ok @@ -2450,18 +2445,22 @@ func isConstType(x Expr) bool { func cmpSpecificity(t1, t2 Type) int { debugPP.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) - // debugPP.Printf("comSpecificity, t1: %T, t2: %T \n", t1, t2) - // debugPP.Printf("comSpecificity, t1.kind: %v, t2.kind: %v \n", t1.Kind(), t2.Kind()) if it1, ok := baseOf(t1).(*InterfaceType); ok { - debugPP.Printf("it1: %v: \n", it1) - if it2, ok := baseOf(t2).(*InterfaceType); ok { - debugPP.Printf("it1: %v: \n", it2) - return 0 + if it1.IsEmptyInterface() { + return 1 // left empty interface } else { - return 1 + if it2, ok := baseOf(t2).(*InterfaceType); ok { + if it2.IsEmptyInterface() { // right empty interface + return -1 + } else { + return 0 // both non-empty interface + } + } else { + return 1 // right not interface + } } } else if _, ok := t2.(*InterfaceType); ok { - return -1 + return -1 // left not interface, right is interface } t1s, t2s := 0, 0 @@ -2500,13 +2499,13 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) if cx, ok := (*x).(*ConstExpr); ok { - // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if !coerce { + // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno, TODO: make it !coerced // the reason why we need this is that the checkOperandWithOp can not filter out all mismatch case, // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=, it's actually postponed to runtime check.) // we still need a safe guard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). - // It does not guarantee convertible, e.g. s1{foo: 1} == 1), why this pass check? XXX. + // It does not guarantee convertible, e.g. s1{foo: 1} == 1), why this is considered as assignable? pass check? XXX. checkAssignable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } } @@ -2514,14 +2513,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) - if t == nil { - if isUntyped(xt) { - t = defaultTypeOf(xt) - } else { - t = xt // xt maybe typed while assign, with t is the type of LHS - } - } - if _, ok := t.(*InterfaceType); ok { + if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { t = defaultTypeOf(xt) } else { @@ -2535,14 +2527,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 // dt not interface type - // if _, ok := t.(*InterfaceType); !ok { // t could be nil in case of assignStmt and lhs is untyped, pass nil checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - //} else { - // XXX, this should be unreachable, if lhs is interface type and rhs is untyped shift expr, it will fail in checkOperandWithOp - // checkAssignable(xt, t, false) // XXX, left is interface, right untyped, 0_a_3b.gno - //} } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable checkAssignable(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno } @@ -2550,20 +2537,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if ux, ok := (*x).(*UnaryExpr); ok { debugPP.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) xt := evalStaticTypeOf(store, last, *x) - if t == nil { + if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { t = defaultTypeOf(xt) } else { t = xt } } - if _, ok := t.(*InterfaceType); ok { - if isUntyped(xt) { - t = defaultTypeOf(xt) - } else { - t = xt // xt maybe typed while assign, with t is the type of LHS - } - } if coerce { // mostly when explicitly conversion, type call checkOperandWithOp(store, last, &ux.X, t, ux.Op, Unary) // "push" expected type into shift binary's left operand. @@ -2583,19 +2563,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v \n", *x, xt, t) - - // check convertible prior - var isUnamed bool + debugPP.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) + var isUnnamed bool if t != nil && !coerce { - isUnamed = checkAssignable(xt, t, autoNative) + isUnnamed = checkAssignable(xt, t, autoNative) } if isUntyped(xt) { - debugPP.Println("xt untyped") - if t == nil { - t = defaultTypeOf(xt) - } - if _, ok := t.(*InterfaceType); ok { + if _, ok := t.(*InterfaceType); ok || t == nil { t = defaultTypeOf(xt) } debugPP.Printf("default type of t: %v \n", t) @@ -2604,7 +2578,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: - debugPP.Println("binary, going recursive call") // push t into bx.Left and bx.Right, recursively checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) @@ -2612,9 +2585,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return case EQL, LSS, GTR, NEQ, LEQ, GEQ: - // TODO: convert untyped to typed // nothing to do, quick forward - debugPP.Printf("compare, bx: %v, op: %v \n", bx, bx.Op) default: // do nothing } @@ -2625,8 +2596,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative *x = cx } - // cover all declared type case - if isUnamed { + // unnamed to named + if isUnnamed { cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx @@ -2708,7 +2679,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, if nt == Unary || nt == IncDec { switch nt { case Unary: - if pred, ok := unaryPredicates[op]; ok { + if pred, ok := unaryChecker[op]; ok { if !pred(dt) { if dt != nil { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) @@ -2718,7 +2689,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, } } case IncDec: - if pred, ok := IncDecStmtPredicates[op]; ok { + if pred, ok := IncDecStmtChecker[op]; ok { if !pred(dt) { if dt != nil { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) @@ -2745,9 +2716,9 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, // NOTE: not checking types strict identical here, unlike ADD, etc. // this will pass the case of lhs is interface and rhs implements this interface, vice versa. // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkAssignable - assertEqualityCompatible(xt, dt) + assertComparable(xt, dt) case LSS, LEQ, GTR, GEQ: - if pred, ok := binaryPredicates[op]; ok { + if pred, ok := binaryChecker[op]; ok { if !pred(dt) { if dt != nil { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) @@ -2760,7 +2731,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic("invalid comparison operator") } } else { - if pred, ok := binaryPredicates[op]; ok { + if pred, ok := binaryChecker[op]; ok { if !pred(dt) { if dt != nil { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) @@ -2784,7 +2755,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, } } case Assign: - if pred, ok := AssignStmtPredicates[op]; ok { + if pred, ok := AssignStmtChecker[op]; ok { if !pred(dt) { if dt != nil { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 2d1730fc749..5a635355e2d 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -977,14 +977,6 @@ func (it *InterfaceType) FindEmbeddedFieldType(callerPath string, n Name, m map[ // For run-time type assertion. // TODO: optimize somehow. func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { - debugPP.Printf("isImplementedBy, it %v, ot:%v \n", it, ot) - //// empty interface{} - //if iot, ok := ot.(*InterfaceType); ok { - // if iot.IsEmptyInterface() { - // return true - // } - //} - for _, im := range it.Methods { if im.Type.Kind() == InterfaceKind { // field is embedded interface... @@ -2114,12 +2106,12 @@ func isSameType(lt, rt Type) bool { (lt.TypeID() == rt.TypeID()) // and identical. } -// TODO: use another name to reduce confusion, we already have checkAssignableTo(or change this) +// runtime assert func assertAssignable(lt, rt Type) { debugPP.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) if isSameType(lt, rt) { // both are nil/undefined or same type. - } else if lt == nil || rt == nil { // TODO: consider this. files/context.gno + } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil // LHS is undefined } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { @@ -2139,18 +2131,16 @@ func assertAssignable(lt, rt Type) { } } -// assertEqualityCompatible is used in preprocess. +// assertComparable is used in preprocess. // The logic here is, when != or == shows up, check if `dt` is equalilty eval compatible. // indicates operand with dt can be used as with == or !=). if this check pass, // then check the corresponding type(the other side of the operator) is convertable to t. // this is located in checkOrConvertType->checkConvertable stage. // so, checkOperandWithOp is working as a pre-check. -// TODO: consider and tune log -func assertEqualityCompatible(xt, dt Type) { - debugPP.Printf("--- assertEqualityCompatible---, xt: %v, dt: %v \n", xt, dt) +func assertComparable(xt, dt Type) { + debugPP.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) switch cdt := baseOf(dt).(type) { - case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage - debugPP.Println("primitive type, return true, fallthrough") + case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage? case *ArrayType: // NOTE: no recursive allowed switch baseOf(cdt.Elem()).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? @@ -2173,13 +2163,11 @@ func assertEqualityCompatible(xt, dt Type) { panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) } } - case *PointerType: - case *InterfaceType: + case *PointerType: // &a == &b + case *InterfaceType: // var a, b interface{} case *SliceType, *FuncType, *MapType: if xt != nil { panic(fmt.Sprintf("%v can only be compared to nil \n", dt)) - } else { - // do nothing } case *NativeType: if !cdt.Type.Comparable() { @@ -2245,11 +2233,6 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok - } else if iot, ok := xt.(*InterfaceType); ok { // XXX. case 0f38_stdlibs_filetest.gno - debugPP.Println("xt is empty interface: ", iot) - if iot.IsEmptyInterface() { - return // ok - } } else { panic(fmt.Sprintf( "%s does not implement %s", @@ -2348,7 +2331,7 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { dt.String())) } else { // carry on with baseOf(dxt) - xt = dxt.Base + xt = dxt.Base // set as base to do the rest check conversionNeeded = true } } From 87f3a8e7c79b77f5487feb0ab954f0086a83cee0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Jan 2024 23:34:50 +0800 Subject: [PATCH 091/193] fixup --- gnovm/pkg/gnolang/op_compatibility.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 56 ++++++++++------------- gnovm/pkg/gnolang/types.go | 21 +++------ gnovm/tests/files/types/18a4_filetest.gno | 10 ++++ 4 files changed, 42 insertions(+), 47 deletions(-) create mode 100644 gnovm/tests/files/types/18a4_filetest.gno diff --git a/gnovm/pkg/gnolang/op_compatibility.go b/gnovm/pkg/gnolang/op_compatibility.go index f296244489b..a1721887cd4 100644 --- a/gnovm/pkg/gnolang/op_compatibility.go +++ b/gnovm/pkg/gnolang/op_compatibility.go @@ -2,7 +2,7 @@ package gnolang import "fmt" -// here are a range of rules predefines for preprocessor to check the compatibility between operands and operators +// here are a range of rules predefined for preprocessor to check the compatibility between operands and operators // e,g. for binary expr x + y, x, y can only be numeric or string, 1+2, "a" + "b" // this is used in checkOperandWithOp(). var ( diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index d853f37deef..62a911c3a05 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -790,13 +790,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if cmp == 0 { debugPP.Println("cmp == 0") // to typed-nil. refer to 0f46 - if lcx.T == nil { + if lcx.T == nil { // TODO: make nil check happen in cmpSpecificity checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) - } else { // default case + } else { // default case, e.g. int(1) == int8(1), will also conduct type check checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } @@ -819,7 +819,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debugPP.Printf("const evaluated: %v \n", cx) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { // untyped -> not const - debugPP.Printf("left: %v is untyped const, right: %v is not const \n", lt, rt) // Left untyped const, Right not const ---------------- if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native) TODO: check this case if isShift { // RHS of shift should not be native @@ -860,12 +859,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } - } else { // left is typed const, right is not const(also typed), and not nil - if !isShift { // ? dir makes sense here, since non-const(right) implies more dynamic(interface) - // TODO: check if right untyped - if isUntyped(rt) { + } else { // left is typed const, right not const + if !isShift { + if isUntyped(rt) { // refer to 0_d.gno checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) - // the other way round should work too checkOrConvertType(store, last, &n.Right, lt, false, false) } else { checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) @@ -905,20 +902,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil - // no need to check lhs here since if rhs type is nil, it would fail earlier debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest - //if lnt, ok := lt.(*NativeType); ok { - // if ilnt, ok := baseOf(lnt).(*InterfaceType); ok { - // checkOperandWithOp(store, last, &n.Right, ilnt, n.Op, Binary) - // checkOrConvertType(store, last, &n.Right, ilnt, false) - // } - //} - // in case of rcx.T == nil(untyped nil), require lt is maybeNil checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else if !isShift { // left not const(typed), right is typed const, both typed - // TODO: if left untyped? - if isUntyped(lt) { + if isUntyped(lt) { // refer to 0_d.gno checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else { @@ -937,7 +925,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if lnt, ok := lt.(*NativeType); ok { if debug { if !isShift { - assertSameTypes(lt, rt) // TODO: what is this for? possible untyped? + assertAssignable(lt, rt) } } // If left and right are native type, @@ -993,7 +981,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } - } else { // both typed vars, refer to 0a1f_filetest + } else { // both typed, refer to 0a1f if !isShift { debugPP.Println("---both typed") cmp := cmpSpecificity(lt, rt) @@ -1748,19 +1736,21 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Special case if shift assign <<= or >>=. convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check lt := evalStaticTypeOf(store, last, n.Lhs[0]) - checkOperandWithOp(store, last, &n.Lhs[0], lt, n.Op, Assign) + checkOperandWithOp(store, last, &n.Lhs[0], lt, n.Op, XAssign) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, // TODO: assert length lt := evalStaticTypeOf(store, last, n.Lhs[0]) // a += b, requires b -> a conversion - checkOperandWithOp(store, last, &n.Rhs[0], lt, n.Op, Assign) + checkOperandWithOp(store, last, &n.Rhs[0], lt, n.Op, XAssign) checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) } else { // all else, like BAND_ASSIGN, etc // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) - checkOperandWithOp(store, last, &n.Rhs[i], lt, n.Op, Assign) + if n.Op != ASSIGN { // filter out = + checkOperandWithOp(store, last, &n.Rhs[i], lt, n.Op, XAssign) + } // if lt is interface, nothing will happen checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) } @@ -2662,7 +2652,7 @@ const ( Binary = iota Unary IncDec - Assign + XAssign ) // checkOperandWithOp works as a pre-check prior to checkOrConvertType() @@ -2671,9 +2661,6 @@ const ( // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. -// there are two steps of check: -// first, check is the dt type satisfies op; -// second, check if xt can be converted to dt, this is done after checkOperandWithOp, in checkOrConvertType(), func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { debugPP.Printf("checkOperandWithOp, dt: %v,op: %v, nt: %v \n", dt, op, nt) if nt == Unary || nt == IncDec { @@ -2687,6 +2674,8 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } + } else { + panic("should not happen") } case IncDec: if pred, ok := IncDecStmtChecker[op]; ok { @@ -2697,6 +2686,8 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } + } else { + panic("should not happen") } default: panic("should not happen") @@ -2713,9 +2704,6 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, if isComparison(op) { switch op { case EQL, NEQ: - // NOTE: not checking types strict identical here, unlike ADD, etc. - // this will pass the case of lhs is interface and rhs implements this interface, vice versa. - // as for the general case int(1) == int(8), the work is left to checkOrConvertType -> checkAssignable assertComparable(xt, dt) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryChecker[op]; ok { @@ -2726,6 +2714,8 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } + } else { + panic("should not happen") } default: panic("invalid comparison operator") @@ -2739,6 +2729,8 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) } } + } else { + panic("should not happen") } switch op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: @@ -2754,7 +2746,7 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, // do nothing } } - case Assign: + case XAssign: if pred, ok := AssignStmtChecker[op]; ok { if !pred(dt) { if dt != nil { @@ -2776,6 +2768,8 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, default: // do nothing } + } else { + panic("should not happen") } default: panic("should not happen") diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 5a635355e2d..6db756af34c 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2132,11 +2132,8 @@ func assertAssignable(lt, rt Type) { } // assertComparable is used in preprocess. -// The logic here is, when != or == shows up, check if `dt` is equalilty eval compatible. -// indicates operand with dt can be used as with == or !=). if this check pass, -// then check the corresponding type(the other side of the operator) is convertable to t. -// this is located in checkOrConvertType->checkConvertable stage. -// so, checkOperandWithOp is working as a pre-check. +// assert value with dt is comparable +// special case when both typed, check if type identical func assertComparable(xt, dt Type) { debugPP.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) switch cdt := baseOf(dt).(type) { @@ -2173,7 +2170,7 @@ func assertComparable(xt, dt Type) { if !cdt.Type.Comparable() { panic(fmt.Sprintf("%v is not comparable \n", dt)) } - case nil: // refer to 0a01_filetest, 0f32_filetest. + case nil: // refer to 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. assertMaybeNil("invalid operation, nil can not be compared to", xt) default: panic(fmt.Sprintf("%v is not comparable \n", dt)) @@ -2220,17 +2217,12 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { return } // case3 - // if xt or dt is empty interface, checkAssignable - // if no empty interface, then check if xt satisfied dt if dt.Kind() == InterfaceKind { - debugPP.Println("dt is interface") if idt, ok := baseOf(dt).(*InterfaceType); ok { if idt.IsEmptyInterface() { // XXX, can this be merged with IsImplementedBy? - debugPP.Println("dt is empty interface") // if dt is an empty Gno interface, any x ok. return // ok } else if idt.IsImplementedBy(xt) { - debugPP.Println("dt is implemented by xt") // if dt implements idt, ok. return // ok } else { @@ -2331,8 +2323,8 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { dt.String())) } else { // carry on with baseOf(dxt) - xt = dxt.Base // set as base to do the rest check - conversionNeeded = true + xt = dxt.Base // set as base to do the rest check + conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass } } } else if ddt, ok := dt.(*DeclaredType); ok { @@ -2350,11 +2342,10 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } else { // carry on with baseOf(ddt) dt = ddt.Base - conversionNeeded = true + conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass } } - // case 1 plus composite part // General cases. switch cdt := dt.(type) { case PrimitiveType: // case 1 diff --git a/gnovm/tests/files/types/18a4_filetest.gno b/gnovm/tests/files/types/18a4_filetest.gno new file mode 100644 index 00000000000..96c90100417 --- /dev/null +++ b/gnovm/tests/files/types/18a4_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := "a" + r &= "b" + println(r) +} + +// Error: +// main/files/types/18a4_filetest.gno:5: operator &= not defined on: StringKind From 792a3686d928065b2f039c42aa9ad440af93f7ed Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 19 Jan 2024 00:23:05 +0800 Subject: [PATCH 092/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 49 ++++++++++++++------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 62a911c3a05..b600b53ba72 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2484,44 +2484,45 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() -// TODO: replace all ConvertConst with this -// TODO: more docs +// coerce implies a mandatory convert, it happens with explicit conversion, uint64(int(1)), or RHS of a +// shift expr, or key of slice/array. func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) if cx, ok := (*x).(*ConstExpr); ok { if !coerce { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint - if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno, TODO: make it !coerced - // the reason why we need this is that the checkOperandWithOp can not filter out all mismatch case, - // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=, it's actually postponed to runtime check.) - // we still need a safe guard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). - // It does not guarantee convertible, e.g. s1{foo: 1} == 1), why this is considered as assignable? pass check? XXX. + if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. + // the reason why we need this is that the checkOperandWithOp() can not filter out all mismatch case, + // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). + // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). + // It does not guarantee convertible, e.g. s1{foo: 1} == 1). (why this is considered as assignable and pass check?). checkAssignable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args } } convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + // core logic to determine/convert type of shift expr. + // the type of untyped shift expr is determined by its usage context, define, assign, explicit conversion, etc. + // if dest type is nil or interface, adopt its default type, if not, adopt the concrete dest type + // if conduct explicit conversion on typed shift, set coerce to be true, this always happens in callExpr. xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { t = defaultTypeOf(xt) } else { - t = xt // xt maybe typed while assign, with t is the type of LHS + return // is x is typed and dest t is nil or interface type(even for type cast), do nothing. } } // deal with binary expr(bx.Left), determine its type - if coerce { // mostly when explicitly conversion, type call, while arg is binary expr + if coerce || !coerce && isUntyped(xt) { + // coerce mostly when explicitly conversion, type call, while arg is binary expr + // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) // left is the target operand // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else if !coerce && isUntyped(xt) { // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 - // dt not interface type - checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else { // not coerce, xt is typed. refer to 10a17b1, param is typed, check convertable - checkAssignable(xt, t, false) // XXX, left is interface, right is typed refer to 0_a_2.gno, 0_a_3.gno + } else { // not coerce, xt is typed, no need to convert but check. refer to 10a17b1. + checkAssignable(xt, t, false) // refer to 0_a_2.gno, 0_a_3.gno } } else if ux, ok := (*x).(*UnaryExpr); ok { @@ -2531,26 +2532,16 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if isUntyped(xt) { t = defaultTypeOf(xt) } else { - t = xt + return } } - if coerce { // mostly when explicitly conversion, type call + if coerce || !coerce && isUntyped(xt) { checkOperandWithOp(store, last, &ux.X, t, ux.Op, Unary) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) - } else if !coerce && isUntyped(xt) { // assign, func call - if _, ok := t.(*InterfaceType); !ok { // TODO: consider this - checkOperandWithOp(store, last, &ux.X, t, ux.Op, Unary) - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) - } else { - checkAssignable(xt, t, false) - } } else { checkAssignable(xt, t, false) } - // "push" expected type into shift unary's operand - // checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) debugPP.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) @@ -2564,6 +2555,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } debugPP.Printf("default type of t: %v \n", t) // Push type into expr if qualifying binary expr. + // main logic for handling nested binary expr + // e.g. 1 << 2 + 1 << x, will be handled recursively until its type is determined. if bx, ok := (*x).(*BinaryExpr); ok { switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, From 7a9b8a46227d8b6a73260f3fbc2ad6c4a1748df7 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 21 Jan 2024 00:31:15 +0800 Subject: [PATCH 093/193] add check --- gnovm/pkg/gnolang/preprocess.go | 3 +-- gnovm/pkg/gnolang/types.go | 5 +++-- gnovm/tests/files/types/0b2_filetest.gno | 2 +- gnovm/tests/files/types/22a18_filetest.gno | 12 ++++++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 gnovm/tests/files/types/22a18_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index b600b53ba72..6bd40341f4c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2495,8 +2495,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // the reason why we need this is that the checkOperandWithOp() can not filter out all mismatch case, // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). - // It does not guarantee convertible, e.g. s1{foo: 1} == 1). (why this is considered as assignable and pass check?). - checkAssignable(cx.T, t, autoNative) // refer to 22a17a_filetest, check args + checkAssignable(cx.T, t, autoNative) // refer to 22a17a } } convertConst(store, last, cx, t) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 6db756af34c..f76ab8f48b0 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2330,7 +2330,7 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } else if ddt, ok := dt.(*DeclaredType); ok { // special case if implicitly named primitive type. // TODO simplify with .IsNamedType(). - if _, ok := xt.(PrimitiveType); ok { + if _, ok := xt.(PrimitiveType); ok { // e.g. 1 == Int(1) debugPP.Printf("xt is primitiveType: %v, ddt: %v \n", xt, ddt) // this is special when dt is the declared type of x if !isUntyped(xt) { @@ -2338,9 +2338,10 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { "cannot use %s as %s without explicit conversion", xt.String(), ddt.String())) + } else { // xt untyped, carry on with check below + dt = ddt.Base } } else { - // carry on with baseOf(ddt) dt = ddt.Base conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass } diff --git a/gnovm/tests/files/types/0b2_filetest.gno b/gnovm/tests/files/types/0b2_filetest.gno index 2f918d8d18c..f0214b6e2cf 100644 --- a/gnovm/tests/files/types/0b2_filetest.gno +++ b/gnovm/tests/files/types/0b2_filetest.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/types/0b2_filetest.gno:14: cannot convert untyped bigint type to StringKind +// main/files/types/0b2_filetest.gno:14: cannot use untyped Bigint/Bigdec as StringKind diff --git a/gnovm/tests/files/types/22a18_filetest.gno b/gnovm/tests/files/types/22a18_filetest.gno new file mode 100644 index 00000000000..88aae826e85 --- /dev/null +++ b/gnovm/tests/files/types/22a18_filetest.gno @@ -0,0 +1,12 @@ +package main + +type s1 struct { + foo int +} + +func main() { + println(s1{foo: 1} == 1) +} + +// Error: +// main/files/types/22a18_filetest.gno:8: cannot use bigint as struct{foo int} From 94262aaa3acac555bcd81be6487a96b31f5bae4c Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 31 Jan 2024 17:58:06 +0800 Subject: [PATCH 094/193] clean most debug log, can be revert here --- gnovm/pkg/gnolang/debug.go | 23 +----- gnovm/pkg/gnolang/gonative.go | 3 - gnovm/pkg/gnolang/op_assign.go | 8 +++ gnovm/pkg/gnolang/op_binary.go | 37 +++++----- gnovm/pkg/gnolang/op_expressions.go | 7 -- gnovm/pkg/gnolang/preprocess.go | 96 ++++++++----------------- gnovm/pkg/gnolang/types.go | 23 +++--- gnovm/pkg/gnolang/values.go | 4 -- gnovm/pkg/gnolang/values_conversions.go | 26 ++----- gnovm/pkg/gnolang/values_string.go | 5 +- 10 files changed, 79 insertions(+), 153 deletions(-) diff --git a/gnovm/pkg/gnolang/debug.go b/gnovm/pkg/gnolang/debug.go index 33ad29bbaae..cb21da12ef2 100644 --- a/gnovm/pkg/gnolang/debug.go +++ b/gnovm/pkg/gnolang/debug.go @@ -18,21 +18,14 @@ import ( // so it is still faster to first check the truth value // before calling debug.Println or debug.Printf. -type ( - debugging bool - debugPreprocess bool -) +type debugging bool // using a const is probably faster. // const debug debugging = true // or flip -var ( - debug debugging = false - debugPP debugPreprocess = false -) +var debug debugging = false func init() { debug = os.Getenv("DEBUG") == "1" - debugPP = os.Getenv("DEBUG_PP") == "1" if debug { go func() { // e.g. @@ -70,18 +63,6 @@ func (d debugging) Printf(format string, args ...interface{}) { } } -func (d debugPreprocess) Println(args ...interface{}) { - if d { - fmt.Println(append([]interface{}{"DEBUG:"}, args...)...) - } -} - -func (d debugPreprocess) Printf(format string, args ...interface{}) { - if d { - fmt.Printf("DEBUG: "+format, args...) - } -} - var derrors []string = nil // Instead of actually panic'ing, which messes with tests, errors are sometimes diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 655517c3eb0..7a797a969c1 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -359,7 +359,6 @@ func Gno2GoValue(tv *TypedValue, rv reflect.Value) (ret reflect.Value) { // ConvertTo(). // Unlike go2GnoValue2(), rv may be invalid. func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { - debugPP.Printf("go2GnoValue---, rv: %v \n", rv.Kind()) if !rv.IsValid() { return } @@ -438,7 +437,6 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { // reflection, any child Gno declared types cannot change // types, and pointer values cannot change. func go2GnoValueUpdate(alloc *Allocator, rlm *Realm, lvl int, tv *TypedValue, rv reflect.Value) { - debugPP.Println("go2GnoValueUpdate---") // Special case if nil: if tv.IsUndefined() { return // do nothing @@ -1407,7 +1405,6 @@ func (m *Machine) doOpStructLitGoNative() { // NOTE: Unlike doOpCall(), doOpCallGoNative() also handles // conversions, similarly to doOpConvert(). func (m *Machine) doOpCallGoNative() { - debugPP.Println("doOpCallGoNative---") fr := m.LastFrame() fv := fr.GoFunc ft := fv.Value.Type() diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index 198813e8d29..0cc30861355 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -75,6 +75,7 @@ func (m *Machine) doOpSubAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -97,6 +98,7 @@ func (m *Machine) doOpMulAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -119,6 +121,7 @@ func (m *Machine) doOpQuoAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -141,6 +144,7 @@ func (m *Machine) doOpRemAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -163,6 +167,7 @@ func (m *Machine) doOpBandAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -185,6 +190,7 @@ func (m *Machine) doOpBandnAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -207,6 +213,7 @@ func (m *Machine) doOpBorAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { @@ -229,6 +236,7 @@ func (m *Machine) doOpXorAssign() { if debug { assertSameTypes(lv.TV.T, rv.T) } + // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := lv.Base.(Object); ok { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index a51e1fd00b6..ab66c645254 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -40,13 +40,6 @@ func (m *Machine) doOpBinary1() { } } -// XXX. in preprocess stage, we have checked: -// 1. if dt(type of lhs or rhs, depends on its convert dir); -// 2. whether lt and rt is identical if they are typed(typeID ==); or if one is not typed, but is -// checkAssignable to the other side. -// so, logically, there's no need to check the type equivalence here. leave the check in debug mode. -// NOTE: one exception is for == and !=, where there's a relaxed scope of operands for compare(maybeIdentical), -// there might be cases lt and rt is not identical. e.g. two different types conform same interface. func (m *Machine) doOpLor() { // get right and left operands. rv := m.PopValue() @@ -54,6 +47,7 @@ func (m *Machine) doOpLor() { if debug { assertSameTypes(lv.T, rv.T) } + // set result in lv. if isUntyped(lv.T) { lv.T = rv.T @@ -68,6 +62,7 @@ func (m *Machine) doOpLand() { if debug { assertSameTypes(lv.T, rv.T) } + // set result in lv. if isUntyped(lv.T) { lv.T = rv.T @@ -76,40 +71,35 @@ func (m *Machine) doOpLand() { } func (m *Machine) doOpEql() { - debugPP.Println("doOpEql---") m.PopExpr() // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool if debug { assertAssignable(lv.T, rv.T) } res = isEql(m.Store, lv, rv) - debugPP.Println("------is EQL:-----", res) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) } func (m *Machine) doOpNeq() { - debugPP.Println("doOpNeq---") m.PopExpr() // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - debugPP.Printf("lv: %v, rv: %v \n", lv, rv) var res bool if debug { assertAssignable(lv.T, rv.T) } + res = !isEql(m.Store, lv, rv) - debugPP.Println("------is NEQ:-----", res) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -124,6 +114,7 @@ func (m *Machine) doOpLss() { if debug { assertSameTypes(lv.T, rv.T) } + // set the result in lv. res := isLss(lv, rv) lv.T = UntypedBoolType @@ -140,6 +131,7 @@ func (m *Machine) doOpLeq() { if debug { assertSameTypes(lv.T, rv.T) } + // set the result in lv. res := isLeq(lv, rv) lv.T = UntypedBoolType @@ -156,6 +148,7 @@ func (m *Machine) doOpGtr() { if debug { assertSameTypes(lv.T, rv.T) } + // set the result in lv. res := isGtr(lv, rv) lv.T = UntypedBoolType @@ -172,6 +165,7 @@ func (m *Machine) doOpGeq() { if debug { assertSameTypes(lv.T, rv.T) } + // set the result in lv. res := isGeq(lv, rv) lv.T = UntypedBoolType @@ -188,6 +182,7 @@ func (m *Machine) doOpAdd() { if debug { assertSameTypes(lv.T, rv.T) } + // add rv to lv. addAssign(m.Alloc, lv, rv) } @@ -201,6 +196,7 @@ func (m *Machine) doOpSub() { if debug { assertSameTypes(lv.T, rv.T) } + // sub rv from lv. subAssign(lv, rv) } @@ -214,6 +210,7 @@ func (m *Machine) doOpBor() { if debug { assertSameTypes(lv.T, rv.T) } + // lv | rv borAssign(lv, rv) } @@ -227,6 +224,7 @@ func (m *Machine) doOpXor() { if debug { assertSameTypes(lv.T, rv.T) } + // lv ^ rv xorAssign(lv, rv) } @@ -338,7 +336,6 @@ func (m *Machine) doOpBandn() { // TODO: can be much faster. func isEql(store Store, lv, rv *TypedValue) bool { - debugPP.Printf("isEql: lv: %v, rv: %v \n", lv, rv) // If one is undefined, the other must be as well. // Fields/items are set to defaultValue along the way. lvu := lv.IsUndefined() @@ -458,11 +455,12 @@ func isEql(store Store, lv, rv *TypedValue) bool { } return lv.V == rv.V case FuncKind: - // if debug { - if lv.V != nil && rv.V != nil { - panic("function can only be compared with `nil`") + if debug { + if lv.V != nil && rv.V != nil { + panic("function can only be compared with `nil`") + } } - //} + if _, ok := lv.V.(*BoundMethodValue); ok { // BoundMethodValues are objects so just compare. return lv.V == rv.V @@ -926,7 +924,7 @@ func remAssign(lv, rv *TypedValue) { lv.V = BigintValue{V: lb} default: panic(fmt.Sprintf( - "operators rem and rem= not defined for %s", + "operators %% and %%= not defined for %s", lv.T, )) } @@ -1090,7 +1088,6 @@ func xorAssign(lv, rv *TypedValue) { // for doOpShl and doOpShlAssign. func shlAssign(lv, rv *TypedValue) { - debugPP.Println("---shl Assign") // set the result in lv. // NOTE: baseOf(rv.T) is always UintType. switch baseOf(lv.T) { diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 773f3339665..0f107b84fc6 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -83,7 +83,6 @@ func (m *Machine) doOpSelector() { } func (m *Machine) doOpSlice() { - debugPP.Println("doOpSlice") sx := m.PopExpr().(*SliceExpr) var low, high, max int = -1, -1, -1 // max @@ -113,15 +112,12 @@ func (m *Machine) doOpSlice() { if sx.High == nil { high = xv.GetLength() } - debugPP.Printf("low: %v , high: %v \n", low, high) // all low:high:max cases var sv TypedValue if max == -1 { sv = xv.GetSlice(m.Alloc, low, high) - debugPP.Printf("sv: %v \n", sv) } else { sv = xv.GetSlice2(m.Alloc, low, high, max) - debugPP.Printf("sv: %v \n", sv) } if isUntyped(sv.T) { ConvertUntypedTo(&sv, defaultTypeOf(sv.T)) @@ -488,11 +484,9 @@ func (m *Machine) doOpArrayLit() { } func (m *Machine) doOpSliceLit() { - debugPP.Println("doOpSliceLit") // assess performance TODO x := m.PopExpr().(*CompositeLitExpr) el := len(x.Elts) - debugPP.Println("el: ", el) // peek slice type. st := m.PeekValue(1 + el).V.(TypeValue).Type // construct element buf slice. @@ -708,7 +702,6 @@ func (m *Machine) doOpFuncLit() { } func (m *Machine) doOpConvert() { - debugPP.Println("---doOpConvert---") xv := m.PopValue() t := m.PopValue().GetType() ConvertTo(m.Alloc, m.Store, xv, t) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 6bd40341f4c..9cce37c8e9e 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -154,14 +154,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { defer func() { if r := recover(); r != nil { - if debugPP { - fmt.Println("--- preprocess stack ---") - for i := len(stack) - 1; i >= 0; i-- { - sbn := stack[i] - fmt.Printf("stack %d: %s\n", i, sbn.String()) - } - fmt.Println("------------------------") + fmt.Println("--- preprocess stack ---") + for i := len(stack) - 1; i >= 0; i-- { + sbn := stack[i] + fmt.Printf("stack %d: %s\n", i, sbn.String()) } + fmt.Println("------------------------") // before re-throwing the error, append location information to message. loc := last.GetLocation() if nline := n.GetLine(); nline > 0 { @@ -179,7 +177,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if debug { debug.Printf("Preprocess %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } - // debugPP.Printf("Preprocess %s, (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) switch stage { // ---------------------------------------- @@ -626,7 +623,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { switch n := n.(type) { // TRANS_LEAVE ----------------------- case *NameExpr: // e.g. var a int, a is NameExpr - debugPP.Printf("---NameExpr---: %v \n", n) // Validity: check that name isn't reserved. if isReservedName(n.Name) { panic(fmt.Sprintf( @@ -737,7 +733,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BasicLitExpr: - debugPP.Printf("basicLitExpr---, %v \n", n) // Replace with *ConstExpr. cx := evalConst(store, last, n) return cx, TRANS_CONTINUE @@ -745,7 +740,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: // TODO: improve readability - debugPP.Printf("---binaryExpr---:%v \n", n) lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) // Special (recursive) case if shift and right isn't uint. @@ -773,7 +767,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) - debugPP.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + debug.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) if lic { if ric { // Left const, Right const ---------------------- @@ -783,12 +777,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if !isShift { cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { - debugPP.Println("cmp < 0, ->") + debug.Println("cmp < 0, ->") // convert n.Left to right type. checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { - debugPP.Println("cmp == 0") + debug.Println("cmp == 0") // to typed-nil. refer to 0f46 if lcx.T == nil { // TODO: make nil check happen in cmpSpecificity checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) @@ -801,7 +795,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } } else { - debugPP.Println("cmp > 0, <-") + debug.Println("cmp > 0, <-") // convert n.Right to left type. checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) @@ -816,7 +810,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Then, evaluate the expression. // also for shift cx := evalConst(store, last, n) - debugPP.Printf("const evaluated: %v \n", cx) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { // untyped -> not const // Left untyped const, Right not const ---------------- @@ -845,7 +838,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - debugPP.Println("right not native") if !isShift { // convert n.Left to right type. checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) @@ -853,7 +845,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if lcx.T == nil { // LHS is nil - debugPP.Println("lcx.T is nil") if !isShift { // convert n.Left to typed-nil type. checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) @@ -902,7 +893,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else if rcx.T == nil { // RHS is nil - debugPP.Println("rcx.T == nil ") // refer to 0f20_filetest + // refer to 0f20_filetest checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else if !isShift { // left not const(typed), right is typed const, both typed @@ -961,7 +952,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // computed in gno, never with // reflect. } else { - debugPP.Println("lt not native") // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) if liu { @@ -972,7 +962,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Left, n.Op, n.Right)) } } else { // left untyped, right typed - debugPP.Println("left untyped, right is typed") checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } @@ -983,9 +972,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // both typed, refer to 0a1f if !isShift { - debugPP.Println("---both typed") cmp := cmpSpecificity(lt, rt) - debugPP.Println("cmp: ", cmp) + debug.Println("cmp: ", cmp) if cmp == -1 { checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) @@ -1003,12 +991,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // TRANS_LEAVE ----------------------- case *CallExpr: - debugPP.Printf("---CallExpr---: %v \n", n) + debug.Printf("---CallExpr---: %v \n", n) // Func type evaluation. var ft *FuncType ift := evalStaticTypeOf(store, last, n.Func) - debugPP.Printf("---func type---: %v \n", ift) switch cft := baseOf(ift).(type) { case *FuncType: ft = cft @@ -1021,7 +1008,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.NumArgs = 1 var dt Type ct := evalStaticType(store, last, n.Func) - debugPP.Printf("ct: %v \n", ct) at := evalStaticTypeOf(store, last, n.Args[0]) switch arg0 := n.Args[0].(type) { case *ConstExpr: @@ -1063,7 +1049,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx.SetAttribute(ATTR_TYPEOF_VALUE, dt) return cx, TRANS_CONTINUE case *BinaryExpr: // special case to evaluate type of binaryExpr/UnaryExpr which has untyped shift nested - debugPP.Printf("---callExpr, arg is binary expr, bx: %v \n", arg0) if isUntyped(at) { // only when untyped, this is checked in checkOrConvertType too, but guard here switch arg0.Op { case EQL, NEQ, LSS, GTR, LEQ, GEQ: // refer to 10a0012. TODO: convert to typed too @@ -1073,16 +1058,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } case *UnaryExpr: - debugPP.Printf("---callExpr, arg is unary expr, bx: %v \n", arg0) if isUntyped(at) { checkOrConvertType(store, last, &n.Args[0], ct, false, true) } default: - debugPP.Printf("default: arg type is: %T \n", arg0) + // do nothing } // general case, for non-const untyped && no nested untyped shift // after handling const, and special cases recursively, set the target node type - debugPP.Println("general case") // ct := evalStaticType(store, last, n.Func) n.SetAttribute(ATTR_TYPEOF_VALUE, ct) return n, TRANS_CONTINUE @@ -1125,7 +1108,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } - debugPP.Println("general cases---") // Continue with general case. hasVarg := ft.HasVarg() isVarg := n.Varg @@ -1218,7 +1200,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Check given argument type against required. // Also replace const Args with *ConstExpr unless embedded. if embedded { - debugPP.Println("embedded") if isVarg { panic("should not happen") } @@ -1259,7 +1240,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *IndexExpr: - debugPP.Println("IndexExpr---") dt := evalStaticTypeOf(store, last, n.X) if dt.Kind() == PointerKind { // if a is a pointer to an array, @@ -1285,7 +1265,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SliceExpr: - debugPP.Println("SliceExpr---") // Replace const L/H/M with int *ConstExpr, // or if not const, assert integer type.. checkOrConvertIntegerType(store, last, n.Low) @@ -1294,7 +1273,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *TypeAssertExpr: - debugPP.Println("TypeAssertExpr---") if n.Type == nil { panic("should not happen") } @@ -1304,11 +1282,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: - debugPP.Println("UnaryExpr---") xt := evalStaticTypeOf(store, last, n.X) - debugPP.Printf("---unaryExpr---, op: %v, xt: %v \n", n.Op, xt) if xnt, ok := xt.(*NativeType); ok { - debugPP.Println("nativeType") // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) // convert n.X to gno type, @@ -1329,7 +1304,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const X. // checkOperandWithOp, like +a, while a should be numeric if cx, ok := n.X.(*ConstExpr); ok { - debugPP.Println("not native, ConstExpr") // checkOperandWithOp, e.g. +a while a should be numeric checkOperandWithOp(store, last, nil, cx.T, n.Op, Unary) cx := evalConst(store, last, n) @@ -1412,13 +1386,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *KeyValueExpr: - debugPP.Println("KeyValueExpr---") // NOTE: For simplicity we just // use the *CompositeLitExpr. // TRANS_LEAVE ----------------------- case *SelectorExpr: - debugPP.Println("SelectorExpr---") xt := evalStaticTypeOf(store, last, n.X) // Set selector path based on xt's type. @@ -1611,7 +1583,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: - debugPP.Printf("---AssignStmt---, Op: %v, LHS: %v, RHS:%v \n", n.Op, n.Lhs, n.Rhs) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { // Rhs consts become default *ConstExprs. @@ -1638,7 +1609,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, lx := range n.Lhs { ln := lx.(*NameExpr).Name rf := cft.Results[i] - debugPP.Printf("rf.Type: %v \n", rf.Type) // re-definition last.Define(ln, anyValue(rf.Type)) } @@ -1672,7 +1642,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } } else { - debugPP.Println("else---") // General case: a, b := x, y for i, lx := range n.Lhs { ln := lx.(*NameExpr).Name @@ -1894,7 +1863,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ValueDecl: - debugPP.Printf("---valueDecl: %v \n", n) // evaluate value if const expr. if n.Const { // NOTE: may or may not be a *ConstExpr, @@ -2115,7 +2083,6 @@ func pushRealBlock(bn BlockNode, last *BlockNode, stack *[]BlockNode) { // To discourage mis-use, expects x to already be // preprocessed. func evalStaticType(store Store, last BlockNode, x Expr) Type { - debugPP.Printf("---evalStaticType of: %v \n", x) if t, ok := x.GetAttribute(ATTR_TYPE_VALUE).(Type); ok { return t } else if ctx, ok := x.(*constTypeExpr); ok { @@ -2166,7 +2133,6 @@ func gnoTypeOf(store Store, t Type) Type { // Unlike evalStaticType, x is not expected to be a typeval, // but rather computes the type OF x. func evalStaticTypeOf(store Store, last BlockNode, x Expr) Type { - debugPP.Printf("---evalStaticTypeOf: x : %v \n", x) t := evalStaticTypeOfRaw(store, last, x) if tt, ok := t.(*tupleType); ok { if len(tt.Elts) != 1 { @@ -2184,18 +2150,13 @@ func evalStaticTypeOf(store Store, last BlockNode, x Expr) Type { // like evalStaticTypeOf() but returns the raw *tupleType for *CallExpr. func evalStaticTypeOfRaw(store Store, last BlockNode, x Expr) (t Type) { - debugPP.Printf("---evalStaticTypeOfRaw: %v \n", x) if t, ok := x.GetAttribute(ATTR_TYPEOF_VALUE).(Type); ok { - debugPP.Printf("1, t: %v \n", t) return t } else if _, ok := x.(*constTypeExpr); ok { - debugPP.Println("2") return gTypeType } else if ctx, ok := x.(*ConstExpr); ok { - debugPP.Println("3") return ctx.T } else { - debugPP.Println("4") pn := packageOf(last) // NOTE: do not load the package value from store, // because we may be preprocessing in the middle of @@ -2302,20 +2263,17 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { - debugPP.Printf("evalConst: %v \n", x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) tv := cv.EvalStatic(last, x) cv.Release() - // debugPP.Printf("result: %v \n", tv) cx := &ConstExpr{ Source: x, TypedValue: tv, } cx.SetAttribute(ATTR_PREPROCESSED, true) setConstAttrs(cx) - // debugPP.Printf("cx: %+v, source: %v, tv: %v \n", cx, cx.Source, cx.TypedValue) return cx } @@ -2434,7 +2392,7 @@ func isConstType(x Expr) bool { } func cmpSpecificity(t1, t2 Type) int { - debugPP.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) + debug.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) if it1, ok := baseOf(t1).(*InterfaceType); ok { if it1.IsEmptyInterface() { return 1 // left empty interface @@ -2472,7 +2430,6 @@ func cmpSpecificity(t1, t2 Type) int { // for special case to bypass check for typed -> typed conversion, e.g. array index conversion func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { - debugPP.Printf("convertConstType, x: %v, t:%v, \n", x, t) if cx, ok := (*x).(*ConstExpr); ok { convertConst(store, last, cx, t) } @@ -2487,7 +2444,9 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // coerce implies a mandatory convert, it happens with explicit conversion, uint64(int(1)), or RHS of a // shift expr, or key of slice/array. func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { - debugPP.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) + if debug { + debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) + } if cx, ok := (*x).(*ConstExpr); ok { if !coerce { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint @@ -2505,7 +2464,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // if dest type is nil or interface, adopt its default type, if not, adopt the concrete dest type // if conduct explicit conversion on typed shift, set coerce to be true, this always happens in callExpr. xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) + if debug { + debug.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) + } if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { t = defaultTypeOf(xt) @@ -2525,7 +2486,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } else if ux, ok := (*x).(*UnaryExpr); ok { - debugPP.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) + if debug { + debug.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) + } xt := evalStaticTypeOf(store, last, *x) if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { @@ -2543,7 +2506,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) - debugPP.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) + if debug { + debug.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) + } var isUnnamed bool if t != nil && !coerce { isUnnamed = checkAssignable(xt, t, autoNative) @@ -2552,7 +2517,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if _, ok := t.(*InterfaceType); ok || t == nil { t = defaultTypeOf(xt) } - debugPP.Printf("default type of t: %v \n", t) + debug.Printf("default type of t: %v \n", t) // Push type into expr if qualifying binary expr. // main logic for handling nested binary expr // e.g. 1 << 2 + 1 << x, will be handled recursively until its type is determined. @@ -2595,19 +2560,14 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - debugPP.Printf("---convertConst---, cx:%v,cx.T: %v, t:%v \n", cx, cx.T, t) if t != nil && t.Kind() == InterfaceKind { if cx.IsUndefined() && cx.T == nil { // if cx is nil, not undefined interface if _, ok := t.(*NativeType); !ok { // bypass native nil interface, not support native interface(nil) now - debugPP.Println("special case for undefined to interface{}") - debugPP.Printf("before convert, cx: %v, cx.T: %v \n", cx, cx.T) ConvertTo(nilAllocator, store, &cx.TypedValue, t) setConstAttrs(cx) - debugPP.Printf("after convert, cx: %v, cx.T: %v \n", cx, cx.T) return } } - debugPP.Println(("set interface to nil, nothing else happens")) t = nil } if isUntyped(cx.T) { @@ -2654,7 +2614,7 @@ const ( // checkOrConvertType() operation to optimize performance. func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { - debugPP.Printf("checkOperandWithOp, dt: %v,op: %v, nt: %v \n", dt, op, nt) + debug.Printf("checkOperandWithOp, dt: %v,op: %v, nt: %v \n", dt, op, nt) if nt == Unary || nt == IncDec { switch nt { case Unary: diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index f76ab8f48b0..248197f140c 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1011,7 +1011,6 @@ func (it *InterfaceType) IsImplementedBy(ot Type) (result bool) { dmtid := mt.TypeID() imtid := im.Type.TypeID() if dmtid != imtid { - debugPP.Println("fourth false") return false } } @@ -2108,7 +2107,9 @@ func isSameType(lt, rt Type) bool { // runtime assert func assertAssignable(lt, rt Type) { - debugPP.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + if debug { + debug.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + } if isSameType(lt, rt) { // both are nil/undefined or same type. } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil @@ -2135,7 +2136,9 @@ func assertAssignable(lt, rt Type) { // assert value with dt is comparable // special case when both typed, check if type identical func assertComparable(xt, dt Type) { - debugPP.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) + if debug { + debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) + } switch cdt := baseOf(dt).(type) { case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage? case *ArrayType: // NOTE: no recursive allowed @@ -2207,7 +2210,9 @@ func assertMaybeNil(msg string, t Type) { // XXX. the name of checkAssignable should be considered. // we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { - debugPP.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) + if debug { + debug.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) + } // case0 if xt == nil { // refer to 0f18_filetest assertMaybeNil("invalid operation, nil can not be compared to", dt) @@ -2331,7 +2336,9 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // special case if implicitly named primitive type. // TODO simplify with .IsNamedType(). if _, ok := xt.(PrimitiveType); ok { // e.g. 1 == Int(1) - debugPP.Printf("xt is primitiveType: %v, ddt: %v \n", xt, ddt) + if debug { + debug.Printf("xt is primitiveType: %v, ddt: %v \n", xt, ddt) + } // this is special when dt is the declared type of x if !isUntyped(xt) { panic(fmt.Sprintf( @@ -2350,7 +2357,6 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // General cases. switch cdt := dt.(type) { case PrimitiveType: // case 1 - debugPP.Println("primitive type") // if xt is untyped, ensure dt is compatible. switch xt { case UntypedBoolType: @@ -2441,7 +2447,9 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *NativeType: if !autoNative { - debugPP.Printf("native type, xt.TypeID: %v, cdt.TypeID: %v \n", xt.TypeID(), cdt.TypeID()) + if debug { + debug.Printf("native type, xt.TypeID: %v, cdt.TypeID: %v \n", xt.TypeID(), cdt.TypeID()) + } if xt.TypeID() == cdt.TypeID() { return // ok } @@ -2453,7 +2461,6 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { if gno2GoTypeMatches(xt, cdt.Type) { return // ok } - debugPP.Println("gno2Go type not match") } default: panic(fmt.Sprintf( diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index cbd3fc69f73..4cf944e5f2d 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -2376,8 +2376,6 @@ func (b *Block) GetParent(store Store) *Block { } func (b *Block) GetPointerToInt(store Store, index int) PointerValue { - // debugPP.Printf("---GetPointerToInt, path: %v \n", index) - // debugPP.Printf("---GetPointerToInt, b: %v \n", b) vv := fillValueTV(store, &b.Values[index]) return PointerValue{ TV: vv, @@ -2387,8 +2385,6 @@ func (b *Block) GetPointerToInt(store Store, index int) PointerValue { } func (b *Block) GetPointerTo(store Store, path ValuePath) PointerValue { - // debugPP.Printf("---GetPointerTo, path: %v \n", path) - // debugPP.Printf("---GetPointerTo, b: %v \n", b) if path.IsBlockBlankPath() { if debug { if path.Name != "_" { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 2acae558320..35ed1999d69 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -14,7 +14,6 @@ import ( // the conversion is forced and overflow/underflow is ignored. // TODO: return error, and let caller also print the file and line. func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { - debugPP.Printf("--------------ConvertTo, tv: %v, t: %v \n", tv, t) if debug { if t == nil { panic("ConvertTo() requires non-nil type") @@ -33,9 +32,7 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { ntv, tvIsNat := tv.T.(*NativeType) nt, tIsNat := t.(*NativeType) if tvIsNat { - debugPP.Println("tvIsNat") if tIsNat { - debugPP.Println("t IsNat") // both NativeType, use reflect to assert. if debug { if !ntv.Type.ConvertibleTo(nt.Type) { @@ -47,12 +44,10 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { tv.T = t return } else { - debugPP.Println("t not IsNat") // both NativeType, use reflect to assert. // convert go-native to gno type (shallow). *tv = go2GnoValue2(alloc, store, tv.V.(*NativeValue).Value, false) ConvertTo(alloc, store, tv, t) - debugPP.Printf("tv after conversion: %v \n", tv) return } } else { @@ -80,10 +75,8 @@ GNO_CASE: // special case for interface target if t.Kind() == InterfaceKind { if tv.IsUndefined() && tv.T == nil { // if tv.T == nil, nil T and nil Value. not a nil interface - debugPP.Printf("-----convertTo, tv: %v, tv.T: %v \n", tv, tv.T) - debugPP.Println("tv.T is nil") if _, ok := t.(*NativeType); !ok { // no support for native now - debugPP.Printf("t is interface and not native, t: %v \n", t) + debug.Printf("t is interface and not native, t: %v \n", t) tv.T = t } } @@ -91,7 +84,6 @@ GNO_CASE: } // special case for undefined/nil source if tv.IsUndefined() { - debugPP.Println("case of undefined") tv.T = t return } @@ -880,7 +872,6 @@ GNO_CASE: tv.T.String(), k.String())) } case BigintKind: - debugPP.Println("---bigIntKind---") ConvertUntypedBigintTo(tv, tv.V.(BigintValue), t) default: panic(fmt.Sprintf( @@ -895,10 +886,11 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { - debugPP.Printf("---ConvertUntypedTo---, tv:%v, t:%v \n", tv, t) - defer func() { - debugPP.Printf("---after ConvertUntypedTo---, tv:%v \n", tv) - }() + if debug { + defer func() { + debug.Printf("---after ConvertUntypedTo---, tv:%v \n", tv) + }() + } if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( @@ -925,7 +917,6 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { } // special case: native if nt, ok := t.(*NativeType); ok { - debugPP.Println("native type") // first convert untyped to typed gno value. gnot := go2GnoBaseType(nt.Type) if debug { @@ -941,13 +932,11 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { // special case: simple conversion if t != nil && tv.T.Kind() == t.Kind() { tv.T = t - debugPP.Printf("simple conversion, tv.T: %v \n", tv.T) return } // general case if t == nil { t = defaultTypeOf(tv.T) - debugPP.Printf("give t its default type, to be:%v \n", t) } switch tv.T { case UntypedBoolType: @@ -970,13 +959,11 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { } ConvertUntypedBigdecTo(tv, tv.V.(BigdecValue), t) case UntypedStringType: - debugPP.Println("untyped string to string") if preprocessing == 0 { panic("untyped String conversion should not happen during interpretation") } if t.Kind() == StringKind { tv.T = t - debugPP.Printf("tv.T %v \n", tv.T) return } else { ConvertTo(nilAllocator, nil, tv, t) @@ -1076,7 +1063,6 @@ func ConvertUntypedRuneTo(dst *TypedValue, t Type) { } func ConvertUntypedBigintTo(dst *TypedValue, bv BigintValue, t Type) { - debugPP.Printf("ConvertUntypedBigintTo, dst: %v, bv:%v, t:%v \n", dst, bv, t) k := t.Kind() bi := bv.V var sv int64 = 0 // if signed. diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index 669c8067787..b00ab352fde 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -162,7 +162,6 @@ func (v RefValue) String() string { // for print() and println(). func (tv *TypedValue) Sprint(m *Machine) string { - debugPP.Println("sprint") // if undefined, just "undefined". if tv == nil || tv.T == nil { return undefinedStr @@ -267,7 +266,9 @@ func (tv *TypedValue) Sprint(m *Machine) string { } func printNilOrValue(tv *TypedValue, valueType interface{}) string { - debugPP.Printf("printNilOrValue: tv: %v, T:%v, V:%v \n", *tv, (*tv).T, (*tv).V) + if debug { + debug.Printf("printNilOrValue: tv: %v, T:%v, V:%v \n", *tv, (*tv).T, (*tv).V) + } if tv.V == nil { return nilStr + " " + tv.T.String() } From afde8b00d2f8e440d9b15825f5cc2b732802606b Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 8 Feb 2024 21:30:08 +0800 Subject: [PATCH 095/193] escape op on render side --- gnovm/pkg/gnolang/nodes_string.go | 4 ++-- gnovm/pkg/gnolang/preprocess.go | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index c6e47f9dcff..37db308fe31 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -13,7 +13,7 @@ var wordTokenStrings = map[Word]string{ SUB: "-", MUL: "*", QUO: "/", - REM: "%%", // escape to be rendered correctly + REM: "%", // escape to be rendered correctly BAND: "&", BOR: "|", XOR: "^", @@ -24,7 +24,7 @@ var wordTokenStrings = map[Word]string{ SUB_ASSIGN: "-=", MUL_ASSIGN: "*=", QUO_ASSIGN: "/=", - REM_ASSIGN: "%%=", + REM_ASSIGN: "%=", BAND_ASSIGN: "&=", BOR_ASSIGN: "|=", XOR_ASSIGN: "^=", diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9cce37c8e9e..a13fd152600 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" "reflect" + "strings" "github.com/gnolang/gno/tm2/pkg/errors" ) @@ -2615,15 +2616,16 @@ const ( func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { debug.Printf("checkOperandWithOp, dt: %v,op: %v, nt: %v \n", dt, op, nt) + escapedOpStr := strings.Replace(wordTokenStrings[op], "%", "%%", 1) if nt == Unary || nt == IncDec { switch nt { case Unary: if pred, ok := unaryChecker[op]; ok { if !pred(dt) { if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) } } } else { @@ -2633,9 +2635,9 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, if pred, ok := IncDecStmtChecker[op]; ok { if !pred(dt) { if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) } } } else { @@ -2661,9 +2663,9 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, if pred, ok := binaryChecker[op]; ok { if !pred(dt) { if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) } } } else { @@ -2676,9 +2678,9 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, if pred, ok := binaryChecker[op]; ok { if !pred(dt) { if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) } } } else { @@ -2702,9 +2704,9 @@ func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, if pred, ok := AssignStmtChecker[op]; ok { if !pred(dt) { if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt.Kind())) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[op], dt)) + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) } } switch op { From 40ec4938c54bc62eb41d7da668e3730125742499 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 1 Mar 2024 18:12:20 +0800 Subject: [PATCH 096/193] migrate logic to type_check.go; move compatibility check as method of node, that make somes originally logic happens in ealier stages --- gnovm/pkg/gnolang/op_compatibility.go | 198 ----------- gnovm/pkg/gnolang/preprocess.go | 47 +-- gnovm/pkg/gnolang/type_check.go | 318 ++++++++++++++++++ gnovm/pkg/gnolang/types.go | 18 +- gnovm/tests/debug/binary_1.gno | 8 + gnovm/tests/debug/binary_1a.gno | 8 + gnovm/tests/debug/binary_1b.gno | 8 + gnovm/tests/debug2/0f26_stdlibs_filetest.gno | 27 ++ gnovm/tests/debug2/5d0_filetest.gnoa | 10 + gnovm/tests/debug2/5d0a_filetest.gno | 10 + gnovm/tests/debug2/5d0b_filetest.gno | 10 + gnovm/tests/debug2/binary_1a.gno | 8 + gnovm/tests/debug2/binary_2.gnoa | 8 + gnovm/tests/debug2/binary_3.gnoa | 8 + gnovm/tests/files/types/0b2_filetest.gno | 2 +- gnovm/tests/files/types/0f20_filetest.gno | 2 +- .../tests/files/types/11a8_LAND_filetest.gno | 2 +- gnovm/tests/files/types/1a0_ADD_filetest.gno | 2 +- gnovm/tests/files/types/1a1_filetest.gno | 2 +- gnovm/tests/files/types/1b2_filetest.gno | 2 +- gnovm/tests/files/types/1e0_filetest.gno | 2 +- gnovm/tests/files/types/2a0_SUB_filetest.gno | 2 +- gnovm/tests/files/types/2a1_filetest.gno | 2 +- gnovm/tests/files/types/2e0_filetest.gno | 2 +- gnovm/tests/files/types/3a0_MUL_filetest.gno | 2 +- gnovm/tests/files/types/3a1_filetest.gno | 2 +- gnovm/tests/files/types/3e0_filetest.gno | 2 +- gnovm/tests/files/types/4a0_QUO_filetest.gno | 2 +- gnovm/tests/files/types/4a1_filetest.gno | 2 +- gnovm/tests/files/types/4e0_filetest.gno | 2 +- gnovm/tests/files/types/5a0_REM_filetest.gno | 2 +- gnovm/tests/files/types/5a1_filetest.gno | 2 +- gnovm/tests/files/types/5e0_filetest.gno | 2 +- gnovm/tests/files/types/6a0_AND_filetest.gno | 2 +- gnovm/tests/files/types/6a1_filetest.gno | 2 +- gnovm/tests/files/types/6e0_filetest.gno | 2 +- gnovm/tests/files/types/7a0_OR_filetest.gno | 2 +- gnovm/tests/files/types/7a1_filetest.gno | 2 +- gnovm/tests/files/types/7e0_filetest.gno | 2 +- gnovm/tests/files/types/8a0_XOR_filetest.gno | 2 +- gnovm/tests/files/types/8a1_filetest.gno | 2 +- gnovm/tests/files/types/8e0_filetest.gno | 2 +- .../tests/files/types/9a0_ANDNOT_filetest.gno | 2 +- gnovm/tests/files/types/9a1_filetest.gno | 2 +- gnovm/tests/files/types/9e0_filetest.gno | 2 +- 45 files changed, 497 insertions(+), 251 deletions(-) delete mode 100644 gnovm/pkg/gnolang/op_compatibility.go create mode 100644 gnovm/pkg/gnolang/type_check.go create mode 100644 gnovm/tests/debug/binary_1.gno create mode 100644 gnovm/tests/debug/binary_1a.gno create mode 100644 gnovm/tests/debug/binary_1b.gno create mode 100644 gnovm/tests/debug2/0f26_stdlibs_filetest.gno create mode 100644 gnovm/tests/debug2/5d0_filetest.gnoa create mode 100644 gnovm/tests/debug2/5d0a_filetest.gno create mode 100644 gnovm/tests/debug2/5d0b_filetest.gno create mode 100644 gnovm/tests/debug2/binary_1a.gno create mode 100644 gnovm/tests/debug2/binary_2.gnoa create mode 100644 gnovm/tests/debug2/binary_3.gnoa diff --git a/gnovm/pkg/gnolang/op_compatibility.go b/gnovm/pkg/gnolang/op_compatibility.go deleted file mode 100644 index a1721887cd4..00000000000 --- a/gnovm/pkg/gnolang/op_compatibility.go +++ /dev/null @@ -1,198 +0,0 @@ -package gnolang - -import "fmt" - -// here are a range of rules predefined for preprocessor to check the compatibility between operands and operators -// e,g. for binary expr x + y, x, y can only be numeric or string, 1+2, "a" + "b" -// this is used in checkOperandWithOp(). -var ( - binaryChecker = map[Word]func(t Type) bool{ - ADD: isNumericOrString, - SUB: isNumeric, - MUL: isNumeric, - QUO: isNumeric, - REM: isIntNum, - SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. - SHR: isIntNum, - BAND: isIntNum, // bit ops - XOR: isIntNum, - BOR: isIntNum, - BAND_NOT: isIntNum, - LAND: isBoolean, // logic - LOR: isBoolean, - LSS: isOrdered, // compare - LEQ: isOrdered, - GTR: isOrdered, - GEQ: isOrdered, - } - unaryChecker = map[Word]func(t Type) bool{ - ADD: isNumeric, - SUB: isNumeric, - XOR: isIntNum, - NOT: isBoolean, - } - IncDecStmtChecker = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). - INC: isNumeric, - DEC: isNumeric, - } - AssignStmtChecker = map[Word]func(t Type) bool{ - ADD_ASSIGN: isNumericOrString, - SUB_ASSIGN: isNumeric, - MUL_ASSIGN: isNumeric, - QUO_ASSIGN: isNumeric, - REM_ASSIGN: isIntNum, - SHL_ASSIGN: isNumeric, - SHR_ASSIGN: isNumeric, - BAND_ASSIGN: isIntNum, - XOR_ASSIGN: isIntNum, - BOR_ASSIGN: isIntNum, - BAND_NOT_ASSIGN: isIntNum, - } -) - -type category int - -const ( - IsInvalid category = 0 - IsBoolean category = 1 << iota - IsInteger - IsUnsigned - IsFloat - IsString - IsBigInt - IsBigDec - IsRune - - IsNumeric = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec - IsOrdered = IsNumeric | IsString - IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec -) - -// category makes it more convenient than compare with types -func (pt PrimitiveType) predicate() category { - switch pt { - case InvalidType: - return IsInvalid - case UntypedBoolType: - return IsBoolean - case BoolType: - return IsBoolean - case UntypedStringType: - return IsString - case StringType: - return IsString - case IntType: - return IsInteger - case Int8Type: - return IsInteger - case Int16Type: - return IsInteger - case UntypedRuneType: // TODO: this is treat as DataByteType, GUESS, refer to op_inc_dec - return IsRune - case Int32Type: - return IsInteger - case Int64Type: - return IsInteger - case UintType: - return IsUnsigned - case Uint8Type: - return IsUnsigned - case DataByteType: - return IsUnsigned // TODO: consider this - case Uint16Type: - return IsUnsigned - case Uint32Type: - return IsUnsigned - case Uint64Type: - return IsUnsigned - case Float32Type: - return IsFloat - case Float64Type: - return IsFloat - case UntypedBigintType: - return IsBigInt - case BigintType: - return IsBigInt - case UntypedBigdecType: - return IsBigDec - case BigdecType: - return IsBigDec - default: - panic(fmt.Sprintf("unexpected primitive type %d", pt)) - } -} - -func isOrdered(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -func isBoolean(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsBoolean != 0 { - return true - } - return false - default: - return false - } -} - -// rune can be numeric and string -// TODO: consider, do we need complex? -func isNumeric(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -func isIntOrFloat(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsIntOrFloat != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -// signed or unsigned int -func isIntNum(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsBigInt != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} - -func isNumericOrString(t Type) bool { - switch t := baseOf(t).(type) { - case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsString != 0 || t.predicate()&IsRune != 0 { - return true - } - return false - default: - return false - } -} diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a13fd152600..e164bbc64c4 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -765,6 +765,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } + n.AssertCompatible(store, last) + // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) @@ -780,25 +782,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cmp < 0 { debug.Println("cmp < 0, ->") // convert n.Left to right type. - checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) + n.AssertCompatible(store, last) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { debug.Println("cmp == 0") // to typed-nil. refer to 0f46 if lcx.T == nil { // TODO: make nil check happen in cmpSpecificity - checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) + //n.AssertCompatible(store, last) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { - checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } else { // default case, e.g. int(1) == int8(1), will also conduct type check - checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) + //n.AssertCompatible(store, last) + //checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } } else { debug.Println("cmp > 0, <-") // convert n.Right to left type. - checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } // check special case: zero divisor @@ -821,7 +826,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - checkOperandWithOp(store, last, &n.Left, pt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, pt, false, false) // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) @@ -841,23 +846,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { if !isShift { // convert n.Left to right type. - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } } else if lcx.T == nil { // LHS is nil if !isShift { // convert n.Left to typed-nil type. - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } else { // left is typed const, right not const if !isShift { if isUntyped(rt) { // refer to 0_d.gno - checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else { - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } @@ -872,7 +877,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - checkOperandWithOp(store, last, &n.Right, pt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, pt, false, false) // and convert result back. tx := constType(n, lnt) @@ -889,20 +894,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } } else if rcx.T == nil { // RHS is nil // refer to 0f20_filetest - checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else if !isShift { // left not const(typed), right is typed const, both typed if isUntyped(lt) { // refer to 0_d.gno - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else { - checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } @@ -963,12 +968,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Left, n.Op, n.Right)) } } else { // left untyped, right typed - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } else if riu { // left typed, right untyped if !isShift { - checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } else { // both typed, refer to 0a1f @@ -976,13 +981,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cmp := cmpSpecificity(lt, rt) debug.Println("cmp: ", cmp) if cmp == -1 { - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else if cmp == 1 { - checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else { - checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } @@ -2445,6 +2450,8 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // coerce implies a mandatory convert, it happens with explicit conversion, uint64(int(1)), or RHS of a // shift expr, or key of slice/array. func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { + // check compatibility with operand and op + if debug { debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go new file mode 100644 index 00000000000..f9415a52360 --- /dev/null +++ b/gnovm/pkg/gnolang/type_check.go @@ -0,0 +1,318 @@ +package gnolang + +import ( + "fmt" + "strings" +) + +// here are a range of rules predefined for preprocessor to check the compatibility between operands and operators +// e,g. for binary expr x + y, x, y can only be numeric or string, 1+2, "a" + "b" +// this is used in checkOperandWithOp(). +var ( + binaryChecker = map[Word]func(t Type) bool{ + ADD: isNumericOrString, + SUB: isNumeric, + MUL: isNumeric, + QUO: isNumeric, + REM: isIntNum, // in compile stage good for bigdec, that can be converted to int, `checkAssignable` + SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. + SHR: isIntNum, + BAND: isIntNum, // bit ops + XOR: isIntNum, + BOR: isIntNum, + BAND_NOT: isIntNum, + LAND: isBoolean, // logic + LOR: isBoolean, + LSS: isOrdered, // compare + LEQ: isOrdered, + GTR: isOrdered, + GEQ: isOrdered, + } + unaryChecker = map[Word]func(t Type) bool{ + ADD: isNumeric, + SUB: isNumeric, + XOR: isIntNum, + NOT: isBoolean, + } + IncDecStmtChecker = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). + INC: isNumeric, + DEC: isNumeric, + } + AssignStmtChecker = map[Word]func(t Type) bool{ + ADD_ASSIGN: isNumericOrString, + SUB_ASSIGN: isNumeric, + MUL_ASSIGN: isNumeric, + QUO_ASSIGN: isNumeric, + REM_ASSIGN: isIntNum, + SHL_ASSIGN: isNumeric, + SHR_ASSIGN: isNumeric, + BAND_ASSIGN: isIntNum, + XOR_ASSIGN: isIntNum, + BOR_ASSIGN: isIntNum, + BAND_NOT_ASSIGN: isIntNum, + } +) + +type category int + +const ( + IsInvalid category = 0 + IsBoolean category = 1 << iota + IsInteger + IsUnsigned + IsFloat + IsString + IsBigInt + IsBigDec + IsRune + + IsNumeric = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec + IsOrdered = IsNumeric | IsString + //IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec +) + +// category makes it more convenient than compare with types +func (pt PrimitiveType) predicate() category { + switch pt { + case InvalidType: + return IsInvalid + case UntypedBoolType: + return IsBoolean + case BoolType: + return IsBoolean + case UntypedStringType: + return IsString + case StringType: + return IsString + case IntType: + return IsInteger + case Int8Type: + return IsInteger + case Int16Type: + return IsInteger + case UntypedRuneType: // TODO: this is treat as DataByteType, GUESS, refer to op_inc_dec + return IsRune + case Int32Type: + return IsInteger + case Int64Type: + return IsInteger + case UintType: + return IsUnsigned + case Uint8Type: + return IsUnsigned + case DataByteType: + return IsUnsigned // TODO: consider this + case Uint16Type: + return IsUnsigned + case Uint32Type: + return IsUnsigned + case Uint64Type: + return IsUnsigned + case Float32Type: + return IsFloat + case Float64Type: + return IsFloat + case UntypedBigintType: + return IsBigInt + case BigintType: + return IsBigInt + case UntypedBigdecType: + return IsBigDec + case BigdecType: + return IsBigDec + default: + panic(fmt.Sprintf("unexpected primitive type %d", pt)) + } +} + +func isOrdered(t Type) bool { + debug.Printf("---isOrdered, t is %v \n", t) + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { + debug.Println("is Ordered!") + return true + } + return false + default: + return false + } +} + +func isBoolean(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsBoolean != 0 { + return true + } + return false + default: + return false + } +} + +// rune can be numeric and string +// TODO: consider, do we need complex? +func isNumeric(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +//func isIntOrFloat(t Type) bool { +// switch t := baseOf(t).(type) { +// case PrimitiveType: +// if t.predicate() != IsInvalid && t.predicate()&IsIntOrFloat != 0 || t.predicate()&IsRune != 0 { +// return true +// } +// return false +// default: +// return false +// } +//} + +// signed or unsigned int +func isIntNum(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsBigInt != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +func isNumericOrString(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsString != 0 || t.predicate()&IsRune != 0 { + return true + } + return false + default: + return false + } +} + +// =========================================================== + +type Checker struct { +} + +// check both sides since no aware of which side is dest type +// TODO: add check assignable, 1.0 % uint64(1) is valid as is assignable +// that lt not compatible but rt is compatible would be good +// things like this would fail: println(1.0 % 1) + +func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode) { + debug.Printf("---AssertCompatible, bx: %v \n", bx) + + debug.Printf("---AssertCompatible, bx.Left: %T \n", bx.Left) + debug.Printf("---AssertCompatible, bx.Right: %T \n", bx.Right) + + // get left type and right type + var lt, rt Type + if lx, ok := (bx.Left).(*ConstExpr); ok { + lt = lx.T + } else if bx.Left != nil { + lt = evalStaticTypeOf(store, last, bx.Left) + } + + if rx, ok := (bx.Right).(*ConstExpr); ok { + rt = rx.T + } else if bx.Left != nil { + rt = evalStaticTypeOf(store, last, bx.Right) + } + + debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, bx.Op) + escapedOpStr := strings.Replace(wordTokenStrings[bx.Op], "%", "%%", 1) + if isComparison(bx.Op) { + switch bx.Op { + case EQL, NEQ: + assertComparable(lt, rt) + case LSS, LEQ, GTR, GEQ: + if pred, ok := binaryChecker[bx.Op]; ok { + assertCompatible2(lt, rt, pred, escapedOpStr) + } else { + panic("should not happen") + } + default: + panic("invalid comparison operator") + } + } else { + if pred, ok := binaryChecker[bx.Op]; ok { + assertCompatible2(lt, rt, pred, escapedOpStr) + } else { + panic("should not happen") + } + + switch bx.Op { + case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: + // if both typed + if !isUntyped(lt) && !isUntyped(rt) { + if lt != nil && rt != nil { // NOTE: is this necessary? + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + } + } + } + default: + // do nothing + } + } +} + +func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) { + var destKind interface{} + cmp := cmpSpecificity(lt, rt) + if !pred(lt) { // lt not compatible with op + if !pred(rt) { // rt not compatible with op + if lt != nil { // return error on left side that is checked first + destKind = lt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + } else { + debug.Println("---2") + // left not compatible, right is compatible + // cmp means the expected convert direction + // if cmp < 0, means potential conversion + // from left to right, so check assignable + // if cmp > 0, means potential conversion to + // left side that is not compatible, so stop + // the check here, assertion fail. + if cmp < 0 { + checkAssignable(lt, rt, false) + debug.Println("---assignable") + // TODO: set attr + } else { + if lt != nil { // return error on left side that is checked first + destKind = lt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + } + } + } else if !pred(rt) { // if left is compatible, right is not + // we don't need to check cmp == 0, for instance like 1 - "a", + // xxx, the fact of one of them is compatible while the other is not + // when they share same specificity implies not assignable? + if cmp > 0 { // right to left + checkAssignable(rt, lt, false) + } else { + if rt != nil { // return error on left side that is checked first + destKind = rt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + } + } else { + // both good + debug.Println("---both good") + } +} diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 248197f140c..2d719e13433 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2135,6 +2135,8 @@ func assertAssignable(lt, rt Type) { // assertComparable is used in preprocess. // assert value with dt is comparable // special case when both typed, check if type identical +// TODO: move this to type_checker? as a method? +// TODO: check mismatch on this, not postpone to checkOrConvertType func assertComparable(xt, dt Type) { if debug { debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) @@ -2375,7 +2377,19 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { "cannot use untyped string as %s", dt.Kind())) } - case UntypedBigintType, UntypedBigdecType: + + case UntypedBigdecType: // can bigdec assign to bigint? + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped Bigdec as %s", + dt.Kind())) + } + case UntypedBigintType: switch dt.Kind() { case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind, UintKind, Uint8Kind, Uint16Kind, @@ -2383,7 +2397,7 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { return // ok default: panic(fmt.Sprintf( - "cannot use untyped Bigint/Bigdec as %s", + "cannot use untyped Bigint as %s", dt.Kind())) } case UntypedRuneType: diff --git a/gnovm/tests/debug/binary_1.gno b/gnovm/tests/debug/binary_1.gno new file mode 100644 index 00000000000..2a34ff399df --- /dev/null +++ b/gnovm/tests/debug/binary_1.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 - "a") +} + +// Error: +// main/debug/binary_1.gno:4: operator - not defined on: StringKind diff --git a/gnovm/tests/debug/binary_1a.gno b/gnovm/tests/debug/binary_1a.gno new file mode 100644 index 00000000000..58645824754 --- /dev/null +++ b/gnovm/tests/debug/binary_1a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 == "a") +} + +// Error: +// main/debug/binary_1a.gno:4: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug/binary_1b.gno b/gnovm/tests/debug/binary_1b.gno new file mode 100644 index 00000000000..ee5e339929b --- /dev/null +++ b/gnovm/tests/debug/binary_1b.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 > "a") +} + +// Error: +// main/debug/binary_1b.gno:4: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug2/0f26_stdlibs_filetest.gno b/gnovm/tests/debug2/0f26_stdlibs_filetest.gno new file mode 100644 index 00000000000..70895cc5409 --- /dev/null +++ b/gnovm/tests/debug2/0f26_stdlibs_filetest.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if 1 > errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/debug/0f26_stdlibs_filetest.gno:19: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/debug2/5d0_filetest.gnoa b/gnovm/tests/debug2/5d0_filetest.gnoa new file mode 100644 index 00000000000..4b2e76cef6a --- /dev/null +++ b/gnovm/tests/debug2/5d0_filetest.gnoa @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 % uint64(1)) +} + +// Output: +// 0 diff --git a/gnovm/tests/debug2/5d0a_filetest.gno b/gnovm/tests/debug2/5d0a_filetest.gno new file mode 100644 index 00000000000..a94b7bb6267 --- /dev/null +++ b/gnovm/tests/debug2/5d0a_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 % 1) +} + +// Error: +// main/debug/5d0a_filetest.gno:6: operator % not defined on: BigdecKind \ No newline at end of file diff --git a/gnovm/tests/debug2/5d0b_filetest.gno b/gnovm/tests/debug2/5d0b_filetest.gno new file mode 100644 index 00000000000..781e42c8818 --- /dev/null +++ b/gnovm/tests/debug2/5d0b_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1 % 1.0) +} + +// Error: +// main/debug/5d0b_filetest.gno:6: operator % not defined on: BigdecKind diff --git a/gnovm/tests/debug2/binary_1a.gno b/gnovm/tests/debug2/binary_1a.gno new file mode 100644 index 00000000000..c5e87f1c583 --- /dev/null +++ b/gnovm/tests/debug2/binary_1a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println("a" - 1) +} + +// Error: +// main/debug/binary_1a.gno:4: operator - not defined on: StringKind diff --git a/gnovm/tests/debug2/binary_2.gnoa b/gnovm/tests/debug2/binary_2.gnoa new file mode 100644 index 00000000000..3559298a655 --- /dev/null +++ b/gnovm/tests/debug2/binary_2.gnoa @@ -0,0 +1,8 @@ +package main + +func main() { + println((1 + 2) == (int(1) + "a")) +} + +// Error: +// main/debug/binary_2.gno:4: ===invalid operation: mismatched types int and string diff --git a/gnovm/tests/debug2/binary_3.gnoa b/gnovm/tests/debug2/binary_3.gnoa new file mode 100644 index 00000000000..04bd98f3b58 --- /dev/null +++ b/gnovm/tests/debug2/binary_3.gnoa @@ -0,0 +1,8 @@ +package main + +func main() { + println(((1 + 2) + 3) == (int32(1) + 'a')) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/0b2_filetest.gno b/gnovm/tests/files/types/0b2_filetest.gno index f0214b6e2cf..0136f62da85 100644 --- a/gnovm/tests/files/types/0b2_filetest.gno +++ b/gnovm/tests/files/types/0b2_filetest.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/files/types/0b2_filetest.gno:14: cannot use untyped Bigint/Bigdec as StringKind +// main/files/types/0b2_filetest.gno:14: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index d42aceef7e4..5184d635afc 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types/0f20_filetest.gno:9: and [2]main.f cannot be compared +// main/files/types/0f20_filetest.gno:9: invalid operation, nil can not be compared to [2]main.f diff --git a/gnovm/tests/files/types/11a8_LAND_filetest.gno b/gnovm/tests/files/types/11a8_LAND_filetest.gno index 19505bf3574..379adcca6f6 100644 --- a/gnovm/tests/files/types/11a8_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a8_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/11a8_LAND_filetest.gno:4: cannot use untyped Bigint/Bigdec as BoolKind +// main/files/types/11a8_LAND_filetest.gno:4: cannot use untyped Bigint as BoolKind diff --git a/gnovm/tests/files/types/1a0_ADD_filetest.gno b/gnovm/tests/files/types/1a0_ADD_filetest.gno index 8bc3c607c42..ab289f63cae 100644 --- a/gnovm/tests/files/types/1a0_ADD_filetest.gno +++ b/gnovm/tests/files/types/1a0_ADD_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/1a0_ADD_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/1a0_ADD_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/1a1_filetest.gno b/gnovm/tests/files/types/1a1_filetest.gno index 68cb813fef9..0a33e70266d 100644 --- a/gnovm/tests/files/types/1a1_filetest.gno +++ b/gnovm/tests/files/types/1a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/1a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/1a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/1b2_filetest.gno b/gnovm/tests/files/types/1b2_filetest.gno index 2181f0d8a77..c8c1ba175db 100644 --- a/gnovm/tests/files/types/1b2_filetest.gno +++ b/gnovm/tests/files/types/1b2_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/1b2_filetest.gno:5: cannot use untyped Bigint/Bigdec as StringKind +// main/files/types/1b2_filetest.gno:5: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/files/types/1e0_filetest.gno b/gnovm/tests/files/types/1e0_filetest.gno index 4e31870425c..301859bd538 100644 --- a/gnovm/tests/files/types/1e0_filetest.gno +++ b/gnovm/tests/files/types/1e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/1e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/1e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/2a0_SUB_filetest.gno b/gnovm/tests/files/types/2a0_SUB_filetest.gno index e3793e0d36a..79881e8583b 100644 --- a/gnovm/tests/files/types/2a0_SUB_filetest.gno +++ b/gnovm/tests/files/types/2a0_SUB_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2a0_SUB_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/2a0_SUB_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/2a1_filetest.gno b/gnovm/tests/files/types/2a1_filetest.gno index 3b4e28d066b..1155f93370d 100644 --- a/gnovm/tests/files/types/2a1_filetest.gno +++ b/gnovm/tests/files/types/2a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/2a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/2a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/2e0_filetest.gno b/gnovm/tests/files/types/2e0_filetest.gno index 33430eb7bf1..5e72d7ee487 100644 --- a/gnovm/tests/files/types/2e0_filetest.gno +++ b/gnovm/tests/files/types/2e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/2e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/2e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/3a0_MUL_filetest.gno b/gnovm/tests/files/types/3a0_MUL_filetest.gno index 2a38ffa48f4..71a3ff8f957 100644 --- a/gnovm/tests/files/types/3a0_MUL_filetest.gno +++ b/gnovm/tests/files/types/3a0_MUL_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3a0_MUL_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/3a0_MUL_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/3a1_filetest.gno b/gnovm/tests/files/types/3a1_filetest.gno index a472459d4a9..3cd8d284400 100644 --- a/gnovm/tests/files/types/3a1_filetest.gno +++ b/gnovm/tests/files/types/3a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/3a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/3a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/3e0_filetest.gno b/gnovm/tests/files/types/3e0_filetest.gno index f4a85ac3ca9..c1080dcd091 100644 --- a/gnovm/tests/files/types/3e0_filetest.gno +++ b/gnovm/tests/files/types/3e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/3e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/3e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/4a0_QUO_filetest.gno b/gnovm/tests/files/types/4a0_QUO_filetest.gno index d7e69d7f10c..84376642b72 100644 --- a/gnovm/tests/files/types/4a0_QUO_filetest.gno +++ b/gnovm/tests/files/types/4a0_QUO_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4a0_QUO_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/4a0_QUO_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/4a1_filetest.gno b/gnovm/tests/files/types/4a1_filetest.gno index 018e51bfdcd..6dab9a883ad 100644 --- a/gnovm/tests/files/types/4a1_filetest.gno +++ b/gnovm/tests/files/types/4a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/4a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/4a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/4e0_filetest.gno b/gnovm/tests/files/types/4e0_filetest.gno index 2787bfe292e..e70bc1670ce 100644 --- a/gnovm/tests/files/types/4e0_filetest.gno +++ b/gnovm/tests/files/types/4e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/4e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/4e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/5a0_REM_filetest.gno b/gnovm/tests/files/types/5a0_REM_filetest.gno index b2199a69489..b12303f8ef5 100644 --- a/gnovm/tests/files/types/5a0_REM_filetest.gno +++ b/gnovm/tests/files/types/5a0_REM_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5a0_REM_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/5a0_REM_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/5a1_filetest.gno b/gnovm/tests/files/types/5a1_filetest.gno index c9d4eea47b4..ccb98a06446 100644 --- a/gnovm/tests/files/types/5a1_filetest.gno +++ b/gnovm/tests/files/types/5a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/5a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/5a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/5e0_filetest.gno b/gnovm/tests/files/types/5e0_filetest.gno index 7cb4a1adf48..37fd9ab2eb5 100644 --- a/gnovm/tests/files/types/5e0_filetest.gno +++ b/gnovm/tests/files/types/5e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/5e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/5e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/6a0_AND_filetest.gno b/gnovm/tests/files/types/6a0_AND_filetest.gno index 9b8d7590c56..e9555bbb34c 100644 --- a/gnovm/tests/files/types/6a0_AND_filetest.gno +++ b/gnovm/tests/files/types/6a0_AND_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/6a0_AND_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/6a0_AND_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/6a1_filetest.gno b/gnovm/tests/files/types/6a1_filetest.gno index b95f2cecf24..45e0596625f 100644 --- a/gnovm/tests/files/types/6a1_filetest.gno +++ b/gnovm/tests/files/types/6a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/6a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/6a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/6e0_filetest.gno b/gnovm/tests/files/types/6e0_filetest.gno index a7d605ee834..0d9349850f7 100644 --- a/gnovm/tests/files/types/6e0_filetest.gno +++ b/gnovm/tests/files/types/6e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/6e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/6e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/7a0_OR_filetest.gno b/gnovm/tests/files/types/7a0_OR_filetest.gno index 01c82fc0b4d..a53972c2883 100644 --- a/gnovm/tests/files/types/7a0_OR_filetest.gno +++ b/gnovm/tests/files/types/7a0_OR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/7a0_OR_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/7a0_OR_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/7a1_filetest.gno b/gnovm/tests/files/types/7a1_filetest.gno index 9fec5f4f466..111a5ec95d0 100644 --- a/gnovm/tests/files/types/7a1_filetest.gno +++ b/gnovm/tests/files/types/7a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/7a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/7a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/7e0_filetest.gno b/gnovm/tests/files/types/7e0_filetest.gno index 699c6538fb2..b19ab007e05 100644 --- a/gnovm/tests/files/types/7e0_filetest.gno +++ b/gnovm/tests/files/types/7e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/7e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/7e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/8a0_XOR_filetest.gno b/gnovm/tests/files/types/8a0_XOR_filetest.gno index cfd863e9992..991a4afdcc1 100644 --- a/gnovm/tests/files/types/8a0_XOR_filetest.gno +++ b/gnovm/tests/files/types/8a0_XOR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/8a0_XOR_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/8a0_XOR_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/8a1_filetest.gno b/gnovm/tests/files/types/8a1_filetest.gno index 8d677c807cb..b6e2d6ab6d6 100644 --- a/gnovm/tests/files/types/8a1_filetest.gno +++ b/gnovm/tests/files/types/8a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/8a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/8a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/8e0_filetest.gno b/gnovm/tests/files/types/8e0_filetest.gno index b09844c2702..66da7325199 100644 --- a/gnovm/tests/files/types/8e0_filetest.gno +++ b/gnovm/tests/files/types/8e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/8e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/8e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno index 27c053d46cd..143535662bf 100644 --- a/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno +++ b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/9a0_ANDNOT_filetest.gno:5: invalid operation: mismatched types int8 and int +// main/files/types/9a0_ANDNOT_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/9a1_filetest.gno b/gnovm/tests/files/types/9a1_filetest.gno index 842843852be..56224382fae 100644 --- a/gnovm/tests/files/types/9a1_filetest.gno +++ b/gnovm/tests/files/types/9a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/9a1_filetest.gno:21: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/9a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/9e0_filetest.gno b/gnovm/tests/files/types/9e0_filetest.gno index e23ad2b37a5..14dcd736468 100644 --- a/gnovm/tests/files/types/9e0_filetest.gno +++ b/gnovm/tests/files/types/9e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/9e0_filetest.gno:23: invalid operation: mismatched types main.Error2 and main.Error1 +// main/files/types/9e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 From 5f0cf8b5f3e3d1dc3f7993a1308fe2454e84ede1 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 1 Mar 2024 18:40:33 +0800 Subject: [PATCH 097/193] make test pass --- gnovm/pkg/gnolang/preprocess.go | 1 + gnovm/pkg/gnolang/type_check.go | 15 ++++++++++++--- gnovm/tests/debug/assign0b_native.gno | 19 +++++++++++++++++++ gnovm/tests/debug/binary_1a.gno | 8 -------- gnovm/tests/{debug => debug2}/binary_1.gno | 0 gnovm/tests/debug2/binary_1a.gno | 4 ++-- gnovm/tests/{debug => debug2}/binary_1b.gno | 0 gnovm/tests/files/type31.gno | 2 +- gnovm/tests/files/type32.gno | 2 +- 9 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 gnovm/tests/debug/assign0b_native.gno delete mode 100644 gnovm/tests/debug/binary_1a.gno rename gnovm/tests/{debug => debug2}/binary_1.gno (100%) rename gnovm/tests/{debug => debug2}/binary_1b.gno (100%) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e164bbc64c4..bbfff7fd87d 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2462,6 +2462,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // the reason why we need this is that the checkOperandWithOp() can not filter out all mismatch case, // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). + // TODO: if cx.GetAttribute(Attr_Assignable) == true checkAssignable(cx.T, t, autoNative) // refer to 22a17a } } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index f9415a52360..0d893e8ce75 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -217,7 +217,6 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode) { debug.Printf("---AssertCompatible, bx.Left: %T \n", bx.Left) debug.Printf("---AssertCompatible, bx.Right: %T \n", bx.Right) - // get left type and right type var lt, rt Type if lx, ok := (bx.Left).(*ConstExpr); ok { @@ -232,6 +231,15 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode) { rt = evalStaticTypeOf(store, last, bx.Right) } + // we can't check compatible with native types + // so leave it to checkOrConvertStage + if _, ok := lt.(*NativeType); ok { + return + } + if _, ok := rt.(*NativeType); ok { + return + } + debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, bx.Op) escapedOpStr := strings.Replace(wordTokenStrings[bx.Op], "%", "%%", 1) if isComparison(bx.Op) { @@ -281,6 +289,7 @@ func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } else { debug.Println("---2") + debug.Println("---cmp: ", cmp) // left not compatible, right is compatible // cmp means the expected convert direction // if cmp < 0, means potential conversion @@ -289,7 +298,7 @@ func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) // left side that is not compatible, so stop // the check here, assertion fail. if cmp < 0 { - checkAssignable(lt, rt, false) + checkAssignable(lt, rt, true) debug.Println("---assignable") // TODO: set attr } else { @@ -304,7 +313,7 @@ func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) // xxx, the fact of one of them is compatible while the other is not // when they share same specificity implies not assignable? if cmp > 0 { // right to left - checkAssignable(rt, lt, false) + checkAssignable(rt, lt, true) } else { if rt != nil { // return error on left side that is checked first destKind = rt.Kind() diff --git a/gnovm/tests/debug/assign0b_native.gno b/gnovm/tests/debug/assign0b_native.gno new file mode 100644 index 00000000000..42faa57634d --- /dev/null +++ b/gnovm/tests/debug/assign0b_native.gno @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + "time" + + "github.com/gnolang/gno/_test/net/http" +) + +func main() { + http.DefaultClient.Timeout = time.Second * 10 + fmt.Println(http.DefaultClient) + http.DefaultClient = &http.Client{} + fmt.Println(http.DefaultClient) +} + +// Output: +// &{ 10s} +// &{ 0s} diff --git a/gnovm/tests/debug/binary_1a.gno b/gnovm/tests/debug/binary_1a.gno deleted file mode 100644 index 58645824754..00000000000 --- a/gnovm/tests/debug/binary_1a.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1 == "a") -} - -// Error: -// main/debug/binary_1a.gno:4: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug/binary_1.gno b/gnovm/tests/debug2/binary_1.gno similarity index 100% rename from gnovm/tests/debug/binary_1.gno rename to gnovm/tests/debug2/binary_1.gno diff --git a/gnovm/tests/debug2/binary_1a.gno b/gnovm/tests/debug2/binary_1a.gno index c5e87f1c583..58645824754 100644 --- a/gnovm/tests/debug2/binary_1a.gno +++ b/gnovm/tests/debug2/binary_1a.gno @@ -1,8 +1,8 @@ package main func main() { - println("a" - 1) + println(1 == "a") } // Error: -// main/debug/binary_1a.gno:4: operator - not defined on: StringKind +// main/debug/binary_1a.gno:4: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug/binary_1b.gno b/gnovm/tests/debug2/binary_1b.gno similarity index 100% rename from gnovm/tests/debug/binary_1b.gno rename to gnovm/tests/debug2/binary_1b.gno diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index 7087561f33e..68c92e9a504 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/type31.gno:8: invalid operation: mismatched types main.String and string +// main/files/type31.gno:8: invalid operation: mismatched types string and main.String diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index 1a087ec1140..9565cdba245 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/type32.gno:9#1: invalid operation: mismatched types main.S and string +// main/files/type32.gno:9#1: invalid operation: mismatched types string and main.S From cbdc979056769205840859eeb33aef7c3fcc80d1 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 4 Mar 2024 22:09:11 +0800 Subject: [PATCH 098/193] done refactor to type_checker --- .../gno.land/r/gnoland/faucet/z2_filetest.gno | 6 +- .../gno.land/r/gnoland/faucet/z3_filetest.gno | 12 +- gnovm/pkg/gnolang/nodes.go | 1 + gnovm/pkg/gnolang/preprocess.go | 265 ++++-------------- gnovm/pkg/gnolang/type_check.go | 202 +++++++++++-- gnovm/pkg/gnolang/types.go | 20 ++ gnovm/tests/debug/0_a_3b.gno | 39 +++ gnovm/tests/debug2/10a11_filetest.gno | 10 + .../tests/debug2/13a0_ADD_ASSIGN_filetest.gno | 9 + gnovm/tests/debug2/5d0_filetest.gno | 10 + gnovm/tests/debug2/assign.gno | 10 + .../{debug => debug2}/assign0b_native.gno | 0 gnovm/tests/debug2/default_type.gno | 8 + gnovm/tests/debug2/inc.gno | 10 + gnovm/tests/debug2/native.gno | 12 + gnovm/tests/debug2/unary.gno | 8 + 16 files changed, 386 insertions(+), 236 deletions(-) create mode 100644 gnovm/tests/debug/0_a_3b.gno create mode 100644 gnovm/tests/debug2/10a11_filetest.gno create mode 100644 gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno create mode 100644 gnovm/tests/debug2/5d0_filetest.gno create mode 100644 gnovm/tests/debug2/assign.gno rename gnovm/tests/{debug => debug2}/assign0b_native.gno (100%) create mode 100644 gnovm/tests/debug2/default_type.gno create mode 100644 gnovm/tests/debug2/inc.gno create mode 100644 gnovm/tests/debug2/native.gno create mode 100644 gnovm/tests/debug2/unary.gno diff --git a/examples/gno.land/r/gnoland/faucet/z2_filetest.gno b/examples/gno.land/r/gnoland/faucet/z2_filetest.gno index 1791cd91989..39aad01002a 100644 --- a/examples/gno.land/r/gnoland/faucet/z2_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z2_filetest.gno @@ -16,11 +16,13 @@ func main() { ) std.TestSetOrigCaller(adminaddr) err := faucet.AdminAddController(controlleraddr1) - if err != nil { + //if err != nil { + if err != "" { panic(err) } err = faucet.AdminAddController(controlleraddr2) - if err != nil { + //if err != nil { + if err != "" { panic(err) } println(faucet.Render("")) diff --git a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno index 1dca56811a9..4d6fa19f198 100644 --- a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno @@ -18,21 +18,25 @@ func main() { ) std.TestSetOrigCaller(adminaddr) err := faucet.AdminAddController(controlleraddr1) - if err != nil { + //if err != nil { + if err != "" { panic(err) } err = faucet.AdminAddController(controlleraddr2) - if err != nil { + if err != "" { + //if err != nil { panic(err) } std.TestSetOrigCaller(controlleraddr1) err = faucet.Transfer(testaddr1, 1000000) - if err != nil { + if err != "" { + //if err != nil { panic(err) } std.TestSetOrigCaller(controlleraddr2) err = faucet.Transfer(testaddr1, 2000000) - if err != nil { + if err != "" { + //if err != nil { panic(err) } println(faucet.Render("")) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 2a9e0b51a97..30fa6d3973b 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -2021,6 +2021,7 @@ const ( ATTR_IOTA GnoAttribute = "ATTR_IOTA" ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" ATTR_INJECTED GnoAttribute = "ATTR_INJECTED" + ATTR_ASSIGNABLE GnoAttribute = "ATTR_ASSIGNABLE" ) // TODO: consider length restrictions. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index bbfff7fd87d..142cc74f61b 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,11 +2,9 @@ package gnolang import ( "fmt" + "github.com/gnolang/gno/tm2/pkg/errors" "math/big" "reflect" - "strings" - - "github.com/gnolang/gno/tm2/pkg/errors" ) // In the case of a *FileSet, some declaration steps have to happen @@ -124,6 +122,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { preprocessing += 1 defer func() { preprocessing -= 1 + AC = nil // xxx, clean, why ns not cleaned? }() } @@ -168,9 +167,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } if rerr, ok := r.(error); ok { // NOTE: gotuna/gorilla expects error exceptions. + fmt.Println(errors.Wrap(rerr, loc.String())) panic(errors.Wrap(rerr, loc.String())) } else { // NOTE: gotuna/gorilla expects error exceptions. + fmt.Println(errors.New(fmt.Sprintf("%s: %v", loc.String(), r))) panic(errors.New(fmt.Sprintf("%s: %v", loc.String(), r))) } } @@ -740,6 +741,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: + debug.Println("---BinaryExpr") + n.AssertCompatible(store, last, nil) + // TODO: improve readability lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) @@ -748,10 +752,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // special case of shift if isShift { // check LHS type compatibility - checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) + //checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) // checkOrConvert RHS if baseOf(rt) != UintType { - // checkOperandWithOp(store, last, &n.Left, lt, n.Op, true) // check lt with op, sh* // convert n.Right to (gno) uint type, rn := Expr(Call("uint", n.Right)) // reset/create n2 to preprocess right child. @@ -765,8 +768,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } - n.AssertCompatible(store, last) - // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) @@ -782,28 +783,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if cmp < 0 { debug.Println("cmp < 0, ->") // convert n.Left to right type. - //checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) - n.AssertCompatible(store, last) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { debug.Println("cmp == 0") // to typed-nil. refer to 0f46 if lcx.T == nil { // TODO: make nil check happen in cmpSpecificity - //checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) - //n.AssertCompatible(store, last) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { - //checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } else { // default case, e.g. int(1) == int8(1), will also conduct type check - //n.AssertCompatible(store, last) - //checkOperandWithOp(store, last, &n.Left, rcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } } else { debug.Println("cmp > 0, <-") // convert n.Right to left type. - //checkOperandWithOp(store, last, &n.Right, lcx.T, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } // check special case: zero divisor @@ -823,15 +816,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { // RHS of shift should not be native panic("should not happen") } + debug.Printf("---n: %v \n", n) + debug.Printf("---rt: %v \n", rt) + debug.Printf("---rnt: %v \n", rnt) // get concrete native base type. pt := go2GnoBaseType(rnt.Type).(PrimitiveType) // convert n.Left to pt type, - //checkOperandWithOp(store, last, &n.Left, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, pt, false, false) // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) + debug.Printf("---rn : %v \n", rn) // and convert result back. tx := constType(n, rnt) + debug.Printf("---tx : %v \n", tx) // reset/create n2 to preprocess right child. n2 := &BinaryExpr{ Left: n.Left, @@ -840,29 +837,26 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } resn := Node(Call(tx, n2)) resn = Preprocess(store, last, resn) + debug.Printf("---resn : %v \n", resn) return resn, TRANS_CONTINUE // NOTE: binary operations are always computed in // gno, never with reflect. } else { if !isShift { // convert n.Left to right type. - //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } } else if lcx.T == nil { // LHS is nil if !isShift { // convert n.Left to typed-nil type. - //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } else { // left is typed const, right not const if !isShift { if isUntyped(rt) { // refer to 0_d.gno - //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else { - //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } @@ -877,7 +871,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, - //checkOperandWithOp(store, last, &n.Right, pt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, pt, false, false) // and convert result back. tx := constType(n, lnt) @@ -894,20 +887,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // gno, never with reflect. } else { // convert n.Right to left type. - //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } } else if rcx.T == nil { // RHS is nil // refer to 0f20_filetest - //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else if !isShift { // left not const(typed), right is typed const, both typed if isUntyped(lt) { // refer to 0_d.gno - //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else { - //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } @@ -973,7 +962,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else if riu { // left typed, right untyped if !isShift { - //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } } else { // both typed, refer to 0a1f @@ -981,13 +969,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cmp := cmpSpecificity(lt, rt) debug.Println("cmp: ", cmp) if cmp == -1 { - //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } else if cmp == 1 { - //checkOperandWithOp(store, last, &n.Right, lt, n.Op, Binary) checkOrConvertType(store, last, &n.Right, lt, false, false) } else { - //checkOperandWithOp(store, last, &n.Left, rt, n.Op, Binary) checkOrConvertType(store, last, &n.Left, rt, false, false) } } @@ -1288,6 +1273,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: + n.AssertCompatible(store, last, nil) xt := evalStaticTypeOf(store, last, n.X) if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. @@ -1308,15 +1294,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // always computed in gno, never with reflect. } // Replace with *ConstExpr if const X. - // checkOperandWithOp, like +a, while a should be numeric - if cx, ok := n.X.(*ConstExpr); ok { - // checkOperandWithOp, e.g. +a while a should be numeric - checkOperandWithOp(store, last, nil, cx.T, n.Op, Unary) + if _, ok := n.X.(*ConstExpr); ok { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } - checkOperandWithOp(store, last, nil, xt, n.Op, Unary) - // checkOrConvertType(store, last, &n.X, nil, false) // TRANS_LEAVE ----------------------- case *CompositeLitExpr: @@ -1679,6 +1660,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } switch cx := n.Rhs[0].(type) { + // TODO: check compatible with this case? a, b = x(...) case *CallExpr: // Call case: a, b = x(...) ift := evalStaticTypeOf(store, last, cx.Func) @@ -1704,30 +1686,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { default: panic("should not happen") } - } else if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { - if len(n.Lhs) != 1 || len(n.Rhs) != 1 { - panic("should not happen") + } else { + if n.Op != ASSIGN { // filter out = + n.AssertCompatible(store, last) } - // Special case if shift assign <<= or >>=. - convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check - lt := evalStaticTypeOf(store, last, n.Lhs[0]) - checkOperandWithOp(store, last, &n.Lhs[0], lt, n.Op, XAssign) - } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { - // e.g. a += b, single value for lhs and rhs, - // TODO: assert length - lt := evalStaticTypeOf(store, last, n.Lhs[0]) - // a += b, requires b -> a conversion - checkOperandWithOp(store, last, &n.Rhs[0], lt, n.Op, XAssign) - checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) - } else { // all else, like BAND_ASSIGN, etc - // General case: a, b = x, y. - for i, lx := range n.Lhs { - lt := evalStaticTypeOf(store, last, lx) - if n.Op != ASSIGN { // filter out = - checkOperandWithOp(store, last, &n.Rhs[i], lt, n.Op, XAssign) + if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { + if len(n.Lhs) != 1 || len(n.Rhs) != 1 { + panic("should not happen") + } + // Special case if shift assign <<= or >>=. + convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check + } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { + // e.g. a += b, single value for lhs and rhs, + // TODO: assert length + lt := evalStaticTypeOf(store, last, n.Lhs[0]) + checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) + } else { // all else, like BAND_ASSIGN, etc + // General case: a, b = x, y. + for i, lx := range n.Lhs { + lt := evalStaticTypeOf(store, last, lx) + // if lt is interface, nothing will happen + checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) } - // if lt is interface, nothing will happen - checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) } } } @@ -1760,8 +1740,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *IncDecStmt: - xt := evalStaticTypeOf(store, last, n.X) - checkOperandWithOp(store, last, nil, xt, n.Op, IncDec) + n.AssertCompatible(store, last) // TRANS_LEAVE ----------------------- case *ForStmt: @@ -2463,6 +2442,14 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). // TODO: if cx.GetAttribute(Attr_Assignable) == true + //if cx.GetAttribute(ATTR_ASSIGNABLE) == true { + // debug.Printf("---assignable already set for: % \n", cx) + //} + if AC != nil { + if AC.cache[ExprTypePair{X: *x, T: t}] == true { + debug.Printf("---assignable already set for: %v => %v \n", cx, t) + } + } checkAssignable(cx.T, t, autoNative) // refer to 22a17a } } @@ -2487,7 +2474,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if coerce || !coerce && isUntyped(xt) { // coerce mostly when explicitly conversion, type call, while arg is binary expr // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 - checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) // left is the target operand + // TODO: do we need this any more? since already checked before? + // NO, it's from callExpr and should checked recursively + bx.AssertCompatible(store, last, t) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { // not coerce, xt is typed, no need to convert but check. refer to 10a17b1. @@ -2507,7 +2496,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } if coerce || !coerce && isUntyped(xt) { - checkOperandWithOp(store, last, &ux.X, t, ux.Op, Unary) + ux.AssertCompatible(store, last, t) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else { @@ -2535,9 +2524,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: // push t into bx.Left and bx.Right, recursively - checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) + //checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - checkOperandWithOp(store, last, &bx.Right, t, bx.Op, Binary) + //checkOperandWithOp(store, last, &bx.Right, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return case EQL, LSS, GTR, NEQ, LEQ, GEQ: @@ -2589,156 +2578,6 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { } } -func isQuoOrRem(op Word) bool { - switch op { - case QUO, QUO_ASSIGN, REM, REM_ASSIGN: - return true - default: - return false - } -} - -func isComparison(op Word) bool { - switch op { - case EQL, NEQ, LSS, LEQ, GTR, GEQ: - return true - default: - return false - } -} - -type nodeType int - -const ( - Binary = iota - Unary - IncDec - XAssign -) - -// checkOperandWithOp works as a pre-check prior to checkOrConvertType() -// It checks expressions to ensure the compatibility between operands and operators. -// e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. -// Overall,it efficiently filters out incompatible expressions, stopping before the next -// checkOrConvertType() operation to optimize performance. - -func checkOperandWithOp(store Store, last BlockNode, x *Expr, dt Type, op Word, nt nodeType) { - debug.Printf("checkOperandWithOp, dt: %v,op: %v, nt: %v \n", dt, op, nt) - escapedOpStr := strings.Replace(wordTokenStrings[op], "%", "%%", 1) - if nt == Unary || nt == IncDec { - switch nt { - case Unary: - if pred, ok := unaryChecker[op]; ok { - if !pred(dt) { - if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) - } - } - } else { - panic("should not happen") - } - case IncDec: - if pred, ok := IncDecStmtChecker[op]; ok { - if !pred(dt) { - if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) - } - } - } else { - panic("should not happen") - } - default: - panic("should not happen") - } - } else { - var xt Type - if cx, ok := (*x).(*ConstExpr); ok { - xt = cx.T - } else if *x != nil { - xt = evalStaticTypeOf(store, last, *x) - } - switch nt { - case Binary: - if isComparison(op) { - switch op { - case EQL, NEQ: - assertComparable(xt, dt) - case LSS, LEQ, GTR, GEQ: - if pred, ok := binaryChecker[op]; ok { - if !pred(dt) { - if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) - } - } - } else { - panic("should not happen") - } - default: - panic("invalid comparison operator") - } - } else { - if pred, ok := binaryChecker[op]; ok { - if !pred(dt) { - if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) - } - } - } else { - panic("should not happen") - } - switch op { - case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: - // if both typed - if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if xt != nil && dt != nil { - if xt.TypeID() != dt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) - } - } - } - default: - // do nothing - } - } - case XAssign: - if pred, ok := AssignStmtChecker[op]; ok { - if !pred(dt) { - if dt != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt.Kind())) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, dt)) - } - } - switch op { - case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: - // if both typed - if !isUntyped(xt) { // dt won't be untyped in this case, you won't convert typed to untyped - if xt != nil && dt != nil { - if xt.TypeID() != dt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", dt, xt)) - } - } - } - default: - // do nothing - } - } else { - panic("should not happen") - } - default: - panic("should not happen") - } - } -} - // Returns any names not yet defined nor predefined in expr. These happen // upon transcribe:enter from the top, so value paths cannot be used. If no // names are un and x is TypeExpr, evalStaticType(store,last, x) must not diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 0d893e8ce75..38cf178b3ba 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -28,6 +28,7 @@ var ( GTR: isOrdered, GEQ: isOrdered, } + // TODO: star, addressable unaryChecker = map[Word]func(t Type) bool{ ADD: isNumeric, SUB: isNumeric, @@ -207,48 +208,52 @@ func isNumericOrString(t Type) bool { type Checker struct { } +var AC *AssignabilityCache + // check both sides since no aware of which side is dest type // TODO: add check assignable, 1.0 % uint64(1) is valid as is assignable // that lt not compatible but rt is compatible would be good // things like this would fail: println(1.0 % 1) -func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode) { +// AssertCompatible works as a pre-check prior to checkOrConvertType() +// It checks expressions to ensure the compatibility between operands and operators. +// e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. +// Overall,it efficiently filters out incompatible expressions, stopping before the next +// checkOrConvertType() operation to optimize performance. + +// dt is a special case for binary expr that the dest type for the +// lhs determined by outer context +func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { debug.Printf("---AssertCompatible, bx: %v \n", bx) debug.Printf("---AssertCompatible, bx.Left: %T \n", bx.Left) debug.Printf("---AssertCompatible, bx.Right: %T \n", bx.Right) // get left type and right type - var lt, rt Type - if lx, ok := (bx.Left).(*ConstExpr); ok { - lt = lx.T - } else if bx.Left != nil { - lt = evalStaticTypeOf(store, last, bx.Left) - } - - if rx, ok := (bx.Right).(*ConstExpr); ok { - rt = rx.T - } else if bx.Left != nil { - rt = evalStaticTypeOf(store, last, bx.Right) - } + lt := evalStaticTypeOf(store, last, bx.Left) + rt := evalStaticTypeOf(store, last, bx.Right) // we can't check compatible with native types - // so leave it to checkOrConvertStage + // at current stage, so leave it to checkOrConvertType + // to secondary call this assert logic again if _, ok := lt.(*NativeType); ok { + debug.Println("---left native, return") return } if _, ok := rt.(*NativeType); ok { + debug.Println("---right native, return") return } debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, bx.Op) escapedOpStr := strings.Replace(wordTokenStrings[bx.Op], "%", "%%", 1) + if isComparison(bx.Op) { switch bx.Op { case EQL, NEQ: assertComparable(lt, rt) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryChecker[bx.Op]; ok { - assertCompatible2(lt, rt, pred, escapedOpStr) + bx.assertCompatible2(lt, rt, pred, escapedOpStr, dt) } else { panic("should not happen") } @@ -257,7 +262,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode) { } } else { if pred, ok := binaryChecker[bx.Op]; ok { - assertCompatible2(lt, rt, pred, escapedOpStr) + bx.assertCompatible2(lt, rt, pred, escapedOpStr, dt) } else { panic("should not happen") } @@ -278,8 +283,29 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode) { } } -func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) { +// TODO: turn into method of bx +func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string, dt Type) { + debug.Println("---assertCompatible2, op: ", bx.Op) + debug.Printf("---assertCompatible2, lt: %v, rt: %v \n", lt, rt) + debug.Printf("---assertCompatible2, dt: %v \n", dt) + AC = NewAssignabilityCache() var destKind interface{} + + // shl/shr + if bx.Op == SHL || bx.Op == SHR { + if dt == nil { + dt = lt + } + if dt != nil { + destKind = dt.Kind() + } + if !pred(dt) { + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + } + return + } + + // other cases cmp := cmpSpecificity(lt, rt) if !pred(lt) { // lt not compatible with op if !pred(rt) { // rt not compatible with op @@ -301,6 +327,7 @@ func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) checkAssignable(lt, rt, true) debug.Println("---assignable") // TODO: set attr + AC.cache[ExprTypePair{X: bx.Left, T: rt}] = true } else { if lt != nil { // return error on left side that is checked first destKind = lt.Kind() @@ -325,3 +352,144 @@ func assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string) debug.Println("---both good") } } + +func (ux *UnaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { + debug.Printf("---AssertCompatible, ux: %v \n", ux) + debug.Printf("---AssertCompatible, ux.X: %T \n", ux.X) + + var destKind interface{} + + // get left type and right type + t := evalStaticTypeOf(store, last, ux.X) + // we can't check compatible with native types + // at current stage, so leave it to checkOrConvertType + // to secondary call this assert logic again + if _, ok := t.(*NativeType); ok { + debug.Println("---left native, return") + return + } + + // check compatible + if pred, ok := unaryChecker[ux.Op]; ok { + if dt == nil { + dt = t + } + if !pred(dt) { + if dt != nil { + destKind = dt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[ux.Op], destKind)) + } + } else { + panic("should not happen") + } +} + +func (idst *IncDecStmt) AssertCompatible(store Store, last BlockNode) { + debug.Printf("---AssertCompatible, st: %v \n", idst) + debug.Printf("---AssertCompatible, st.X: %T \n", idst.X) + debug.Printf("---AssertCompatible, st.Op: %T \n", idst.Op) + + var destKind interface{} + + // get left type and right type + t := evalStaticTypeOf(store, last, idst.X) + + // we can't check compatible with native types + // at current stage, so leave it to checkOrConvertType + // to secondary call this assert logic again + if _, ok := t.(*NativeType); ok { + debug.Println("---left native, return") + return + } + + // check compatible + if pred, ok := IncDecStmtChecker[idst.Op]; ok { + if !pred(t) { + if t != nil { + destKind = t.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[idst.Op], destKind)) + } + } else { + panic("should not happen") + } +} + +func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { + debug.Printf("---AssertCompatible, as: %v \n", as) + debug.Printf("---AssertCompatible, as len lhs: %T \n", len(as.Lhs)) + //debug.Printf("---AssertCompatible, as.X: %T \n", len(as.Lhs)) + debug.Printf("---AssertCompatible, as.Op: %v \n", as.Op) + + escapedOpStr := strings.Replace(wordTokenStrings[as.Op], "%", "%%", 1) + + var destKind interface{} + + // XXX, assume lhs length is same with of rhs + // TODO: check call case? + for i, x := range as.Lhs { + lt := evalStaticTypeOf(store, last, x) + rt := evalStaticTypeOf(store, last, as.Rhs[i]) + + // we can't check compatible with native types + // at current stage, so leave it to checkOrConvertType + // to secondary call this assert logic again + if _, ok := lt.(*NativeType); ok { + debug.Println("---left native, return") + return + } + + if _, ok := rt.(*NativeType); ok { + debug.Println("---right native, return") + return + } + + debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, as.Op) + + // check compatible + if pred, ok := AssignStmtChecker[as.Op]; ok { + if !pred(lt) { + if lt != nil { + destKind = lt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + } + switch as.Op { + case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: + // if both typed + if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet + debug.Println("---both typed") + if lt != nil && rt != nil { + // TODO: filter byte that has no typeID? + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + } + } + } + default: + // do nothing + } + } else { + panic("should not happen") + } + } +} + +func isQuoOrRem(op Word) bool { + switch op { + case QUO, QUO_ASSIGN, REM, REM_ASSIGN: + return true + default: + return false + } +} + +func isComparison(op Word) bool { + switch op { + case EQL, NEQ, LSS, LEQ, GTR, GEQ: + return true + default: + return false + } +} diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 2d719e13433..46a1f197917 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -6,6 +6,7 @@ import ( "sort" "strconv" "strings" + "sync" ) // NOTE: TypeID() implementations are currently @@ -2199,6 +2200,24 @@ func assertMaybeNil(msg string, t Type) { } } +// ExprTypePair represents a unique combination of an expression and a type. +type ExprTypePair struct { + X Expr + T Type +} + +// AssignabilityCache caches the results of assignability checks. +type AssignabilityCache struct { + mu sync.RWMutex + cache map[ExprTypePair]bool +} + +func NewAssignabilityCache() *AssignabilityCache { + return &AssignabilityCache{ + cache: make(map[ExprTypePair]bool), + } +} + // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. @@ -2211,6 +2230,7 @@ func assertMaybeNil(msg string, t Type) { // case 4. general cases for primitives and composite. // XXX. the name of checkAssignable should be considered. // we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime +// TODO: move these to type_check.go func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { if debug { debug.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) diff --git a/gnovm/tests/debug/0_a_3b.gno b/gnovm/tests/debug/0_a_3b.gno new file mode 100644 index 00000000000..ff53044fde2 --- /dev/null +++ b/gnovm/tests/debug/0_a_3b.gno @@ -0,0 +1,39 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +// case of expr in type call +func main() { + x := 2 + var r R + // assign to interface + r = 1 << x // 2 step. first binary, second call type + + r.foo() + + fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type +} + +// Error: +// main/debug/0_a_3b.gno:31: operator << not defined on: InterfaceKind diff --git a/gnovm/tests/debug2/10a11_filetest.gno b/gnovm/tests/debug2/10a11_filetest.gno new file mode 100644 index 00000000000..01b90c91783 --- /dev/null +++ b/gnovm/tests/debug2/10a11_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + r := a << "hello" // NOTE: go vet would fail, but still process + println(r) +} + +// Error: +// main/debug/10a11_filetest.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno b/gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno new file mode 100644 index 00000000000..6636a74448e --- /dev/null +++ b/gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + int(0) += int8(1) +} + +// Error: +// main/debug/13a0_ADD_ASSIGN_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/debug2/5d0_filetest.gno b/gnovm/tests/debug2/5d0_filetest.gno new file mode 100644 index 00000000000..4b2e76cef6a --- /dev/null +++ b/gnovm/tests/debug2/5d0_filetest.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation, and this should happen in process stage!!! +func main() { + println(1.0 % uint64(1)) +} + +// Output: +// 0 diff --git a/gnovm/tests/debug2/assign.gno b/gnovm/tests/debug2/assign.gno new file mode 100644 index 00000000000..1861fc70b9d --- /dev/null +++ b/gnovm/tests/debug2/assign.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := "hello" + x -= 1 + println(x) +} + +// Error: +// main/debug/assign.gno:5: operator -= not defined on: StringKind diff --git a/gnovm/tests/debug/assign0b_native.gno b/gnovm/tests/debug2/assign0b_native.gno similarity index 100% rename from gnovm/tests/debug/assign0b_native.gno rename to gnovm/tests/debug2/assign0b_native.gno diff --git a/gnovm/tests/debug2/default_type.gno b/gnovm/tests/debug2/default_type.gno new file mode 100644 index 00000000000..ff32d383f04 --- /dev/null +++ b/gnovm/tests/debug2/default_type.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1) +} + +// Output: +// 1 diff --git a/gnovm/tests/debug2/inc.gno b/gnovm/tests/debug2/inc.gno new file mode 100644 index 00000000000..31a47b6504e --- /dev/null +++ b/gnovm/tests/debug2/inc.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + a++ + println(a) +} + +// Error: +// main/debug/inc.gno:5: operator ++ not defined on: StringKind diff --git a/gnovm/tests/debug2/native.gno b/gnovm/tests/debug2/native.gno new file mode 100644 index 00000000000..fbdb59f1eed --- /dev/null +++ b/gnovm/tests/debug2/native.gno @@ -0,0 +1,12 @@ +package main + +import "time" + +func main() { + println(1 && time.Second) + //println(1 * time.Second) +} + +// Error: +// main/debug/native.gno:5: operator && not defined on: Int64Kind +// *** CHECK THE ERR MESSAGES ABOVE, MAKE SURE IT'S WHAT YOU EXPECTED, DELETE THIS LINE AND RUN TEST AGAIN *** diff --git a/gnovm/tests/debug2/unary.gno b/gnovm/tests/debug2/unary.gno new file mode 100644 index 00000000000..176f8824ed1 --- /dev/null +++ b/gnovm/tests/debug2/unary.gno @@ -0,0 +1,8 @@ +package main + +func main() { + a := "hello" + println(+a) +} + +// main/debug/unary.gno:5: operator + not defined on: StringKind From 118598dbeba2e671fa151287c748ddc64bc2c7d0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 5 Mar 2024 10:11:07 +0800 Subject: [PATCH 099/193] clean --- gnovm/pkg/gnolang/preprocess.go | 11 +++-------- gnovm/pkg/gnolang/type_check.go | 28 +++++----------------------- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 142cc74f61b..5e000734bd6 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -122,7 +122,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { preprocessing += 1 defer func() { preprocessing -= 1 - AC = nil // xxx, clean, why ns not cleaned? + AssignableCheckCache = nil // xxx, clean, why ns not cleaned? }() } @@ -2429,8 +2429,6 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // coerce implies a mandatory convert, it happens with explicit conversion, uint64(int(1)), or RHS of a // shift expr, or key of slice/array. func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { - // check compatibility with operand and op - if debug { debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) } @@ -2442,11 +2440,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). // TODO: if cx.GetAttribute(Attr_Assignable) == true - //if cx.GetAttribute(ATTR_ASSIGNABLE) == true { - // debug.Printf("---assignable already set for: % \n", cx) - //} - if AC != nil { - if AC.cache[ExprTypePair{X: *x, T: t}] == true { + if AssignableCheckCache != nil { + if AssignableCheckCache.cache[ExprTypePair{X: *x, T: t}] == true { debug.Printf("---assignable already set for: %v => %v \n", cx, t) } } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 38cf178b3ba..bfecc93b115 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -127,11 +127,9 @@ func (pt PrimitiveType) predicate() category { } func isOrdered(t Type) bool { - debug.Printf("---isOrdered, t is %v \n", t) switch t := baseOf(t).(type) { case PrimitiveType: if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { - debug.Println("is Ordered!") return true } return false @@ -153,7 +151,6 @@ func isBoolean(t Type) bool { } // rune can be numeric and string -// TODO: consider, do we need complex? func isNumeric(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: @@ -166,18 +163,6 @@ func isNumeric(t Type) bool { } } -//func isIntOrFloat(t Type) bool { -// switch t := baseOf(t).(type) { -// case PrimitiveType: -// if t.predicate() != IsInvalid && t.predicate()&IsIntOrFloat != 0 || t.predicate()&IsRune != 0 { -// return true -// } -// return false -// default: -// return false -// } -//} - // signed or unsigned int func isIntNum(t Type) bool { switch t := baseOf(t).(type) { @@ -208,12 +193,11 @@ func isNumericOrString(t Type) bool { type Checker struct { } -var AC *AssignabilityCache +var AssignableCheckCache *AssignabilityCache // check both sides since no aware of which side is dest type -// TODO: add check assignable, 1.0 % uint64(1) is valid as is assignable // that lt not compatible but rt is compatible would be good -// things like this would fail: println(1.0 % 1) +// things like this would fail: 1.0 % 1, bigInt has a bigger specificity than bidDec. // AssertCompatible works as a pre-check prior to checkOrConvertType() // It checks expressions to ensure the compatibility between operands and operators. @@ -283,12 +267,11 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } } -// TODO: turn into method of bx func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string, dt Type) { debug.Println("---assertCompatible2, op: ", bx.Op) debug.Printf("---assertCompatible2, lt: %v, rt: %v \n", lt, rt) debug.Printf("---assertCompatible2, dt: %v \n", dt) - AC = NewAssignabilityCache() + AssignableCheckCache = NewAssignabilityCache() var destKind interface{} // shl/shr @@ -314,7 +297,6 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc } panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } else { - debug.Println("---2") debug.Println("---cmp: ", cmp) // left not compatible, right is compatible // cmp means the expected convert direction @@ -326,8 +308,8 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc if cmp < 0 { checkAssignable(lt, rt, true) debug.Println("---assignable") - // TODO: set attr - AC.cache[ExprTypePair{X: bx.Left, T: rt}] = true + // cache, XXX, is this needed? + AssignableCheckCache.cache[ExprTypePair{X: bx.Left, T: rt}] = true } else { if lt != nil { // return error on left side that is checked first destKind = lt.Kind() From 33a3c9db837ee884a7eb5c4c2b8f1e047a16ce22 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 5 Mar 2024 18:40:17 +0800 Subject: [PATCH 100/193] prepared for split --- .../gno.land/r/gnoland/faucet/z2_filetest.gno | 2 - .../gno.land/r/gnoland/faucet/z3_filetest.gno | 4 - gnovm/pkg/gnolang/nodes.go | 1 - gnovm/pkg/gnolang/preprocess.go | 14 +- gnovm/pkg/gnolang/type_check.go | 455 +++++++++++++++++- gnovm/pkg/gnolang/types.go | 441 ----------------- gnovm/tests/debug/0_a_3b.gno | 39 -- .../files/{types => types2}/26a1_filetest.gno | 2 +- 8 files changed, 460 insertions(+), 498 deletions(-) delete mode 100644 gnovm/tests/debug/0_a_3b.gno rename gnovm/tests/files/{types => types2}/26a1_filetest.gno (59%) diff --git a/examples/gno.land/r/gnoland/faucet/z2_filetest.gno b/examples/gno.land/r/gnoland/faucet/z2_filetest.gno index 39aad01002a..9b59d7c07d3 100644 --- a/examples/gno.land/r/gnoland/faucet/z2_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z2_filetest.gno @@ -16,12 +16,10 @@ func main() { ) std.TestSetOrigCaller(adminaddr) err := faucet.AdminAddController(controlleraddr1) - //if err != nil { if err != "" { panic(err) } err = faucet.AdminAddController(controlleraddr2) - //if err != nil { if err != "" { panic(err) } diff --git a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno index 4d6fa19f198..682a619256a 100644 --- a/examples/gno.land/r/gnoland/faucet/z3_filetest.gno +++ b/examples/gno.land/r/gnoland/faucet/z3_filetest.gno @@ -18,25 +18,21 @@ func main() { ) std.TestSetOrigCaller(adminaddr) err := faucet.AdminAddController(controlleraddr1) - //if err != nil { if err != "" { panic(err) } err = faucet.AdminAddController(controlleraddr2) if err != "" { - //if err != nil { panic(err) } std.TestSetOrigCaller(controlleraddr1) err = faucet.Transfer(testaddr1, 1000000) if err != "" { - //if err != nil { panic(err) } std.TestSetOrigCaller(controlleraddr2) err = faucet.Transfer(testaddr1, 2000000) if err != "" { - //if err != nil { panic(err) } println(faucet.Render("")) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 30fa6d3973b..2a9e0b51a97 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -2021,7 +2021,6 @@ const ( ATTR_IOTA GnoAttribute = "ATTR_IOTA" ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" ATTR_INJECTED GnoAttribute = "ATTR_INJECTED" - ATTR_ASSIGNABLE GnoAttribute = "ATTR_ASSIGNABLE" ) // TODO: consider length restrictions. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 5e000734bd6..a619da5eda9 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -98,6 +98,7 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // are only called during the preprocessing stage. // It is a counter because Preprocess() is recursive. var preprocessing int +var AssignableCheckCache *AssignabilityCache // Preprocess n whose parent block node is ctx. If any names // are defined in another file, generally you must call @@ -122,7 +123,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { preprocessing += 1 defer func() { preprocessing -= 1 - AssignableCheckCache = nil // xxx, clean, why ns not cleaned? + AssignableCheckCache = nil }() } @@ -2439,13 +2440,12 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // the reason why we need this is that the checkOperandWithOp() can not filter out all mismatch case, // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). - // TODO: if cx.GetAttribute(Attr_Assignable) == true - if AssignableCheckCache != nil { - if AssignableCheckCache.cache[ExprTypePair{X: *x, T: t}] == true { - debug.Printf("---assignable already set for: %v => %v \n", cx, t) - } + // this is for binaryExpr that assignable has already been checked and cached + if AssignableCheckCache != nil && AssignableCheckCache.Exists(*x, t) { + debug.Printf("---assignable already set for: %v => %v \n", cx, t) + } else { + checkAssignable(cx.T, t, autoNative) // refer to 22a17a } - checkAssignable(cx.T, t, autoNative) // refer to 22a17a } } convertConst(store, last, cx, t) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index bfecc93b115..a7ed0c5f090 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -2,6 +2,7 @@ package gnolang import ( "fmt" + "reflect" "strings" ) @@ -190,10 +191,456 @@ func isNumericOrString(t Type) bool { // =========================================================== -type Checker struct { +// main type-assertion functions. +// TODO: document what class of problems its for. +// One of them can be nil, and this lets uninitialized primitives +// and others serve as empty values. See doOpAdd() +// usage: if debug { assertSameTypes() } +func assertSameTypes(lt, rt Type) { + if lt == nil && rt == nil { + // both are nil. + } else if lt == nil || rt == nil { + // one is nil. see function comment. + } else if lt.Kind() == rt.Kind() && + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + } else if lt.Kind() == rt.Kind() && + isDataByte(lt) { + // left is databyte of same kind, + // specifically for assignments. + // TODO: make another function + // and remove this case? + } else if lt.TypeID() == rt.TypeID() { + // non-nil types are identical. + } else { + // panic("panic assertSameTypes") + debug.Errorf( + "incompatible operands in binary expression: %s and %s", + lt.String(), + rt.String(), + ) + } +} + +func isSameType(lt, rt Type) bool { + return lt == nil && rt == nil || // both are nil/undefined + (lt != nil && rt != nil) && // both are defined + (lt.TypeID() == rt.TypeID()) // and identical. +} + +// runtime assert +func assertAssignable(lt, rt Type) { + if debug { + debug.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + } + if isSameType(lt, rt) { + // both are nil/undefined or same type. + } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil + // LHS is undefined + } else if lt.Kind() == rt.Kind() && + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + } else if lt.Kind() == rt.Kind() && + isDataByte(lt) { + // left is databyte of same kind, + // specifically for assignments. + // TODO: make another function + // and remove this case? + } else { + debug.Errorf( + "incompatible operands in binary expression: %s and %s", + lt.String(), + rt.String(), + ) + } +} + +// assertComparable is used in preprocess. +// assert value with dt is comparable +// special case when both typed, check if type identical +// TODO: move this to type_checker? as a method? +// TODO: check mismatch on this, not postpone to checkOrConvertType +func assertComparable(xt, dt Type) { + if debug { + debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) + } + switch cdt := baseOf(dt).(type) { + case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage? + case *ArrayType: // NOTE: no recursive allowed + switch baseOf(cdt.Elem()).(type) { + case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? + switch cxt := baseOf(xt).(type) { + case *ArrayType: + if cxt.Len != cdt.Len { // check length + panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) + } + default: + panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) + } + default: + panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) + } + case *StructType: + for _, f := range cdt.Fields { + switch baseOf(f.Type).(type) { + case PrimitiveType, *PointerType, *InterfaceType, *NativeType: + default: + panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) + } + } + case *PointerType: // &a == &b + case *InterfaceType: // var a, b interface{} + case *SliceType, *FuncType, *MapType: + if xt != nil { + panic(fmt.Sprintf("%v can only be compared to nil \n", dt)) + } + case *NativeType: + if !cdt.Type.Comparable() { + panic(fmt.Sprintf("%v is not comparable \n", dt)) + } + case nil: // refer to 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. + assertMaybeNil("invalid operation, nil can not be compared to", xt) + default: + panic(fmt.Sprintf("%v is not comparable \n", dt)) + } +} + +func assertMaybeNil(msg string, t Type) { + if t == nil { + panic(fmt.Sprintf("%s %s \n", msg, "nil")) + } + switch cxt := baseOf(t).(type) { + case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer + case *NativeType: + switch nk := cxt.Type.Kind(); nk { + case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: + default: + panic(fmt.Sprintf("%s %s \n", msg, nk)) + } + default: + panic(fmt.Sprintf("%s %s \n", msg, t)) + } +} + +// AssignabilityCache caches the results of assignability checks. +type AssignabilityCache struct { + storage map[string]map[string]bool +} + +func NewAssignabilityCache() *AssignabilityCache { + return &AssignabilityCache{ + storage: make(map[string]map[string]bool), + } +} + +func (ac *AssignabilityCache) Add(key Expr, value Type) { + if ac.storage[key.String()] == nil { + ac.storage[key.String()] = make(map[string]bool) + } + ac.storage[key.String()][value.String()] = true +} + +func (ac *AssignabilityCache) Exists(key Expr, value Type) bool { + if valSet, ok := ac.storage[key.String()]; ok { + // Check if the value exists in the set + return valSet[value.String()] + } + return false +} + +// Assert that xt can be assigned as dt (dest type). +// If autoNative is true, a broad range of xt can match against +// a target native dt type, if and only if dt is a native type. + +// check if xt can be assigned to dt. conversionNeeded indicates further conversion needed especially from unnamed -> named +// case 0. nil check +// case 1. untyped const to typed const with same kind +// case 2. unnamed to named +// case 3. dt is interface, xt satisfied dt +// case 4. general cases for primitives and composite. +// XXX. the name of checkAssignable should be considered. +// we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime +func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { + if debug { + debug.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) + } + // case0 + if xt == nil { // refer to 0f18_filetest + assertMaybeNil("invalid operation, nil can not be compared to", dt) + return + } + if dt == nil { // refer to assign8.gno + return + } + // case3 + if dt.Kind() == InterfaceKind { + if idt, ok := baseOf(dt).(*InterfaceType); ok { + if idt.IsEmptyInterface() { // XXX, can this be merged with IsImplementedBy? + // if dt is an empty Gno interface, any x ok. + return // ok + } else if idt.IsImplementedBy(xt) { + // if dt implements idt, ok. + return // ok + } else { + panic(fmt.Sprintf( + "%s does not implement %s", + xt.String(), + dt.String())) + } + } else if ndt, ok := baseOf(dt).(*NativeType); ok { + nidt := ndt.Type + if nidt.NumMethod() == 0 { + // if dt is an empty Go native interface, ditto. + return // ok + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nidt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + nxt.String(), + nidt.String())) + } + } else if pxt, ok := baseOf(xt).(*PointerType); ok { + nxt, ok := pxt.Elt.(*NativeType) + if !ok { + panic(fmt.Sprintf( + "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", + pxt.String(), + nidt.String())) + } + // if xt has native base, do the naive native. + if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s", + pxt.String(), + nidt.String())) + } + } else { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + xt.String(), + dt.String())) + } + } else { + panic("should not happen") + } + } + + // case2 + // Special case if xt or dt is *PointerType to *NativeType, + // convert to *NativeType of pointer kind. + if pxt, ok := xt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + //nolint:misspell + if enxt, ok := pxt.Elt.(*NativeType); ok { + xt = &NativeType{ + Type: reflect.PtrTo(enxt.Type), + } + } + } + if pdt, ok := dt.(*PointerType); ok { + // *gonative{x} is gonative{*x} + if endt, ok := pdt.Elt.(*NativeType); ok { + dt = &NativeType{ + Type: reflect.PtrTo(endt.Type), + } + } + } + + // Special case of xt or dt is *DeclaredType, + // allow implicit conversion unless both are declared. + // TODO simplify with .IsNamedType(). + if dxt, ok := xt.(*DeclaredType); ok { + if ddt, ok := dt.(*DeclaredType); ok { + // types must match exactly. + if !dxt.sealed && !ddt.sealed && + dxt.PkgPath == ddt.PkgPath && + dxt.Name == ddt.Name { // not yet sealed + return // ok + } else if dxt.TypeID() == ddt.TypeID() { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + ddt.String())) + } + } else { + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := dt.(PrimitiveType); ok { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + dxt.String(), + dt.String())) + } else { + // carry on with baseOf(dxt) + xt = dxt.Base // set as base to do the rest check + conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass + } + } + } else if ddt, ok := dt.(*DeclaredType); ok { + // special case if implicitly named primitive type. + // TODO simplify with .IsNamedType(). + if _, ok := xt.(PrimitiveType); ok { // e.g. 1 == Int(1) + if debug { + debug.Printf("xt is primitiveType: %v, ddt: %v \n", xt, ddt) + } + // this is special when dt is the declared type of x + if !isUntyped(xt) { + panic(fmt.Sprintf( + "cannot use %s as %s without explicit conversion", + xt.String(), + ddt.String())) + } else { // xt untyped, carry on with check below + dt = ddt.Base + } + } else { + dt = ddt.Base + conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass + } + } + + // General cases. + switch cdt := dt.(type) { + case PrimitiveType: // case 1 + // if xt is untyped, ensure dt is compatible. + switch xt { + case UntypedBoolType: + if dt.Kind() == BoolKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped bool as %s", + dt.Kind())) + } + case UntypedStringType: + if dt.Kind() == StringKind { + return // ok + } else { + panic(fmt.Sprintf( + "cannot use untyped string as %s", + dt.Kind())) + } + + case UntypedBigdecType: // can bigdec assign to bigint? + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped Bigdec as %s", + dt.Kind())) + } + case UntypedBigintType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped Bigint as %s", + dt.Kind())) + } + case UntypedRuneType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: + return // ok + default: + panic(fmt.Sprintf( + "cannot use untyped rune as %s", + dt.Kind())) + } + + default: + if isUntyped(xt) { + panic("unexpected untyped type") + } + if xt.TypeID() == cdt.TypeID() { + return // ok + } + } + case *PointerType: // case 4 from here on + if pt, ok := xt.(*PointerType); ok { + cdt := checkAssignable(pt.Elt, cdt.Elt, false) + return cdt || conversionNeeded + } + case *ArrayType: + if at, ok := xt.(*ArrayType); ok { + cdt := checkAssignable(at.Elt, cdt.Elt, false) + return cdt || conversionNeeded + } + case *SliceType: + if st, ok := xt.(*SliceType); ok { + cdt := checkAssignable(st.Elt, cdt.Elt, false) + return cdt || conversionNeeded + } + case *MapType: + if mt, ok := xt.(*MapType); ok { + cn1 := checkAssignable(mt.Key, cdt.Key, false) + cn2 := checkAssignable(mt.Value, cdt.Value, false) + return cn1 || cn2 || conversionNeeded + } + case *FuncType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *InterfaceType: + panic("should not happen") + case *DeclaredType: + // do nothing, untyped to declared type + return + // panic("should not happen") + case *StructType, *PackageType, *ChanType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *TypeType: + if xt.TypeID() == cdt.TypeID() { + return // ok + } + case *NativeType: + if !autoNative { + if debug { + debug.Printf("native type, xt.TypeID: %v, cdt.TypeID: %v \n", xt.TypeID(), cdt.TypeID()) + } + if xt.TypeID() == cdt.TypeID() { + return // ok + } + } else { + // autoNative, so check whether matches. + // xt: any type but a *DeclaredType; could be native. + // cdt: actual concrete native target type. + // ie, if cdt can match against xt. + if gno2GoTypeMatches(xt, cdt.Type) { + return // ok + } + } + default: + panic(fmt.Sprintf( + "unexpected type %s", + dt.String())) + } + panic(fmt.Sprintf( + "cannot use %s as %s", + xt.String(), + dt.String())) } -var AssignableCheckCache *AssignabilityCache +// =========================================================== + +// TODO: expand this +//type Checker struct { +//} // check both sides since no aware of which side is dest type // that lt not compatible but rt is compatible would be good @@ -309,7 +756,7 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc checkAssignable(lt, rt, true) debug.Println("---assignable") // cache, XXX, is this needed? - AssignableCheckCache.cache[ExprTypePair{X: bx.Left, T: rt}] = true + AssignableCheckCache.Add(bx.Left, rt) } else { if lt != nil { // return error on left side that is checked first destKind = lt.Kind() @@ -323,6 +770,7 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc // when they share same specificity implies not assignable? if cmp > 0 { // right to left checkAssignable(rt, lt, true) + AssignableCheckCache.Add(bx.Right, lt) } else { if rt != nil { // return error on left side that is checked first destKind = rt.Kind() @@ -458,6 +906,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } +// misc func isQuoOrRem(op Word) bool { switch op { case QUO, QUO_ASSIGN, REM, REM_ASSIGN: diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 46a1f197917..ece5aa43f01 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -6,7 +6,6 @@ import ( "sort" "strconv" "strings" - "sync" ) // NOTE: TypeID() implementations are currently @@ -2067,446 +2066,6 @@ func KindOf(t Type) Kind { } } -// ---------------------------------------- -// main type-assertion functions. - -// TODO: document what class of problems its for. -// One of them can be nil, and this lets uninitialized primitives -// and others serve as empty values. See doOpAdd() -// usage: if debug { assertSameTypes() } -func assertSameTypes(lt, rt Type) { - if lt == nil && rt == nil { - // both are nil. - } else if lt == nil || rt == nil { - // one is nil. see function comment. - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. - } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { - // left is databyte of same kind, - // specifically for assignments. - // TODO: make another function - // and remove this case? - } else if lt.TypeID() == rt.TypeID() { - // non-nil types are identical. - } else { - // panic("panic assertSameTypes") - debug.Errorf( - "incompatible operands in binary expression: %s and %s", - lt.String(), - rt.String(), - ) - } -} - -func isSameType(lt, rt Type) bool { - return lt == nil && rt == nil || // both are nil/undefined - (lt != nil && rt != nil) && // both are defined - (lt.TypeID() == rt.TypeID()) // and identical. -} - -// runtime assert -func assertAssignable(lt, rt Type) { - if debug { - debug.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) - } - if isSameType(lt, rt) { - // both are nil/undefined or same type. - } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil - // LHS is undefined - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. - } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { - // left is databyte of same kind, - // specifically for assignments. - // TODO: make another function - // and remove this case? - } else { - debug.Errorf( - "incompatible operands in binary expression: %s and %s", - lt.String(), - rt.String(), - ) - } -} - -// assertComparable is used in preprocess. -// assert value with dt is comparable -// special case when both typed, check if type identical -// TODO: move this to type_checker? as a method? -// TODO: check mismatch on this, not postpone to checkOrConvertType -func assertComparable(xt, dt Type) { - if debug { - debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) - } - switch cdt := baseOf(dt).(type) { - case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage? - case *ArrayType: // NOTE: no recursive allowed - switch baseOf(cdt.Elem()).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? - switch cxt := baseOf(xt).(type) { - case *ArrayType: - if cxt.Len != cdt.Len { // check length - panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) - } - default: - panic(fmt.Sprintf("%v and %v cannot be compared \n", cxt, cdt)) - } - default: - panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) - } - case *StructType: - for _, f := range cdt.Fields { - switch baseOf(f.Type).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType: - default: - panic(fmt.Sprintf("%v and %v cannot be compared \n", xt, cdt)) - } - } - case *PointerType: // &a == &b - case *InterfaceType: // var a, b interface{} - case *SliceType, *FuncType, *MapType: - if xt != nil { - panic(fmt.Sprintf("%v can only be compared to nil \n", dt)) - } - case *NativeType: - if !cdt.Type.Comparable() { - panic(fmt.Sprintf("%v is not comparable \n", dt)) - } - case nil: // refer to 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. - assertMaybeNil("invalid operation, nil can not be compared to", xt) - default: - panic(fmt.Sprintf("%v is not comparable \n", dt)) - } -} - -func assertMaybeNil(msg string, t Type) { - if t == nil { - panic(fmt.Sprintf("%s %s \n", msg, "nil")) - } - switch cxt := baseOf(t).(type) { - case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer - case *NativeType: - switch nk := cxt.Type.Kind(); nk { - case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: - default: - panic(fmt.Sprintf("%s %s \n", msg, nk)) - } - default: - panic(fmt.Sprintf("%s %s \n", msg, t)) - } -} - -// ExprTypePair represents a unique combination of an expression and a type. -type ExprTypePair struct { - X Expr - T Type -} - -// AssignabilityCache caches the results of assignability checks. -type AssignabilityCache struct { - mu sync.RWMutex - cache map[ExprTypePair]bool -} - -func NewAssignabilityCache() *AssignabilityCache { - return &AssignabilityCache{ - cache: make(map[ExprTypePair]bool), - } -} - -// Assert that xt can be assigned as dt (dest type). -// If autoNative is true, a broad range of xt can match against -// a target native dt type, if and only if dt is a native type. - -// check if xt can be assigned to dt. conversionNeeded indicates further conversion needed especially from unnamed -> named -// case 0. nil check -// case 1. untyped const to typed const with same kind -// case 2. unnamed to named -// case 3. dt is interface, xt satisfied dt -// case 4. general cases for primitives and composite. -// XXX. the name of checkAssignable should be considered. -// we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime -// TODO: move these to type_check.go -func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { - if debug { - debug.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) - } - // case0 - if xt == nil { // refer to 0f18_filetest - assertMaybeNil("invalid operation, nil can not be compared to", dt) - return - } - if dt == nil { // refer to assign8.gno - return - } - // case3 - if dt.Kind() == InterfaceKind { - if idt, ok := baseOf(dt).(*InterfaceType); ok { - if idt.IsEmptyInterface() { // XXX, can this be merged with IsImplementedBy? - // if dt is an empty Gno interface, any x ok. - return // ok - } else if idt.IsImplementedBy(xt) { - // if dt implements idt, ok. - return // ok - } else { - panic(fmt.Sprintf( - "%s does not implement %s", - xt.String(), - dt.String())) - } - } else if ndt, ok := baseOf(dt).(*NativeType); ok { - nidt := ndt.Type - if nidt.NumMethod() == 0 { - // if dt is an empty Go native interface, ditto. - return // ok - } else if nxt, ok := baseOf(xt).(*NativeType); ok { - // if xt has native base, do the naive native. - if nxt.Type.AssignableTo(nidt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - nxt.String(), - nidt.String())) - } - } else if pxt, ok := baseOf(xt).(*PointerType); ok { - nxt, ok := pxt.Elt.(*NativeType) - if !ok { - panic(fmt.Sprintf( - "pointer to non-native type cannot satisfy non-empty native interface; %s doesn't implement %s", - pxt.String(), - nidt.String())) - } - // if xt has native base, do the naive native. - if reflect.PtrTo(nxt.Type).AssignableTo(nidt) { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s", - pxt.String(), - nidt.String())) - } - } else { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - xt.String(), - dt.String())) - } - } else { - panic("should not happen") - } - } - - // case2 - // Special case if xt or dt is *PointerType to *NativeType, - // convert to *NativeType of pointer kind. - if pxt, ok := xt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - //nolint:misspell - if enxt, ok := pxt.Elt.(*NativeType); ok { - xt = &NativeType{ - Type: reflect.PtrTo(enxt.Type), - } - } - } - if pdt, ok := dt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - if endt, ok := pdt.Elt.(*NativeType); ok { - dt = &NativeType{ - Type: reflect.PtrTo(endt.Type), - } - } - } - - // Special case of xt or dt is *DeclaredType, - // allow implicit conversion unless both are declared. - // TODO simplify with .IsNamedType(). - if dxt, ok := xt.(*DeclaredType); ok { - if ddt, ok := dt.(*DeclaredType); ok { - // types must match exactly. - if !dxt.sealed && !ddt.sealed && - dxt.PkgPath == ddt.PkgPath && - dxt.Name == ddt.Name { // not yet sealed - return // ok - } else if dxt.TypeID() == ddt.TypeID() { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - ddt.String())) - } - } else { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := dt.(PrimitiveType); ok { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - dxt.String(), - dt.String())) - } else { - // carry on with baseOf(dxt) - xt = dxt.Base // set as base to do the rest check - conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass - } - } - } else if ddt, ok := dt.(*DeclaredType); ok { - // special case if implicitly named primitive type. - // TODO simplify with .IsNamedType(). - if _, ok := xt.(PrimitiveType); ok { // e.g. 1 == Int(1) - if debug { - debug.Printf("xt is primitiveType: %v, ddt: %v \n", xt, ddt) - } - // this is special when dt is the declared type of x - if !isUntyped(xt) { - panic(fmt.Sprintf( - "cannot use %s as %s without explicit conversion", - xt.String(), - ddt.String())) - } else { // xt untyped, carry on with check below - dt = ddt.Base - } - } else { - dt = ddt.Base - conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass - } - } - - // General cases. - switch cdt := dt.(type) { - case PrimitiveType: // case 1 - // if xt is untyped, ensure dt is compatible. - switch xt { - case UntypedBoolType: - if dt.Kind() == BoolKind { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use untyped bool as %s", - dt.Kind())) - } - case UntypedStringType: - if dt.Kind() == StringKind { - return // ok - } else { - panic(fmt.Sprintf( - "cannot use untyped string as %s", - dt.Kind())) - } - - case UntypedBigdecType: // can bigdec assign to bigint? - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind, BigdecKind, Float32Kind, Float64Kind: - return // ok - default: - panic(fmt.Sprintf( - "cannot use untyped Bigdec as %s", - dt.Kind())) - } - case UntypedBigintType: - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: - return // ok - default: - panic(fmt.Sprintf( - "cannot use untyped Bigint as %s", - dt.Kind())) - } - case UntypedRuneType: - switch dt.Kind() { - case IntKind, Int8Kind, Int16Kind, Int32Kind, - Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: - return // ok - default: - panic(fmt.Sprintf( - "cannot use untyped rune as %s", - dt.Kind())) - } - - default: - if isUntyped(xt) { - panic("unexpected untyped type") - } - if xt.TypeID() == cdt.TypeID() { - return // ok - } - } - case *PointerType: // case 4 from here on - if pt, ok := xt.(*PointerType); ok { - cdt := checkAssignable(pt.Elt, cdt.Elt, false) - return cdt || conversionNeeded - } - case *ArrayType: - if at, ok := xt.(*ArrayType); ok { - cdt := checkAssignable(at.Elt, cdt.Elt, false) - return cdt || conversionNeeded - } - case *SliceType: - if st, ok := xt.(*SliceType); ok { - cdt := checkAssignable(st.Elt, cdt.Elt, false) - return cdt || conversionNeeded - } - case *MapType: - if mt, ok := xt.(*MapType); ok { - cn1 := checkAssignable(mt.Key, cdt.Key, false) - cn2 := checkAssignable(mt.Value, cdt.Value, false) - return cn1 || cn2 || conversionNeeded - } - case *FuncType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *InterfaceType: - panic("should not happen") - case *DeclaredType: - // do nothing, untyped to declared type - return - // panic("should not happen") - case *StructType, *PackageType, *ChanType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *TypeType: - if xt.TypeID() == cdt.TypeID() { - return // ok - } - case *NativeType: - if !autoNative { - if debug { - debug.Printf("native type, xt.TypeID: %v, cdt.TypeID: %v \n", xt.TypeID(), cdt.TypeID()) - } - if xt.TypeID() == cdt.TypeID() { - return // ok - } - } else { - // autoNative, so check whether matches. - // xt: any type but a *DeclaredType; could be native. - // cdt: actual concrete native target type. - // ie, if cdt can match against xt. - if gno2GoTypeMatches(xt, cdt.Type) { - return // ok - } - } - default: - panic(fmt.Sprintf( - "unexpected type %s", - dt.String())) - } - panic(fmt.Sprintf( - "cannot use %s as %s", - xt.String(), - dt.String())) -} - // ---------------------------------------- // misc diff --git a/gnovm/tests/debug/0_a_3b.gno b/gnovm/tests/debug/0_a_3b.gno deleted file mode 100644 index ff53044fde2..00000000000 --- a/gnovm/tests/debug/0_a_3b.gno +++ /dev/null @@ -1,39 +0,0 @@ -package main - -// 1. checkOrConvert is the core logic, to convert type(recursively if needed) -// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call -// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; -// it's not coerced -// 4. type call should be checked, it's coerced even RHS is typed. -// 5. func call should be checked, it's not coerced. - -import "fmt" - -type R interface { - foo() -} - -type U64 uint64 - -func (u64 U64) foo() { - println("bar") -} - -func bar(r R) { - r.foo() -} - -// case of expr in type call -func main() { - x := 2 - var r R - // assign to interface - r = 1 << x // 2 step. first binary, second call type - - r.foo() - - fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type -} - -// Error: -// main/debug/0_a_3b.gno:31: operator << not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/26a1_filetest.gno b/gnovm/tests/files/types2/26a1_filetest.gno similarity index 59% rename from gnovm/tests/files/types/26a1_filetest.gno rename to gnovm/tests/files/types2/26a1_filetest.gno index ead8962aba0..04292e50b9d 100644 --- a/gnovm/tests/files/types/26a1_filetest.gno +++ b/gnovm/tests/files/types2/26a1_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/26a1_filetest.gno:6: operator ++ not defined on: BoolKind +// main/files/types2/26a1_filetest.gno:6: operator ++ not defined on: BoolKind From 6d6590abdfcbd5f078b9d4488a9f9efb9e07aeba Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 6 Mar 2024 00:09:46 +0800 Subject: [PATCH 101/193] mv some check logic to type_check --- gnovm/pkg/gnolang/preprocess.go | 4 ++- gnovm/pkg/gnolang/type_check.go | 32 +++++++++++++++++-- gnovm/tests/files/types/0a0_EQL_filetest.gno | 2 +- gnovm/tests/files/types/0a1_filetest.gno | 2 +- gnovm/tests/files/types/0a1a0_filetest.gno | 2 +- gnovm/tests/files/types/0a1a1_filetest.gno | 2 +- gnovm/tests/files/types/0a1f_filetest.gno | 4 +-- gnovm/tests/files/types/0a2_filetest.gno | 2 +- gnovm/tests/files/types/0a3_filetest.gno | 2 +- gnovm/tests/files/types/0a4_filetest.gno | 2 +- gnovm/tests/files/types/0e0_filetest.gno | 2 +- gnovm/tests/files/types/0e1_filetest.gno | 2 +- gnovm/tests/files/types/20a0_LSS_filetest.gno | 2 +- 13 files changed, 45 insertions(+), 15 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a619da5eda9..79161cd6e79 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -793,11 +793,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if rcx.T == nil { checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } else { // default case, e.g. int(1) == int8(1), will also conduct type check - checkOrConvertType(store, last, &n.Left, rcx.T, false, false) + //checkOrConvertType(store, last, &n.Left, rcx.T, false, false) + // do nothing, all compatibility is checked } } else { debug.Println("cmp > 0, <-") // convert n.Right to left type. + // XXX, consider this with 0a0_EQL_filetest.gno checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } // check special case: zero divisor diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index a7ed0c5f090..780315ca796 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -265,7 +265,19 @@ func assertComparable(xt, dt Type) { debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) } switch cdt := baseOf(dt).(type) { - case PrimitiveType: // TODO: more strict when both typed primitive, rather than delayed to checkOrConvert->checkConvertable stage? + case PrimitiveType: + // both typed primitive types + if _, ok := baseOf(xt).(PrimitiveType); ok { + if !isUntyped(xt) && !isUntyped(dt) { // in this stage, lt or rt maybe untyped, not converted yet + debug.Println("---both typed") + if xt != nil && dt != nil { + // TODO: filter byte that has no typeID? + if xt.TypeID() != dt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", xt, dt)) + } + } + } + } case *ArrayType: // NOTE: no recursive allowed switch baseOf(cdt.Elem()).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? @@ -779,7 +791,23 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc } } else { // both good - debug.Println("---both good") + if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet + // check when both typed + if lt != nil && rt != nil { // XXX, this should already be excluded by previous pred check. + // TODO: filter byte that has no typeID? + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + } + } + } + // check even when both side compatible with op + // it's ok since assertCompatible2 only for lss, add, etc + // that only with isOrdered + if cmp <= 0 { + checkAssignable(lt, rt, true) + } else { + checkAssignable(rt, lt, true) + } } } diff --git a/gnovm/tests/files/types/0a0_EQL_filetest.gno b/gnovm/tests/files/types/0a0_EQL_filetest.gno index 6ddb8b993c0..ea0eba7fbbe 100644 --- a/gnovm/tests/files/types/0a0_EQL_filetest.gno +++ b/gnovm/tests/files/types/0a0_EQL_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a0_EQL_filetest.gno:5: cannot use int as int8 +// main/files/types/0a0_EQL_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/0a1_filetest.gno b/gnovm/tests/files/types/0a1_filetest.gno index 10373e92992..dda07879f27 100644 --- a/gnovm/tests/files/types/0a1_filetest.gno +++ b/gnovm/tests/files/types/0a1_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a1_filetest.gno:5: cannot use int as int8 +// main/files/types/0a1_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/0a1a0_filetest.gno b/gnovm/tests/files/types/0a1a0_filetest.gno index f10b0cf599a..9b5d953e013 100644 --- a/gnovm/tests/files/types/0a1a0_filetest.gno +++ b/gnovm/tests/files/types/0a1a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a1a0_filetest.gno:5: cannot use uint64 as uint +// main/files/types/0a1a0_filetest.gno:5: invalid operation: mismatched types uint64 and uint diff --git a/gnovm/tests/files/types/0a1a1_filetest.gno b/gnovm/tests/files/types/0a1a1_filetest.gno index 996950e6092..64df0d47913 100644 --- a/gnovm/tests/files/types/0a1a1_filetest.gno +++ b/gnovm/tests/files/types/0a1a1_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a1a1_filetest.gno:5: cannot use uint64 as uint +// main/files/types/0a1a1_filetest.gno:5: invalid operation: mismatched types uint and uint64 diff --git a/gnovm/tests/files/types/0a1f_filetest.gno b/gnovm/tests/files/types/0a1f_filetest.gno index d5268239128..984edb9e8b5 100644 --- a/gnovm/tests/files/types/0a1f_filetest.gno +++ b/gnovm/tests/files/types/0a1f_filetest.gno @@ -3,8 +3,8 @@ package main func main() { expected := `hello`[:] a := 1 - println(a == expected) + println(a == expected) // both typed } // Error: -// main/files/types/0a1f_filetest.gno:6: cannot use int as string +// main/files/types/0a1f_filetest.gno:6: invalid operation: mismatched types int and string diff --git a/gnovm/tests/files/types/0a2_filetest.gno b/gnovm/tests/files/types/0a2_filetest.gno index 3c28a8eb12c..b6a940f5e10 100644 --- a/gnovm/tests/files/types/0a2_filetest.gno +++ b/gnovm/tests/files/types/0a2_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/0a2_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/0a2_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/0a3_filetest.gno b/gnovm/tests/files/types/0a3_filetest.gno index 6767d7aae9f..ecba7d40f74 100644 --- a/gnovm/tests/files/types/0a3_filetest.gno +++ b/gnovm/tests/files/types/0a3_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/0a3_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/0a3_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/0a4_filetest.gno b/gnovm/tests/files/types/0a4_filetest.gno index f44f895a779..5ae407e5add 100644 --- a/gnovm/tests/files/types/0a4_filetest.gno +++ b/gnovm/tests/files/types/0a4_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/0a4_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/0a4_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/0e0_filetest.gno b/gnovm/tests/files/types/0e0_filetest.gno index fc845f73e1e..30af49f7f2a 100644 --- a/gnovm/tests/files/types/0e0_filetest.gno +++ b/gnovm/tests/files/types/0e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/0e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 \ No newline at end of file diff --git a/gnovm/tests/files/types/0e1_filetest.gno b/gnovm/tests/files/types/0e1_filetest.gno index ba937d9a110..a07aa1f433f 100644 --- a/gnovm/tests/files/types/0e1_filetest.gno +++ b/gnovm/tests/files/types/0e1_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0e1_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion +// main/files/types/0e1_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/20a0_LSS_filetest.gno b/gnovm/tests/files/types/20a0_LSS_filetest.gno index f11bda7fd5c..8031eaca468 100644 --- a/gnovm/tests/files/types/20a0_LSS_filetest.gno +++ b/gnovm/tests/files/types/20a0_LSS_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/20a0_LSS_filetest.gno:4: cannot use int as int8 +// main/files/types/20a0_LSS_filetest.gno:4: invalid operation: mismatched types int and int8 From 218fff0807d70b4df5dc95c9a375d8cb4e0a4fa0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Mar 2024 17:59:41 +0800 Subject: [PATCH 102/193] fix binary non-const native handling --- gnovm/Makefile | 2 +- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 1 + gnovm/pkg/gnolang/op_expressions.go | 1 + gnovm/pkg/gnolang/op_types.go | 11 ++ gnovm/pkg/gnolang/preprocess.go | 179 +++++++++++++-------- gnovm/pkg/gnolang/type_check.go | 108 ++++++++++--- gnovm/pkg/gnolang/types.go | 6 +- gnovm/pkg/gnolang/values.go | 1 + gnovm/pkg/gnolang/values_conversions.go | 14 ++ gnovm/tests/debug/issue-558b.gno | 77 +++++++++ gnovm/tests/debug/time1_native.gno | 12 ++ gnovm/tests/debug/time1_stdlibs.gno | 12 ++ gnovm/tests/debug/time2_native.gno | 11 ++ gnovm/tests/debug/time2_stdlibs.gno | 11 ++ gnovm/tests/debug/time_native.gno | 12 ++ gnovm/tests/debug/time_stdlibs.gno | 12 ++ gnovm/tests/debug2/0_a_3b.gno | 39 +++++ gnovm/tests/debug2/0a1f_filetest.gno | 10 ++ gnovm/tests/debug2/1.gno | 9 ++ gnovm/tests/debug2/1b2_filetest.gno | 9 ++ gnovm/tests/debug2/native.gno | 2 +- gnovm/tests/debug2/time4_native.gno | 15 ++ gnovm/tests/debug2/type34.gno | 10 ++ gnovm/tests/debug3/0f2_filetest.gnoa | 28 ++++ gnovm/tests/debug3/0f2b_native.gnoa | 28 ++++ gnovm/tests/debug3/0f47f_filetest.gnoa | 16 ++ gnovm/tests/debug3/2.gnoa | 10 ++ gnovm/tests/files/types/0f47f_filetest.gno | 14 ++ gnovm/tests/note/1.gno | 12 ++ gnovm/tests/note/2.gno | 10 ++ gnovm/tests/note/iface.gno | 14 ++ 32 files changed, 601 insertions(+), 97 deletions(-) create mode 100644 gnovm/tests/debug/issue-558b.gno create mode 100644 gnovm/tests/debug/time1_native.gno create mode 100644 gnovm/tests/debug/time1_stdlibs.gno create mode 100644 gnovm/tests/debug/time2_native.gno create mode 100644 gnovm/tests/debug/time2_stdlibs.gno create mode 100644 gnovm/tests/debug/time_native.gno create mode 100644 gnovm/tests/debug/time_stdlibs.gno create mode 100644 gnovm/tests/debug2/0_a_3b.gno create mode 100644 gnovm/tests/debug2/0a1f_filetest.gno create mode 100644 gnovm/tests/debug2/1.gno create mode 100644 gnovm/tests/debug2/1b2_filetest.gno create mode 100644 gnovm/tests/debug2/time4_native.gno create mode 100644 gnovm/tests/debug2/type34.gno create mode 100644 gnovm/tests/debug3/0f2_filetest.gnoa create mode 100644 gnovm/tests/debug3/0f2b_native.gnoa create mode 100644 gnovm/tests/debug3/0f47f_filetest.gnoa create mode 100644 gnovm/tests/debug3/2.gnoa create mode 100644 gnovm/tests/files/types/0f47f_filetest.gno create mode 100644 gnovm/tests/note/1.gno create mode 100644 gnovm/tests/note/2.gno create mode 100644 gnovm/tests/note/iface.gno diff --git a/gnovm/Makefile b/gnovm/Makefile index ca1ef8e5340..9f564f7aa65 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -50,7 +50,7 @@ _test.pkg: go test ./pkg/... $(GOTEST_FLAGS) .PHONY: _test.gnolang -_test.gnolang: _test.gnolang.types _test.gnolang.types2 _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other +_test.gnolang: _test.gnolang.types _test.gnolang.types.native _test.gnolang.types2 _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other _test.gnolang.other:; go test tests/*.go -run "(TestFileStr|TestSelectors)" $(GOTEST_FLAGS) _test.gnolang.realm:; go test tests/*.go -run "TestFiles/^zrealm" $(GOTEST_FLAGS) _test.gnolang.pkg0:; go test tests/*.go -run "TestPackages/(bufio|crypto|encoding|errors|internal|io|math|sort|std|stdshim|strconv|strings|testing|unicode)" $(GOTEST_FLAGS) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 7a797a969c1..b34ffc86c05 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -901,7 +901,7 @@ func gno2GoType(t Type) reflect.Type { // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). -// This is called when autoNative is true in checkAssignable(). +// This is called when autoNative is true in checkAssignableTo(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index ab66c645254..49462130cd2 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -336,6 +336,7 @@ func (m *Machine) doOpBandn() { // TODO: can be much faster. func isEql(store Store, lv, rv *TypedValue) bool { + debug.Printf("---isEql, lv: %v, rt: %v \n", lv, rv) // If one is undefined, the other must be as well. // Fields/items are set to defaultValue along the way. lvu := lv.IsUndefined() diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 0f107b84fc6..a6141854fe0 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -78,6 +78,7 @@ func (m *Machine) doOpIndex2() { func (m *Machine) doOpSelector() { sx := m.PopExpr().(*SelectorExpr) xv := m.PeekValue(1) + debug.Printf("---doOpSelector, xv:%v \n", xv) res := xv.GetPointerTo(m.Alloc, m.Store, sx.Path) *xv = res.Deref() // reuse as result } diff --git a/gnovm/pkg/gnolang/op_types.go b/gnovm/pkg/gnolang/op_types.go index a38010bac4e..d26c455cd88 100644 --- a/gnovm/pkg/gnolang/op_types.go +++ b/gnovm/pkg/gnolang/op_types.go @@ -231,6 +231,8 @@ func (m *Machine) doOpStaticTypeOf() { // NOTE: this code segment similar to that in op_types.go var dxt Type path := x.Path // mutable + debug.Printf("---SelectorExpr, path: %v \n", path) + debug.Printf("---SelectorExpr, path.Type: %v \n", path.Type) switch path.Type { case VPField: switch path.Depth { // see tests/selector_test.go for cases. @@ -297,6 +299,15 @@ func (m *Machine) doOpStaticTypeOf() { } switch path.Type { + case VPUverse: + println("---case match vpuverse") + switch path.Depth { + case 0: + println("---depth is 0") + dxt = xt + default: + panic("should not happen") + } case VPBlock: switch dxt.(type) { case *PackageType: diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 79161cd6e79..7ec4d6172b0 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -755,7 +755,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // check LHS type compatibility //checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) // checkOrConvert RHS - if baseOf(rt) != UintType { + if baseOf(rt) != UintType { // TODO: XXX, is it good for native? // convert n.Right to (gno) uint type, rn := Expr(Call("uint", n.Right)) // reset/create n2 to preprocess right child. @@ -792,30 +792,24 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { checkOrConvertType(store, last, &n.Right, lcx.T, false, false) - } else { // default case, e.g. int(1) == int8(1), will also conduct type check + } else { //checkOrConvertType(store, last, &n.Left, rcx.T, false, false) - // do nothing, all compatibility is checked + // do nothing, all compatibility is checked, + // e.g. int(1) == int8(1), will also conduct type check } } else { debug.Println("cmp > 0, <-") // convert n.Right to left type. - // XXX, consider this with 0a0_EQL_filetest.gno checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } - // check special case: zero divisor - if isQuoOrRem(n.Op) { - if rcx.TypedValue.isZero() { - panic("invalid operation: division by zero") - } - } } // Then, evaluate the expression. // also for shift cx := evalConst(store, last, n) return cx, TRANS_CONTINUE - } else if isUntyped(lcx.T) { // untyped -> not const + } else if isUntyped(lcx.T) { // left untyped const -> right not const // Left untyped const, Right not const ---------------- - if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native) TODO: check this case + if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native), e.g. 1*time.Second if isShift { // RHS of shift should not be native panic("should not happen") } @@ -838,7 +832,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { Op: n.Op, Right: rn, } - resn := Node(Call(tx, n2)) + resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} resn = Preprocess(store, last, resn) debug.Printf("---resn : %v \n", resn) return resn, TRANS_CONTINUE @@ -850,21 +844,24 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false, false) } } - } else if lcx.T == nil { // LHS is nil + } else if lcx.T == nil { // LHS is nil. XXX, should this be located in isUntyped? if !isShift { // convert n.Left to typed-nil type. checkOrConvertType(store, last, &n.Left, rt, false, false) } } else { // left is typed const, right not const if !isShift { - if isUntyped(rt) { // refer to 0_d.gno + if isUntyped(rt) { // refer to 0_d.gno. e.g. int(1) + 1< native. it's reasonable for gno is a superset of go type, e.g. bigint if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. + debug.Println("---dt not native, go check") // the reason why we need this is that the checkOperandWithOp() can not filter out all mismatch case, // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). @@ -2446,7 +2483,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if AssignableCheckCache != nil && AssignableCheckCache.Exists(*x, t) { debug.Printf("---assignable already set for: %v => %v \n", cx, t) } else { - checkAssignable(cx.T, t, autoNative) // refer to 22a17a + // still need for non-binary, like arg + checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a + debug.Println("---check pass!") } } } @@ -2477,7 +2516,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { // not coerce, xt is typed, no need to convert but check. refer to 10a17b1. - checkAssignable(xt, t, false) // refer to 0_a_2.gno, 0_a_3.gno + checkAssignableTo(xt, t, false) // refer to 0_a_2.gno, 0_a_3.gno } } else if ux, ok := (*x).(*UnaryExpr); ok { @@ -2497,7 +2536,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else { - checkAssignable(xt, t, false) + checkAssignableTo(xt, t, false) } } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) @@ -2506,7 +2545,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } var isUnnamed bool if t != nil && !coerce { - isUnnamed = checkAssignable(xt, t, autoNative) + isUnnamed = checkAssignableTo(xt, t, autoNative) } if isUntyped(xt) { if _, ok := t.(*InterfaceType); ok || t == nil { @@ -2555,9 +2594,11 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { + debug.Println("---convertConst") if t != nil && t.Kind() == InterfaceKind { if cx.IsUndefined() && cx.T == nil { // if cx is nil, not undefined interface if _, ok := t.(*NativeType); !ok { // bypass native nil interface, not support native interface(nil) now + debug.Println("---going to convert undefined interface") ConvertTo(nilAllocator, store, &cx.TypedValue, t) setConstAttrs(cx) return diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 780315ca796..45c7744024f 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -15,7 +15,7 @@ var ( SUB: isNumeric, MUL: isNumeric, QUO: isNumeric, - REM: isIntNum, // in compile stage good for bigdec, that can be converted to int, `checkAssignable` + REM: isIntNum, // in compile stage good for bigdec, that can be converted to int, `checkAssignableTo` SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. SHR: isIntNum, BAND: isIntNum, // bit ops @@ -229,24 +229,37 @@ func isSameType(lt, rt Type) bool { } // runtime assert +// TODO: consider this!!! func assertAssignable(lt, rt Type) { if debug { - debug.Printf("check assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + debug.Printf("assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) } if isSameType(lt, rt) { + println("1") // both are nil/undefined or same type. } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil + println("2") // LHS is undefined } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { // one is untyped of same kind. + println("3") } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? + println("4") + } else if lt.Kind() == InterfaceKind && + IsImplementedBy(lt, rt) { + // rt implements lt (and lt is nil interface). + } else if rt.Kind() == InterfaceKind && + IsImplementedBy(rt, lt) { + println("---assertEqulityTypes, match") + // lt implements rt (and rt is nil interface). } else { + //panic("---5") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -268,6 +281,19 @@ func assertComparable(xt, dt Type) { case PrimitiveType: // both typed primitive types if _, ok := baseOf(xt).(PrimitiveType); ok { + //var isMixed bool + //if _, ok := xt.(*NativeType); ok { + // if _, ok := dt.(*NativeType); ok { + // isMixed = false + // } else { + // isMixed = true + // } + //} else { + // if _, ok := dt.(*NativeType); ok { + // isMixed = true + // } + //} + //if !isMixed { // both not native or both native we can check typeID == if !isUntyped(xt) && !isUntyped(dt) { // in this stage, lt or rt maybe untyped, not converted yet debug.Println("---both typed") if xt != nil && dt != nil { @@ -277,6 +303,7 @@ func assertComparable(xt, dt Type) { } } } + //} } case *ArrayType: // NOTE: no recursive allowed switch baseOf(cdt.Elem()).(type) { @@ -370,15 +397,18 @@ func (ac *AssignabilityCache) Exists(key Expr, value Type) bool { // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general cases for primitives and composite. -// XXX. the name of checkAssignable should be considered. +// XXX. the name of checkAssignableTo should be considered. // we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime -func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { +// TODO: make it (t Type) CheckAssignableTo +// TODO: make cmp specificity here +func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { if debug { - debug.Printf("checkAssignable, xt: %v dt: %v \n", xt, dt) + debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) } // case0 if xt == nil { // refer to 0f18_filetest - assertMaybeNil("invalid operation, nil can not be compared to", dt) + // XXX, this seems duplicated with assertComparable + //assertMaybeNil("invalid operation, nil can not be compared to", dt) return } if dt == nil { // refer to assign8.gno @@ -583,23 +613,23 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := checkAssignable(pt.Elt, cdt.Elt, false) + cdt := checkAssignableTo(pt.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := checkAssignable(at.Elt, cdt.Elt, false) + cdt := checkAssignableTo(at.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := checkAssignable(st.Elt, cdt.Elt, false) + cdt := checkAssignableTo(st.Elt, cdt.Elt, false) return cdt || conversionNeeded } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := checkAssignable(mt.Key, cdt.Key, false) - cn2 := checkAssignable(mt.Value, cdt.Value, false) + cn1 := checkAssignableTo(mt.Key, cdt.Key, false) + cn2 := checkAssignableTo(mt.Value, cdt.Value, false) return cn1 || cn2 || conversionNeeded } case *FuncType: @@ -668,9 +698,9 @@ func checkAssignable(xt, dt Type, autoNative bool) (conversionNeeded bool) { // lhs determined by outer context func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { debug.Printf("---AssertCompatible, bx: %v \n", bx) - debug.Printf("---AssertCompatible, bx.Left: %T \n", bx.Left) debug.Printf("---AssertCompatible, bx.Right: %T \n", bx.Right) + // get left type and right type lt := evalStaticTypeOf(store, last, bx.Left) rt := evalStaticTypeOf(store, last, bx.Right) @@ -678,13 +708,35 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { // we can't check compatible with native types // at current stage, so leave it to checkOrConvertType // to secondary call this assert logic again - if _, ok := lt.(*NativeType); ok { - debug.Println("---left native, return") - return + + //var isMixed bool + //if _, ok := lt.(*NativeType); ok { + // if _, ok := rt.(*NativeType); ok { + // isMixed = false + // } else { + // isMixed = true + // } + //} else { + // if _, ok := rt.(*NativeType); ok { + // isMixed = true + // } + //} + + if lnt, ok := lt.(*NativeType); ok { + println("---lt native") + _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) + if ok { + debug.Println("---lt native primitive, return") + return + } } - if _, ok := rt.(*NativeType); ok { - debug.Println("---right native, return") - return + if rnt, ok := rt.(*NativeType); ok { + println("---rt native, gnoType", rnt.gnoType) + _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) // TODO: check kind instead + if ok { + debug.Println("---right native primitive, return") + return + } } debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, bx.Op) @@ -704,6 +756,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { panic("invalid comparison operator") } } else { + // TODO: if not assign, check implicit compatible if pred, ok := binaryChecker[bx.Op]; ok { bx.assertCompatible2(lt, rt, pred, escapedOpStr, dt) } else { @@ -713,6 +766,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: // if both typed + //if !isMixed { // both native or both not native that we can check if !isUntyped(lt) && !isUntyped(rt) { if lt != nil && rt != nil { // NOTE: is this necessary? if lt.TypeID() != rt.TypeID() { @@ -720,6 +774,15 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } } } + //} + // special case of zero divisor + if isQuoOrRem(bx.Op) { + if rcx, ok := bx.Right.(*ConstExpr); ok { + if rcx.TypedValue.isZero() { + panic("invalid operation: division by zero") + } + } + } default: // do nothing } @@ -765,7 +828,7 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc // left side that is not compatible, so stop // the check here, assertion fail. if cmp < 0 { - checkAssignable(lt, rt, true) + checkAssignableTo(lt, rt, true) debug.Println("---assignable") // cache, XXX, is this needed? AssignableCheckCache.Add(bx.Left, rt) @@ -781,7 +844,7 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc // xxx, the fact of one of them is compatible while the other is not // when they share same specificity implies not assignable? if cmp > 0 { // right to left - checkAssignable(rt, lt, true) + checkAssignableTo(rt, lt, true) AssignableCheckCache.Add(bx.Right, lt) } else { if rt != nil { // return error on left side that is checked first @@ -791,6 +854,7 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc } } else { // both good + // TODO: both untyped or both typed if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet // check when both typed if lt != nil && rt != nil { // XXX, this should already be excluded by previous pred check. @@ -804,9 +868,9 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc // it's ok since assertCompatible2 only for lss, add, etc // that only with isOrdered if cmp <= 0 { - checkAssignable(lt, rt, true) + checkAssignableTo(lt, rt, true) } else { - checkAssignable(rt, lt, true) + checkAssignableTo(rt, lt, true) } } } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index ece5aa43f01..e829e3e8fcd 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2170,7 +2170,7 @@ func fillEmbeddedName(ft *FieldType) { ft.Embedded = true } -// TODO: empty interface? refer to checkAssignable +// TODO: empty interface? refer to checkAssignableTo func IsImplementedBy(it Type, ot Type) bool { switch cbt := baseOf(it).(type) { case *InterfaceType: @@ -2305,7 +2305,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkAssignable(spec, match.Elem(), false) + checkAssignableTo(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -2319,7 +2319,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkAssignable(spec, match, false) + checkAssignableTo(spec, match, false) return // ok } else { if isUntyped(spec) { diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 4cf944e5f2d..a9af089433b 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -952,6 +952,7 @@ func (tv *TypedValue) IsUndefined() bool { func (tv *TypedValue) IsNilInterface() bool { if tv.T != nil && tv.T.Kind() == InterfaceKind { if tv.V == nil { + debug.Println("---isNilInterface") return true } if debug { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 35ed1999d69..916d6bcda13 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -14,6 +14,10 @@ import ( // the conversion is forced and overflow/underflow is ignored. // TODO: return error, and let caller also print the file and line. func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { + debug.Printf("---convertTo: tv: %v, t: %v \n", tv, t) + defer func() { + debug.Printf("---after convert: tv: %v \n", tv) + }() if debug { if t == nil { panic("ConvertTo() requires non-nil type") @@ -73,6 +77,16 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { } GNO_CASE: // special case for interface target + // TODO: consider interface{}(nil) + // var a interface, a == 1 + // seems the second case is not match with here + // the second case should be a empty interface + // that both type and data is nil, (0x00) + // look line 91 + // is it specified for nil to typed-nil? + // that nil is different with undefined? + + // XXX, go does not do this, see: go.dev/issue/13061 if t.Kind() == InterfaceKind { if tv.IsUndefined() && tv.T == nil { // if tv.T == nil, nil T and nil Value. not a nil interface if _, ok := t.(*NativeType); !ok { // no support for native now diff --git a/gnovm/tests/debug/issue-558b.gno b/gnovm/tests/debug/issue-558b.gno new file mode 100644 index 00000000000..760c677d3f5 --- /dev/null +++ b/gnovm/tests/debug/issue-558b.gno @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + "io" + "log" + "strings" +) + +type readAutoCloser struct { + r io.ReadCloser +} + +func (a readAutoCloser) Read(b []byte) (n int, err error) { + if a.r == nil { + return 0, io.EOF + } + n, err = a.r.Read(b) + if err == io.EOF { + a.Close() + } + return n, err +} + +func (a readAutoCloser) Close() error { + if a.r == nil { + return nil + } + return a.r.(io.Closer).Close() +} + +type pipe struct { + Reader readAutoCloser +} + +func newReadAutoCloser(r io.Reader) readAutoCloser { + if _, ok := r.(io.Closer); !ok { + return readAutoCloser{io.NopCloser(r)} + } + return readAutoCloser{r.(io.ReadCloser)} +} + +type Reader interface { + Read(b []byte) (n int, err error) +} + +func ReadAll(r Reader) ([]byte, error) { + b := make([]byte, 0, 512) + for { + if len(b) == cap(b) { + // Add more capacity (let append pick how much). + b = append(b, 0)[:len(b)] + } + n, err := r.Read(b[len(b):cap(b)]) + b = b[:len(b)+n] + if err != nil { + //if err == io.EOF { + if io.EOF == err { + err = nil + } + return b, err + } + } +} + +func main() { + p := &pipe{} + p.Reader = newReadAutoCloser(strings.NewReader("test")) + b, err := ReadAll(p.Reader) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(b)) +} + +// Output: +// test diff --git a/gnovm/tests/debug/time1_native.gno b/gnovm/tests/debug/time1_native.gno new file mode 100644 index 00000000000..d66c4365045 --- /dev/null +++ b/gnovm/tests/debug/time1_native.gno @@ -0,0 +1,12 @@ +package main + +import "time" + +func main() { + var a int8 + a = 1 + println(a * time.Second) +} + +// Error: +// main/debug/time1_native.gno:8: cannot use int8 as int64 diff --git a/gnovm/tests/debug/time1_stdlibs.gno b/gnovm/tests/debug/time1_stdlibs.gno new file mode 100644 index 00000000000..d41342fc362 --- /dev/null +++ b/gnovm/tests/debug/time1_stdlibs.gno @@ -0,0 +1,12 @@ +package main + +import "time" + +func main() { + var a int8 + a = 1 + println(a * time.Second) +} + +// Error: +// main/debug/time1_stdlibs.gno:8: invalid operation: mismatched types int8 and time.Duration diff --git a/gnovm/tests/debug/time2_native.gno b/gnovm/tests/debug/time2_native.gno new file mode 100644 index 00000000000..eac7a061264 --- /dev/null +++ b/gnovm/tests/debug/time2_native.gno @@ -0,0 +1,11 @@ +package main + +import "time" + +func main() { + + println(time.Second * time.Second) +} + +// Output: +// 277777h46m40s diff --git a/gnovm/tests/debug/time2_stdlibs.gno b/gnovm/tests/debug/time2_stdlibs.gno new file mode 100644 index 00000000000..eac7a061264 --- /dev/null +++ b/gnovm/tests/debug/time2_stdlibs.gno @@ -0,0 +1,11 @@ +package main + +import "time" + +func main() { + + println(time.Second * time.Second) +} + +// Output: +// 277777h46m40s diff --git a/gnovm/tests/debug/time_native.gno b/gnovm/tests/debug/time_native.gno new file mode 100644 index 00000000000..4c5ee4270be --- /dev/null +++ b/gnovm/tests/debug/time_native.gno @@ -0,0 +1,12 @@ +package main + +import "time" + +func main() { + var a int8 + a = 1 + println(time.Second * a) +} + +// Error: +// main/debug/time_native.gno:8: cannot use int8 as int64 diff --git a/gnovm/tests/debug/time_stdlibs.gno b/gnovm/tests/debug/time_stdlibs.gno new file mode 100644 index 00000000000..a8ec9524155 --- /dev/null +++ b/gnovm/tests/debug/time_stdlibs.gno @@ -0,0 +1,12 @@ +package main + +import "time" + +func main() { + var a int8 + a = 1 + println(time.Second * a) +} + +// Error: +// main/debug/time_stdlibs.gno:8: invalid operation: mismatched types time.Duration and int8 diff --git a/gnovm/tests/debug2/0_a_3b.gno b/gnovm/tests/debug2/0_a_3b.gno new file mode 100644 index 00000000000..ff53044fde2 --- /dev/null +++ b/gnovm/tests/debug2/0_a_3b.gno @@ -0,0 +1,39 @@ +package main + +// 1. checkOrConvert is the core logic, to convert type(recursively if needed) +// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call +// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; +// it's not coerced +// 4. type call should be checked, it's coerced even RHS is typed. +// 5. func call should be checked, it's not coerced. + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +// case of expr in type call +func main() { + x := 2 + var r R + // assign to interface + r = 1 << x // 2 step. first binary, second call type + + r.foo() + + fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type +} + +// Error: +// main/debug/0_a_3b.gno:31: operator << not defined on: InterfaceKind diff --git a/gnovm/tests/debug2/0a1f_filetest.gno b/gnovm/tests/debug2/0a1f_filetest.gno new file mode 100644 index 00000000000..4861fe84c03 --- /dev/null +++ b/gnovm/tests/debug2/0a1f_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + expected := `hello`[:] + a := 1 + println(a == expected) // both typed +} + +// Error: +// main/files/types/0a1f_filetest.gno:6: cannot use int as string diff --git a/gnovm/tests/debug2/1.gno b/gnovm/tests/debug2/1.gno new file mode 100644 index 00000000000..bb30d64b42b --- /dev/null +++ b/gnovm/tests/debug2/1.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var a interface{} + println(1 == a) +} + +// Output: +// false diff --git a/gnovm/tests/debug2/1b2_filetest.gno b/gnovm/tests/debug2/1b2_filetest.gno new file mode 100644 index 00000000000..bd6508b1899 --- /dev/null +++ b/gnovm/tests/debug2/1b2_filetest.gno @@ -0,0 +1,9 @@ +package main + +// untyped const +func main() { + println(1 + "a") +} + +// Error: +// main/files/types/1b2_filetest.gno:5: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug2/native.gno b/gnovm/tests/debug2/native.gno index fbdb59f1eed..cbb76327ef7 100644 --- a/gnovm/tests/debug2/native.gno +++ b/gnovm/tests/debug2/native.gno @@ -8,5 +8,5 @@ func main() { } // Error: -// main/debug/native.gno:5: operator && not defined on: Int64Kind +// main/debug/time_stdlibs.gno:5: operator && not defined on: Int64Kind // *** CHECK THE ERR MESSAGES ABOVE, MAKE SURE IT'S WHAT YOU EXPECTED, DELETE THIS LINE AND RUN TEST AGAIN *** diff --git a/gnovm/tests/debug2/time4_native.gno b/gnovm/tests/debug2/time4_native.gno new file mode 100644 index 00000000000..3662e35cb01 --- /dev/null +++ b/gnovm/tests/debug2/time4_native.gno @@ -0,0 +1,15 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + var m time.Month + m = 9 + fmt.Println(m) +} + +// Output: +// September diff --git a/gnovm/tests/debug2/type34.gno b/gnovm/tests/debug2/type34.gno new file mode 100644 index 00000000000..240e1918837 --- /dev/null +++ b/gnovm/tests/debug2/type34.gno @@ -0,0 +1,10 @@ +package main + +type FooS struct { +} + +type BarS FooS + +func main() { + var _ *BarS = (*BarS)(nil) +} diff --git a/gnovm/tests/debug3/0f2_filetest.gnoa b/gnovm/tests/debug3/0f2_filetest.gnoa new file mode 100644 index 00000000000..67361dc8424 --- /dev/null +++ b/gnovm/tests/debug3/0f2_filetest.gnoa @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + //if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 + if errCmp == Error(0) { // this would not convert, errCmp is interface, refer to preprocess, line2526 + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/debug3/0f2b_native.gnoa b/gnovm/tests/debug3/0f2b_native.gnoa new file mode 100644 index 00000000000..8b9ba7ba0e5 --- /dev/null +++ b/gnovm/tests/debug3/0f2b_native.gnoa @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if Error(0) <= errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/debug/0f2b_native.gno:19: operator <= not defined on: InterfaceKind diff --git a/gnovm/tests/debug3/0f47f_filetest.gnoa b/gnovm/tests/debug3/0f47f_filetest.gnoa new file mode 100644 index 00000000000..4b2c6120dd0 --- /dev/null +++ b/gnovm/tests/debug3/0f47f_filetest.gnoa @@ -0,0 +1,16 @@ +package main + +import "fmt" + +// note, cast untyped nil to interface{}, hence comparable, special case +// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false +func main() { + println(interface{}(nil) == (*int)(nil)) // refer to convertConst and convertTo + fmt.Printf("%T \n", interface{}(nil)) + println(interface{}(nil)) +} + +// Output: +// false +// +// nil diff --git a/gnovm/tests/debug3/2.gnoa b/gnovm/tests/debug3/2.gnoa new file mode 100644 index 00000000000..230a58ed2b5 --- /dev/null +++ b/gnovm/tests/debug3/2.gnoa @@ -0,0 +1,10 @@ +package main + +var e error + +func main() { + e = 1 // this check is currently happening in checkOrConvert, should be in assertCompatibility +} + +// Error: +// main/debug/2.gno:6: bigint does not implement .uverse.error diff --git a/gnovm/tests/files/types/0f47f_filetest.gno b/gnovm/tests/files/types/0f47f_filetest.gno new file mode 100644 index 00000000000..b25b534f718 --- /dev/null +++ b/gnovm/tests/files/types/0f47f_filetest.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +// note, cast untyped nil to interface{}, hence comparable, special case +// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false +func main() { + println(interface{}(nil) == (*int)(nil)) // refer to convertConst and convertTo + fmt.Printf("%T \n", interface{}(nil)) +} + +// Output: +// false +// diff --git a/gnovm/tests/note/1.gno b/gnovm/tests/note/1.gno new file mode 100644 index 00000000000..4f2e7e03af1 --- /dev/null +++ b/gnovm/tests/note/1.gno @@ -0,0 +1,12 @@ +package main + +func main() { + var a interface{} + //var b = 1 + + //println(b == a) + println(1 == a) +} + +// Output: +// false diff --git a/gnovm/tests/note/2.gno b/gnovm/tests/note/2.gno new file mode 100644 index 00000000000..a3d30a3814d --- /dev/null +++ b/gnovm/tests/note/2.gno @@ -0,0 +1,10 @@ +package main + +var e error + +func main() { + e = 1 // this check is currently happening in checkOrConvert, should be in assertCompatibility +} + +// Error: +// main/debug/2.gnoa:6: bigint does not implement .uverse.error diff --git a/gnovm/tests/note/iface.gno b/gnovm/tests/note/iface.gno new file mode 100644 index 00000000000..80aae4d2774 --- /dev/null +++ b/gnovm/tests/note/iface.gno @@ -0,0 +1,14 @@ +package main + +type MyError struct { + error +} + +var err error + +func main() { + err = (*MyError)(nil) + println(err) +} + +// Output: From a6838b6558930cafdce8445e54e043030f1440d2 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 7 Mar 2024 23:18:26 +0800 Subject: [PATCH 103/193] fix compatible check for assign in type_check --- gnovm/pkg/gnolang/preprocess.go | 5 +- gnovm/pkg/gnolang/type_check.go | 92 +++++++++---------- gnovm/tests/{debug => debug4}/issue-558b.gno | 0 .../tests/{debug => debug4}/time1_native.gno | 0 .../tests/{debug => debug4}/time1_stdlibs.gno | 0 .../tests/{debug => debug4}/time2_native.gno | 0 .../tests/{debug => debug4}/time2_stdlibs.gno | 0 gnovm/tests/{debug => debug4}/time_native.gno | 0 .../tests/{debug => debug4}/time_stdlibs.gno | 0 gnovm/tests/files/types2/0_a_3b.gno | 2 +- 10 files changed, 49 insertions(+), 50 deletions(-) rename gnovm/tests/{debug => debug4}/issue-558b.gno (100%) rename gnovm/tests/{debug => debug4}/time1_native.gno (100%) rename gnovm/tests/{debug => debug4}/time1_stdlibs.gno (100%) rename gnovm/tests/{debug => debug4}/time2_native.gno (100%) rename gnovm/tests/{debug => debug4}/time2_stdlibs.gno (100%) rename gnovm/tests/{debug => debug4}/time_native.gno (100%) rename gnovm/tests/{debug => debug4}/time_stdlibs.gno (100%) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 7ec4d6172b0..6413c4b4425 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -920,6 +920,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { rpt := go2GnoBaseType(rnt.Type).(PrimitiveType) // check assignable, if pass, convert right to gno first // TODO: cmp? + // XXX, can we just check on native type? checkAssignableTo(lpt, rpt, false) // both primitive types rn = Expr(Call(rpt.String(), n.Right)) // checkOrCovertType should happen in future when both sides to be gno'd @@ -1726,9 +1727,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // TODO: should also check assign with checkAssignableTo, like var e error, e = 1 - if n.Op != ASSIGN { // filter out = - n.AssertCompatible(store, last) - } + n.AssertCompatible(store, last) if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { if len(n.Lhs) != 1 || len(n.Rhs) != 1 { panic("should not happen") diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 45c7744024f..b411950a9fd 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -709,21 +709,8 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { // at current stage, so leave it to checkOrConvertType // to secondary call this assert logic again - //var isMixed bool - //if _, ok := lt.(*NativeType); ok { - // if _, ok := rt.(*NativeType); ok { - // isMixed = false - // } else { - // isMixed = true - // } - //} else { - // if _, ok := rt.(*NativeType); ok { - // isMixed = true - // } - //} - if lnt, ok := lt.(*NativeType); ok { - println("---lt native") + debug.Println("---lt native") _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) if ok { debug.Println("---lt native primitive, return") @@ -731,7 +718,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } } if rnt, ok := rt.(*NativeType); ok { - println("---rt native, gnoType", rnt.gnoType) + debug.Println("---rt native, gnoType", rnt.gnoType) _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) // TODO: check kind instead if ok { debug.Println("---right native primitive, return") @@ -748,7 +735,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { assertComparable(lt, rt) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryChecker[bx.Op]; ok { - bx.assertCompatible2(lt, rt, pred, escapedOpStr, dt) + bx.checkCompatibility(lt, rt, pred, escapedOpStr, dt) } else { panic("should not happen") } @@ -758,7 +745,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } else { // TODO: if not assign, check implicit compatible if pred, ok := binaryChecker[bx.Op]; ok { - bx.assertCompatible2(lt, rt, pred, escapedOpStr, dt) + bx.checkCompatibility(lt, rt, pred, escapedOpStr, dt) } else { panic("should not happen") } @@ -789,10 +776,10 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } } -func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, escapedOpStr string, dt Type) { - debug.Println("---assertCompatible2, op: ", bx.Op) - debug.Printf("---assertCompatible2, lt: %v, rt: %v \n", lt, rt) - debug.Printf("---assertCompatible2, dt: %v \n", dt) +func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, escapedOpStr string, dt Type) { + debug.Println("---checkCompatibility, op: ", bx.Op) + debug.Printf("---checkCompatibility, lt: %v, rt: %v \n", lt, rt) + debug.Printf("---checkCompatibility, dt: %v \n", dt) AssignableCheckCache = NewAssignabilityCache() var destKind interface{} @@ -865,7 +852,7 @@ func (bx *BinaryExpr) assertCompatible2(lt, rt Type, pred func(t Type) bool, esc } } // check even when both side compatible with op - // it's ok since assertCompatible2 only for lss, add, etc + // it's ok since checkCompatibility only for lss, add, etc // that only with isOrdered if cmp <= 0 { checkAssignableTo(lt, rt, true) @@ -957,43 +944,56 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { // we can't check compatible with native types // at current stage, so leave it to checkOrConvertType // to secondary call this assert logic again - if _, ok := lt.(*NativeType); ok { - debug.Println("---left native, return") - return + if lnt, ok := lt.(*NativeType); ok { + if _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType); ok { + debug.Println("---left native, return") + return + } } - if _, ok := rt.(*NativeType); ok { - debug.Println("---right native, return") - return + if rnt, ok := rt.(*NativeType); ok { + if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { + debug.Println("---right native, return") + return + } } debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, as.Op) // check compatible - if pred, ok := AssignStmtChecker[as.Op]; ok { - if !pred(lt) { - if lt != nil { - destKind = lt.Kind() + if as.Op != ASSIGN { + if pred, ok := AssignStmtChecker[as.Op]; ok { + if !pred(lt) { + if lt != nil { + destKind = lt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) - } - switch as.Op { - case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: - // if both typed - if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet - debug.Println("---both typed") - if lt != nil && rt != nil { - // TODO: filter byte that has no typeID? - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + switch as.Op { + case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: + // if both typed + if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet + debug.Println("---both typed") + if lt != nil && rt != nil { + // TODO: filter byte that has no typeID? + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + } } } + default: + // do nothing } - default: - // do nothing + } else { + panic("should not happen") } } else { - panic("should not happen") + // check assignable, if done check operand with op + // XXX, always right -> left? see preprocess line1746 + // special case if rhs is(or contained) untyped shift, + // type of RHS is determined by LHS, no simply check + // assignable for this case. + checkAssignableTo(rt, lt, false) } } } diff --git a/gnovm/tests/debug/issue-558b.gno b/gnovm/tests/debug4/issue-558b.gno similarity index 100% rename from gnovm/tests/debug/issue-558b.gno rename to gnovm/tests/debug4/issue-558b.gno diff --git a/gnovm/tests/debug/time1_native.gno b/gnovm/tests/debug4/time1_native.gno similarity index 100% rename from gnovm/tests/debug/time1_native.gno rename to gnovm/tests/debug4/time1_native.gno diff --git a/gnovm/tests/debug/time1_stdlibs.gno b/gnovm/tests/debug4/time1_stdlibs.gno similarity index 100% rename from gnovm/tests/debug/time1_stdlibs.gno rename to gnovm/tests/debug4/time1_stdlibs.gno diff --git a/gnovm/tests/debug/time2_native.gno b/gnovm/tests/debug4/time2_native.gno similarity index 100% rename from gnovm/tests/debug/time2_native.gno rename to gnovm/tests/debug4/time2_native.gno diff --git a/gnovm/tests/debug/time2_stdlibs.gno b/gnovm/tests/debug4/time2_stdlibs.gno similarity index 100% rename from gnovm/tests/debug/time2_stdlibs.gno rename to gnovm/tests/debug4/time2_stdlibs.gno diff --git a/gnovm/tests/debug/time_native.gno b/gnovm/tests/debug4/time_native.gno similarity index 100% rename from gnovm/tests/debug/time_native.gno rename to gnovm/tests/debug4/time_native.gno diff --git a/gnovm/tests/debug/time_stdlibs.gno b/gnovm/tests/debug4/time_stdlibs.gno similarity index 100% rename from gnovm/tests/debug/time_stdlibs.gno rename to gnovm/tests/debug4/time_stdlibs.gno diff --git a/gnovm/tests/files/types2/0_a_3b.gno b/gnovm/tests/files/types2/0_a_3b.gno index ccc85747b98..e9e567a987d 100644 --- a/gnovm/tests/files/types2/0_a_3b.gno +++ b/gnovm/tests/files/types2/0_a_3b.gno @@ -36,4 +36,4 @@ func main() { } // Error: -// main/files/types2/0_a_3b.gno:31: operator << not defined on: InterfaceKind +// main/files/types2/0_a_3b.gno:31: bigint does not implement main.R From 4744d09dc3c8855c918d79709e084e2ba6413a22 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 8 Mar 2024 15:55:08 +0800 Subject: [PATCH 104/193] make rhs native type check in type_check --- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 3 +- gnovm/pkg/gnolang/preprocess.go | 40 ++++++++++++---------- gnovm/pkg/gnolang/type_check.go | 9 ++++- gnovm/tests/debug/0f0_native_filetest.gnoa | 28 +++++++++++++++ gnovm/tests/debug/0f2_filetest.gnoa | 28 +++++++++++++++ gnovm/tests/debug/2.gnoa | 10 ++++++ gnovm/tests/debug/22a12_filetest.gnoa | 20 +++++++++++ gnovm/tests/debug/dec_rem.gnoa | 8 +++++ gnovm/tests/debug/iface_eql.gno | 9 +++++ 10 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 gnovm/tests/debug/0f0_native_filetest.gnoa create mode 100644 gnovm/tests/debug/0f2_filetest.gnoa create mode 100644 gnovm/tests/debug/2.gnoa create mode 100644 gnovm/tests/debug/22a12_filetest.gnoa create mode 100644 gnovm/tests/debug/dec_rem.gnoa create mode 100644 gnovm/tests/debug/iface_eql.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index b34ffc86c05..5cd35e1086c 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -364,7 +364,7 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { } if rv.Kind() == reflect.Interface { if rv.IsNil() { - return TypedValue{} + return TypedValue{} // TODO: with type? } else { rv = rv.Elem() } diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 49462130cd2..b7275007822 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -77,6 +77,7 @@ func (m *Machine) doOpEql() { rv := m.PopValue() lv := m.PeekValue(1) // also the result + debug.Printf("---doOpEql: lv: %v, rv: %v \n", lv, rv) var res bool if debug { assertAssignable(lv.T, rv.T) @@ -336,7 +337,7 @@ func (m *Machine) doOpBandn() { // TODO: can be much faster. func isEql(store Store, lv, rv *TypedValue) bool { - debug.Printf("---isEql, lv: %v, rt: %v \n", lv, rv) + debug.Printf("---isEql, lv: %v, rv: %v \n", lv, rv) // If one is undefined, the other must be as well. // Fields/items are set to defaultValue along the way. lvu := lv.IsUndefined() diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 6413c4b4425..19e9c409917 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -817,25 +817,29 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debug.Printf("---rt: %v \n", rt) debug.Printf("---rnt: %v \n", rnt) // get concrete native base type. - pt := go2GnoBaseType(rnt.Type).(PrimitiveType) - // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, false, false) - // if check pass, convert n.Right to (gno) pt type, - rn := Expr(Call(pt.String(), n.Right)) - debug.Printf("---rn : %v \n", rn) - // and convert result back. - tx := constType(n, rnt) - debug.Printf("---tx : %v \n", tx) - // reset/create n2 to preprocess right child. - n2 := &BinaryExpr{ - Left: n.Left, - Op: n.Op, - Right: rn, + pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) + if ok { + // convert n.Left to pt type, + checkOrConvertType(store, last, &n.Left, pt, false, false) + // if check pass, convert n.Right to (gno) pt type, + rn := Expr(Call(pt.String(), n.Right)) + debug.Printf("---rn : %v \n", rn) + // and convert result back. + tx := constType(n, rnt) + debug.Printf("---tx : %v \n", tx) + // reset/create n2 to preprocess right child. + n2 := &BinaryExpr{ + Left: n.Left, + Op: n.Op, + Right: rn, + } + resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} + resn = Preprocess(store, last, resn) + debug.Printf("---resn : %v \n", resn) + return resn, TRANS_CONTINUE + } else { + return n, TRANS_CONTINUE } - resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} - resn = Preprocess(store, last, resn) - debug.Printf("---resn : %v \n", resn) - return resn, TRANS_CONTINUE // NOTE: binary operations are always computed in // gno, never with reflect. } else { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index b411950a9fd..b162a919adc 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -223,6 +223,7 @@ func assertSameTypes(lt, rt Type) { } func isSameType(lt, rt Type) bool { + debug.Printf("---isSameType, lt: %v, rt: %v \n", lt, rt) return lt == nil && rt == nil || // both are nil/undefined (lt != nil && rt != nil) && // both are defined (lt.TypeID() == rt.TypeID()) // and identical. @@ -252,7 +253,7 @@ func assertAssignable(lt, rt Type) { // and remove this case? println("4") } else if lt.Kind() == InterfaceKind && - IsImplementedBy(lt, rt) { + IsImplementedBy(lt, rt) { // TODO: consider this // rt implements lt (and lt is nil interface). } else if rt.Kind() == InterfaceKind && IsImplementedBy(rt, lt) { @@ -733,6 +734,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { switch bx.Op { case EQL, NEQ: assertComparable(lt, rt) + checkAssignableTo(lt, rt, true) case LSS, LEQ, GTR, GEQ: if pred, ok := binaryChecker[bx.Op]; ok { bx.checkCompatibility(lt, rt, pred, escapedOpStr, dt) @@ -798,6 +800,10 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es } // other cases + // TODO: XXX, this logic based on an assumption that one side is not defined on op + // while the other side is ok, and this side is assignable to the other side, pass + // is this general??? or the only case? + // consider 1.2 % int64(1), and 1.0 % int64 cmp := cmpSpecificity(lt, rt) if !pred(lt) { // lt not compatible with op if !pred(rt) { // rt not compatible with op @@ -859,6 +865,7 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es } else { checkAssignableTo(rt, lt, true) } + // TODO: cache } } diff --git a/gnovm/tests/debug/0f0_native_filetest.gnoa b/gnovm/tests/debug/0f0_native_filetest.gnoa new file mode 100644 index 00000000000..8456b73ade7 --- /dev/null +++ b/gnovm/tests/debug/0f0_native_filetest.gnoa @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if 1 == errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/debug/0f0_native_filetest.gno:19: unexpected type pair: cannot use bigint as gonative{error} diff --git a/gnovm/tests/debug/0f2_filetest.gnoa b/gnovm/tests/debug/0f2_filetest.gnoa new file mode 100644 index 00000000000..7ded58b4ff0 --- /dev/null +++ b/gnovm/tests/debug/0f2_filetest.gnoa @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +func main() { + if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/debug/2.gnoa b/gnovm/tests/debug/2.gnoa new file mode 100644 index 00000000000..230a58ed2b5 --- /dev/null +++ b/gnovm/tests/debug/2.gnoa @@ -0,0 +1,10 @@ +package main + +var e error + +func main() { + e = 1 // this check is currently happening in checkOrConvert, should be in assertCompatibility +} + +// Error: +// main/debug/2.gno:6: bigint does not implement .uverse.error diff --git a/gnovm/tests/debug/22a12_filetest.gnoa b/gnovm/tests/debug/22a12_filetest.gnoa new file mode 100644 index 00000000000..e791c05bd43 --- /dev/null +++ b/gnovm/tests/debug/22a12_filetest.gnoa @@ -0,0 +1,20 @@ +package main + +type c uint +type word c +type nat []word + +func (n nat) add() bool { + return true +} + +func main() { + var abs nat + + abs = []c{0} + + println(abs.add()) +} + +// Error: +// main/debug/22a12_filetest.gno:14: cannot use main.c as main.word without explicit conversion diff --git a/gnovm/tests/debug/dec_rem.gnoa b/gnovm/tests/debug/dec_rem.gnoa new file mode 100644 index 00000000000..48c50c5589d --- /dev/null +++ b/gnovm/tests/debug/dec_rem.gnoa @@ -0,0 +1,8 @@ +package main + +func main() { + println(1.2 % int(1)) +} + +// Error: +// main/debug/dec_rem.gno:4: cannot convert untyped bigdec to integer -- 1.2 not an exact integer diff --git a/gnovm/tests/debug/iface_eql.gno b/gnovm/tests/debug/iface_eql.gno new file mode 100644 index 00000000000..59a7d7060e1 --- /dev/null +++ b/gnovm/tests/debug/iface_eql.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var l interface{} + println(1 == l) +} + +// Output: +// false From 5631d3af800b4de82340e656dc73a1dda24b3ef7 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 11 Mar 2024 23:58:12 +0800 Subject: [PATCH 105/193] try handle checking declared type against native interface, temp here, gotta move to other place --- gnovm/pkg/gnolang/gonative.go | 80 ++++++++++++ gnovm/pkg/gnolang/op_binary.go | 4 + gnovm/pkg/gnolang/preprocess.go | 60 +++------ gnovm/pkg/gnolang/type_check.go | 121 ++++++++++++++++-- gnovm/pkg/gnolang/types.go | 27 ++++ gnovm/tests/debug/0f2_filetest.gno | 29 +++++ .../{0f2_filetest.gnoa => 0f7_filetest.gnoa} | 5 +- gnovm/tests/debug/dynamic.gnoa | 13 ++ gnovm/tests/debug/iface_eql.gno | 9 -- gnovm/tests/debug/iface_eql.gnoa | 15 +++ gnovm/tests/debug/struct.gnoa | 43 +++++++ .../tests/files/types/0b4_native_filetest.gno | 2 +- .../tests/files/types/0f0_native_filetest.gno | 2 +- 13 files changed, 339 insertions(+), 71 deletions(-) create mode 100644 gnovm/tests/debug/0f2_filetest.gno rename gnovm/tests/debug/{0f2_filetest.gnoa => 0f7_filetest.gnoa} (69%) create mode 100644 gnovm/tests/debug/dynamic.gnoa delete mode 100644 gnovm/tests/debug/iface_eql.gno create mode 100644 gnovm/tests/debug/iface_eql.gnoa create mode 100644 gnovm/tests/debug/struct.gnoa diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 5cd35e1086c..b90a1bc6d58 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -899,15 +899,91 @@ func gno2GoType(t Type) reflect.Type { } } +func signaturesMatch(nativeMethod reflect.Type, gnoMethod *FuncType) bool { + debug.Printf("---signatureMatch, nativeMethodType: %v \n", nativeMethod) + debug.Printf("---signatureMatch, gnoMethodType: %v \n", gnoMethod) + debug.Printf("---signatureMatch, nativeNumIn: %v \n", nativeMethod.NumIn()) + debug.Printf("---signatureMatch, gnoNumIn: %v \n", gnoMethod.NumIn()) + debug.Printf("---signatureMatch, nativeMethodNumOut: %v \n", nativeMethod.NumOut()) + debug.Printf("---signatureMatch, gnoMethodNumOut: %v \n", gnoMethod.NumOut()) + // Adjusting for the receiver in the gnoMethod's signature + // An interface method implicitly expects a receiver, so we start comparing from the second parameter of the gnoMethod. + if nativeMethod.NumIn() != gnoMethod.NumIn() || nativeMethod.NumOut() != gnoMethod.NumOut() { + return false + } + + // Compare input parameters types, adjusting for the receiver + for i := 1; i < gnoMethod.NumIn(); i++ { + debug.Printf("nativeMethod In [%d] is: %v \n", i, nativeMethod.In(i)) + debug.Printf("gnoMethod In [%d] is: %v \n", i, gnoMethod.In(i)) + if !gno2GoTypeMatches(gnoMethod.In(i), nativeMethod.In(i)) { + //if nativeMethod.In(i-1) != gnoMethod.In(i) { + return false + } + } + + // Compare output values types + for i := 0; i < nativeMethod.NumOut(); i++ { + debug.Printf("nativeMethod Out [%d] is: %v \n", i, nativeMethod.Out(i)) + debug.Printf("gnoMethod Out [%d] is : %v \n", i, gnoMethod.Out(i)) + + if fdt, ok := gnoMethod.Out(i).(FieldType); ok { + debug.Printf("---t is field type: %v \n", fdt) + debug.Println("fdt.Type: ", fdt.Type) + debug.Println("base of fdt.Type: ", baseOf(fdt.Type)) + // TODO: more test on param/result non-primitive cases + return gno2GoTypeMatches(baseOf(fdt.Type), nativeMethod.Out(i)) + } else { + return false + } + } + + return true +} + // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). // This is called when autoNative is true in checkAssignableTo(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { + debug.Printf("---gno2GoTypeMatches, t: %v, rt: %v, type of t: %v \n", t, rt, reflect.TypeOf(t)) if rt == nil { panic("should not happen") } + // TODO: + // consider the pattern, only declaredType <=> interface ? + // params/results check + if dt, ok := t.(*DeclaredType); ok { + debug.Println("dt.Name: ", dt.Name) + debug.Println("len of rt.Methods :", rt.NumMethod()) + if rt.Kind() == reflect.Interface && rt.NumMethod() != 0 { + for i := 0; i < rt.NumMethod(); i++ { + method := rt.Method(i) + m := dt.Methods[i] + if fv, ok := m.V.(*FuncValue); ok { + if string(fv.Name) == method.Name { + if ft, ok := m.T.(*FuncType); ok { + // Check if the method signatures match + if !signaturesMatch(method.Type, ft) { + fmt.Printf("Method %s has a different signature in Dog and Animal\n", method.Name) + return false + } + } else { + return false + } + } else { + return false + } + } else { + return false + } + } + debug.Println("---satisfy native interface") + return true + } + } + // special case if t == Float32Type or Float64Type if t == Float32Type { return rt.Kind() == reflect.Float32 @@ -920,6 +996,9 @@ func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { case BoolType, UntypedBoolType: return rt.Kind() == reflect.Bool case StringType, UntypedStringType: + debug.Println("---string type") + debug.Println("---rt.Kind: ", rt.Kind()) + debug.Println(rt.Kind() == reflect.String) return rt.Kind() == reflect.String case IntType: return rt.Kind() == reflect.Int @@ -1405,6 +1484,7 @@ func (m *Machine) doOpStructLitGoNative() { // NOTE: Unlike doOpCall(), doOpCallGoNative() also handles // conversions, similarly to doOpConvert(). func (m *Machine) doOpCallGoNative() { + debug.Println("---doOpCallGoNative") fr := m.LastFrame() fv := fr.GoFunc ft := fv.Value.Type() diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index b7275007822..e4a654143eb 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -78,6 +78,9 @@ func (m *Machine) doOpEql() { lv := m.PeekValue(1) // also the result debug.Printf("---doOpEql: lv: %v, rv: %v \n", lv, rv) + debug.Printf("---doOpEql: lv.T: %v, rv.T: %v \n", lv.T, rv.T) + debug.Printf("---doOpEql: lv.V: %v, rv.V: %v \n", lv.V, rv.V) + debug.Printf("---doOpEql: lv.N: %v, rv.N: %v \n", lv.N, rv.N) var res bool if debug { assertAssignable(lv.T, rv.T) @@ -350,6 +353,7 @@ func isEql(store Store, lv, rv *TypedValue) bool { if !isSameType(lv.T, rv.T) { return false } + debug.Println("---assert to be same types") if lnt, ok := lv.T.(*NativeType); ok { if rnt, ok := rv.T.(*NativeType); ok { if lnt.Type != rnt.Type { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 19e9c409917..4d714372656 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -743,11 +743,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: debug.Println("---BinaryExpr") - n.AssertCompatible(store, last, nil) // TODO: improve readability lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) + + n.AssertCompatible(lt, rt, nil) + // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR // special case of shift @@ -1313,8 +1315,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: - n.AssertCompatible(store, last, nil) xt := evalStaticTypeOf(store, last, n.X) + + n.AssertCompatible(xt, nil) + if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) @@ -1782,7 +1786,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *IncDecStmt: - n.AssertCompatible(store, last) + xt := evalStaticTypeOf(store, last, n.X) + n.AssertCompatible(xt) // TRANS_LEAVE ----------------------- case *ForStmt: @@ -2418,43 +2423,6 @@ func isConstType(x Expr) bool { return ok } -func cmpSpecificity(t1, t2 Type) int { - debug.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) - if it1, ok := baseOf(t1).(*InterfaceType); ok { - if it1.IsEmptyInterface() { - return 1 // left empty interface - } else { - if it2, ok := baseOf(t2).(*InterfaceType); ok { - if it2.IsEmptyInterface() { // right empty interface - return -1 - } else { - return 0 // both non-empty interface - } - } else { - return 1 // right not interface - } - } - } else if _, ok := t2.(*InterfaceType); ok { - return -1 // left not interface, right is interface - } - - t1s, t2s := 0, 0 - if t1p, ok := t1.(PrimitiveType); ok { - t1s = t1p.Specificity() - } - if t2p, ok := t2.(PrimitiveType); ok { - t2s = t2p.Specificity() - } - if t1s < t2s { - // NOTE: higher specificity has lower value, so backwards. - return 1 - } else if t1s == t2s { - return 0 - } else { - return -1 - } -} - // for special case to bypass check for typed -> typed conversion, e.g. array index conversion func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { if cx, ok := (*x).(*ConstExpr); ok { @@ -2488,7 +2456,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else { // still need for non-binary, like arg checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a - debug.Println("---check pass!") + debug.Println("---check pass in checkOrConvertType!") } } } @@ -2514,8 +2482,11 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // coerce mostly when explicitly conversion, type call, while arg is binary expr // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 // TODO: do we need this any more? since already checked before? - // NO, it's from callExpr and should checked recursively - bx.AssertCompatible(store, last, t) + // NO, it's from callExpr and should checked recursively? huh? + + lt := evalStaticTypeOf(store, last, bx.Left) + rt := evalStaticTypeOf(store, last, bx.Right) + bx.AssertCompatible(lt, rt, t) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else { // not coerce, xt is typed, no need to convert but check. refer to 10a17b1. @@ -2535,7 +2506,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } if coerce || !coerce && isUntyped(xt) { - ux.AssertCompatible(store, last, t) + uxt := evalStaticTypeOf(store, last, ux.X) + ux.AssertCompatible(uxt, t) // "push" expected type into shift binary's left operand. checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) } else { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index b162a919adc..274f3c43893 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -256,11 +256,23 @@ func assertAssignable(lt, rt Type) { IsImplementedBy(lt, rt) { // TODO: consider this // rt implements lt (and lt is nil interface). } else if rt.Kind() == InterfaceKind && - IsImplementedBy(rt, lt) { - println("---assertEqulityTypes, match") + IsImplementedBy(rt, lt) { // TODO: consider this + println("5") // lt implements rt (and rt is nil interface). + } else if nrt, ok := rt.(*NativeType); ok { // see 0f2, for native types + if gno2GoTypeMatches(lt, nrt.Type) { + println("6.1") + } else { + println("6.2") + } + } else if nlt, ok := lt.(*NativeType); ok { + if gno2GoTypeMatches(rt, nlt.Type) { + println("7.1") + } else { + println("7.2") + } } else { - //panic("---5") + panic("---8") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -417,6 +429,10 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { } // case3 if dt.Kind() == InterfaceKind { + debug.Println("---dt: ", dt) + debug.Println("---baseOf dt: ", baseOf(dt)) + debug.Println("---dt.Kind: ", dt.Kind()) + debug.Printf("---xt: %v, baseOf(xt): %v \n", xt, baseOf(xt)) if idt, ok := baseOf(dt).(*InterfaceType); ok { if idt.IsEmptyInterface() { // XXX, can this be merged with IsImplementedBy? // if dt is an empty Gno interface, any x ok. @@ -431,6 +447,7 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { dt.String())) } } else if ndt, ok := baseOf(dt).(*NativeType); ok { + debug.Printf("---ndt: %v \n", ndt) nidt := ndt.Type if nidt.NumMethod() == 0 { // if dt is an empty Go native interface, ditto. @@ -462,6 +479,10 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { pxt.String(), nidt.String())) } + } else if xdt, ok := xt.(*DeclaredType); ok { + gno2GoTypeMatches(baseOf(xdt), ndt.Type) + debug.Println("---matches!") + return } else { panic(fmt.Sprintf( "unexpected type pair: cannot use %s as %s", @@ -664,6 +685,7 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // xt: any type but a *DeclaredType; could be native. // cdt: actual concrete native target type. // ie, if cdt can match against xt. + debug.Println("---going to check gno2go matches") if gno2GoTypeMatches(xt, cdt.Type) { return // ok } @@ -697,21 +719,23 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // dt is a special case for binary expr that the dest type for the // lhs determined by outer context -func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { +func (bx *BinaryExpr) AssertCompatible(lt, rt, dt Type) { debug.Printf("---AssertCompatible, bx: %v \n", bx) debug.Printf("---AssertCompatible, bx.Left: %T \n", bx.Left) debug.Printf("---AssertCompatible, bx.Right: %T \n", bx.Right) // get left type and right type - lt := evalStaticTypeOf(store, last, bx.Left) - rt := evalStaticTypeOf(store, last, bx.Right) + //lt := evalStaticTypeOf(store, last, bx.Left) + //rt := evalStaticTypeOf(store, last, bx.Right) // we can't check compatible with native types // at current stage, so leave it to checkOrConvertType // to secondary call this assert logic again + //var leftNative, rightNative bool if lnt, ok := lt.(*NativeType); ok { debug.Println("---lt native") + //leftNative = true _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) if ok { debug.Println("---lt native primitive, return") @@ -719,6 +743,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } } if rnt, ok := rt.(*NativeType); ok { + //rightNative = true debug.Println("---rt native, gnoType", rnt.gnoType) _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) // TODO: check kind instead if ok { @@ -734,7 +759,17 @@ func (bx *BinaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { switch bx.Op { case EQL, NEQ: assertComparable(lt, rt) - checkAssignableTo(lt, rt, true) + // XXX, should not check compatible for equality compare? + // the native type here are both non-primitive + // not able to check assignable, e.g. MyError == err, that if left satisfied right native interface. + //if !leftNative && !rightNative { + cmp := cmpSpecificity(lt, rt) + if cmp <= 0 { + checkAssignableTo(lt, rt, true) + } else { + checkAssignableTo(rt, lt, true) + } + //} case LSS, LEQ, GTR, GEQ: if pred, ok := binaryChecker[bx.Op]; ok { bx.checkCompatibility(lt, rt, pred, escapedOpStr, dt) @@ -869,18 +904,18 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es } } -func (ux *UnaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { +func (ux *UnaryExpr) AssertCompatible(uxt, dt Type) { debug.Printf("---AssertCompatible, ux: %v \n", ux) debug.Printf("---AssertCompatible, ux.X: %T \n", ux.X) var destKind interface{} // get left type and right type - t := evalStaticTypeOf(store, last, ux.X) + //t := evalStaticTypeOf(store, last, ux.X) // we can't check compatible with native types // at current stage, so leave it to checkOrConvertType // to secondary call this assert logic again - if _, ok := t.(*NativeType); ok { + if _, ok := uxt.(*NativeType); ok { debug.Println("---left native, return") return } @@ -888,7 +923,7 @@ func (ux *UnaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { // check compatible if pred, ok := unaryChecker[ux.Op]; ok { if dt == nil { - dt = t + dt = uxt } if !pred(dt) { if dt != nil { @@ -901,7 +936,7 @@ func (ux *UnaryExpr) AssertCompatible(store Store, last BlockNode, dt Type) { } } -func (idst *IncDecStmt) AssertCompatible(store Store, last BlockNode) { +func (idst *IncDecStmt) AssertCompatible(t Type) { debug.Printf("---AssertCompatible, st: %v \n", idst) debug.Printf("---AssertCompatible, st.X: %T \n", idst.X) debug.Printf("---AssertCompatible, st.Op: %T \n", idst.Op) @@ -909,7 +944,7 @@ func (idst *IncDecStmt) AssertCompatible(store Store, last BlockNode) { var destKind interface{} // get left type and right type - t := evalStaticTypeOf(store, last, idst.X) + //t := evalStaticTypeOf(store, last, idst.X) // we can't check compatible with native types // at current stage, so leave it to checkOrConvertType @@ -1023,3 +1058,63 @@ func isComparison(op Word) bool { return false } } + +func cmpSpecificity(t1, t2 Type) int { + debug.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) + + if nt1, ok := t1.(*NativeType); ok { + if nt1.Type.Kind() == reflect.Interface { // is interface + if nt1.Type.NumMethod() == 0 { // empty interface + return 1 + } else if t2 != nil && t2.Kind() != InterfaceKind { + return 1 + } + } else { + t1 = go2GnoType(nt1.Type) // if not interface, convert to gno type + } + } else if nt2, ok := t2.(*NativeType); ok { + if nt2.Type.Kind() == reflect.Interface { // is interface + if nt2.Type.NumMethod() == 0 { + return -1 + } else if t1 != nil && t1.Kind() != InterfaceKind { + return -1 + } + } else { + t2 = go2GnoType(nt2.Type) + } + } + + if it1, ok := baseOf(t1).(*InterfaceType); ok { + if it1.IsEmptyInterface() { + return 1 // left empty interface + } else { + if it2, ok := baseOf(t2).(*InterfaceType); ok { + if it2.IsEmptyInterface() { // right empty interface + return -1 + } else { + return 0 // both non-empty interface + } + } else { + return 1 // right not interface + } + } + } else if _, ok := t2.(*InterfaceType); ok { + return -1 // left not interface, right is interface + } + + t1s, t2s := 0, 0 + if t1p, ok := t1.(PrimitiveType); ok { + t1s = t1p.Specificity() + } + if t2p, ok := t2.(PrimitiveType); ok { + t2s = t2p.Specificity() + } + if t1s < t2s { + // NOTE: higher specificity has lower value, so backwards. + return 1 + } else if t1s == t2s { + return 0 + } else { + return -1 + } +} diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index e829e3e8fcd..5fa3d73282b 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1084,6 +1084,31 @@ type FuncType struct { bound *FuncType } +func (ft *FuncType) NumIn() int { + if len(ft.Params) >= 1 { + return len(ft.Params) - 1 // TODO: assert to be method + } + return 0 +} + +func (ft *FuncType) In(i int) Type { + if len(ft.Params) >= 1 { + return ft.Params[len(ft.Params)-1-i] + } + return nil +} + +func (ft *FuncType) Out(i int) Type { + if len(ft.Params) >= 1 { + return ft.Params[len(ft.Results)-1-i] + } + return nil +} + +func (ft *FuncType) NumOut() int { + return len(ft.Results) +} + // if ft is a method, returns whether method takes a pointer receiver. func (ft *FuncType) HasPointerReceiver() bool { if debug { @@ -2172,10 +2197,12 @@ func fillEmbeddedName(ft *FieldType) { // TODO: empty interface? refer to checkAssignableTo func IsImplementedBy(it Type, ot Type) bool { + debug.Printf("---IsImplementedBy, it: %v, ot: %v \n", it, ot) switch cbt := baseOf(it).(type) { case *InterfaceType: return cbt.IsImplementedBy(ot) case *NativeType: + debug.Println("---native type") return gno2GoTypeMatches(ot, cbt.Type) default: panic("should not happen") diff --git a/gnovm/tests/debug/0f2_filetest.gno b/gnovm/tests/debug/0f2_filetest.gno new file mode 100644 index 00000000000..6e18520d226 --- /dev/null +++ b/gnovm/tests/debug/0f2_filetest.gno @@ -0,0 +1,29 @@ +package main + +import ( + "errors" +) + +type Error string + +func (e Error) Error() string { + return string(e) +} + +var errCmp = errors.New("XXXX") + +// specil case: +// one is interface +// TODO: seems what we can do is to not allowed gonative non-empty interface come into gno +// namely, we don't run this in .native mode, (withNativeLibs) +func main() { + if Error("XXXX") == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/debug/0f2_filetest.gnoa b/gnovm/tests/debug/0f7_filetest.gnoa similarity index 69% rename from gnovm/tests/debug/0f2_filetest.gnoa rename to gnovm/tests/debug/0f7_filetest.gnoa index 7ded58b4ff0..29a6061cd77 100644 --- a/gnovm/tests/debug/0f2_filetest.gnoa +++ b/gnovm/tests/debug/0f7_filetest.gnoa @@ -13,11 +13,10 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// specil case: +// special case: // one is interface func main() { - if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 - //if errCmp == 1 { + if errCmp == Error(1) { println("what the firetruck?") } else { println("something else") diff --git a/gnovm/tests/debug/dynamic.gnoa b/gnovm/tests/debug/dynamic.gnoa new file mode 100644 index 00000000000..75558dc67ed --- /dev/null +++ b/gnovm/tests/debug/dynamic.gnoa @@ -0,0 +1,13 @@ +package main + +import "errors" + +var err1 = errors.New("xxx") +var err2 = errors.New("xxx") + +func main() { + println(err1 == err2) +} + +// Output: +// false diff --git a/gnovm/tests/debug/iface_eql.gno b/gnovm/tests/debug/iface_eql.gno deleted file mode 100644 index 59a7d7060e1..00000000000 --- a/gnovm/tests/debug/iface_eql.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - var l interface{} - println(1 == l) -} - -// Output: -// false diff --git a/gnovm/tests/debug/iface_eql.gnoa b/gnovm/tests/debug/iface_eql.gnoa new file mode 100644 index 00000000000..905778bcd21 --- /dev/null +++ b/gnovm/tests/debug/iface_eql.gnoa @@ -0,0 +1,15 @@ +package main + +type Foo struct { + n int +} + +func main() { + var l interface{} + //var l interface{} = 1 + //var l interface{} = (*Foo)(nil) + println(1 == l) +} + +// Output: +// false diff --git a/gnovm/tests/debug/struct.gnoa b/gnovm/tests/debug/struct.gnoa new file mode 100644 index 00000000000..3b49842e3ef --- /dev/null +++ b/gnovm/tests/debug/struct.gnoa @@ -0,0 +1,43 @@ +package main + +import ( + "errors" + "fmt" +) + +type Foo struct { + N int +} + +func main() { + err1 := errors.New("xxx") + err2 := errors.New("xxx") + + println(err1 == err2) + + s1 := &Foo{N: 1} + s2 := &Foo{N: 1} + + fmt.Println(s1) + fmt.Println(s2) + + println(s1 == s2) + + s3 := Foo{N: 1} + s4 := Foo{N: 1} + + fmt.Println(s3) + fmt.Println(s4) + + println(s3 == s4) + +} + +// Output: +// false +// &{1} +// &{1} +// false +// {1} +// {1} +// true diff --git a/gnovm/tests/files/types/0b4_native_filetest.gno b/gnovm/tests/files/types/0b4_native_filetest.gno index ae73a2dbd66..24badb4a9e1 100644 --- a/gnovm/tests/files/types/0b4_native_filetest.gno +++ b/gnovm/tests/files/types/0b4_native_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// interface conversion: gnolang.Type is *gnolang.NativeType, not gnolang.PrimitiveType +// main/files/types/0b4_native_filetest.gno:9: unexpected type pair: cannot use bigint as gonative{error} diff --git a/gnovm/tests/files/types/0f0_native_filetest.gno b/gnovm/tests/files/types/0f0_native_filetest.gno index d625f5deb4f..cc77a125ad0 100644 --- a/gnovm/tests/files/types/0f0_native_filetest.gno +++ b/gnovm/tests/files/types/0f0_native_filetest.gno @@ -25,4 +25,4 @@ func main() { } // Error: -// interface conversion: gnolang.Type is *gnolang.NativeType, not gnolang.PrimitiveType +// main/files/types/0f0_native_filetest.gno:19: unexpected type pair: cannot use bigint as gonative{error} From a2862ba91f277e0b7090f409335ba5f59f783466 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 13 Mar 2024 18:19:28 +0800 Subject: [PATCH 106/193] consolidate delay handling for untyped shift expr logic --- gnovm/pkg/gnolang/nodes.go | 1 + gnovm/pkg/gnolang/preprocess.go | 115 +++++++-- gnovm/pkg/gnolang/type_check.go | 232 ++++++++---------- gnovm/pkg/gnolang/types.go | 1 + .../{0f2_filetest.gno => 0f2_filetest.gnoa} | 0 gnovm/tests/debug/10a001_filetest.gnoa | 9 + gnovm/tests/debug/10a14_filetest.gno | 10 + gnovm/tests/debug/10a27e.gnoa | 13 + gnovm/tests/debug/15b.gnoa | 30 +++ gnovm/tests/debug/untyped.gnoa | 11 + gnovm/tests/files/types2/10a27c.gno | 5 +- gnovm/tests/files/types2/27a_filetest.gno | 4 +- 12 files changed, 287 insertions(+), 144 deletions(-) rename gnovm/tests/debug/{0f2_filetest.gno => 0f2_filetest.gnoa} (100%) create mode 100644 gnovm/tests/debug/10a001_filetest.gnoa create mode 100644 gnovm/tests/debug/10a14_filetest.gno create mode 100644 gnovm/tests/debug/10a27e.gnoa create mode 100644 gnovm/tests/debug/15b.gnoa create mode 100644 gnovm/tests/debug/untyped.gnoa diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 2a9e0b51a97..9aa6d5646cd 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -2021,6 +2021,7 @@ const ( ATTR_IOTA GnoAttribute = "ATTR_IOTA" ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" ATTR_INJECTED GnoAttribute = "ATTR_INJECTED" + ATTR_DELAY GnoAttribute = "ATTR_DELAY" ) // TODO: consider length restrictions. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 4d714372656..96cf4ad5ade 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -748,14 +748,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) - n.AssertCompatible(lt, rt, nil) - // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR // special case of shift if isShift { // check LHS type compatibility - //checkOperandWithOp(store, last, &n.Left, lt, n.Op, Binary) + // check compatible + n.checkShiftExpr(lt, false) // checkOrConvert RHS if baseOf(rt) != UintType { // TODO: XXX, is it good for native? // convert n.Right to (gno) uint type, @@ -769,6 +768,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { resn := Preprocess(store, last, n2) return resn, TRANS_CONTINUE } + } else { + n.AssertCompatible(lt, rt) } // General case. @@ -807,6 +808,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // Then, evaluate the expression. // also for shift + + if isShift { + if n.GetAttribute(ATTR_DELAY) == true { // only in this case not to eval const, namely, delayed + return n, TRANS_CONTINUE + } + //bxt := evalStaticTypeOf(store, last, n) + //if isUntyped(bxt) { // delay determine type and value(const) + //} + } + //debug.Println("---before eval const") cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { // left untyped const -> right not const @@ -1044,6 +1055,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { at := evalStaticTypeOf(store, last, n.Args[0]) switch arg0 := n.Args[0].(type) { case *ConstExpr: + debug.Println("---constExpr: ", arg0) // check legal type for nil if arg0.IsUndefined() { switch ct.Kind() { // special case for nil conversion check. refer to 0f47a @@ -1085,14 +1097,35 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isUntyped(at) { // only when untyped, this is checked in checkOrConvertType too, but guard here switch arg0.Op { case EQL, NEQ, LSS, GTR, LEQ, GEQ: // refer to 10a0012. TODO: convert to typed too + checkAssignableTo(at, ct, true) break // quick forward default: checkOrConvertType(store, last, &n.Args[0], ct, false, true) + ////// TODO: evalConst for already typed shift expr + //debug.Printf("len of n.Args: %v \n", len(n.Args)) + //debug.Printf("before eval const n.Args[0]: %v \n", n.Args[0]) + //_, lic := arg0.Left.(*ConstExpr) + //_, ric := arg0.Right.(*ConstExpr) + //if lic && ric { + // n.Args[0] = evalConst(store, last, n.Args[0]) + //} + //debug.Printf("after eval const n.Args[0]: %v \n", n.Args[0]) } } case *UnaryExpr: + debug.Println("---unary expr: ", arg0) if isUntyped(at) { checkOrConvertType(store, last, &n.Args[0], ct, false, true) + //_, xic := arg0.X.(*ConstExpr) + //debug.Printf("len of n.Args: %v \n", len(n.Args)) + //debug.Println("---delay process unaryExpr") + //if xic { + // debug.Printf("before eval const n.Args[0]: %v \n", n.Args[0]) + // //n.Args[0] = evalConst(store, last, n.Args[0]) + // //debug.Printf("after eval const n.Args[0]: %v \n", n.Args[0]) + //} + } else { + debug.Printf("---unary, at is typed: %v \n", at) } default: // do nothing @@ -1317,7 +1350,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *UnaryExpr: xt := evalStaticTypeOf(store, last, n.X) - n.AssertCompatible(xt, nil) + n.AssertCompatible(store, last, xt, nil, nil) if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. @@ -2295,6 +2328,7 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { + debug.Printf("---evalConst, x: %v \n", x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) @@ -2442,6 +2476,12 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if debug { debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) } + defer func() { + if r := recover(); r != nil { + debug.Printf("---recover in checkOrConvertType, r: %v \n", r) + panic(r) + } + }() if cx, ok := (*x).(*ConstExpr); ok { if !coerce { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint @@ -2468,27 +2508,61 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // if conduct explicit conversion on typed shift, set coerce to be true, this always happens in callExpr. xt := evalStaticTypeOf(store, last, *x) if debug { - debug.Printf("shift, xt: %v, Op: %v, t: %v \n", *x, bx.Op, t) + debug.Printf("shift, xt: %v, Op: %v, t: %v \n", xt, bx.Op, t) } + + //lt := evalStaticTypeOf(store, last, bx.Left) + //rt := evalStaticTypeOf(store, last, bx.Right) + // going to check if shift expr is compatible with type from outer context + var originType Type if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { + originType = xt t = defaultTypeOf(xt) + //t = defaultTypeOf(lt) + } else if xt == nil { + originType = nil } else { - return // is x is typed and dest t is nil or interface type(even for type cast), do nothing. + //return // is x is typed and dest t is nil or interface type(even for type cast), do nothing. + bx.checkShiftExpr(xt, true) + // return? } + } else { + originType = t } + + debug.Printf("---origin type for untyped shift is: %v \n", originType) + debug.Printf("---dest type for untyped shift is: %v \n", t) + debug.Println("xt == nil? ", xt == nil) // deal with binary expr(bx.Left), determine its type - if coerce || !coerce && isUntyped(xt) { + if coerce || !coerce && isUntyped(xt) || xt == nil { // XXX, simplify? // coerce mostly when explicitly conversion, type call, while arg is binary expr // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 // TODO: do we need this any more? since already checked before? // NO, it's from callExpr and should checked recursively? huh? - lt := evalStaticTypeOf(store, last, bx.Left) - rt := evalStaticTypeOf(store, last, bx.Right) - bx.AssertCompatible(lt, rt, t) - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + // XXX, no need for this, already check assignable in checkOrConvertType + // check against dest type from outer context + //bx.AssertCompatible(t, t) + bx.checkShiftExpr(originType, true) + debug.Println("---going to eval delayed const shift expr") + // eval const for delayed shift expr + if _, ok := (*x).(*ConstExpr); !ok { + debug.Println("---not const") + _, lic := bx.Left.(*ConstExpr) + _, ric := bx.Right.(*ConstExpr) + if lic && ric { + *x = evalConst(store, last, *x) + } + } + debug.Printf("---after eval, *x: %v \n", *x) + + if _, ok := (*x).(*ConstExpr); ok { + //checkOrConvertType(store, last, x, t, autoNative, coerce) + } else { + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) + } } else { // not coerce, xt is typed, no need to convert but check. refer to 10a17b1. checkAssignableTo(xt, t, false) // refer to 0_a_2.gno, 0_a_3.gno } @@ -2507,9 +2581,22 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } if coerce || !coerce && isUntyped(xt) { uxt := evalStaticTypeOf(store, last, ux.X) - ux.AssertCompatible(uxt, t) - // "push" expected type into shift binary's left operand. + ux.AssertCompatible(store, last, uxt, xt, t) + // recursively check leaf node checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) + debug.Printf("---after checkOrConvertType for unaryExpr, ux: %v \n", ux) + + // check ux against t + if _, ok := (ux.X).(*ConstExpr); ok { + // re-eval ux + nux := evalConst(store, last, *x) + debug.Println("---nux: ", nux) + nxt := evalStaticTypeOf(store, last, ux) + debug.Println("---nxt: ", nxt) + checkAssignableTo(nxt, t, false) // this is not all right, should check convertible + debug.Println("---t: ", t) + convertConst(store, last, nux, t) // or just check convertible? + } } else { checkAssignableTo(xt, t, false) } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 274f3c43893..c2f0e8a95a0 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -58,79 +58,40 @@ var ( type category int const ( - IsInvalid category = 0 IsBoolean category = 1 << iota IsInteger - IsUnsigned IsFloat IsString IsBigInt IsBigDec - IsRune - IsNumeric = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec + IsNumeric = IsInteger | IsFloat | IsBigInt | IsBigDec IsOrdered = IsNumeric | IsString - //IsIntOrFloat = IsInteger | IsUnsigned | IsFloat | IsBigInt | IsBigDec ) -// category makes it more convenient than compare with types -func (pt PrimitiveType) predicate() category { - switch pt { - case InvalidType: - return IsInvalid - case UntypedBoolType: +func (pt PrimitiveType) category() category { + switch pt.Kind() { + case BoolKind: return IsBoolean - case BoolType: - return IsBoolean - case UntypedStringType: - return IsString - case StringType: + case StringKind: return IsString - case IntType: - return IsInteger - case Int8Type: - return IsInteger - case Int16Type: - return IsInteger - case UntypedRuneType: // TODO: this is treat as DataByteType, GUESS, refer to op_inc_dec - return IsRune - case Int32Type: - return IsInteger - case Int64Type: - return IsInteger - case UintType: - return IsUnsigned - case Uint8Type: - return IsUnsigned - case DataByteType: - return IsUnsigned // TODO: consider this - case Uint16Type: - return IsUnsigned - case Uint32Type: - return IsUnsigned - case Uint64Type: - return IsUnsigned - case Float32Type: - return IsFloat - case Float64Type: + case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind, UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind: + return IsInteger // UntypedRuneType is int32kind, DataByteType is uint8 kind + case Float32Kind, Float64Kind: return IsFloat - case UntypedBigintType: + case BigintKind: return IsBigInt - case BigintType: - return IsBigInt - case UntypedBigdecType: - return IsBigDec - case BigdecType: + case BigdecKind: return IsBigDec default: - panic(fmt.Sprintf("unexpected primitive type %d", pt)) + panic(fmt.Sprintf("unexpected primitive type %v", pt)) } } func isOrdered(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsOrdered != 0 || t.predicate()&IsRune != 0 { + if t.category()&IsOrdered != 0 { return true } return false @@ -142,7 +103,7 @@ func isOrdered(t Type) bool { func isBoolean(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsBoolean != 0 { + if t.category()&IsBoolean != 0 { return true } return false @@ -155,7 +116,7 @@ func isBoolean(t Type) bool { func isNumeric(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsRune != 0 { + if t.category()&IsNumeric != 0 { return true } return false @@ -164,11 +125,11 @@ func isNumeric(t Type) bool { } } -// signed or unsigned int +// TODO: also compatible with 1.0, 2.0... func isIntNum(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsInteger != 0 || t.predicate()&IsUnsigned != 0 || t.predicate()&IsBigInt != 0 || t.predicate()&IsRune != 0 { + if t.category()&IsInteger != 0 || t.category()&IsBigInt != 0 { return true } return false @@ -180,7 +141,7 @@ func isIntNum(t Type) bool { func isNumericOrString(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.predicate() != IsInvalid && t.predicate()&IsNumeric != 0 || t.predicate()&IsString != 0 || t.predicate()&IsRune != 0 { + if t.category()&IsNumeric != 0 || t.category()&IsString != 0 { return true } return false @@ -284,8 +245,6 @@ func assertAssignable(lt, rt Type) { // assertComparable is used in preprocess. // assert value with dt is comparable // special case when both typed, check if type identical -// TODO: move this to type_checker? as a method? -// TODO: check mismatch on this, not postpone to checkOrConvertType func assertComparable(xt, dt Type) { if debug { debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) @@ -294,29 +253,13 @@ func assertComparable(xt, dt Type) { case PrimitiveType: // both typed primitive types if _, ok := baseOf(xt).(PrimitiveType); ok { - //var isMixed bool - //if _, ok := xt.(*NativeType); ok { - // if _, ok := dt.(*NativeType); ok { - // isMixed = false - // } else { - // isMixed = true - // } - //} else { - // if _, ok := dt.(*NativeType); ok { - // isMixed = true - // } - //} - //if !isMixed { // both not native or both native we can check typeID == if !isUntyped(xt) && !isUntyped(dt) { // in this stage, lt or rt maybe untyped, not converted yet - debug.Println("---both typed") if xt != nil && dt != nil { - // TODO: filter byte that has no typeID? if xt.TypeID() != dt.TypeID() { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", xt, dt)) } } } - //} } case *ArrayType: // NOTE: no recursive allowed switch baseOf(cdt.Elem()).(type) { @@ -718,61 +661,43 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // checkOrConvertType() operation to optimize performance. // dt is a special case for binary expr that the dest type for the -// lhs determined by outer context -func (bx *BinaryExpr) AssertCompatible(lt, rt, dt Type) { - debug.Printf("---AssertCompatible, bx: %v \n", bx) - debug.Printf("---AssertCompatible, bx.Left: %T \n", bx.Left) - debug.Printf("---AssertCompatible, bx.Right: %T \n", bx.Right) - - // get left type and right type - //lt := evalStaticTypeOf(store, last, bx.Left) - //rt := evalStaticTypeOf(store, last, bx.Right) +// shift expr is determined by outer context +func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { + debug.Printf("---AssertCompatible, bx: %v, lt: %v, rt: %v \n", bx, lt, rt) // we can't check compatible with native types // at current stage, so leave it to checkOrConvertType - // to secondary call this assert logic again - - //var leftNative, rightNative bool + // to convert gonative to gno, and AssertCompatible + // would be called again for that check if lnt, ok := lt.(*NativeType); ok { - debug.Println("---lt native") - //leftNative = true _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) if ok { - debug.Println("---lt native primitive, return") return } } if rnt, ok := rt.(*NativeType); ok { - //rightNative = true - debug.Println("---rt native, gnoType", rnt.gnoType) _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) // TODO: check kind instead if ok { - debug.Println("---right native primitive, return") return } } - debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, bx.Op) escapedOpStr := strings.Replace(wordTokenStrings[bx.Op], "%", "%%", 1) if isComparison(bx.Op) { switch bx.Op { case EQL, NEQ: - assertComparable(lt, rt) - // XXX, should not check compatible for equality compare? - // the native type here are both non-primitive - // not able to check assignable, e.g. MyError == err, that if left satisfied right native interface. - //if !leftNative && !rightNative { cmp := cmpSpecificity(lt, rt) if cmp <= 0 { + assertComparable(lt, rt) checkAssignableTo(lt, rt, true) } else { + assertComparable(rt, lt) checkAssignableTo(rt, lt, true) } - //} case LSS, LEQ, GTR, GEQ: if pred, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(lt, rt, pred, escapedOpStr, dt) + bx.checkCompatibility(lt, rt, pred, escapedOpStr) } else { panic("should not happen") } @@ -780,25 +705,27 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt, dt Type) { panic("invalid comparison operator") } } else { - // TODO: if not assign, check implicit compatible if pred, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(lt, rt, pred, escapedOpStr, dt) + bx.checkCompatibility(lt, rt, pred, escapedOpStr) } else { panic("should not happen") } switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: - // if both typed - //if !isMixed { // both native or both not native that we can check - if !isUntyped(lt) && !isUntyped(rt) { - if lt != nil && rt != nil { // NOTE: is this necessary? - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) - } - } - } + //if !isUntyped(lt) && !isUntyped(rt) { // both typed + // if lt != nil && rt != nil { + // if lt.TypeID() != rt.TypeID() { + // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + // } + // } + //} + //if isUntyped(lt) && isUntyped(rt) { // both untyped + // if lt.TypeID() != rt.TypeID() { + // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + // } //} + // special case of zero divisor if isQuoOrRem(bx.Op) { if rcx, ok := bx.Right.(*ConstExpr); ok { @@ -813,24 +740,53 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt, dt Type) { } } -func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, escapedOpStr string, dt Type) { - debug.Println("---checkCompatibility, op: ", bx.Op) - debug.Printf("---checkCompatibility, lt: %v, rt: %v \n", lt, rt) - debug.Printf("---checkCompatibility, dt: %v \n", dt) +// for a shift expression, dt would be either the type of lhs +// or the type of the outer context that would be used as the +// type of the shift expr when it's untyped +func (bx *BinaryExpr) checkShiftExpr(dt Type, isFinal bool) { + debug.Printf("---checkShiftExpr: dt: %v, isFinal: %t \n", dt, isFinal) + var destKind interface{} + if dt != nil { + destKind = dt.Kind() + } + if pred, ok := binaryChecker[bx.Op]; ok { + if !pred(dt) { + if !isFinal { + // just tag it for delayed determine + bx.SetAttribute(ATTR_DELAY, true) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) + } + } + } else { + panic("should not happen") + } +} + +func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, escapedOpStr string) { + debug.Printf("---checkCompatibility, op: %v, lt: %v, rt: %v\n", bx.Op, lt, rt) + // cache it and can be used by later stage in checkOrConvertType AssignableCheckCache = NewAssignabilityCache() + var destKind interface{} - // shl/shr + // for shl/shr, it's type might be delayed determined by its context + // if it's originally untyped if bx.Op == SHL || bx.Op == SHR { - if dt == nil { - dt = lt - } - if dt != nil { - destKind = dt.Kind() + // check compatible within shift expr + if lt != nil { + destKind = lt.Kind() } - if !pred(dt) { + if !pred(lt) { panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } + //// check against type from outer context + //if isUntyped(bxt) { // source shl/shr expr is untyped + // if dt != nil { + // // check assignableTo dt + // checkAssignableTo(bxt, dt, true) + // } + //} return } @@ -853,7 +809,7 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es // if cmp < 0, means potential conversion // from left to right, so check assignable // if cmp > 0, means potential conversion to - // left side that is not compatible, so stop + // left side which is not compatible, so stop // the check here, assertion fail. if cmp < 0 { checkAssignableTo(lt, rt, true) @@ -892,6 +848,13 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es } } } + + //if isUntyped(lt) && isUntyped(rt) { // both untyped + // if lt.TypeID() != rt.TypeID() { + // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + // } + //} + // check even when both side compatible with op // it's ok since checkCompatibility only for lss, add, etc // that only with isOrdered @@ -904,8 +867,8 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es } } -func (ux *UnaryExpr) AssertCompatible(uxt, dt Type) { - debug.Printf("---AssertCompatible, ux: %v \n", ux) +func (ux *UnaryExpr) AssertCompatible(store Store, last BlockNode, uxt, xt, dt Type) { + debug.Printf("---AssertCompatible, ux: %v, uxt: %v,xt: %v, dt: %v \n", ux, uxt, xt, dt) debug.Printf("---AssertCompatible, ux.X: %T \n", ux.X) var destKind interface{} @@ -916,7 +879,6 @@ func (ux *UnaryExpr) AssertCompatible(uxt, dt Type) { // at current stage, so leave it to checkOrConvertType // to secondary call this assert logic again if _, ok := uxt.(*NativeType); ok { - debug.Println("---left native, return") return } @@ -931,6 +893,24 @@ func (ux *UnaryExpr) AssertCompatible(uxt, dt Type) { } panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[ux.Op], destKind)) } + + // check outer type against ux + // e.g. uint64(-4) + //if dt != nil { + // destKind = dt.Kind() + // if !pred(dt) { + // panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[ux.Op], destKind)) + // } + // + // //if _, ok := ux.X.(*BinaryExpr); ok { + // // ux.X = evalConst(store, last, ux.X) + // //} + // // + // //xt := evalStaticTypeOf(store, last, ux) + // //debug.Printf("---new xt: %v \n", xt) + // //// check assignableTo dt + // checkAssignableTo(xt, dt, true) + //} } else { panic("should not happen") } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 5fa3d73282b..72a39a806d3 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2115,6 +2115,7 @@ func isDataByte(t Type) bool { // TODO move untyped const stuff to preprocess.go. // TODO associate with ConvertTo() in documentation. func defaultTypeOf(t Type) Type { + debug.Printf("---defaultTypeOf, t: %v \n", t) switch t { case UntypedBoolType: return BoolType diff --git a/gnovm/tests/debug/0f2_filetest.gno b/gnovm/tests/debug/0f2_filetest.gnoa similarity index 100% rename from gnovm/tests/debug/0f2_filetest.gno rename to gnovm/tests/debug/0f2_filetest.gnoa diff --git a/gnovm/tests/debug/10a001_filetest.gnoa b/gnovm/tests/debug/10a001_filetest.gnoa new file mode 100644 index 00000000000..3af624a1d2f --- /dev/null +++ b/gnovm/tests/debug/10a001_filetest.gnoa @@ -0,0 +1,9 @@ +package main + +func main() { + r := uint64(1<<2 == 1>>2) + println(r) +} + +// Error: +// main/files/types2/10a001_filetest.gno:4: cannot convert BoolKind to Uint64Kind \ No newline at end of file diff --git a/gnovm/tests/debug/10a14_filetest.gno b/gnovm/tests/debug/10a14_filetest.gno new file mode 100644 index 00000000000..30769935953 --- /dev/null +++ b/gnovm/tests/debug/10a14_filetest.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + r := a << 1 + println(r) +} + +// Error: +// main/debug/10a14_filetest.gno:5: operator << not defined on: StringKind diff --git a/gnovm/tests/debug/10a27e.gnoa b/gnovm/tests/debug/10a27e.gnoa new file mode 100644 index 00000000000..d0e8658372c --- /dev/null +++ b/gnovm/tests/debug/10a27e.gnoa @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64(-(1 << 2) << x) + println(y) + fmt.Printf("%T \n", y) +} + +// Error: +// main/debug/10a27e.gno:7: bigint underflows target kind diff --git a/gnovm/tests/debug/15b.gnoa b/gnovm/tests/debug/15b.gnoa new file mode 100644 index 00000000000..4cb0b57fb09 --- /dev/null +++ b/gnovm/tests/debug/15b.gnoa @@ -0,0 +1,30 @@ +package main + +// 1. find where shift expr is used +// a) type cast +// b) assign stmt +// c) composite literals + +// 2. get the dest type, if convert condition, convert +// condition: +// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get +// attr: HAS_SHIFT to determine if has shift. + +// 3. in type func, find termination condition when not const +// this condition should be the opposite of the convert condition + +// TODO: composite literal +// TODO: simple print non-const untyped + +func main() { + type S struct { + a float32 + } + s := S{ + a: 1 << 2, + } + println(s.a) +} + +// Output: +// 4 diff --git a/gnovm/tests/debug/untyped.gnoa b/gnovm/tests/debug/untyped.gnoa new file mode 100644 index 00000000000..a81faceb4b0 --- /dev/null +++ b/gnovm/tests/debug/untyped.gnoa @@ -0,0 +1,11 @@ +// You can edit this code! +// Click here and start typing. +package main + +func main() { + println(int64(1.0 << 1)) + //println(int64(1.0)) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types2/10a27c.gno b/gnovm/tests/files/types2/10a27c.gno index 56de66d8caf..99dc9bf7a70 100644 --- a/gnovm/tests/files/types2/10a27c.gno +++ b/gnovm/tests/files/types2/10a27c.gno @@ -9,5 +9,6 @@ func main() { fmt.Printf("%T \n", y) } -// Error: -// main/files/types2/10a27c.gno:7: operator << not defined on: BigdecKind +// Output: +// 18446744073709549568 +// uint64 diff --git a/gnovm/tests/files/types2/27a_filetest.gno b/gnovm/tests/files/types2/27a_filetest.gno index 2f4394dc400..8490c751c88 100644 --- a/gnovm/tests/files/types2/27a_filetest.gno +++ b/gnovm/tests/files/types2/27a_filetest.gno @@ -6,5 +6,5 @@ func main() { println(y) } -// Error: -// main/files/types2/27a_filetest.gno:5: operator << not defined on: BigdecKind +// Output: +// 2048 From 7bd03e16e01b9603f0b52aadad365a68a4221d05 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Mar 2024 16:16:05 +0800 Subject: [PATCH 107/193] cache better; clear unused logic --- gnovm/pkg/gnolang/preprocess.go | 17 +- gnovm/pkg/gnolang/store.go | 76 ++++-- gnovm/pkg/gnolang/type_check.go | 340 ++++++++++----------------- gnovm/tests/debug/0a2_filetest.gno | 25 ++ gnovm/tests/debug/10a14_filetest.gno | 10 - 5 files changed, 206 insertions(+), 262 deletions(-) create mode 100644 gnovm/tests/debug/0a2_filetest.gno delete mode 100644 gnovm/tests/debug/10a14_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 96cf4ad5ade..09929e2eeeb 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -98,7 +98,6 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // are only called during the preprocessing stage. // It is a counter because Preprocess() is recursive. var preprocessing int -var AssignableCheckCache *AssignabilityCache // Preprocess n whose parent block node is ctx. If any names // are defined in another file, generally you must call @@ -123,7 +122,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { preprocessing += 1 defer func() { preprocessing -= 1 - AssignableCheckCache = nil }() } @@ -769,7 +767,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return resn, TRANS_CONTINUE } } else { - n.AssertCompatible(lt, rt) + n.AssertCompatible(store, lt, rt) } // General case. @@ -1350,7 +1348,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *UnaryExpr: xt := evalStaticTypeOf(store, last, n.X) - n.AssertCompatible(store, last, xt, nil, nil) + n.AssertCompatible(xt, nil) if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. @@ -1767,7 +1765,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } } else { - // TODO: should also check assign with checkAssignableTo, like var e error, e = 1 n.AssertCompatible(store, last) if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { if len(n.Lhs) != 1 || len(n.Rhs) != 1 { @@ -2476,9 +2473,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if debug { debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) } + // pop up to preprocess to handle defer func() { if r := recover(); r != nil { - debug.Printf("---recover in checkOrConvertType, r: %v \n", r) panic(r) } }() @@ -2491,7 +2488,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). // this is for binaryExpr that assignable has already been checked and cached - if AssignableCheckCache != nil && AssignableCheckCache.Exists(*x, t) { + if store.AssertAssignableExists(*x, t) { debug.Printf("---assignable already set for: %v => %v \n", cx, t) } else { // still need for non-binary, like arg @@ -2514,6 +2511,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative //lt := evalStaticTypeOf(store, last, bx.Left) //rt := evalStaticTypeOf(store, last, bx.Right) // going to check if shift expr is compatible with type from outer context + + // used to check compatible rather than check on a converted type(default type) + // e.g. 1.0 % 2, should show err msg of bigDecKind not the float32Kind var originType Type if _, ok := t.(*InterfaceType); ok || t == nil { if isUntyped(xt) { @@ -2580,8 +2580,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } } if coerce || !coerce && isUntyped(xt) { - uxt := evalStaticTypeOf(store, last, ux.X) - ux.AssertCompatible(store, last, uxt, xt, t) + ux.AssertCompatible(xt, t) // recursively check leaf node checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) debug.Printf("---after checkOrConvertType for unaryExpr, ux: %v \n", ux) diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index 24aff4936f3..17510f180b3 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -24,6 +24,8 @@ type Store interface { SetCachePackage(*PackageValue) GetPackageRealm(pkgPath string) *Realm SetPackageRealm(*Realm) + AddAssignableCheckResult(key Expr, value Type) + AssertAssignableExists(key Expr, value Type) bool GetObject(oid ObjectID) Object GetObjectSafe(oid ObjectID) Object SetObject(Object) @@ -61,17 +63,18 @@ type Store interface { // Used to keep track of in-mem objects during tx. type defaultStore struct { - alloc *Allocator // for accounting for cached items - pkgGetter PackageGetter // non-realm packages - cacheObjects map[ObjectID]Object - cacheTypes map[TypeID]Type - cacheNodes map[Location]BlockNode - cacheNativeTypes map[reflect.Type]Type // go spec: reflect.Type are comparable - baseStore store.Store // for objects, types, nodes - iavlStore store.Store // for escaped object hashes - pkgInjector PackageInjector // for injecting natives - go2gnoMap map[string]string // go pkgpath.name -> gno pkgpath.name - go2gnoStrict bool // if true, native->gno type conversion must be registered. + alloc *Allocator // for accounting for cached items + pkgGetter PackageGetter // non-realm packages + cacheObjects map[ObjectID]Object + cacheTypes map[TypeID]Type + cacheNodes map[Location]BlockNode + cacheNativeTypes map[reflect.Type]Type // go spec: reflect.Type are comparable + cacheAssignableCheck map[string]map[string]bool + baseStore store.Store // for objects, types, nodes + iavlStore store.Store // for escaped object hashes + pkgInjector PackageInjector // for injecting natives + go2gnoMap map[string]string // go pkgpath.name -> gno pkgpath.name + go2gnoStrict bool // if true, native->gno type conversion must be registered. // transient opslog []StoreOp // for debugging and testing. @@ -80,17 +83,18 @@ type defaultStore struct { func NewStore(alloc *Allocator, baseStore, iavlStore store.Store) *defaultStore { ds := &defaultStore{ - alloc: alloc, - pkgGetter: nil, - cacheObjects: make(map[ObjectID]Object), - cacheTypes: make(map[TypeID]Type), - cacheNodes: make(map[Location]BlockNode), - cacheNativeTypes: make(map[reflect.Type]Type), - baseStore: baseStore, - iavlStore: iavlStore, - go2gnoMap: make(map[string]string), - go2gnoStrict: true, - current: make(map[string]struct{}), + alloc: alloc, + pkgGetter: nil, + cacheObjects: make(map[ObjectID]Object), + cacheTypes: make(map[TypeID]Type), + cacheNodes: make(map[Location]BlockNode), + cacheNativeTypes: make(map[reflect.Type]Type), + cacheAssignableCheck: make(map[string]map[string]bool), + baseStore: baseStore, + iavlStore: iavlStore, + go2gnoMap: make(map[string]string), + go2gnoStrict: true, + current: make(map[string]struct{}), } InitStoreCaches(ds) return ds @@ -198,6 +202,33 @@ func (ds *defaultStore) GetPackage(pkgPath string, isImport bool) *PackageValue return nil } +func (ds *defaultStore) AddAssignableCheckResult(key Expr, value Type) { + if ds.cacheAssignableCheck[key.String()] == nil { + ds.cacheAssignableCheck[key.String()] = make(map[string]bool) + } + var destTypeStr string + if value != nil { + destTypeStr = value.String() + } else { + destTypeStr = "" + } + ds.cacheAssignableCheck[key.String()][destTypeStr] = true +} + +func (ds *defaultStore) AssertAssignableExists(key Expr, value Type) bool { + if valSet, ok := ds.cacheAssignableCheck[key.String()]; ok { + // Check if the value exists in the set + var destTypeStr string + if value != nil { + destTypeStr = value.String() + } else { + destTypeStr = "" + } + return valSet[destTypeStr] + } + return false +} + // Used to set throwaway packages. func (ds *defaultStore) SetCachePackage(pv *PackageValue) { oid := ObjectIDFromPkgPath(pv.PkgPath) @@ -697,6 +728,7 @@ func (ds *defaultStore) ClearCache() { ds.cacheTypes = make(map[TypeID]Type) ds.cacheNodes = make(map[Location]BlockNode) ds.cacheNativeTypes = make(map[reflect.Type]Type) + ds.cacheAssignableCheck = make(map[string]map[string]bool) // restore builtin types to cache. InitStoreCaches(ds) } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index c2f0e8a95a0..9f15df1e9d8 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -15,8 +15,8 @@ var ( SUB: isNumeric, MUL: isNumeric, QUO: isNumeric, - REM: isIntNum, // in compile stage good for bigdec, that can be converted to int, `checkAssignableTo` - SHL: isIntNum, // NOTE: 1.0 << 1 is legal in Go. consistent with op_binary for now. + REM: isIntNum, + SHL: isIntNum, SHR: isIntNum, BAND: isIntNum, // bit ops XOR: isIntNum, @@ -174,7 +174,6 @@ func assertSameTypes(lt, rt Type) { } else if lt.TypeID() == rt.TypeID() { // non-nil types are identical. } else { - // panic("panic assertSameTypes") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -317,32 +316,6 @@ func assertMaybeNil(msg string, t Type) { } } -// AssignabilityCache caches the results of assignability checks. -type AssignabilityCache struct { - storage map[string]map[string]bool -} - -func NewAssignabilityCache() *AssignabilityCache { - return &AssignabilityCache{ - storage: make(map[string]map[string]bool), - } -} - -func (ac *AssignabilityCache) Add(key Expr, value Type) { - if ac.storage[key.String()] == nil { - ac.storage[key.String()] = make(map[string]bool) - } - ac.storage[key.String()][value.String()] = true -} - -func (ac *AssignabilityCache) Exists(key Expr, value Type) bool { - if valSet, ok := ac.storage[key.String()]; ok { - // Check if the value exists in the set - return valSet[value.String()] - } - return false -} - // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. @@ -355,23 +328,17 @@ func (ac *AssignabilityCache) Exists(key Expr, value Type) bool { // case 4. general cases for primitives and composite. // XXX. the name of checkAssignableTo should be considered. // we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime -// TODO: make it (t Type) CheckAssignableTo -// TODO: make cmp specificity here +// XXX: make it (t Type) CheckAssignableTo? func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { if debug { debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) } // case0 - if xt == nil { // refer to 0f18_filetest - // XXX, this seems duplicated with assertComparable - //assertMaybeNil("invalid operation, nil can not be compared to", dt) - return - } - if dt == nil { // refer to assign8.gno + if xt == nil || dt == nil { // see 0f18, assign8.gno return } // case3 - if dt.Kind() == InterfaceKind { + if dt.Kind() == InterfaceKind { // note native interface debug.Println("---dt: ", dt) debug.Println("---baseOf dt: ", baseOf(dt)) debug.Println("---dt.Kind: ", dt.Kind()) @@ -646,13 +613,40 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // =========================================================== -// TODO: expand this -//type Checker struct { -//} +// type_check for shift expr is a `delayed check`, it has two stages: +// stage1. check on first encounter of a shift expr, if it asserts to be good, pass, +// and if it has const on both side, evalConst, e.g. float32(1 << 4) is legal. +// or if it fails assertion, e.g. uint64(1.0 << 1), tag it to be delayed, to be handled +// on stage2. +// stage2. when an untyped shift expr is used in somewhere, e.g. uint64(1.0 << 1), +// uint64 is used as the potential type of this expr, so uint64(1.0 << 1) is a +// valid representation. +// so dt would be either the type of lhs or the type from outer context. +// isFinal indicates whether it's first check or final check(this happens in checkOrConvertType) + +// XXX, is this logic only for this special case? +func (bx *BinaryExpr) checkShiftExpr(dt Type, isFinal bool) { + debug.Printf("---checkShiftExpr: dt: %v, isFinal: %t \n", dt, isFinal) + var destKind interface{} + if dt != nil { + destKind = dt.Kind() + } + if checker, ok := binaryChecker[bx.Op]; ok { + if !checker(dt) { + if !isFinal { + // just tag it for delayed determination + bx.SetAttribute(ATTR_DELAY, true) + } else { + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) + } + } + } else { + panic("should not happen") + } +} -// check both sides since no aware of which side is dest type -// that lt not compatible but rt is compatible would be good -// things like this would fail: 1.0 % 1, bigInt has a bigger specificity than bidDec. +// check both sides since no aware of which side is dest type, +// that lt not compatible but rt is compatible would be good. // AssertCompatible works as a pre-check prior to checkOrConvertType() // It checks expressions to ensure the compatibility between operands and operators. @@ -660,15 +654,16 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. -// dt is a special case for binary expr that the dest type for the -// shift expr is determined by outer context -func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { +// things like this would fail: 1.0 % 1, bigInt has a bigger specificity than bidDec. +func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { debug.Printf("---AssertCompatible, bx: %v, lt: %v, rt: %v \n", bx, lt, rt) - - // we can't check compatible with native types - // at current stage, so leave it to checkOrConvertType - // to convert gonative to gno, and AssertCompatible - // would be called again for that check + // we can't check compatible with native types at current stage, + // so leave it to later operations(trans_leave on binaryExpr) + // to be converted into gno(only for primitive types), and do + // this check again. (AssertCompatible would be invoked again) + // non-primitive types is a special case that is not handled + // (not needed at all?), or it might be expanded to check for case + // like a gno declared type implement a native interface? if lnt, ok := lt.(*NativeType); ok { _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) if ok { @@ -676,7 +671,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } if rnt, ok := rt.(*NativeType); ok { - _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) // TODO: check kind instead + _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) if ok { return } @@ -687,17 +682,17 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { if isComparison(bx.Op) { switch bx.Op { case EQL, NEQ: - cmp := cmpSpecificity(lt, rt) + cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion if cmp <= 0 { - assertComparable(lt, rt) - checkAssignableTo(lt, rt, true) + assertComparable(lt, rt) // only check if dest type is comparable + checkAssignableTo(lt, rt, true) // check if src type is assignable to dest type } else { assertComparable(rt, lt) checkAssignableTo(rt, lt, true) } case LSS, LEQ, GTR, GEQ: - if pred, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(lt, rt, pred, escapedOpStr) + if checker, ok := binaryChecker[bx.Op]; ok { + bx.checkCompatibility(store, lt, rt, checker, escapedOpStr) } else { panic("should not happen") } @@ -705,27 +700,14 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { panic("invalid comparison operator") } } else { - if pred, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(lt, rt, pred, escapedOpStr) + if checker, ok := binaryChecker[bx.Op]; ok { + bx.checkCompatibility(store, lt, rt, checker, escapedOpStr) } else { panic("should not happen") } switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: - //if !isUntyped(lt) && !isUntyped(rt) { // both typed - // if lt != nil && rt != nil { - // if lt.TypeID() != rt.TypeID() { - // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) - // } - // } - //} - //if isUntyped(lt) && isUntyped(rt) { // both untyped - // if lt.TypeID() != rt.TypeID() { - // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) - // } - //} - // special case of zero divisor if isQuoOrRem(bx.Op) { if rcx, ok := bx.Right.(*ConstExpr); ok { @@ -740,64 +722,22 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } -// for a shift expression, dt would be either the type of lhs -// or the type of the outer context that would be used as the -// type of the shift expr when it's untyped -func (bx *BinaryExpr) checkShiftExpr(dt Type, isFinal bool) { - debug.Printf("---checkShiftExpr: dt: %v, isFinal: %t \n", dt, isFinal) - var destKind interface{} - if dt != nil { - destKind = dt.Kind() - } - if pred, ok := binaryChecker[bx.Op]; ok { - if !pred(dt) { - if !isFinal { - // just tag it for delayed determine - bx.SetAttribute(ATTR_DELAY, true) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) - } - } - } else { - panic("should not happen") - } -} - -func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, escapedOpStr string) { +// XXX, these kind of type_check happens before checkOrConvertType which get type conversion all +// sorted out, kinda make the type check logic complex, for we have to deal with much undetermined +// types. the upside for this is it quick fails the incompatibility before concrete type conversion +// happens in checkOrConvertType, but does this weigh out the complexity it brings in? +// TODO: maybe should simplify this to only check dt and left other work to checkOrConvertType +func (bx *BinaryExpr) checkCompatibility(store Store, lt, rt Type, checker func(t Type) bool, escapedOpStr string) { debug.Printf("---checkCompatibility, op: %v, lt: %v, rt: %v\n", bx.Op, lt, rt) - // cache it and can be used by later stage in checkOrConvertType - AssignableCheckCache = NewAssignabilityCache() - + // cache it to be reused in later stage in checkOrConvertType var destKind interface{} - - // for shl/shr, it's type might be delayed determined by its context - // if it's originally untyped - if bx.Op == SHL || bx.Op == SHR { - // check compatible within shift expr - if lt != nil { - destKind = lt.Kind() - } - if !pred(lt) { - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) - } - //// check against type from outer context - //if isUntyped(bxt) { // source shl/shr expr is untyped - // if dt != nil { - // // check assignableTo dt - // checkAssignableTo(bxt, dt, true) - // } - //} - return - } - - // other cases - // TODO: XXX, this logic based on an assumption that one side is not defined on op - // while the other side is ok, and this side is assignable to the other side, pass - // is this general??? or the only case? - // consider 1.2 % int64(1), and 1.0 % int64 + // XXX, this logic is based on an assumption that one side is not defined on op + // while the other side is ok, and this side is assignable to the other side + // (that would be converted to the other side eventually). + // consider 1.2 % int64(1), and 1.0 % int64, is this the only scenario? cmp := cmpSpecificity(lt, rt) - if !pred(lt) { // lt not compatible with op - if !pred(rt) { // rt not compatible with op + if !checker(lt) { // lt not compatible with op + if !checker(rt) { // rt not compatible with op if lt != nil { // return error on left side that is checked first destKind = lt.Kind() } @@ -808,135 +748,103 @@ func (bx *BinaryExpr) checkCompatibility(lt, rt Type, pred func(t Type) bool, es // cmp means the expected convert direction // if cmp < 0, means potential conversion // from left to right, so check assignable + // from left to right. // if cmp > 0, means potential conversion to - // left side which is not compatible, so stop - // the check here, assertion fail. + // left side which is already asserted to be + // not compatible, so assert fail. + // no check for cmp == 0 since no possible they have + // same specificity with one side is compatible + // and the other is not while assert to be assignable. + // e.g. "a" - 1. if cmp < 0 { checkAssignableTo(lt, rt, true) - debug.Println("---assignable") - // cache, XXX, is this needed? - AssignableCheckCache.Add(bx.Left, rt) + store.AddAssignableCheckResult(bx.Left, rt) } else { - if lt != nil { // return error on left side that is checked first + if lt != nil { destKind = lt.Kind() } panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } } - } else if !pred(rt) { // if left is compatible, right is not - // we don't need to check cmp == 0, for instance like 1 - "a", - // xxx, the fact of one of them is compatible while the other is not - // when they share same specificity implies not assignable? + } else if !checker(rt) { // left is compatible, right is not if cmp > 0 { // right to left checkAssignableTo(rt, lt, true) - AssignableCheckCache.Add(bx.Right, lt) + store.AddAssignableCheckResult(bx.Right, lt) } else { - if rt != nil { // return error on left side that is checked first + if rt != nil { destKind = rt.Kind() } panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } } else { // both good - // TODO: both untyped or both typed + // only check both typed. + // should not check on both untyped case TypeID equality, e.g. + // MaxRune = '\U0010FFFF' + // MaxRune + 1 + // that left type is untyped rune with default type of Int32Type + // and right type is untyped bigInt can be converted to int32 too. if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet // check when both typed - if lt != nil && rt != nil { // XXX, this should already be excluded by previous pred check. + if lt != nil && rt != nil { // XXX, this should already be excluded by previous checker check. // TODO: filter byte that has no typeID? if lt.TypeID() != rt.TypeID() { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) } } } - - //if isUntyped(lt) && isUntyped(rt) { // both untyped - // if lt.TypeID() != rt.TypeID() { - // panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) - // } - //} - - // check even when both side compatible with op - // it's ok since checkCompatibility only for lss, add, etc - // that only with isOrdered + // check even when both sides are compatible with op, if cmp <= 0 { checkAssignableTo(lt, rt, true) + store.AddAssignableCheckResult(bx.Left, rt) + } else { checkAssignableTo(rt, lt, true) + store.AddAssignableCheckResult(bx.Right, lt) } - // TODO: cache } } -func (ux *UnaryExpr) AssertCompatible(store Store, last BlockNode, uxt, xt, dt Type) { - debug.Printf("---AssertCompatible, ux: %v, uxt: %v,xt: %v, dt: %v \n", ux, uxt, xt, dt) - debug.Printf("---AssertCompatible, ux.X: %T \n", ux.X) +func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { + debug.Printf("---AssertCompatible, ux: %v, xt: %v, dt: %v \n", ux, xt, dt) var destKind interface{} - - // get left type and right type - //t := evalStaticTypeOf(store, last, ux.X) - // we can't check compatible with native types - // at current stage, so leave it to checkOrConvertType - // to secondary call this assert logic again - if _, ok := uxt.(*NativeType); ok { - return + if nt, ok := xt.(*NativeType); ok { + if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { + return + } } // check compatible - if pred, ok := unaryChecker[ux.Op]; ok { + if checker, ok := unaryChecker[ux.Op]; ok { if dt == nil { - dt = uxt + dt = xt } - if !pred(dt) { + if !checker(dt) { if dt != nil { destKind = dt.Kind() } panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[ux.Op], destKind)) } - - // check outer type against ux - // e.g. uint64(-4) - //if dt != nil { - // destKind = dt.Kind() - // if !pred(dt) { - // panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[ux.Op], destKind)) - // } - // - // //if _, ok := ux.X.(*BinaryExpr); ok { - // // ux.X = evalConst(store, last, ux.X) - // //} - // // - // //xt := evalStaticTypeOf(store, last, ux) - // //debug.Printf("---new xt: %v \n", xt) - // //// check assignableTo dt - // checkAssignableTo(xt, dt, true) - //} } else { panic("should not happen") } } func (idst *IncDecStmt) AssertCompatible(t Type) { - debug.Printf("---AssertCompatible, st: %v \n", idst) - debug.Printf("---AssertCompatible, st.X: %T \n", idst.X) - debug.Printf("---AssertCompatible, st.Op: %T \n", idst.Op) + debug.Printf("---AssertCompatible, stmt: %v, t: %v, op: %v \n", idst, t, idst.Op) var destKind interface{} - // get left type and right type - //t := evalStaticTypeOf(store, last, idst.X) - - // we can't check compatible with native types - // at current stage, so leave it to checkOrConvertType - // to secondary call this assert logic again - if _, ok := t.(*NativeType); ok { - debug.Println("---left native, return") - return + if nt, ok := t.(*NativeType); ok { + if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { + return + } } // check compatible - if pred, ok := IncDecStmtChecker[idst.Op]; ok { - if !pred(t) { + if checker, ok := IncDecStmtChecker[idst.Op]; ok { + if !checker(t) { if t != nil { destKind = t.Kind() } @@ -949,43 +857,33 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { debug.Printf("---AssertCompatible, as: %v \n", as) - debug.Printf("---AssertCompatible, as len lhs: %T \n", len(as.Lhs)) - //debug.Printf("---AssertCompatible, as.X: %T \n", len(as.Lhs)) - debug.Printf("---AssertCompatible, as.Op: %v \n", as.Op) escapedOpStr := strings.Replace(wordTokenStrings[as.Op], "%", "%%", 1) - var destKind interface{} // XXX, assume lhs length is same with of rhs - // TODO: check call case? + // TODO: how about call func case? + // Call case: a, b = x(...) for i, x := range as.Lhs { lt := evalStaticTypeOf(store, last, x) rt := evalStaticTypeOf(store, last, as.Rhs[i]) - // we can't check compatible with native types - // at current stage, so leave it to checkOrConvertType - // to secondary call this assert logic again if lnt, ok := lt.(*NativeType); ok { if _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType); ok { - debug.Println("---left native, return") return } } - if rnt, ok := rt.(*NativeType); ok { if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { - debug.Println("---right native, return") return } } debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, as.Op) - // check compatible if as.Op != ASSIGN { - if pred, ok := AssignStmtChecker[as.Op]; ok { - if !pred(lt) { + if checker, ok := AssignStmtChecker[as.Op]; ok { + if !checker(lt) { if lt != nil { destKind = lt.Kind() } @@ -995,7 +893,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: // if both typed if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet - debug.Println("---both typed") if lt != nil && rt != nil { // TODO: filter byte that has no typeID? if lt.TypeID() != rt.TypeID() { @@ -1003,19 +900,20 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } + // TODO: checkAssignable default: // do nothing } } else { panic("should not happen") } - } else { - // check assignable, if done check operand with op - // XXX, always right -> left? see preprocess line1746 - // special case if rhs is(or contained) untyped shift, - // type of RHS is determined by LHS, no simply check - // assignable for this case. - checkAssignableTo(rt, lt, false) + } else if as.Op != SHR_ASSIGN && as.Op != SHL_ASSIGN { + // TODO: test on simple assign + // check assignable, after done check operand with op. + // special case if rhs is(or embedded) untyped shift, + // assignable is checked prior to this. + checkAssignableTo(rt, lt, false) // TODO: should be for all + store.AddAssignableCheckResult(as.Rhs[i], lt) } } } diff --git a/gnovm/tests/debug/0a2_filetest.gno b/gnovm/tests/debug/0a2_filetest.gno new file mode 100644 index 00000000000..b6a940f5e10 --- /dev/null +++ b/gnovm/tests/debug/0a2_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +type Error2 int + +func (e Error2) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both typed(different) const +func main() { + println(Error1(0) == Error2(0)) +} + +// Error: +// main/files/types/0a2_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/debug/10a14_filetest.gno b/gnovm/tests/debug/10a14_filetest.gno deleted file mode 100644 index 30769935953..00000000000 --- a/gnovm/tests/debug/10a14_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := "hello" - r := a << 1 - println(r) -} - -// Error: -// main/debug/10a14_filetest.gno:5: operator << not defined on: StringKind From f9517ebeeee7946e9894c820a041d917cbed9490 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Mar 2024 17:08:06 +0800 Subject: [PATCH 108/193] #cherry-pick. rm logic of check declared type against native interface, for immature and not necessary(non-primitive native types is limited, namely, has a gno version. --- gnovm/pkg/gnolang/gonative.go | 75 --------- gnovm/pkg/gnolang/preprocess.go | 155 ++++++++---------- gnovm/tests/debug/0a2_filetest.gno | 25 --- gnovm/tests/debug/issue-558b.gno | 78 +++++++++ ...{issue-558b.gno => issue-558b_stdlibs.gno} | 0 5 files changed, 146 insertions(+), 187 deletions(-) delete mode 100644 gnovm/tests/debug/0a2_filetest.gno create mode 100644 gnovm/tests/debug/issue-558b.gno rename gnovm/tests/files/{issue-558b.gno => issue-558b_stdlibs.gno} (100%) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index b90a1bc6d58..fa68b80f91c 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -899,48 +899,6 @@ func gno2GoType(t Type) reflect.Type { } } -func signaturesMatch(nativeMethod reflect.Type, gnoMethod *FuncType) bool { - debug.Printf("---signatureMatch, nativeMethodType: %v \n", nativeMethod) - debug.Printf("---signatureMatch, gnoMethodType: %v \n", gnoMethod) - debug.Printf("---signatureMatch, nativeNumIn: %v \n", nativeMethod.NumIn()) - debug.Printf("---signatureMatch, gnoNumIn: %v \n", gnoMethod.NumIn()) - debug.Printf("---signatureMatch, nativeMethodNumOut: %v \n", nativeMethod.NumOut()) - debug.Printf("---signatureMatch, gnoMethodNumOut: %v \n", gnoMethod.NumOut()) - // Adjusting for the receiver in the gnoMethod's signature - // An interface method implicitly expects a receiver, so we start comparing from the second parameter of the gnoMethod. - if nativeMethod.NumIn() != gnoMethod.NumIn() || nativeMethod.NumOut() != gnoMethod.NumOut() { - return false - } - - // Compare input parameters types, adjusting for the receiver - for i := 1; i < gnoMethod.NumIn(); i++ { - debug.Printf("nativeMethod In [%d] is: %v \n", i, nativeMethod.In(i)) - debug.Printf("gnoMethod In [%d] is: %v \n", i, gnoMethod.In(i)) - if !gno2GoTypeMatches(gnoMethod.In(i), nativeMethod.In(i)) { - //if nativeMethod.In(i-1) != gnoMethod.In(i) { - return false - } - } - - // Compare output values types - for i := 0; i < nativeMethod.NumOut(); i++ { - debug.Printf("nativeMethod Out [%d] is: %v \n", i, nativeMethod.Out(i)) - debug.Printf("gnoMethod Out [%d] is : %v \n", i, gnoMethod.Out(i)) - - if fdt, ok := gnoMethod.Out(i).(FieldType); ok { - debug.Printf("---t is field type: %v \n", fdt) - debug.Println("fdt.Type: ", fdt.Type) - debug.Println("base of fdt.Type: ", baseOf(fdt.Type)) - // TODO: more test on param/result non-primitive cases - return gno2GoTypeMatches(baseOf(fdt.Type), nativeMethod.Out(i)) - } else { - return false - } - } - - return true -} - // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). // This is called when autoNative is true in checkAssignableTo(). @@ -951,39 +909,6 @@ func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { if rt == nil { panic("should not happen") } - // TODO: - // consider the pattern, only declaredType <=> interface ? - // params/results check - if dt, ok := t.(*DeclaredType); ok { - debug.Println("dt.Name: ", dt.Name) - debug.Println("len of rt.Methods :", rt.NumMethod()) - if rt.Kind() == reflect.Interface && rt.NumMethod() != 0 { - for i := 0; i < rt.NumMethod(); i++ { - method := rt.Method(i) - m := dt.Methods[i] - if fv, ok := m.V.(*FuncValue); ok { - if string(fv.Name) == method.Name { - if ft, ok := m.T.(*FuncType); ok { - // Check if the method signatures match - if !signaturesMatch(method.Type, ft) { - fmt.Printf("Method %s has a different signature in Dog and Animal\n", method.Name) - return false - } - } else { - return false - } - } else { - return false - } - } else { - return false - } - } - debug.Println("---satisfy native interface") - return true - } - } - // special case if t == Float32Type or Float64Type if t == Float32Type { return rt.Kind() == reflect.Float32 diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 09929e2eeeb..ad374ea2475 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -805,17 +805,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } // Then, evaluate the expression. - // also for shift - if isShift { if n.GetAttribute(ATTR_DELAY) == true { // only in this case not to eval const, namely, delayed return n, TRANS_CONTINUE } - //bxt := evalStaticTypeOf(store, last, n) - //if isUntyped(bxt) { // delay determine type and value(const) - //} } - //debug.Println("---before eval const") cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { // left untyped const -> right not const @@ -828,29 +822,25 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debug.Printf("---rt: %v \n", rt) debug.Printf("---rnt: %v \n", rnt) // get concrete native base type. - pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) - if ok { - // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, false, false) - // if check pass, convert n.Right to (gno) pt type, - rn := Expr(Call(pt.String(), n.Right)) - debug.Printf("---rn : %v \n", rn) - // and convert result back. - tx := constType(n, rnt) - debug.Printf("---tx : %v \n", tx) - // reset/create n2 to preprocess right child. - n2 := &BinaryExpr{ - Left: n.Left, - Op: n.Op, - Right: rn, - } - resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} - resn = Preprocess(store, last, resn) - debug.Printf("---resn : %v \n", resn) - return resn, TRANS_CONTINUE - } else { - return n, TRANS_CONTINUE + pt := go2GnoBaseType(rnt.Type).(PrimitiveType) + // convert n.Left to pt type, + checkOrConvertType(store, last, &n.Left, pt, false, false) + // if check pass, convert n.Right to (gno) pt type, + rn := Expr(Call(pt.String(), n.Right)) + debug.Printf("---rn : %v \n", rn) + // and convert result back. + tx := constType(n, rnt) + debug.Printf("---tx : %v \n", tx) + // reset/create n2 to preprocess right child. + n2 := &BinaryExpr{ + Left: n.Left, + Op: n.Op, + Right: rn, } + resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} + resn = Preprocess(store, last, resn) + debug.Printf("---resn : %v \n", resn) + return resn, TRANS_CONTINUE // NOTE: binary operations are always computed in // gno, never with reflect. } else { @@ -917,6 +907,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // ---both not const--- if !isShift { + debug.Printf("---both not const, lt: %v, rt: %v \n", lt, rt) if lnt, ok := lt.(*NativeType); ok { debug.Println("---both not const, left is native") // If left and right are native type, @@ -924,79 +915,69 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert result back to native. // // get concrete native base type. - lpt, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) - if ok { - - // convert n.Left to (gno) pt type, - ln := Expr(Call(lpt.String(), n.Left)) - - rn := n.Right - if rnt, ok := rt.(*NativeType); ok { // e.g. native: time.Second * time.Second - rpt := go2GnoBaseType(rnt.Type).(PrimitiveType) - // check assignable, if pass, convert right to gno first - // TODO: cmp? - // XXX, can we just check on native type? - checkAssignableTo(lpt, rpt, false) // both primitive types - rn = Expr(Call(rpt.String(), n.Right)) - // checkOrCovertType should happen in future when both sides to be gno'd - } else { // rt not native - // convert n.Right to pt or uint type, - // XXX, should check from primitiveType from gonative against potentially non-primitive type - checkOrConvertType(store, last, &n.Right, lpt, false, false) - } + lpt := go2GnoBaseType(lnt.Type).(PrimitiveType) + // convert n.Left to (gno) pt type, + ln := Expr(Call(lpt.String(), n.Left)) + + rn := n.Right + if rnt, ok := rt.(*NativeType); ok { // e.g. native: time.Second * time.Second + rpt := go2GnoBaseType(rnt.Type).(PrimitiveType) + // check assignable, if pass, convert right to gno first + // TODO: cmp? + // XXX, can we just check on native type? + checkAssignableTo(lpt, rpt, false) // both primitive types + rn = Expr(Call(rpt.String(), n.Right)) + // checkOrCovertType should happen in future when both sides to be gno'd + } else { // rt not native + // convert n.Right to pt or uint type, + // XXX, should check from primitiveType from gonative against potentially non-primitive type + checkOrConvertType(store, last, &n.Right, lpt, false, false) + } - // and convert result back. - tx := constType(n, lnt) - // reset/create n2 to preprocess - // children. - n2 := &BinaryExpr{ - Left: ln, - Op: n.Op, - Right: rn, - } - resn := Node(Call(tx, n2)) - resn = Preprocess(store, last, resn) - return resn, TRANS_CONTINUE - } else { - return n, TRANS_CONTINUE + // and convert result back. + tx := constType(n, lnt) + // reset/create n2 to preprocess + // children. + n2 := &BinaryExpr{ + Left: ln, + Op: n.Op, + Right: rn, } + resn := Node(Call(tx, n2)) + resn = Preprocess(store, last, resn) + return resn, TRANS_CONTINUE // NOTE: binary operations are always // computed in gno, never with // reflect. } else if rnt, ok := rt.(*NativeType); ok { // e.g. a * time.Second debug.Println("---both not const, left not native, right native") - // If left and right are native type, // convert left and right to gno, then // convert result back to native. // // get concrete native base type. - pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) - if ok { - // convert n.Left to (gno) pt type, - rn := Expr(Call(pt.String(), n.Right)) - // convert n.Right to pt or uint type, - ln := n.Left - if isShift { - panic("should not happen") - } else { - checkOrConvertType(store, last, &n.Left, pt, false, false) - } - // and convert result back. - tx := constType(n, rnt) - // reset/create n2 to preprocess - // children. - n2 := &BinaryExpr{ - Left: ln, - Op: n.Op, - Right: rn, - } - resn := Node(Call(tx, n2)) - resn = Preprocess(store, last, resn) - return resn, TRANS_CONTINUE + pt := go2GnoBaseType(rnt.Type).(PrimitiveType) + // convert n.Left to (gno) pt type, + rn := Expr(Call(pt.String(), n.Right)) + // convert n.Right to pt or uint type, + ln := n.Left + if isShift { + panic("should not happen") } else { - return n, TRANS_CONTINUE + checkOrConvertType(store, last, &n.Left, pt, false, false) + } + // and convert result back. + tx := constType(n, rnt) + // reset/create n2 to preprocess + // children. + n2 := &BinaryExpr{ + Left: ln, + Op: n.Op, + Right: rn, } + resn := Node(Call(tx, n2)) + resn = Preprocess(store, last, resn) + return resn, TRANS_CONTINUE // NOTE: binary operations are always // computed in gno, never with // reflect. diff --git a/gnovm/tests/debug/0a2_filetest.gno b/gnovm/tests/debug/0a2_filetest.gno deleted file mode 100644 index b6a940f5e10..00000000000 --- a/gnovm/tests/debug/0a2_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - println(Error1(0) == Error2(0)) -} - -// Error: -// main/files/types/0a2_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/debug/issue-558b.gno b/gnovm/tests/debug/issue-558b.gno new file mode 100644 index 00000000000..20d523784e3 --- /dev/null +++ b/gnovm/tests/debug/issue-558b.gno @@ -0,0 +1,78 @@ +package main + +import ( + "fmt" + "io" + "log" + "strings" +) + +type readAutoCloser struct { + r io.ReadCloser +} + +func (a readAutoCloser) Read(b []byte) (n int, err error) { + if a.r == nil { + return 0, io.EOF + } + n, err = a.r.Read(b) + //if err == io.EOF { + if io.EOF == err { + a.Close() + } + return n, err +} + +func (a readAutoCloser) Close() error { + if a.r == nil { + return nil + } + return a.r.(io.Closer).Close() +} + +type pipe struct { + Reader readAutoCloser +} + +func newReadAutoCloser(r io.Reader) readAutoCloser { + if _, ok := r.(io.Closer); !ok { + return readAutoCloser{io.NopCloser(r)} + } + return readAutoCloser{r.(io.ReadCloser)} +} + +type Reader interface { + Read(b []byte) (n int, err error) +} + +func ReadAll(r Reader) ([]byte, error) { + b := make([]byte, 0, 512) + for { + if len(b) == cap(b) { + // Add more capacity (let append pick how much). + b = append(b, 0)[:len(b)] + } + n, err := r.Read(b[len(b):cap(b)]) + b = b[:len(b)+n] + if err != nil { + //if err == io.EOF { + if io.EOF == err { + err = nil + } + return b, err + } + } +} + +func main() { + p := &pipe{} + p.Reader = newReadAutoCloser(strings.NewReader("test")) + b, err := ReadAll(p.Reader) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(b)) +} + +// Error: +// interface conversion: gnolang.Type is *gnolang.NativeType, not gnolang.PrimitiveType diff --git a/gnovm/tests/files/issue-558b.gno b/gnovm/tests/files/issue-558b_stdlibs.gno similarity index 100% rename from gnovm/tests/files/issue-558b.gno rename to gnovm/tests/files/issue-558b_stdlibs.gno From 88f20ea49dee119b6b0fbba740f722046152e8f5 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Mar 2024 17:33:07 +0800 Subject: [PATCH 109/193] #no cherry pick for shift_expr_typecheck branch! rm most logic for handling type of shift expr --- gnovm/Makefile | 3 +- gnovm/pkg/gnolang/preprocess.go | 160 +----------------- gnovm/pkg/gnolang/type_check.go | 11 +- gnovm/tests/files/types2/0.gno | 23 --- gnovm/tests/files/types2/0_a.gno | 22 --- gnovm/tests/files/types2/0_a_1.gno | 22 --- gnovm/tests/files/types2/0_a_2.gno | 40 ----- gnovm/tests/files/types2/0_a_3.gno | 40 ----- gnovm/tests/files/types2/0_a_3a.gno | 40 ----- gnovm/tests/files/types2/0_a_3b.gno | 39 ----- gnovm/tests/files/types2/0_b.gno | 21 --- gnovm/tests/files/types2/0_c.gno | 22 --- gnovm/tests/files/types2/0_d.gno | 22 --- gnovm/tests/files/types2/0_e.gno | 22 --- gnovm/tests/files/types2/0_f.gno | 22 --- gnovm/tests/files/types2/1.gno | 21 --- gnovm/tests/files/types2/10a000_filetest.gno | 9 - gnovm/tests/files/types2/10a0012_filetest.gno | 9 - gnovm/tests/files/types2/10a001_filetest.gno | 9 - gnovm/tests/files/types2/10a00_filetest.gno | 9 - gnovm/tests/files/types2/10a01_filetest.gno | 18 -- gnovm/tests/files/types2/10a02_filetest.gno | 15 -- gnovm/tests/files/types2/10a03_filetest.gno | 18 -- gnovm/tests/files/types2/10a0_filetest.gno | 13 -- gnovm/tests/files/types2/10a10_filetest.gno | 10 -- gnovm/tests/files/types2/10a11_filetest.gno | 13 -- gnovm/tests/files/types2/10a17.gno | 10 -- gnovm/tests/files/types2/10a17a.gno | 21 --- gnovm/tests/files/types2/10a17b.gno | 17 -- gnovm/tests/files/types2/10a17b1.gno | 17 -- gnovm/tests/files/types2/10a17b2.gno | 18 -- gnovm/tests/files/types2/10a18.gno | 10 -- gnovm/tests/files/types2/10a19.gno | 10 -- gnovm/tests/files/types2/10a20.gno | 10 -- gnovm/tests/files/types2/10a21.gno | 10 -- gnovm/tests/files/types2/10a21a.gno | 10 -- gnovm/tests/files/types2/10a22.gno | 10 -- gnovm/tests/files/types2/10a23.gno | 9 - gnovm/tests/files/types2/10a24.gno | 10 -- gnovm/tests/files/types2/10a25.gno | 10 -- gnovm/tests/files/types2/10a25a.gno | 10 -- gnovm/tests/files/types2/10a25b.gno | 11 -- gnovm/tests/files/types2/10a25c.gno | 11 -- gnovm/tests/files/types2/10a26.gno | 11 -- gnovm/tests/files/types2/10a27.gno | 15 -- gnovm/tests/files/types2/10a27a.gno | 14 -- gnovm/tests/files/types2/10a27b.gno | 14 -- gnovm/tests/files/types2/10a27c.gno | 14 -- gnovm/tests/files/types2/10a27d.gno | 14 -- gnovm/tests/files/types2/10a27e.gno | 13 -- gnovm/tests/files/types2/10a27f.gno | 14 -- gnovm/tests/files/types2/11.gno | 14 -- gnovm/tests/files/types2/12.gno | 9 - gnovm/tests/files/types2/13.gno | 8 - gnovm/tests/files/types2/14.gno | 16 -- gnovm/tests/files/types2/15.gno | 26 --- gnovm/tests/files/types2/15a.gno | 26 --- gnovm/tests/files/types2/15b.gno | 30 ---- gnovm/tests/files/types2/15c.gno | 10 -- gnovm/tests/files/types2/1_a.gno | 20 --- gnovm/tests/files/types2/26a1_filetest.gno | 10 -- gnovm/tests/files/types2/27_filetest.gno | 10 -- gnovm/tests/files/types2/27a_filetest.gno | 10 -- gnovm/tests/files/types2/3.gno | 14 -- gnovm/tests/files/types2/3_a.gno | 14 -- gnovm/tests/files/types2/3_b.gno | 14 -- gnovm/tests/files/types2/3_c.gno | 10 -- gnovm/tests/files/types2/4.gno | 22 --- gnovm/tests/files/types2/4_a.gno | 22 --- gnovm/tests/files/types2/4_b.gno | 22 --- gnovm/tests/files/types2/4_c.gno | 22 --- gnovm/tests/files/types2/5.gno | 20 --- gnovm/tests/files/types2/a46.gno | 26 --- gnovm/tests/files/types2/addr0b_stdlibs.gno | 23 --- gnovm/tests/files/types2/comp3.gno | 14 -- 75 files changed, 9 insertions(+), 1369 deletions(-) delete mode 100644 gnovm/tests/files/types2/0.gno delete mode 100644 gnovm/tests/files/types2/0_a.gno delete mode 100644 gnovm/tests/files/types2/0_a_1.gno delete mode 100644 gnovm/tests/files/types2/0_a_2.gno delete mode 100644 gnovm/tests/files/types2/0_a_3.gno delete mode 100644 gnovm/tests/files/types2/0_a_3a.gno delete mode 100644 gnovm/tests/files/types2/0_a_3b.gno delete mode 100644 gnovm/tests/files/types2/0_b.gno delete mode 100644 gnovm/tests/files/types2/0_c.gno delete mode 100644 gnovm/tests/files/types2/0_d.gno delete mode 100644 gnovm/tests/files/types2/0_e.gno delete mode 100644 gnovm/tests/files/types2/0_f.gno delete mode 100644 gnovm/tests/files/types2/1.gno delete mode 100644 gnovm/tests/files/types2/10a000_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a0012_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a001_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a00_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a01_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a02_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a03_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a0_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a10_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a11_filetest.gno delete mode 100644 gnovm/tests/files/types2/10a17.gno delete mode 100644 gnovm/tests/files/types2/10a17a.gno delete mode 100644 gnovm/tests/files/types2/10a17b.gno delete mode 100644 gnovm/tests/files/types2/10a17b1.gno delete mode 100644 gnovm/tests/files/types2/10a17b2.gno delete mode 100644 gnovm/tests/files/types2/10a18.gno delete mode 100644 gnovm/tests/files/types2/10a19.gno delete mode 100644 gnovm/tests/files/types2/10a20.gno delete mode 100644 gnovm/tests/files/types2/10a21.gno delete mode 100644 gnovm/tests/files/types2/10a21a.gno delete mode 100644 gnovm/tests/files/types2/10a22.gno delete mode 100644 gnovm/tests/files/types2/10a23.gno delete mode 100644 gnovm/tests/files/types2/10a24.gno delete mode 100644 gnovm/tests/files/types2/10a25.gno delete mode 100644 gnovm/tests/files/types2/10a25a.gno delete mode 100644 gnovm/tests/files/types2/10a25b.gno delete mode 100644 gnovm/tests/files/types2/10a25c.gno delete mode 100644 gnovm/tests/files/types2/10a26.gno delete mode 100644 gnovm/tests/files/types2/10a27.gno delete mode 100644 gnovm/tests/files/types2/10a27a.gno delete mode 100644 gnovm/tests/files/types2/10a27b.gno delete mode 100644 gnovm/tests/files/types2/10a27c.gno delete mode 100644 gnovm/tests/files/types2/10a27d.gno delete mode 100644 gnovm/tests/files/types2/10a27e.gno delete mode 100644 gnovm/tests/files/types2/10a27f.gno delete mode 100644 gnovm/tests/files/types2/11.gno delete mode 100644 gnovm/tests/files/types2/12.gno delete mode 100644 gnovm/tests/files/types2/13.gno delete mode 100644 gnovm/tests/files/types2/14.gno delete mode 100644 gnovm/tests/files/types2/15.gno delete mode 100644 gnovm/tests/files/types2/15a.gno delete mode 100644 gnovm/tests/files/types2/15b.gno delete mode 100644 gnovm/tests/files/types2/15c.gno delete mode 100644 gnovm/tests/files/types2/1_a.gno delete mode 100644 gnovm/tests/files/types2/26a1_filetest.gno delete mode 100644 gnovm/tests/files/types2/27_filetest.gno delete mode 100644 gnovm/tests/files/types2/27a_filetest.gno delete mode 100644 gnovm/tests/files/types2/3.gno delete mode 100644 gnovm/tests/files/types2/3_a.gno delete mode 100644 gnovm/tests/files/types2/3_b.gno delete mode 100644 gnovm/tests/files/types2/3_c.gno delete mode 100644 gnovm/tests/files/types2/4.gno delete mode 100644 gnovm/tests/files/types2/4_a.gno delete mode 100644 gnovm/tests/files/types2/4_b.gno delete mode 100644 gnovm/tests/files/types2/4_c.gno delete mode 100644 gnovm/tests/files/types2/5.gno delete mode 100644 gnovm/tests/files/types2/a46.gno delete mode 100644 gnovm/tests/files/types2/addr0b_stdlibs.gno delete mode 100644 gnovm/tests/files/types2/comp3.gno diff --git a/gnovm/Makefile b/gnovm/Makefile index 9f564f7aa65..9f3033dc511 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -50,7 +50,7 @@ _test.pkg: go test ./pkg/... $(GOTEST_FLAGS) .PHONY: _test.gnolang -_test.gnolang: _test.gnolang.types _test.gnolang.types.native _test.gnolang.types2 _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other +_test.gnolang: _test.gnolang.types _test.gnolang.types.native _test.gnolang.native _test.gnolang.stdlibs _test.gnolang.realm _test.gnolang.pkg0 _test.gnolang.pkg1 _test.gnolang.pkg2 _test.gnolang.other _test.gnolang.other:; go test tests/*.go -run "(TestFileStr|TestSelectors)" $(GOTEST_FLAGS) _test.gnolang.realm:; go test tests/*.go -run "TestFiles/^zrealm" $(GOTEST_FLAGS) _test.gnolang.pkg0:; go test tests/*.go -run "TestPackages/(bufio|crypto|encoding|errors|internal|io|math|sort|std|stdshim|strconv|strings|testing|unicode)" $(GOTEST_FLAGS) @@ -65,7 +65,6 @@ _test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' -- _test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.debug:; go test tests/*.go -test.short -run 'TestDebug$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.debug.native:; go test tests/*.go -test.short -run 'TestDebugNative$$/' --update-golden-tests $(GOTEST_FLAGS) -_test.gnolang.types2:; go test tests/*.go -test.short -run 'TestTypes2$$/' --update-golden-tests $(GOTEST_FLAGS) ######################################## # Code gen diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ad374ea2475..2a4143438a8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -752,7 +752,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { // check LHS type compatibility // check compatible - n.checkShiftExpr(lt, false) + n.checkShiftExpr(lt) // checkOrConvert RHS if baseOf(rt) != UintType { // TODO: XXX, is it good for native? // convert n.Right to (gno) uint type, @@ -805,11 +805,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } // Then, evaluate the expression. - if isShift { - if n.GetAttribute(ATTR_DELAY) == true { // only in this case not to eval const, namely, delayed - return n, TRANS_CONTINUE - } - } cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { // left untyped const -> right not const @@ -1031,9 +1026,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.NumArgs = 1 var dt Type ct := evalStaticType(store, last, n.Func) - at := evalStaticTypeOf(store, last, n.Args[0]) - switch arg0 := n.Args[0].(type) { - case *ConstExpr: + //switch arg0 := n.Args[0].(type) { + if arg0, ok := n.Args[0].(*ConstExpr); ok { debug.Println("---constExpr: ", arg0) // check legal type for nil if arg0.IsUndefined() { @@ -1072,42 +1066,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // the ATTR_TYPEOF_VALUE is still interface. cx.SetAttribute(ATTR_TYPEOF_VALUE, dt) return cx, TRANS_CONTINUE - case *BinaryExpr: // special case to evaluate type of binaryExpr/UnaryExpr which has untyped shift nested - if isUntyped(at) { // only when untyped, this is checked in checkOrConvertType too, but guard here - switch arg0.Op { - case EQL, NEQ, LSS, GTR, LEQ, GEQ: // refer to 10a0012. TODO: convert to typed too - checkAssignableTo(at, ct, true) - break // quick forward - default: - checkOrConvertType(store, last, &n.Args[0], ct, false, true) - ////// TODO: evalConst for already typed shift expr - //debug.Printf("len of n.Args: %v \n", len(n.Args)) - //debug.Printf("before eval const n.Args[0]: %v \n", n.Args[0]) - //_, lic := arg0.Left.(*ConstExpr) - //_, ric := arg0.Right.(*ConstExpr) - //if lic && ric { - // n.Args[0] = evalConst(store, last, n.Args[0]) - //} - //debug.Printf("after eval const n.Args[0]: %v \n", n.Args[0]) - } - } - case *UnaryExpr: - debug.Println("---unary expr: ", arg0) - if isUntyped(at) { - checkOrConvertType(store, last, &n.Args[0], ct, false, true) - //_, xic := arg0.X.(*ConstExpr) - //debug.Printf("len of n.Args: %v \n", len(n.Args)) - //debug.Println("---delay process unaryExpr") - //if xic { - // debug.Printf("before eval const n.Args[0]: %v \n", n.Args[0]) - // //n.Args[0] = evalConst(store, last, n.Args[0]) - // //debug.Printf("after eval const n.Args[0]: %v \n", n.Args[0]) - //} - } else { - debug.Printf("---unary, at is typed: %v \n", at) - } - default: - // do nothing } // general case, for non-const untyped && no nested untyped shift // after handling const, and special cases recursively, set the target node type @@ -1700,14 +1658,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { last.Define(ln, anyValue(rt)) } - // in define, when RHS is untyped and contains SHR/SHL expression, explicitly - // call this, to give the SHR/SHL a type, the dest type is a faux type. - switch n.Rhs[i].(type) { - case *BinaryExpr, *UnaryExpr: - checkOrConvertType(store, last, &n.Rhs[i], nil, false, false) // 10a03 - default: - // do nothing - } } } } else { // ASSIGN. @@ -2480,106 +2430,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } convertConst(store, last, cx, t) } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // core logic to determine/convert type of shift expr. - // the type of untyped shift expr is determined by its usage context, define, assign, explicit conversion, etc. - // if dest type is nil or interface, adopt its default type, if not, adopt the concrete dest type - // if conduct explicit conversion on typed shift, set coerce to be true, this always happens in callExpr. - xt := evalStaticTypeOf(store, last, *x) - if debug { - debug.Printf("shift, xt: %v, Op: %v, t: %v \n", xt, bx.Op, t) - } - - //lt := evalStaticTypeOf(store, last, bx.Left) - //rt := evalStaticTypeOf(store, last, bx.Right) - // going to check if shift expr is compatible with type from outer context - - // used to check compatible rather than check on a converted type(default type) - // e.g. 1.0 % 2, should show err msg of bigDecKind not the float32Kind - var originType Type - if _, ok := t.(*InterfaceType); ok || t == nil { - if isUntyped(xt) { - originType = xt - t = defaultTypeOf(xt) - //t = defaultTypeOf(lt) - } else if xt == nil { - originType = nil - } else { - //return // is x is typed and dest t is nil or interface type(even for type cast), do nothing. - bx.checkShiftExpr(xt, true) - // return? - } - } else { - originType = t - } - - debug.Printf("---origin type for untyped shift is: %v \n", originType) - debug.Printf("---dest type for untyped shift is: %v \n", t) - debug.Println("xt == nil? ", xt == nil) - // deal with binary expr(bx.Left), determine its type - if coerce || !coerce && isUntyped(xt) || xt == nil { // XXX, simplify? - // coerce mostly when explicitly conversion, type call, while arg is binary expr - // not coerce: assign, refer to 0_a_1.gno, func call(param), 10a17b2 - // TODO: do we need this any more? since already checked before? - // NO, it's from callExpr and should checked recursively? huh? - - // XXX, no need for this, already check assignable in checkOrConvertType - // check against dest type from outer context - //bx.AssertCompatible(t, t) - bx.checkShiftExpr(originType, true) - debug.Println("---going to eval delayed const shift expr") - // eval const for delayed shift expr - if _, ok := (*x).(*ConstExpr); !ok { - debug.Println("---not const") - _, lic := bx.Left.(*ConstExpr) - _, ric := bx.Right.(*ConstExpr) - if lic && ric { - *x = evalConst(store, last, *x) - } - } - debug.Printf("---after eval, *x: %v \n", *x) - - if _, ok := (*x).(*ConstExpr); ok { - //checkOrConvertType(store, last, x, t, autoNative, coerce) - } else { - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } - } else { // not coerce, xt is typed, no need to convert but check. refer to 10a17b1. - checkAssignableTo(xt, t, false) // refer to 0_a_2.gno, 0_a_3.gno - } - - } else if ux, ok := (*x).(*UnaryExpr); ok { - if debug { - debug.Printf("unary expr: %v, Op: %v, t: %v \n", ux, ux.Op, t) - } - xt := evalStaticTypeOf(store, last, *x) - if _, ok := t.(*InterfaceType); ok || t == nil { - if isUntyped(xt) { - t = defaultTypeOf(xt) - } else { - return - } - } - if coerce || !coerce && isUntyped(xt) { - ux.AssertCompatible(xt, t) - // recursively check leaf node - checkOrConvertType(store, last, &ux.X, t, autoNative, coerce) - debug.Printf("---after checkOrConvertType for unaryExpr, ux: %v \n", ux) - - // check ux against t - if _, ok := (ux.X).(*ConstExpr); ok { - // re-eval ux - nux := evalConst(store, last, *x) - debug.Println("---nux: ", nux) - nxt := evalStaticTypeOf(store, last, ux) - debug.Println("---nxt: ", nxt) - checkAssignableTo(nxt, t, false) // this is not all right, should check convertible - debug.Println("---t: ", t) - convertConst(store, last, nux, t) // or just check convertible? - } - } else { - checkAssignableTo(xt, t, false) - } + // "push" expected type into shift binary's left operand. + checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) if debug { @@ -2602,9 +2454,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: // push t into bx.Left and bx.Right, recursively - //checkOperandWithOp(store, last, &bx.Left, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - //checkOperandWithOp(store, last, &bx.Right, t, bx.Op, Binary) checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) return case EQL, LSS, GTR, NEQ, LEQ, GEQ: diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 9f15df1e9d8..52d792779c3 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -625,20 +625,15 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // isFinal indicates whether it's first check or final check(this happens in checkOrConvertType) // XXX, is this logic only for this special case? -func (bx *BinaryExpr) checkShiftExpr(dt Type, isFinal bool) { - debug.Printf("---checkShiftExpr: dt: %v, isFinal: %t \n", dt, isFinal) +func (bx *BinaryExpr) checkShiftExpr(dt Type) { + debug.Printf("---checkShiftExpr: dt: %v, isFinal: %t \n", dt) var destKind interface{} if dt != nil { destKind = dt.Kind() } if checker, ok := binaryChecker[bx.Op]; ok { if !checker(dt) { - if !isFinal { - // just tag it for delayed determination - bx.SetAttribute(ATTR_DELAY, true) - } else { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) - } + panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) } } else { panic("should not happen") diff --git a/gnovm/tests/files/types2/0.gno b/gnovm/tests/files/types2/0.gno deleted file mode 100644 index 551269541dd..00000000000 --- a/gnovm/tests/files/types2/0.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -// 1. checkOrConvert is the core logic, to convert type(recursively if needed) -// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call -// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; -// it's not coerced -// 4. type call should be checked, it's coerced even RHS is typed. -// 5. func call should be checked, it's not coerced. - -import "fmt" - -// case of expr in type call -func main() { - //println(1 << 2) - x := 2 - r := uint64(1 << x) // 2 step. first binary, second call type - println(r) - fmt.Printf("%T \n", r) -} - -// Output: -// 4 -// uint64 diff --git a/gnovm/tests/files/types2/0_a.gno b/gnovm/tests/files/types2/0_a.gno deleted file mode 100644 index 0f78a9c141f..00000000000 --- a/gnovm/tests/files/types2/0_a.gno +++ /dev/null @@ -1,22 +0,0 @@ -package main - -// 1. checkOrConvert is the core logic, to convert type(recursively if needed) -// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call -// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; -// it's not coerced -// 4. type call should be checked, it's coerced even RHS is typed. -// 5. func call should be checked, it's not coerced. - -import "fmt" - -// case of expr in type call -func main() { - x := 2 - r := uint64(1< bigint does not implement main.R diff --git a/gnovm/tests/files/types2/0_b.gno b/gnovm/tests/files/types2/0_b.gno deleted file mode 100644 index d41ef81ae27..00000000000 --- a/gnovm/tests/files/types2/0_b.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -// 1. checkOrConvert is the core logic, to convert type(recursively if needed) -// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call -// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; -// it's not coerced -// 4. type call should be checked, it's coerced even RHS is typed. -// 5. func call should be checked, it's not coerced. - -import "fmt" - -// case of expr in type call -func main() { - x := 2 - r := float32(1<>2) - println(r) -} - -// Output: -// false diff --git a/gnovm/tests/files/types2/10a001_filetest.gno b/gnovm/tests/files/types2/10a001_filetest.gno deleted file mode 100644 index 3af624a1d2f..00000000000 --- a/gnovm/tests/files/types2/10a001_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - r := uint64(1<<2 == 1>>2) - println(r) -} - -// Error: -// main/files/types2/10a001_filetest.gno:4: cannot convert BoolKind to Uint64Kind \ No newline at end of file diff --git a/gnovm/tests/files/types2/10a00_filetest.gno b/gnovm/tests/files/types2/10a00_filetest.gno deleted file mode 100644 index e510b33bf69..00000000000 --- a/gnovm/tests/files/types2/10a00_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - x := 1 - println(uint(+x)) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types2/10a01_filetest.gno b/gnovm/tests/files/types2/10a01_filetest.gno deleted file mode 100644 index 9856d9cce7d..00000000000 --- a/gnovm/tests/files/types2/10a01_filetest.gno +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import "fmt" - -// TODO: this would work in Go. -// consider if we want. -func main() { - x := 1 - y := 1.0 << 1 - println(y) - fmt.Printf("%T \n", y) - fmt.Printf("%T \n", 1) - fmt.Printf("%T \n", x) - -} - -// Error: -// main/files/types2/10a01_filetest.gno:9: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types2/10a02_filetest.gno b/gnovm/tests/files/types2/10a02_filetest.gno deleted file mode 100644 index 703b0fc4dd5..00000000000 --- a/gnovm/tests/files/types2/10a02_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 11 - y := 1.0 << x - println(y) - fmt.Printf("%T \n", y) - fmt.Printf("%T \n", 1) - fmt.Printf("%T \n", x) -} - -// Error: -// main/files/types2/10a02_filetest.gno:7: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types2/10a03_filetest.gno b/gnovm/tests/files/types2/10a03_filetest.gno deleted file mode 100644 index 1ebbf69e67b..00000000000 --- a/gnovm/tests/files/types2/10a03_filetest.gno +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 11 - y := 1 << x - println(y) - fmt.Printf("%T \n", y) - fmt.Printf("%T \n", 1) - fmt.Printf("%T \n", x) -} - -// Output: -// 2048 -// int -// int -// int diff --git a/gnovm/tests/files/types2/10a0_filetest.gno b/gnovm/tests/files/types2/10a0_filetest.gno deleted file mode 100644 index 2ac7ba6d674..00000000000 --- a/gnovm/tests/files/types2/10a0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -func gen() []int { - return nil -} - -func main() { - r := gen() == nil - println(r) -} - -// Output: -// true diff --git a/gnovm/tests/files/types2/10a10_filetest.gno b/gnovm/tests/files/types2/10a10_filetest.gno deleted file mode 100644 index 165307a6477..00000000000 --- a/gnovm/tests/files/types2/10a10_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 1 - r := a << 1 // NOTE: go vet would fail, but still process - println(r) -} - -// Output: -// 2 diff --git a/gnovm/tests/files/types2/10a11_filetest.gno b/gnovm/tests/files/types2/10a11_filetest.gno deleted file mode 100644 index bcb62dc76c3..00000000000 --- a/gnovm/tests/files/types2/10a11_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import "bytes" - -// both not const, and both interface -func main() { - // lv.T: * uint8, rv.T: * uint8 - cmp := bytes.Compare([]byte("a"), []byte("b")) - println(cmp) -} - -// Output: -// -1 diff --git a/gnovm/tests/files/types2/10a17.gno b/gnovm/tests/files/types2/10a17.gno deleted file mode 100644 index 5c504d7d616..00000000000 --- a/gnovm/tests/files/types2/10a17.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := uint64(1 << x) - println(y) -} - -// Output: -// 2048 diff --git a/gnovm/tests/files/types2/10a17a.gno b/gnovm/tests/files/types2/10a17a.gno deleted file mode 100644 index 254c36e613f..00000000000 --- a/gnovm/tests/files/types2/10a17a.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import "fmt" - -func foo(a uint64, b int64) { - fmt.Printf("%T \n", a) - fmt.Printf("%T \n", b) - println(a) - println(b) -} - -func main() { - x := 11 - foo(1<>x) -} - -// Output: -// uint64 -// int64 -// 2048 -// 0 diff --git a/gnovm/tests/files/types2/10a17b.gno b/gnovm/tests/files/types2/10a17b.gno deleted file mode 100644 index e405f2504be..00000000000 --- a/gnovm/tests/files/types2/10a17b.gno +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import "fmt" - -// TODO: the log is runtime log, implies it escape preprocess check -func foo(a uint64, b float32) { - fmt.Printf("%T \n", a) - println(a) -} - -func main() { - x := 11 - foo(1<>x) -} - -// Error: -// main/files/types2/10a17b.gno:13: operator >> not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/10a17b1.gno b/gnovm/tests/files/types2/10a17b1.gno deleted file mode 100644 index d747ba8a617..00000000000 --- a/gnovm/tests/files/types2/10a17b1.gno +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import "fmt" - -// it's like assign -func foo(a uint64, b float32) { - fmt.Printf("%T \n", a) - println(a) -} - -func main() { - x := 11 - foo(1<>x) -} - -// Error: -// main/files/types2/10a17b1.gno:13: cannot use int as float32 diff --git a/gnovm/tests/files/types2/10a17b2.gno b/gnovm/tests/files/types2/10a17b2.gno deleted file mode 100644 index cfeb643e291..00000000000 --- a/gnovm/tests/files/types2/10a17b2.gno +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import "fmt" - -// it's like assign -func foo(a uint64, b int64) { - fmt.Printf("%T \n", a) - println(a) -} - -func main() { - x := 11 - foo(1<>x) -} - -// Output: -// uint64 -// 2048 diff --git a/gnovm/tests/files/types2/10a18.gno b/gnovm/tests/files/types2/10a18.gno deleted file mode 100644 index a29108aef5a..00000000000 --- a/gnovm/tests/files/types2/10a18.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 64 - y := uint64(1 << x) - println(y) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types2/10a19.gno b/gnovm/tests/files/types2/10a19.gno deleted file mode 100644 index 3b7fb0aec50..00000000000 --- a/gnovm/tests/files/types2/10a19.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 64 - y := uint64(1<> 8) - println(b) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types2/10a23.gno b/gnovm/tests/files/types2/10a23.gno deleted file mode 100644 index 44aa5a95561..00000000000 --- a/gnovm/tests/files/types2/10a23.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - b := uint64(1 + 1) - println(b) -} - -// Output: -// 2 diff --git a/gnovm/tests/files/types2/10a24.gno b/gnovm/tests/files/types2/10a24.gno deleted file mode 100644 index d118c422845..00000000000 --- a/gnovm/tests/files/types2/10a24.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := 1 << x - println(y) -} - -// Output: -// 2048 diff --git a/gnovm/tests/files/types2/10a25.gno b/gnovm/tests/files/types2/10a25.gno deleted file mode 100644 index c29c8e2813f..00000000000 --- a/gnovm/tests/files/types2/10a25.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := -(1 << x) - println(y) -} - -// Output: -// -2048 diff --git a/gnovm/tests/files/types2/10a25a.gno b/gnovm/tests/files/types2/10a25a.gno deleted file mode 100644 index da008b9b5a1..00000000000 --- a/gnovm/tests/files/types2/10a25a.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := -(1 + 1< diff --git a/gnovm/tests/files/types2/13.gno b/gnovm/tests/files/types2/13.gno deleted file mode 100644 index 47dc53cc6af..00000000000 --- a/gnovm/tests/files/types2/13.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1 << nil) -} - -// Error: -// main/files/types2/13.gno:3: cannot convert (const (undefined) nil) to UintKind diff --git a/gnovm/tests/files/types2/14.gno b/gnovm/tests/files/types2/14.gno deleted file mode 100644 index 629175ebc19..00000000000 --- a/gnovm/tests/files/types2/14.gno +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 1 - s := []int{1 << x} - - v := float32(s[0]) // type determined when indexed - println(v) - fmt.Printf("%T \n", v) -} - -// Output: -// 2 -// float32 diff --git a/gnovm/tests/files/types2/15.gno b/gnovm/tests/files/types2/15.gno deleted file mode 100644 index f6c249b8e46..00000000000 --- a/gnovm/tests/files/types2/15.gno +++ /dev/null @@ -1,26 +0,0 @@ -package main - -// 1. find where shift expr is used -// a) type cast -// b) assign stmt -// c) composite literals - -// 2. get the dest type, if convert condition, convert -// condition: -// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get -// attr: HAS_SHIFT to determine if has shift. - -// 3. in type func, find termination condition when not const -// this condition should be the opposite of the convert condition - -// TODO: composite literal, checked, OK! -// TODO: simple print non-const untyped, checked, to typed if interface, OK! - -func main() { - a := 2 - s := []float32{1 << a} - println(s[0]) -} - -// Error: -// main/files/types2/15.gno:21: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/15a.gno b/gnovm/tests/files/types2/15a.gno deleted file mode 100644 index 284da3b8748..00000000000 --- a/gnovm/tests/files/types2/15a.gno +++ /dev/null @@ -1,26 +0,0 @@ -package main - -// 1. find where shift expr is used -// a) type cast -// b) assign stmt -// c) composite literals - -// 2. get the dest type, if convert condition, convert -// condition: -// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get -// attr: HAS_SHIFT to determine if has shift. - -// 3. in type func, find termination condition when not const -// this condition should be the opposite of the convert condition - -// TODO: composite literal -// TODO: simple print non-const untyped - -func main() { - a := 2 - s := map[string]float32{"k": 1 << a} - println(s[0]) -} - -// Error: -// main/files/types2/15a.gno:21: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types2/15b.gno b/gnovm/tests/files/types2/15b.gno deleted file mode 100644 index 4cb0b57fb09..00000000000 --- a/gnovm/tests/files/types2/15b.gno +++ /dev/null @@ -1,30 +0,0 @@ -package main - -// 1. find where shift expr is used -// a) type cast -// b) assign stmt -// c) composite literals - -// 2. get the dest type, if convert condition, convert -// condition: -// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get -// attr: HAS_SHIFT to determine if has shift. - -// 3. in type func, find termination condition when not const -// this condition should be the opposite of the convert condition - -// TODO: composite literal -// TODO: simple print non-const untyped - -func main() { - type S struct { - a float32 - } - s := S{ - a: 1 << 2, - } - println(s.a) -} - -// Output: -// 4 diff --git a/gnovm/tests/files/types2/15c.gno b/gnovm/tests/files/types2/15c.gno deleted file mode 100644 index e9b0032ac9a..00000000000 --- a/gnovm/tests/files/types2/15c.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 2 - s := map[string]interface{}{"k": 1 << a} - println(s["k"]) -} - -// Output: -// 4 diff --git a/gnovm/tests/files/types2/1_a.gno b/gnovm/tests/files/types2/1_a.gno deleted file mode 100644 index dcda35a078e..00000000000 --- a/gnovm/tests/files/types2/1_a.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -// 1. checkOrConvert is the core logic, to convert type(recursively if needed) -// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call -// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; -// it's not coerced -// 4. type call should be checked, it's coerced even RHS is typed. -// 5. func call should be checked, it's not coerced. - -import "fmt" - -// case of const in type call -func main() { - r := int(uint(string("hello"))) - println(r) - fmt.Printf("%T \n", r) -} - -// Error: -// main/files/types2/1_a.gno:14: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types2/26a1_filetest.gno b/gnovm/tests/files/types2/26a1_filetest.gno deleted file mode 100644 index 04292e50b9d..00000000000 --- a/gnovm/tests/files/types2/26a1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 1 - b := 1 - (a == b)++ // LHS is untyped bool, determined in preprocess -} - -// Error: -// main/files/types2/26a1_filetest.gno:6: operator ++ not defined on: BoolKind diff --git a/gnovm/tests/files/types2/27_filetest.gno b/gnovm/tests/files/types2/27_filetest.gno deleted file mode 100644 index 5c504d7d616..00000000000 --- a/gnovm/tests/files/types2/27_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := uint64(1 << x) - println(y) -} - -// Output: -// 2048 diff --git a/gnovm/tests/files/types2/27a_filetest.gno b/gnovm/tests/files/types2/27a_filetest.gno deleted file mode 100644 index 8490c751c88..00000000000 --- a/gnovm/tests/files/types2/27a_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := 11 - y := uint64(1.0 << x) - println(y) -} - -// Output: -// 2048 diff --git a/gnovm/tests/files/types2/3.gno b/gnovm/tests/files/types2/3.gno deleted file mode 100644 index f932a970a9a..00000000000 --- a/gnovm/tests/files/types2/3.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 1 - r := uint(+x) - println(r) - fmt.Printf("%T \n", r) -} - -// Output: -// 1 -// uint diff --git a/gnovm/tests/files/types2/3_a.gno b/gnovm/tests/files/types2/3_a.gno deleted file mode 100644 index 6ca9a8b7cc2..00000000000 --- a/gnovm/tests/files/types2/3_a.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 1 - r := uint(+(1 << x)) - println(r) - fmt.Printf("%T \n", r) -} - -// Output: -// 2 -// uint diff --git a/gnovm/tests/files/types2/3_b.gno b/gnovm/tests/files/types2/3_b.gno deleted file mode 100644 index 55b5fa782d7..00000000000 --- a/gnovm/tests/files/types2/3_b.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 63 - r := int32(+(1<>2) -} - -// Output: -// 4 0 diff --git a/gnovm/tests/files/types2/a46.gno b/gnovm/tests/files/types2/a46.gno deleted file mode 100644 index d50c3944e90..00000000000 --- a/gnovm/tests/files/types2/a46.gno +++ /dev/null @@ -1,26 +0,0 @@ -package main - -var specialBytes [16]byte - -func main() { - for i, b := range []byte(`\.+*?()|[]{}^$`) { - specialBytes[b%16] |= 1 << (b / 16) - println(i, (1 << (b / 16)), specialBytes[b%16]) - } -} - -// Output: -// 0 32 32 -// 1 4 4 -// 2 4 4 -// 3 4 4 -// 4 8 8 -// 5 4 4 -// 6 4 4 -// 7 128 160 -// 8 32 36 -// 9 32 32 -// 10 128 164 -// 11 128 160 -// 12 32 36 -// 13 4 4 diff --git a/gnovm/tests/files/types2/addr0b_stdlibs.gno b/gnovm/tests/files/types2/addr0b_stdlibs.gno deleted file mode 100644 index 324a30f8140..00000000000 --- a/gnovm/tests/files/types2/addr0b_stdlibs.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "github.com/gnolang/gno/_test/net/http" -) - -type extendedRequest struct { - Request http.Request - - Data string -} - -func main() { - r := extendedRequest{} - // req := &r.Request - - println(r) - // XXX removed temporarily until recursion detection implemented for sprintString(). - // println(req) -} - -// Output: -// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined) nil,(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) diff --git a/gnovm/tests/files/types2/comp3.gno b/gnovm/tests/files/types2/comp3.gno deleted file mode 100644 index bd926979844..00000000000 --- a/gnovm/tests/files/types2/comp3.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -func main() { - // test against uninitialized value: https://github.com/gnolang/gno/pull/1132 - var x string - y := "Hello" - results := [...]bool{ - x < y, - } - println(results) -} - -// Output: -// array[(true bool)] From 5da29109d9b2e80405f850db73602751173d234a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Mar 2024 19:24:35 +0800 Subject: [PATCH 110/193] cherry pick this. rm remained logic for check against native interface, and fix assertAssignable --- gnovm/pkg/gnolang/gonative.go | 1 + gnovm/pkg/gnolang/preprocess.go | 6 -- gnovm/pkg/gnolang/type_check.go | 51 ++---------- ...iletest.gnoa => 0f7_filetest_stdlibs.gnoa} | 0 .../debug/{iface_eql.gnoa => iface_eql.gno} | 0 gnovm/tests/debug/issue-558b.gno | 78 ------------------- gnovm/tests/files/types/0f2_native.gno | 28 ------- .../{0f2_filetest.gno => 0f2_stdlibs.gno} | 0 .../{0f3_filetest.gno => 0f3_stdlibs.gno} | 0 .../{0f4_filetest.gno => 0f4_stdlibs.gno} | 0 .../{0f5_filetest.gno => 0f5_stdlibs.gno} | 0 .../{0f7_filetest.gno => 0f7_stdlibs.gno} | 0 gnovm/tests/files/types/iface_eql.gno | 15 ++++ 13 files changed, 22 insertions(+), 157 deletions(-) rename gnovm/tests/debug/{0f7_filetest.gnoa => 0f7_filetest_stdlibs.gnoa} (100%) rename gnovm/tests/debug/{iface_eql.gnoa => iface_eql.gno} (100%) delete mode 100644 gnovm/tests/debug/issue-558b.gno delete mode 100644 gnovm/tests/files/types/0f2_native.gno rename gnovm/tests/files/types/{0f2_filetest.gno => 0f2_stdlibs.gno} (100%) rename gnovm/tests/files/types/{0f3_filetest.gno => 0f3_stdlibs.gno} (100%) rename gnovm/tests/files/types/{0f4_filetest.gno => 0f4_stdlibs.gno} (100%) rename gnovm/tests/files/types/{0f5_filetest.gno => 0f5_stdlibs.gno} (100%) rename gnovm/tests/files/types/{0f7_filetest.gno => 0f7_stdlibs.gno} (100%) create mode 100644 gnovm/tests/files/types/iface_eql.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index fa68b80f91c..b76528d8f8a 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -975,6 +975,7 @@ func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { } return gno2GoTypeMatches(ct.Elt, rt.Elem()) case *StructType: + //debug.Println("---struct type") // TODO maybe consider automatically skipping private native fields? for i, field := range ct.Fields { rft := rt.Field(i).Type diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 2a4143438a8..7387b02c112 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2404,12 +2404,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if debug { debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) } - // pop up to preprocess to handle - defer func() { - if r := recover(); r != nil { - panic(r) - } - }() if cx, ok := (*x).(*ConstExpr); ok { if !coerce { // XXX, no check from gno-> native. it's reasonable for gno is a superset of go type, e.g. bigint diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 52d792779c3..05921e385d2 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -212,27 +212,8 @@ func assertAssignable(lt, rt Type) { // TODO: make another function // and remove this case? println("4") - } else if lt.Kind() == InterfaceKind && - IsImplementedBy(lt, rt) { // TODO: consider this - // rt implements lt (and lt is nil interface). - } else if rt.Kind() == InterfaceKind && - IsImplementedBy(rt, lt) { // TODO: consider this - println("5") - // lt implements rt (and rt is nil interface). - } else if nrt, ok := rt.(*NativeType); ok { // see 0f2, for native types - if gno2GoTypeMatches(lt, nrt.Type) { - println("6.1") - } else { - println("6.2") - } - } else if nlt, ok := lt.(*NativeType); ok { - if gno2GoTypeMatches(rt, nlt.Type) { - println("7.1") - } else { - println("7.2") - } } else { - panic("---8") + //panic("---8") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -390,9 +371,11 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { nidt.String())) } } else if xdt, ok := xt.(*DeclaredType); ok { - gno2GoTypeMatches(baseOf(xdt), ndt.Type) - debug.Println("---matches!") - return + if gno2GoTypeMatches(baseOf(xdt), ndt.Type) { + return + } // not check against native interface + //debug.Println("---matches!") + //return } else { panic(fmt.Sprintf( "unexpected type pair: cannot use %s as %s", @@ -935,28 +918,6 @@ func isComparison(op Word) bool { func cmpSpecificity(t1, t2 Type) int { debug.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) - if nt1, ok := t1.(*NativeType); ok { - if nt1.Type.Kind() == reflect.Interface { // is interface - if nt1.Type.NumMethod() == 0 { // empty interface - return 1 - } else if t2 != nil && t2.Kind() != InterfaceKind { - return 1 - } - } else { - t1 = go2GnoType(nt1.Type) // if not interface, convert to gno type - } - } else if nt2, ok := t2.(*NativeType); ok { - if nt2.Type.Kind() == reflect.Interface { // is interface - if nt2.Type.NumMethod() == 0 { - return -1 - } else if t1 != nil && t1.Kind() != InterfaceKind { - return -1 - } - } else { - t2 = go2GnoType(nt2.Type) - } - } - if it1, ok := baseOf(t1).(*InterfaceType); ok { if it1.IsEmptyInterface() { return 1 // left empty interface diff --git a/gnovm/tests/debug/0f7_filetest.gnoa b/gnovm/tests/debug/0f7_filetest_stdlibs.gnoa similarity index 100% rename from gnovm/tests/debug/0f7_filetest.gnoa rename to gnovm/tests/debug/0f7_filetest_stdlibs.gnoa diff --git a/gnovm/tests/debug/iface_eql.gnoa b/gnovm/tests/debug/iface_eql.gno similarity index 100% rename from gnovm/tests/debug/iface_eql.gnoa rename to gnovm/tests/debug/iface_eql.gno diff --git a/gnovm/tests/debug/issue-558b.gno b/gnovm/tests/debug/issue-558b.gno deleted file mode 100644 index 20d523784e3..00000000000 --- a/gnovm/tests/debug/issue-558b.gno +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "fmt" - "io" - "log" - "strings" -) - -type readAutoCloser struct { - r io.ReadCloser -} - -func (a readAutoCloser) Read(b []byte) (n int, err error) { - if a.r == nil { - return 0, io.EOF - } - n, err = a.r.Read(b) - //if err == io.EOF { - if io.EOF == err { - a.Close() - } - return n, err -} - -func (a readAutoCloser) Close() error { - if a.r == nil { - return nil - } - return a.r.(io.Closer).Close() -} - -type pipe struct { - Reader readAutoCloser -} - -func newReadAutoCloser(r io.Reader) readAutoCloser { - if _, ok := r.(io.Closer); !ok { - return readAutoCloser{io.NopCloser(r)} - } - return readAutoCloser{r.(io.ReadCloser)} -} - -type Reader interface { - Read(b []byte) (n int, err error) -} - -func ReadAll(r Reader) ([]byte, error) { - b := make([]byte, 0, 512) - for { - if len(b) == cap(b) { - // Add more capacity (let append pick how much). - b = append(b, 0)[:len(b)] - } - n, err := r.Read(b[len(b):cap(b)]) - b = b[:len(b)+n] - if err != nil { - //if err == io.EOF { - if io.EOF == err { - err = nil - } - return b, err - } - } -} - -func main() { - p := &pipe{} - p.Reader = newReadAutoCloser(strings.NewReader("test")) - b, err := ReadAll(p.Reader) - if err != nil { - log.Fatal(err) - } - fmt.Println(string(b)) -} - -// Error: -// interface conversion: gnolang.Type is *gnolang.NativeType, not gnolang.PrimitiveType diff --git a/gnovm/tests/files/types/0f2_native.gno b/gnovm/tests/files/types/0f2_native.gno deleted file mode 100644 index 7ded58b4ff0..00000000000 --- a/gnovm/tests/files/types/0f2_native.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 - //if errCmp == 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/0f2_filetest.gno b/gnovm/tests/files/types/0f2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/types/0f2_filetest.gno rename to gnovm/tests/files/types/0f2_stdlibs.gno diff --git a/gnovm/tests/files/types/0f3_filetest.gno b/gnovm/tests/files/types/0f3_stdlibs.gno similarity index 100% rename from gnovm/tests/files/types/0f3_filetest.gno rename to gnovm/tests/files/types/0f3_stdlibs.gno diff --git a/gnovm/tests/files/types/0f4_filetest.gno b/gnovm/tests/files/types/0f4_stdlibs.gno similarity index 100% rename from gnovm/tests/files/types/0f4_filetest.gno rename to gnovm/tests/files/types/0f4_stdlibs.gno diff --git a/gnovm/tests/files/types/0f5_filetest.gno b/gnovm/tests/files/types/0f5_stdlibs.gno similarity index 100% rename from gnovm/tests/files/types/0f5_filetest.gno rename to gnovm/tests/files/types/0f5_stdlibs.gno diff --git a/gnovm/tests/files/types/0f7_filetest.gno b/gnovm/tests/files/types/0f7_stdlibs.gno similarity index 100% rename from gnovm/tests/files/types/0f7_filetest.gno rename to gnovm/tests/files/types/0f7_stdlibs.gno diff --git a/gnovm/tests/files/types/iface_eql.gno b/gnovm/tests/files/types/iface_eql.gno new file mode 100644 index 00000000000..905778bcd21 --- /dev/null +++ b/gnovm/tests/files/types/iface_eql.gno @@ -0,0 +1,15 @@ +package main + +type Foo struct { + n int +} + +func main() { + var l interface{} + //var l interface{} = 1 + //var l interface{} = (*Foo)(nil) + println(1 == l) +} + +// Output: +// false From 723aa3bb278d7129059fad839d3fc52f72ffc4ab Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 14 Mar 2024 19:33:53 +0800 Subject: [PATCH 111/193] default cherry pick commit this branch if not marked as not. fixup --- gnovm/pkg/gnolang/type_check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 05921e385d2..ffdb1c50160 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -685,7 +685,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } switch bx.Op { - case ADD, SUB, MUL, QUO, REM, BAND, BOR, BAND_NOT, XOR, LAND, LOR: + case QUO, REM: // special case of zero divisor if isQuoOrRem(bx.Op) { if rcx, ok := bx.Right.(*ConstExpr); ok { From c93111f661fe792498f43e2bda10fb59ca57c628 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 4 Apr 2024 18:37:13 +0800 Subject: [PATCH 112/193] restore typecheck, rm redundant checkAssignableTo, leave it to checkOrConvertType --- gnovm/pkg/gnolang/preprocess.go | 56 +++++-- gnovm/pkg/gnolang/type_check.go | 144 +++--------------- gnovm/tests/debug/0f0_native_filetest.gnoa | 28 ---- gnovm/tests/debug/0f2_filetest.gnoa | 29 ---- gnovm/tests/debug/0f7_filetest_stdlibs.gnoa | 27 ---- gnovm/tests/debug/10a001_filetest.gnoa | 9 -- gnovm/tests/debug/10a27e.gnoa | 13 -- gnovm/tests/debug/15b.gnoa | 30 ---- gnovm/tests/debug/2.gnoa | 10 -- gnovm/tests/debug/22a12_filetest.gnoa | 20 --- gnovm/tests/debug/dec_rem.gnoa | 8 - gnovm/tests/debug/dynamic.gnoa | 13 -- gnovm/tests/debug/iface_eql.gno | 15 -- gnovm/tests/debug/struct.gnoa | 43 ------ gnovm/tests/debug/untyped.gnoa | 11 -- gnovm/tests/debug2/0_a_3b.gno | 39 ----- gnovm/tests/debug2/0a1f_filetest.gno | 10 -- gnovm/tests/debug2/0f26_stdlibs_filetest.gno | 27 ---- gnovm/tests/debug2/1.gno | 9 -- gnovm/tests/debug2/10a11_filetest.gno | 10 -- .../tests/debug2/13a0_ADD_ASSIGN_filetest.gno | 9 -- gnovm/tests/debug2/1b2_filetest.gno | 9 -- gnovm/tests/debug2/5d0_filetest.gno | 10 -- gnovm/tests/debug2/5d0_filetest.gnoa | 10 -- gnovm/tests/debug2/5d0a_filetest.gno | 10 -- gnovm/tests/debug2/5d0b_filetest.gno | 10 -- gnovm/tests/debug2/assign.gno | 10 -- gnovm/tests/debug2/assign0b_native.gno | 19 --- gnovm/tests/debug2/binary_1.gno | 8 - gnovm/tests/debug2/binary_1a.gno | 8 - gnovm/tests/debug2/binary_1b.gno | 8 - gnovm/tests/debug2/binary_2.gnoa | 8 - gnovm/tests/debug2/binary_3.gnoa | 8 - gnovm/tests/debug2/default_type.gno | 8 - gnovm/tests/debug2/inc.gno | 10 -- gnovm/tests/debug2/native.gno | 12 -- gnovm/tests/debug2/time4_native.gno | 15 -- gnovm/tests/debug2/type34.gno | 10 -- gnovm/tests/debug2/unary.gno | 8 - gnovm/tests/debug3/0f2_filetest.gnoa | 28 ---- gnovm/tests/debug3/0f2b_native.gnoa | 28 ---- gnovm/tests/debug3/0f47f_filetest.gnoa | 16 -- gnovm/tests/debug3/2.gnoa | 10 -- gnovm/tests/debug4/issue-558b.gno | 77 ---------- gnovm/tests/debug4/time1_native.gno | 12 -- gnovm/tests/debug4/time1_stdlibs.gno | 12 -- gnovm/tests/debug4/time2_native.gno | 11 -- gnovm/tests/debug4/time2_stdlibs.gno | 11 -- gnovm/tests/debug4/time_native.gno | 12 -- gnovm/tests/debug4/time_stdlibs.gno | 12 -- gnovm/tests/files/type31.gno | 2 +- gnovm/tests/files/type32.gno | 2 +- gnovm/tests/files/types/0f2_stdlibs.gno | 2 +- gnovm/tests/files/types/1a0_ADD_filetest.gno | 2 +- gnovm/tests/files/types/1a1_filetest.gno | 2 +- gnovm/tests/files/types/1e0_filetest.gno | 2 +- gnovm/tests/files/types/20a0_LSS_filetest.gno | 2 +- gnovm/tests/files/types/2a0_SUB_filetest.gno | 2 +- gnovm/tests/files/types/2a1_filetest.gno | 2 +- gnovm/tests/files/types/2e0_filetest.gno | 2 +- gnovm/tests/files/types/3a0_MUL_filetest.gno | 2 +- gnovm/tests/files/types/3a1_filetest.gno | 2 +- gnovm/tests/files/types/3e0_filetest.gno | 2 +- gnovm/tests/files/types/4a0_QUO_filetest.gno | 2 +- gnovm/tests/files/types/4a1_filetest.gno | 2 +- gnovm/tests/files/types/4e01_filetest.gno | 21 +++ gnovm/tests/files/types/4e0_filetest.gno | 2 +- gnovm/tests/files/types/5a0_REM_filetest.gno | 2 +- gnovm/tests/files/types/5a1_filetest.gno | 2 +- gnovm/tests/files/types/5e0_filetest.gno | 2 +- gnovm/tests/files/types/6a0_AND_filetest.gno | 2 +- gnovm/tests/files/types/6a1_filetest.gno | 2 +- gnovm/tests/files/types/6e0_filetest.gno | 2 +- gnovm/tests/files/types/7a0_OR_filetest.gno | 2 +- gnovm/tests/files/types/7a1_filetest.gno | 2 +- gnovm/tests/files/types/7e0_filetest.gno | 2 +- gnovm/tests/files/types/8a0_XOR_filetest.gno | 2 +- gnovm/tests/files/types/8a1_filetest.gno | 2 +- gnovm/tests/files/types/8e0_filetest.gno | 2 +- .../tests/files/types/9a0_ANDNOT_filetest.gno | 2 +- gnovm/tests/files/types/9a1_filetest.gno | 2 +- gnovm/tests/files/types/9e0_filetest.gno | 2 +- 82 files changed, 118 insertions(+), 935 deletions(-) delete mode 100644 gnovm/tests/debug/0f0_native_filetest.gnoa delete mode 100644 gnovm/tests/debug/0f2_filetest.gnoa delete mode 100644 gnovm/tests/debug/0f7_filetest_stdlibs.gnoa delete mode 100644 gnovm/tests/debug/10a001_filetest.gnoa delete mode 100644 gnovm/tests/debug/10a27e.gnoa delete mode 100644 gnovm/tests/debug/15b.gnoa delete mode 100644 gnovm/tests/debug/2.gnoa delete mode 100644 gnovm/tests/debug/22a12_filetest.gnoa delete mode 100644 gnovm/tests/debug/dec_rem.gnoa delete mode 100644 gnovm/tests/debug/dynamic.gnoa delete mode 100644 gnovm/tests/debug/iface_eql.gno delete mode 100644 gnovm/tests/debug/struct.gnoa delete mode 100644 gnovm/tests/debug/untyped.gnoa delete mode 100644 gnovm/tests/debug2/0_a_3b.gno delete mode 100644 gnovm/tests/debug2/0a1f_filetest.gno delete mode 100644 gnovm/tests/debug2/0f26_stdlibs_filetest.gno delete mode 100644 gnovm/tests/debug2/1.gno delete mode 100644 gnovm/tests/debug2/10a11_filetest.gno delete mode 100644 gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/debug2/1b2_filetest.gno delete mode 100644 gnovm/tests/debug2/5d0_filetest.gno delete mode 100644 gnovm/tests/debug2/5d0_filetest.gnoa delete mode 100644 gnovm/tests/debug2/5d0a_filetest.gno delete mode 100644 gnovm/tests/debug2/5d0b_filetest.gno delete mode 100644 gnovm/tests/debug2/assign.gno delete mode 100644 gnovm/tests/debug2/assign0b_native.gno delete mode 100644 gnovm/tests/debug2/binary_1.gno delete mode 100644 gnovm/tests/debug2/binary_1a.gno delete mode 100644 gnovm/tests/debug2/binary_1b.gno delete mode 100644 gnovm/tests/debug2/binary_2.gnoa delete mode 100644 gnovm/tests/debug2/binary_3.gnoa delete mode 100644 gnovm/tests/debug2/default_type.gno delete mode 100644 gnovm/tests/debug2/inc.gno delete mode 100644 gnovm/tests/debug2/native.gno delete mode 100644 gnovm/tests/debug2/time4_native.gno delete mode 100644 gnovm/tests/debug2/type34.gno delete mode 100644 gnovm/tests/debug2/unary.gno delete mode 100644 gnovm/tests/debug3/0f2_filetest.gnoa delete mode 100644 gnovm/tests/debug3/0f2b_native.gnoa delete mode 100644 gnovm/tests/debug3/0f47f_filetest.gnoa delete mode 100644 gnovm/tests/debug3/2.gnoa delete mode 100644 gnovm/tests/debug4/issue-558b.gno delete mode 100644 gnovm/tests/debug4/time1_native.gno delete mode 100644 gnovm/tests/debug4/time1_stdlibs.gno delete mode 100644 gnovm/tests/debug4/time2_native.gno delete mode 100644 gnovm/tests/debug4/time2_stdlibs.gno delete mode 100644 gnovm/tests/debug4/time_native.gno delete mode 100644 gnovm/tests/debug4/time_stdlibs.gno create mode 100644 gnovm/tests/files/types/4e01_filetest.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 7387b02c112..68499b7a674 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -794,7 +794,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if rcx.T == nil { checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } else { - //checkOrConvertType(store, last, &n.Left, rcx.T, false, false) + checkOrConvertType(store, last, &n.Left, rcx.T, false, false) // do nothing, all compatibility is checked, // e.g. int(1) == int8(1), will also conduct type check } @@ -817,7 +817,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { debug.Printf("---rt: %v \n", rt) debug.Printf("---rnt: %v \n", rnt) // get concrete native base type. - pt := go2GnoBaseType(rnt.Type).(PrimitiveType) + pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + lt.String(), + rnt.String())) + } // convert n.Left to pt type, checkOrConvertType(store, last, &n.Left, pt, false, false) // if check pass, convert n.Right to (gno) pt type, @@ -867,7 +873,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if !isShift { if lnt, ok := lt.(*NativeType); ok { // get concrete native base type. - pt := go2GnoBaseType(lnt.Type).(PrimitiveType) + pt, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + rt.String(), + lnt.String())) + } // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) // convert n.Right to pt type, @@ -910,13 +922,25 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert result back to native. // // get concrete native base type. - lpt := go2GnoBaseType(lnt.Type).(PrimitiveType) + lpt, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + rt.String(), + lnt.String())) + } // convert n.Left to (gno) pt type, ln := Expr(Call(lpt.String(), n.Left)) rn := n.Right if rnt, ok := rt.(*NativeType); ok { // e.g. native: time.Second * time.Second - rpt := go2GnoBaseType(rnt.Type).(PrimitiveType) + rpt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + lt.String(), + rnt.String())) + } // check assignable, if pass, convert right to gno first // TODO: cmp? // XXX, can we just check on native type? @@ -951,7 +975,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert result back to native. // // get concrete native base type. - pt := go2GnoBaseType(rnt.Type).(PrimitiveType) + pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + lt.String(), + rnt.String())) + } // convert n.Left to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // convert n.Right to pt or uint type, @@ -2413,13 +2443,13 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). // this is for binaryExpr that assignable has already been checked and cached - if store.AssertAssignableExists(*x, t) { - debug.Printf("---assignable already set for: %v => %v \n", cx, t) - } else { - // still need for non-binary, like arg - checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a - debug.Println("---check pass in checkOrConvertType!") - } + //if store.AssertAssignableExists(*x, t) { + // debug.Printf("---assignable already set for: %v => %v \n", cx, t) + //} else { + // still need for non-binary, like arg + checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a + debug.Println("---check pass in checkOrConvertType!") + //} } } convertConst(store, last, cx, t) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index ffdb1c50160..a9f7f0ce427 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -595,21 +595,8 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { } // =========================================================== - -// type_check for shift expr is a `delayed check`, it has two stages: -// stage1. check on first encounter of a shift expr, if it asserts to be good, pass, -// and if it has const on both side, evalConst, e.g. float32(1 << 4) is legal. -// or if it fails assertion, e.g. uint64(1.0 << 1), tag it to be delayed, to be handled -// on stage2. -// stage2. when an untyped shift expr is used in somewhere, e.g. uint64(1.0 << 1), -// uint64 is used as the potential type of this expr, so uint64(1.0 << 1) is a -// valid representation. -// so dt would be either the type of lhs or the type from outer context. -// isFinal indicates whether it's first check or final check(this happens in checkOrConvertType) - -// XXX, is this logic only for this special case? func (bx *BinaryExpr) checkShiftExpr(dt Type) { - debug.Printf("---checkShiftExpr: dt: %v, isFinal: %t \n", dt) + debug.Printf("---checkShiftExpr: dt: %v \n", dt) var destKind interface{} if dt != nil { destKind = dt.Kind() @@ -623,25 +610,18 @@ func (bx *BinaryExpr) checkShiftExpr(dt Type) { } } -// check both sides since no aware of which side is dest type, -// that lt not compatible but rt is compatible would be good. - // AssertCompatible works as a pre-check prior to checkOrConvertType() -// It checks expressions to ensure the compatibility between operands and operators. +// It checks against expressions to ensure the compatibility between operands and operators. // e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. - -// things like this would fail: 1.0 % 1, bigInt has a bigger specificity than bidDec. func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { debug.Printf("---AssertCompatible, bx: %v, lt: %v, rt: %v \n", bx, lt, rt) // we can't check compatible with native types at current stage, // so leave it to later operations(trans_leave on binaryExpr) // to be converted into gno(only for primitive types), and do // this check again. (AssertCompatible would be invoked again) - // non-primitive types is a special case that is not handled - // (not needed at all?), or it might be expanded to check for case - // like a gno declared type implement a native interface? + // non-primitive types is a special case that is not handled. if lnt, ok := lt.(*NativeType); ok { _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) if ok { @@ -657,20 +637,23 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { escapedOpStr := strings.Replace(wordTokenStrings[bx.Op], "%", "%%", 1) + var xt, dt Type + cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion + if cmp <= 0 { + xt = lt + dt = rt + } else { + xt = rt + dt = lt + } + if isComparison(bx.Op) { switch bx.Op { case EQL, NEQ: - cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion - if cmp <= 0 { - assertComparable(lt, rt) // only check if dest type is comparable - checkAssignableTo(lt, rt, true) // check if src type is assignable to dest type - } else { - assertComparable(rt, lt) - checkAssignableTo(rt, lt, true) - } + assertComparable(xt, dt) // only check if dest type is comparable case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(store, lt, rt, checker, escapedOpStr) + bx.checkCompatibility(store, xt, dt, checker, escapedOpStr) } else { panic("should not happen") } @@ -679,7 +662,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } } else { if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(store, lt, rt, checker, escapedOpStr) + bx.checkCompatibility(store, xt, dt, checker, escapedOpStr) } else { panic("should not happen") } @@ -700,86 +683,15 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } } -// XXX, these kind of type_check happens before checkOrConvertType which get type conversion all -// sorted out, kinda make the type check logic complex, for we have to deal with much undetermined -// types. the upside for this is it quick fails the incompatibility before concrete type conversion -// happens in checkOrConvertType, but does this weigh out the complexity it brings in? -// TODO: maybe should simplify this to only check dt and left other work to checkOrConvertType -func (bx *BinaryExpr) checkCompatibility(store Store, lt, rt Type, checker func(t Type) bool, escapedOpStr string) { - debug.Printf("---checkCompatibility, op: %v, lt: %v, rt: %v\n", bx.Op, lt, rt) +func (bx *BinaryExpr) checkCompatibility(store Store, xt, dt Type, checker func(t Type) bool, escapedOpStr string) { + debug.Printf("---checkCompatibility, op: %v, xt: %v, dt: %v\n", bx.Op, xt, dt) // cache it to be reused in later stage in checkOrConvertType var destKind interface{} - // XXX, this logic is based on an assumption that one side is not defined on op - // while the other side is ok, and this side is assignable to the other side - // (that would be converted to the other side eventually). - // consider 1.2 % int64(1), and 1.0 % int64, is this the only scenario? - cmp := cmpSpecificity(lt, rt) - if !checker(lt) { // lt not compatible with op - if !checker(rt) { // rt not compatible with op - if lt != nil { // return error on left side that is checked first - destKind = lt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) - } else { - debug.Println("---cmp: ", cmp) - // left not compatible, right is compatible - // cmp means the expected convert direction - // if cmp < 0, means potential conversion - // from left to right, so check assignable - // from left to right. - // if cmp > 0, means potential conversion to - // left side which is already asserted to be - // not compatible, so assert fail. - // no check for cmp == 0 since no possible they have - // same specificity with one side is compatible - // and the other is not while assert to be assignable. - // e.g. "a" - 1. - if cmp < 0 { - checkAssignableTo(lt, rt, true) - store.AddAssignableCheckResult(bx.Left, rt) - } else { - if lt != nil { - destKind = lt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) - } - } - } else if !checker(rt) { // left is compatible, right is not - if cmp > 0 { // right to left - checkAssignableTo(rt, lt, true) - store.AddAssignableCheckResult(bx.Right, lt) - } else { - if rt != nil { - destKind = rt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) - } - } else { - // both good - // only check both typed. - // should not check on both untyped case TypeID equality, e.g. - // MaxRune = '\U0010FFFF' - // MaxRune + 1 - // that left type is untyped rune with default type of Int32Type - // and right type is untyped bigInt can be converted to int32 too. - if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet - // check when both typed - if lt != nil && rt != nil { // XXX, this should already be excluded by previous checker check. - // TODO: filter byte that has no typeID? - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) - } - } - } - // check even when both sides are compatible with op, - if cmp <= 0 { - checkAssignableTo(lt, rt, true) - store.AddAssignableCheckResult(bx.Left, rt) - - } else { - checkAssignableTo(rt, lt, true) - store.AddAssignableCheckResult(bx.Right, lt) + if !checker(dt) { // lt not compatible with op + if dt != nil { // return error on left side that is checked first + destKind = dt.Kind() } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } } @@ -840,7 +752,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { var destKind interface{} // XXX, assume lhs length is same with of rhs - // TODO: how about call func case? // Call case: a, b = x(...) for i, x := range as.Lhs { lt := evalStaticTypeOf(store, last, x) @@ -869,29 +780,20 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } switch as.Op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: - // if both typed + // check when both typed if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet if lt != nil && rt != nil { - // TODO: filter byte that has no typeID? if lt.TypeID() != rt.TypeID() { panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) } } } - // TODO: checkAssignable default: // do nothing } } else { panic("should not happen") } - } else if as.Op != SHR_ASSIGN && as.Op != SHL_ASSIGN { - // TODO: test on simple assign - // check assignable, after done check operand with op. - // special case if rhs is(or embedded) untyped shift, - // assignable is checked prior to this. - checkAssignableTo(rt, lt, false) // TODO: should be for all - store.AddAssignableCheckResult(as.Rhs[i], lt) } } } diff --git a/gnovm/tests/debug/0f0_native_filetest.gnoa b/gnovm/tests/debug/0f0_native_filetest.gnoa deleted file mode 100644 index 8456b73ade7..00000000000 --- a/gnovm/tests/debug/0f0_native_filetest.gnoa +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if 1 == errCmp { - //if errCmp == 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/debug/0f0_native_filetest.gno:19: unexpected type pair: cannot use bigint as gonative{error} diff --git a/gnovm/tests/debug/0f2_filetest.gnoa b/gnovm/tests/debug/0f2_filetest.gnoa deleted file mode 100644 index 6e18520d226..00000000000 --- a/gnovm/tests/debug/0f2_filetest.gnoa +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "errors" -) - -type Error string - -func (e Error) Error() string { - return string(e) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -// TODO: seems what we can do is to not allowed gonative non-empty interface come into gno -// namely, we don't run this in .native mode, (withNativeLibs) -func main() { - if Error("XXXX") == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 - //if errCmp == 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/debug/0f7_filetest_stdlibs.gnoa b/gnovm/tests/debug/0f7_filetest_stdlibs.gnoa deleted file mode 100644 index 29a6061cd77..00000000000 --- a/gnovm/tests/debug/0f7_filetest_stdlibs.gnoa +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if errCmp == Error(1) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/debug/10a001_filetest.gnoa b/gnovm/tests/debug/10a001_filetest.gnoa deleted file mode 100644 index 3af624a1d2f..00000000000 --- a/gnovm/tests/debug/10a001_filetest.gnoa +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - r := uint64(1<<2 == 1>>2) - println(r) -} - -// Error: -// main/files/types2/10a001_filetest.gno:4: cannot convert BoolKind to Uint64Kind \ No newline at end of file diff --git a/gnovm/tests/debug/10a27e.gnoa b/gnovm/tests/debug/10a27e.gnoa deleted file mode 100644 index d0e8658372c..00000000000 --- a/gnovm/tests/debug/10a27e.gnoa +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import "fmt" - -func main() { - x := 11 - y := uint64(-(1 << 2) << x) - println(y) - fmt.Printf("%T \n", y) -} - -// Error: -// main/debug/10a27e.gno:7: bigint underflows target kind diff --git a/gnovm/tests/debug/15b.gnoa b/gnovm/tests/debug/15b.gnoa deleted file mode 100644 index 4cb0b57fb09..00000000000 --- a/gnovm/tests/debug/15b.gnoa +++ /dev/null @@ -1,30 +0,0 @@ -package main - -// 1. find where shift expr is used -// a) type cast -// b) assign stmt -// c) composite literals - -// 2. get the dest type, if convert condition, convert -// condition: -// a) arg has shift and untyped. since everytime we deal with non-composed shift expr, we can set and get -// attr: HAS_SHIFT to determine if has shift. - -// 3. in type func, find termination condition when not const -// this condition should be the opposite of the convert condition - -// TODO: composite literal -// TODO: simple print non-const untyped - -func main() { - type S struct { - a float32 - } - s := S{ - a: 1 << 2, - } - println(s.a) -} - -// Output: -// 4 diff --git a/gnovm/tests/debug/2.gnoa b/gnovm/tests/debug/2.gnoa deleted file mode 100644 index 230a58ed2b5..00000000000 --- a/gnovm/tests/debug/2.gnoa +++ /dev/null @@ -1,10 +0,0 @@ -package main - -var e error - -func main() { - e = 1 // this check is currently happening in checkOrConvert, should be in assertCompatibility -} - -// Error: -// main/debug/2.gno:6: bigint does not implement .uverse.error diff --git a/gnovm/tests/debug/22a12_filetest.gnoa b/gnovm/tests/debug/22a12_filetest.gnoa deleted file mode 100644 index e791c05bd43..00000000000 --- a/gnovm/tests/debug/22a12_filetest.gnoa +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type c uint -type word c -type nat []word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - - abs = []c{0} - - println(abs.add()) -} - -// Error: -// main/debug/22a12_filetest.gno:14: cannot use main.c as main.word without explicit conversion diff --git a/gnovm/tests/debug/dec_rem.gnoa b/gnovm/tests/debug/dec_rem.gnoa deleted file mode 100644 index 48c50c5589d..00000000000 --- a/gnovm/tests/debug/dec_rem.gnoa +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1.2 % int(1)) -} - -// Error: -// main/debug/dec_rem.gno:4: cannot convert untyped bigdec to integer -- 1.2 not an exact integer diff --git a/gnovm/tests/debug/dynamic.gnoa b/gnovm/tests/debug/dynamic.gnoa deleted file mode 100644 index 75558dc67ed..00000000000 --- a/gnovm/tests/debug/dynamic.gnoa +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import "errors" - -var err1 = errors.New("xxx") -var err2 = errors.New("xxx") - -func main() { - println(err1 == err2) -} - -// Output: -// false diff --git a/gnovm/tests/debug/iface_eql.gno b/gnovm/tests/debug/iface_eql.gno deleted file mode 100644 index 905778bcd21..00000000000 --- a/gnovm/tests/debug/iface_eql.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -type Foo struct { - n int -} - -func main() { - var l interface{} - //var l interface{} = 1 - //var l interface{} = (*Foo)(nil) - println(1 == l) -} - -// Output: -// false diff --git a/gnovm/tests/debug/struct.gnoa b/gnovm/tests/debug/struct.gnoa deleted file mode 100644 index 3b49842e3ef..00000000000 --- a/gnovm/tests/debug/struct.gnoa +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "errors" - "fmt" -) - -type Foo struct { - N int -} - -func main() { - err1 := errors.New("xxx") - err2 := errors.New("xxx") - - println(err1 == err2) - - s1 := &Foo{N: 1} - s2 := &Foo{N: 1} - - fmt.Println(s1) - fmt.Println(s2) - - println(s1 == s2) - - s3 := Foo{N: 1} - s4 := Foo{N: 1} - - fmt.Println(s3) - fmt.Println(s4) - - println(s3 == s4) - -} - -// Output: -// false -// &{1} -// &{1} -// false -// {1} -// {1} -// true diff --git a/gnovm/tests/debug/untyped.gnoa b/gnovm/tests/debug/untyped.gnoa deleted file mode 100644 index a81faceb4b0..00000000000 --- a/gnovm/tests/debug/untyped.gnoa +++ /dev/null @@ -1,11 +0,0 @@ -// You can edit this code! -// Click here and start typing. -package main - -func main() { - println(int64(1.0 << 1)) - //println(int64(1.0)) -} - -// Output: -// 2 diff --git a/gnovm/tests/debug2/0_a_3b.gno b/gnovm/tests/debug2/0_a_3b.gno deleted file mode 100644 index ff53044fde2..00000000000 --- a/gnovm/tests/debug2/0_a_3b.gno +++ /dev/null @@ -1,39 +0,0 @@ -package main - -// 1. checkOrConvert is the core logic, to convert type(recursively if needed) -// 2. shift expr might remain untyped, until reach its use context, assign, func Call, type call -// 3. assign should be checked, LHS of assign has a type, use it to mutate RHS type if it's untyped; -// it's not coerced -// 4. type call should be checked, it's coerced even RHS is typed. -// 5. func call should be checked, it's not coerced. - -import "fmt" - -type R interface { - foo() -} - -type U64 uint64 - -func (u64 U64) foo() { - println("bar") -} - -func bar(r R) { - r.foo() -} - -// case of expr in type call -func main() { - x := 2 - var r R - // assign to interface - r = 1 << x // 2 step. first binary, second call type - - r.foo() - - fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type -} - -// Error: -// main/debug/0_a_3b.gno:31: operator << not defined on: InterfaceKind diff --git a/gnovm/tests/debug2/0a1f_filetest.gno b/gnovm/tests/debug2/0a1f_filetest.gno deleted file mode 100644 index 4861fe84c03..00000000000 --- a/gnovm/tests/debug2/0a1f_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - expected := `hello`[:] - a := 1 - println(a == expected) // both typed -} - -// Error: -// main/files/types/0a1f_filetest.gno:6: cannot use int as string diff --git a/gnovm/tests/debug2/0f26_stdlibs_filetest.gno b/gnovm/tests/debug2/0f26_stdlibs_filetest.gno deleted file mode 100644 index 70895cc5409..00000000000 --- a/gnovm/tests/debug2/0f26_stdlibs_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if 1 > errCmp { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/debug/0f26_stdlibs_filetest.gno:19: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/debug2/1.gno b/gnovm/tests/debug2/1.gno deleted file mode 100644 index bb30d64b42b..00000000000 --- a/gnovm/tests/debug2/1.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - var a interface{} - println(1 == a) -} - -// Output: -// false diff --git a/gnovm/tests/debug2/10a11_filetest.gno b/gnovm/tests/debug2/10a11_filetest.gno deleted file mode 100644 index 01b90c91783..00000000000 --- a/gnovm/tests/debug2/10a11_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 1 - r := a << "hello" // NOTE: go vet would fail, but still process - println(r) -} - -// Error: -// main/debug/10a11_filetest.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno b/gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno deleted file mode 100644 index 6636a74448e..00000000000 --- a/gnovm/tests/debug2/13a0_ADD_ASSIGN_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - int(0) += int8(1) -} - -// Error: -// main/debug/13a0_ADD_ASSIGN_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/debug2/1b2_filetest.gno b/gnovm/tests/debug2/1b2_filetest.gno deleted file mode 100644 index bd6508b1899..00000000000 --- a/gnovm/tests/debug2/1b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// untyped const -func main() { - println(1 + "a") -} - -// Error: -// main/files/types/1b2_filetest.gno:5: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug2/5d0_filetest.gno b/gnovm/tests/debug2/5d0_filetest.gno deleted file mode 100644 index 4b2e76cef6a..00000000000 --- a/gnovm/tests/debug2/5d0_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1.0 % uint64(1)) -} - -// Output: -// 0 diff --git a/gnovm/tests/debug2/5d0_filetest.gnoa b/gnovm/tests/debug2/5d0_filetest.gnoa deleted file mode 100644 index 4b2e76cef6a..00000000000 --- a/gnovm/tests/debug2/5d0_filetest.gnoa +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1.0 % uint64(1)) -} - -// Output: -// 0 diff --git a/gnovm/tests/debug2/5d0a_filetest.gno b/gnovm/tests/debug2/5d0a_filetest.gno deleted file mode 100644 index a94b7bb6267..00000000000 --- a/gnovm/tests/debug2/5d0a_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1.0 % 1) -} - -// Error: -// main/debug/5d0a_filetest.gno:6: operator % not defined on: BigdecKind \ No newline at end of file diff --git a/gnovm/tests/debug2/5d0b_filetest.gno b/gnovm/tests/debug2/5d0b_filetest.gno deleted file mode 100644 index 781e42c8818..00000000000 --- a/gnovm/tests/debug2/5d0b_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1 % 1.0) -} - -// Error: -// main/debug/5d0b_filetest.gno:6: operator % not defined on: BigdecKind diff --git a/gnovm/tests/debug2/assign.gno b/gnovm/tests/debug2/assign.gno deleted file mode 100644 index 1861fc70b9d..00000000000 --- a/gnovm/tests/debug2/assign.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - x := "hello" - x -= 1 - println(x) -} - -// Error: -// main/debug/assign.gno:5: operator -= not defined on: StringKind diff --git a/gnovm/tests/debug2/assign0b_native.gno b/gnovm/tests/debug2/assign0b_native.gno deleted file mode 100644 index 42faa57634d..00000000000 --- a/gnovm/tests/debug2/assign0b_native.gno +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/gnolang/gno/_test/net/http" -) - -func main() { - http.DefaultClient.Timeout = time.Second * 10 - fmt.Println(http.DefaultClient) - http.DefaultClient = &http.Client{} - fmt.Println(http.DefaultClient) -} - -// Output: -// &{ 10s} -// &{ 0s} diff --git a/gnovm/tests/debug2/binary_1.gno b/gnovm/tests/debug2/binary_1.gno deleted file mode 100644 index 2a34ff399df..00000000000 --- a/gnovm/tests/debug2/binary_1.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1 - "a") -} - -// Error: -// main/debug/binary_1.gno:4: operator - not defined on: StringKind diff --git a/gnovm/tests/debug2/binary_1a.gno b/gnovm/tests/debug2/binary_1a.gno deleted file mode 100644 index 58645824754..00000000000 --- a/gnovm/tests/debug2/binary_1a.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1 == "a") -} - -// Error: -// main/debug/binary_1a.gno:4: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug2/binary_1b.gno b/gnovm/tests/debug2/binary_1b.gno deleted file mode 100644 index ee5e339929b..00000000000 --- a/gnovm/tests/debug2/binary_1b.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1 > "a") -} - -// Error: -// main/debug/binary_1b.gno:4: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/debug2/binary_2.gnoa b/gnovm/tests/debug2/binary_2.gnoa deleted file mode 100644 index 3559298a655..00000000000 --- a/gnovm/tests/debug2/binary_2.gnoa +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println((1 + 2) == (int(1) + "a")) -} - -// Error: -// main/debug/binary_2.gno:4: ===invalid operation: mismatched types int and string diff --git a/gnovm/tests/debug2/binary_3.gnoa b/gnovm/tests/debug2/binary_3.gnoa deleted file mode 100644 index 04bd98f3b58..00000000000 --- a/gnovm/tests/debug2/binary_3.gnoa +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(((1 + 2) + 3) == (int32(1) + 'a')) -} - -// Output: -// false diff --git a/gnovm/tests/debug2/default_type.gno b/gnovm/tests/debug2/default_type.gno deleted file mode 100644 index ff32d383f04..00000000000 --- a/gnovm/tests/debug2/default_type.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(1) -} - -// Output: -// 1 diff --git a/gnovm/tests/debug2/inc.gno b/gnovm/tests/debug2/inc.gno deleted file mode 100644 index 31a47b6504e..00000000000 --- a/gnovm/tests/debug2/inc.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := "hello" - a++ - println(a) -} - -// Error: -// main/debug/inc.gno:5: operator ++ not defined on: StringKind diff --git a/gnovm/tests/debug2/native.gno b/gnovm/tests/debug2/native.gno deleted file mode 100644 index cbb76327ef7..00000000000 --- a/gnovm/tests/debug2/native.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import "time" - -func main() { - println(1 && time.Second) - //println(1 * time.Second) -} - -// Error: -// main/debug/time_stdlibs.gno:5: operator && not defined on: Int64Kind -// *** CHECK THE ERR MESSAGES ABOVE, MAKE SURE IT'S WHAT YOU EXPECTED, DELETE THIS LINE AND RUN TEST AGAIN *** diff --git a/gnovm/tests/debug2/time4_native.gno b/gnovm/tests/debug2/time4_native.gno deleted file mode 100644 index 3662e35cb01..00000000000 --- a/gnovm/tests/debug2/time4_native.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "fmt" - "time" -) - -func main() { - var m time.Month - m = 9 - fmt.Println(m) -} - -// Output: -// September diff --git a/gnovm/tests/debug2/type34.gno b/gnovm/tests/debug2/type34.gno deleted file mode 100644 index 240e1918837..00000000000 --- a/gnovm/tests/debug2/type34.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -type FooS struct { -} - -type BarS FooS - -func main() { - var _ *BarS = (*BarS)(nil) -} diff --git a/gnovm/tests/debug2/unary.gno b/gnovm/tests/debug2/unary.gno deleted file mode 100644 index 176f8824ed1..00000000000 --- a/gnovm/tests/debug2/unary.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - a := "hello" - println(+a) -} - -// main/debug/unary.gno:5: operator + not defined on: StringKind diff --git a/gnovm/tests/debug3/0f2_filetest.gnoa b/gnovm/tests/debug3/0f2_filetest.gnoa deleted file mode 100644 index 67361dc8424..00000000000 --- a/gnovm/tests/debug3/0f2_filetest.gnoa +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - //if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 - if errCmp == Error(0) { // this would not convert, errCmp is interface, refer to preprocess, line2526 - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/debug3/0f2b_native.gnoa b/gnovm/tests/debug3/0f2b_native.gnoa deleted file mode 100644 index 8b9ba7ba0e5..00000000000 --- a/gnovm/tests/debug3/0f2b_native.gnoa +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if Error(0) <= errCmp { - //if errCmp == 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/debug/0f2b_native.gno:19: operator <= not defined on: InterfaceKind diff --git a/gnovm/tests/debug3/0f47f_filetest.gnoa b/gnovm/tests/debug3/0f47f_filetest.gnoa deleted file mode 100644 index 4b2c6120dd0..00000000000 --- a/gnovm/tests/debug3/0f47f_filetest.gnoa +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import "fmt" - -// note, cast untyped nil to interface{}, hence comparable, special case -// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false -func main() { - println(interface{}(nil) == (*int)(nil)) // refer to convertConst and convertTo - fmt.Printf("%T \n", interface{}(nil)) - println(interface{}(nil)) -} - -// Output: -// false -// -// nil diff --git a/gnovm/tests/debug3/2.gnoa b/gnovm/tests/debug3/2.gnoa deleted file mode 100644 index 230a58ed2b5..00000000000 --- a/gnovm/tests/debug3/2.gnoa +++ /dev/null @@ -1,10 +0,0 @@ -package main - -var e error - -func main() { - e = 1 // this check is currently happening in checkOrConvert, should be in assertCompatibility -} - -// Error: -// main/debug/2.gno:6: bigint does not implement .uverse.error diff --git a/gnovm/tests/debug4/issue-558b.gno b/gnovm/tests/debug4/issue-558b.gno deleted file mode 100644 index 760c677d3f5..00000000000 --- a/gnovm/tests/debug4/issue-558b.gno +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "fmt" - "io" - "log" - "strings" -) - -type readAutoCloser struct { - r io.ReadCloser -} - -func (a readAutoCloser) Read(b []byte) (n int, err error) { - if a.r == nil { - return 0, io.EOF - } - n, err = a.r.Read(b) - if err == io.EOF { - a.Close() - } - return n, err -} - -func (a readAutoCloser) Close() error { - if a.r == nil { - return nil - } - return a.r.(io.Closer).Close() -} - -type pipe struct { - Reader readAutoCloser -} - -func newReadAutoCloser(r io.Reader) readAutoCloser { - if _, ok := r.(io.Closer); !ok { - return readAutoCloser{io.NopCloser(r)} - } - return readAutoCloser{r.(io.ReadCloser)} -} - -type Reader interface { - Read(b []byte) (n int, err error) -} - -func ReadAll(r Reader) ([]byte, error) { - b := make([]byte, 0, 512) - for { - if len(b) == cap(b) { - // Add more capacity (let append pick how much). - b = append(b, 0)[:len(b)] - } - n, err := r.Read(b[len(b):cap(b)]) - b = b[:len(b)+n] - if err != nil { - //if err == io.EOF { - if io.EOF == err { - err = nil - } - return b, err - } - } -} - -func main() { - p := &pipe{} - p.Reader = newReadAutoCloser(strings.NewReader("test")) - b, err := ReadAll(p.Reader) - if err != nil { - log.Fatal(err) - } - fmt.Println(string(b)) -} - -// Output: -// test diff --git a/gnovm/tests/debug4/time1_native.gno b/gnovm/tests/debug4/time1_native.gno deleted file mode 100644 index d66c4365045..00000000000 --- a/gnovm/tests/debug4/time1_native.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import "time" - -func main() { - var a int8 - a = 1 - println(a * time.Second) -} - -// Error: -// main/debug/time1_native.gno:8: cannot use int8 as int64 diff --git a/gnovm/tests/debug4/time1_stdlibs.gno b/gnovm/tests/debug4/time1_stdlibs.gno deleted file mode 100644 index d41342fc362..00000000000 --- a/gnovm/tests/debug4/time1_stdlibs.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import "time" - -func main() { - var a int8 - a = 1 - println(a * time.Second) -} - -// Error: -// main/debug/time1_stdlibs.gno:8: invalid operation: mismatched types int8 and time.Duration diff --git a/gnovm/tests/debug4/time2_native.gno b/gnovm/tests/debug4/time2_native.gno deleted file mode 100644 index eac7a061264..00000000000 --- a/gnovm/tests/debug4/time2_native.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import "time" - -func main() { - - println(time.Second * time.Second) -} - -// Output: -// 277777h46m40s diff --git a/gnovm/tests/debug4/time2_stdlibs.gno b/gnovm/tests/debug4/time2_stdlibs.gno deleted file mode 100644 index eac7a061264..00000000000 --- a/gnovm/tests/debug4/time2_stdlibs.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import "time" - -func main() { - - println(time.Second * time.Second) -} - -// Output: -// 277777h46m40s diff --git a/gnovm/tests/debug4/time_native.gno b/gnovm/tests/debug4/time_native.gno deleted file mode 100644 index 4c5ee4270be..00000000000 --- a/gnovm/tests/debug4/time_native.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import "time" - -func main() { - var a int8 - a = 1 - println(time.Second * a) -} - -// Error: -// main/debug/time_native.gno:8: cannot use int8 as int64 diff --git a/gnovm/tests/debug4/time_stdlibs.gno b/gnovm/tests/debug4/time_stdlibs.gno deleted file mode 100644 index a8ec9524155..00000000000 --- a/gnovm/tests/debug4/time_stdlibs.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import "time" - -func main() { - var a int8 - a = 1 - println(time.Second * a) -} - -// Error: -// main/debug/time_stdlibs.gno:8: invalid operation: mismatched types time.Duration and int8 diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index 68c92e9a504..1c8b91b02fd 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/type31.gno:8: invalid operation: mismatched types string and main.String +// main/files/type31.gno:8: cannot use string as main.String without explicit conversion diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index 9565cdba245..58a19f606ae 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/type32.gno:9#1: invalid operation: mismatched types string and main.S +// main/files/type32.gno:9#1: cannot use string as main.S without explicit conversion diff --git a/gnovm/tests/files/types/0f2_stdlibs.gno b/gnovm/tests/files/types/0f2_stdlibs.gno index 7ded58b4ff0..16b4e82476b 100644 --- a/gnovm/tests/files/types/0f2_stdlibs.gno +++ b/gnovm/tests/files/types/0f2_stdlibs.gno @@ -16,7 +16,7 @@ var errCmp = errors.New("XXXX") // specil case: // one is interface func main() { - if Error(0) == errCmp { // this would not convert, errCmp is interface, refer to preprocess, line2526 + if Error(0) == errCmp { // this would not convert, errCmp is interface //if errCmp == 1 { println("what the firetruck?") } else { diff --git a/gnovm/tests/files/types/1a0_ADD_filetest.gno b/gnovm/tests/files/types/1a0_ADD_filetest.gno index ab289f63cae..985b859ec80 100644 --- a/gnovm/tests/files/types/1a0_ADD_filetest.gno +++ b/gnovm/tests/files/types/1a0_ADD_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/1a0_ADD_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/1a0_ADD_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/1a1_filetest.gno b/gnovm/tests/files/types/1a1_filetest.gno index 0a33e70266d..ff236a28012 100644 --- a/gnovm/tests/files/types/1a1_filetest.gno +++ b/gnovm/tests/files/types/1a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/1a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/1a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/1e0_filetest.gno b/gnovm/tests/files/types/1e0_filetest.gno index 301859bd538..61c999ce0af 100644 --- a/gnovm/tests/files/types/1e0_filetest.gno +++ b/gnovm/tests/files/types/1e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/1e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/1e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/20a0_LSS_filetest.gno b/gnovm/tests/files/types/20a0_LSS_filetest.gno index 8031eaca468..f11bda7fd5c 100644 --- a/gnovm/tests/files/types/20a0_LSS_filetest.gno +++ b/gnovm/tests/files/types/20a0_LSS_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/20a0_LSS_filetest.gno:4: invalid operation: mismatched types int and int8 +// main/files/types/20a0_LSS_filetest.gno:4: cannot use int as int8 diff --git a/gnovm/tests/files/types/2a0_SUB_filetest.gno b/gnovm/tests/files/types/2a0_SUB_filetest.gno index 79881e8583b..cb3de0548db 100644 --- a/gnovm/tests/files/types/2a0_SUB_filetest.gno +++ b/gnovm/tests/files/types/2a0_SUB_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2a0_SUB_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/2a0_SUB_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/2a1_filetest.gno b/gnovm/tests/files/types/2a1_filetest.gno index 1155f93370d..53ef6bf03db 100644 --- a/gnovm/tests/files/types/2a1_filetest.gno +++ b/gnovm/tests/files/types/2a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/2a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/2a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/2e0_filetest.gno b/gnovm/tests/files/types/2e0_filetest.gno index 5e72d7ee487..42d9b638e12 100644 --- a/gnovm/tests/files/types/2e0_filetest.gno +++ b/gnovm/tests/files/types/2e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/2e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/2e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/3a0_MUL_filetest.gno b/gnovm/tests/files/types/3a0_MUL_filetest.gno index 71a3ff8f957..45674e75a08 100644 --- a/gnovm/tests/files/types/3a0_MUL_filetest.gno +++ b/gnovm/tests/files/types/3a0_MUL_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/3a0_MUL_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/3a0_MUL_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/3a1_filetest.gno b/gnovm/tests/files/types/3a1_filetest.gno index 3cd8d284400..0244780e786 100644 --- a/gnovm/tests/files/types/3a1_filetest.gno +++ b/gnovm/tests/files/types/3a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/3a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/3a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/3e0_filetest.gno b/gnovm/tests/files/types/3e0_filetest.gno index c1080dcd091..0916d0acede 100644 --- a/gnovm/tests/files/types/3e0_filetest.gno +++ b/gnovm/tests/files/types/3e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/3e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/3e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/4a0_QUO_filetest.gno b/gnovm/tests/files/types/4a0_QUO_filetest.gno index 84376642b72..65cc7d0a438 100644 --- a/gnovm/tests/files/types/4a0_QUO_filetest.gno +++ b/gnovm/tests/files/types/4a0_QUO_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/4a0_QUO_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/4a0_QUO_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/4a1_filetest.gno b/gnovm/tests/files/types/4a1_filetest.gno index 6dab9a883ad..44630848b9c 100644 --- a/gnovm/tests/files/types/4a1_filetest.gno +++ b/gnovm/tests/files/types/4a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/4a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/4a1_filetest.gno:21: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4e01_filetest.gno b/gnovm/tests/files/types/4e01_filetest.gno new file mode 100644 index 00000000000..41f8befcafa --- /dev/null +++ b/gnovm/tests/files/types/4e01_filetest.gno @@ -0,0 +1,21 @@ +package main + +import ( + "strconv" +) + +type Error1 int64 + +func (e Error1) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +// both not const, typed +func main() { + var e1 Error1 = Error1(0) + var e2 Error1 = Error1(0) + println(e1 / e2) +} + +// Error: +// runtime error: integer divide by zero diff --git a/gnovm/tests/files/types/4e0_filetest.gno b/gnovm/tests/files/types/4e0_filetest.gno index e70bc1670ce..ebea41b40a7 100644 --- a/gnovm/tests/files/types/4e0_filetest.gno +++ b/gnovm/tests/files/types/4e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/4e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/4e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion \ No newline at end of file diff --git a/gnovm/tests/files/types/5a0_REM_filetest.gno b/gnovm/tests/files/types/5a0_REM_filetest.gno index b12303f8ef5..779841081cf 100644 --- a/gnovm/tests/files/types/5a0_REM_filetest.gno +++ b/gnovm/tests/files/types/5a0_REM_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/5a0_REM_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/5a0_REM_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/5a1_filetest.gno b/gnovm/tests/files/types/5a1_filetest.gno index ccb98a06446..8fb68a9be3b 100644 --- a/gnovm/tests/files/types/5a1_filetest.gno +++ b/gnovm/tests/files/types/5a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/5a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/5a1_filetest.gno:21: invalid operation: division by zero diff --git a/gnovm/tests/files/types/5e0_filetest.gno b/gnovm/tests/files/types/5e0_filetest.gno index 37fd9ab2eb5..3dc5ebc4dd8 100644 --- a/gnovm/tests/files/types/5e0_filetest.gno +++ b/gnovm/tests/files/types/5e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/5e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/5e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/6a0_AND_filetest.gno b/gnovm/tests/files/types/6a0_AND_filetest.gno index e9555bbb34c..110c6c96046 100644 --- a/gnovm/tests/files/types/6a0_AND_filetest.gno +++ b/gnovm/tests/files/types/6a0_AND_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/6a0_AND_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/6a0_AND_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/6a1_filetest.gno b/gnovm/tests/files/types/6a1_filetest.gno index 45e0596625f..81bfd16a3c5 100644 --- a/gnovm/tests/files/types/6a1_filetest.gno +++ b/gnovm/tests/files/types/6a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/6a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/6a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/6e0_filetest.gno b/gnovm/tests/files/types/6e0_filetest.gno index 0d9349850f7..6a82079919e 100644 --- a/gnovm/tests/files/types/6e0_filetest.gno +++ b/gnovm/tests/files/types/6e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/6e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/6e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/7a0_OR_filetest.gno b/gnovm/tests/files/types/7a0_OR_filetest.gno index a53972c2883..f62be132b3d 100644 --- a/gnovm/tests/files/types/7a0_OR_filetest.gno +++ b/gnovm/tests/files/types/7a0_OR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/7a0_OR_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/7a0_OR_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/7a1_filetest.gno b/gnovm/tests/files/types/7a1_filetest.gno index 111a5ec95d0..df1072fff7a 100644 --- a/gnovm/tests/files/types/7a1_filetest.gno +++ b/gnovm/tests/files/types/7a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/7a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/7a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/7e0_filetest.gno b/gnovm/tests/files/types/7e0_filetest.gno index b19ab007e05..f3dbe2f08cc 100644 --- a/gnovm/tests/files/types/7e0_filetest.gno +++ b/gnovm/tests/files/types/7e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/7e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/7e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/8a0_XOR_filetest.gno b/gnovm/tests/files/types/8a0_XOR_filetest.gno index 991a4afdcc1..3fcdbcc18e6 100644 --- a/gnovm/tests/files/types/8a0_XOR_filetest.gno +++ b/gnovm/tests/files/types/8a0_XOR_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/8a0_XOR_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/8a0_XOR_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/8a1_filetest.gno b/gnovm/tests/files/types/8a1_filetest.gno index b6e2d6ab6d6..c4e63ba9986 100644 --- a/gnovm/tests/files/types/8a1_filetest.gno +++ b/gnovm/tests/files/types/8a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/8a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/8a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/8e0_filetest.gno b/gnovm/tests/files/types/8e0_filetest.gno index 66da7325199..393c2d9be3d 100644 --- a/gnovm/tests/files/types/8e0_filetest.gno +++ b/gnovm/tests/files/types/8e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/8e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/8e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno index 143535662bf..8cdb7bae8cd 100644 --- a/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno +++ b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/9a0_ANDNOT_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/9a0_ANDNOT_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/9a1_filetest.gno b/gnovm/tests/files/types/9a1_filetest.gno index 56224382fae..2a426d60e53 100644 --- a/gnovm/tests/files/types/9a1_filetest.gno +++ b/gnovm/tests/files/types/9a1_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/9a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/9a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/9e0_filetest.gno b/gnovm/tests/files/types/9e0_filetest.gno index 14dcd736468..7f8d83a5f4e 100644 --- a/gnovm/tests/files/types/9e0_filetest.gno +++ b/gnovm/tests/files/types/9e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/9e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/9e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion From 64dc20d40728b466eefd0de3625853f18eced16a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 4 Apr 2024 19:43:50 +0800 Subject: [PATCH 113/193] clean --- gnovm/pkg/gnolang/gonative.go | 8 +-- gnovm/pkg/gnolang/nodes.go | 1 - gnovm/pkg/gnolang/nodes_string.go | 2 +- gnovm/pkg/gnolang/op_binary.go | 18 ++---- gnovm/pkg/gnolang/op_exec.go | 2 +- gnovm/pkg/gnolang/op_expressions.go | 1 - gnovm/pkg/gnolang/op_types.go | 2 - gnovm/pkg/gnolang/preprocess.go | 64 ++++----------------- gnovm/pkg/gnolang/store.go | 76 +++++++------------------ gnovm/pkg/gnolang/type_check.go | 45 ++++----------- gnovm/pkg/gnolang/types.go | 28 --------- gnovm/pkg/gnolang/values.go | 1 - gnovm/pkg/gnolang/values_conversions.go | 16 +----- 13 files changed, 54 insertions(+), 210 deletions(-) diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index b76528d8f8a..b34ffc86c05 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -364,7 +364,7 @@ func go2GnoValue(alloc *Allocator, rv reflect.Value) (tv TypedValue) { } if rv.Kind() == reflect.Interface { if rv.IsNil() { - return TypedValue{} // TODO: with type? + return TypedValue{} } else { rv = rv.Elem() } @@ -905,7 +905,6 @@ func gno2GoType(t Type) reflect.Type { // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { - debug.Printf("---gno2GoTypeMatches, t: %v, rt: %v, type of t: %v \n", t, rt, reflect.TypeOf(t)) if rt == nil { panic("should not happen") } @@ -921,9 +920,6 @@ func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { case BoolType, UntypedBoolType: return rt.Kind() == reflect.Bool case StringType, UntypedStringType: - debug.Println("---string type") - debug.Println("---rt.Kind: ", rt.Kind()) - debug.Println(rt.Kind() == reflect.String) return rt.Kind() == reflect.String case IntType: return rt.Kind() == reflect.Int @@ -975,7 +971,6 @@ func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { } return gno2GoTypeMatches(ct.Elt, rt.Elem()) case *StructType: - //debug.Println("---struct type") // TODO maybe consider automatically skipping private native fields? for i, field := range ct.Fields { rft := rt.Field(i).Type @@ -1410,7 +1405,6 @@ func (m *Machine) doOpStructLitGoNative() { // NOTE: Unlike doOpCall(), doOpCallGoNative() also handles // conversions, similarly to doOpConvert(). func (m *Machine) doOpCallGoNative() { - debug.Println("---doOpCallGoNative") fr := m.LastFrame() fv := fr.GoFunc ft := fv.Value.Type() diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 9aa6d5646cd..2a9e0b51a97 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -2021,7 +2021,6 @@ const ( ATTR_IOTA GnoAttribute = "ATTR_IOTA" ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" ATTR_INJECTED GnoAttribute = "ATTR_INJECTED" - ATTR_DELAY GnoAttribute = "ATTR_DELAY" ) // TODO: consider length restrictions. diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index 37db308fe31..547ad83294d 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -13,7 +13,7 @@ var wordTokenStrings = map[Word]string{ SUB: "-", MUL: "*", QUO: "/", - REM: "%", // escape to be rendered correctly + REM: "%", BAND: "&", BOR: "|", XOR: "^", diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index e4a654143eb..0f2b294f9d2 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -77,15 +77,10 @@ func (m *Machine) doOpEql() { rv := m.PopValue() lv := m.PeekValue(1) // also the result - debug.Printf("---doOpEql: lv: %v, rv: %v \n", lv, rv) - debug.Printf("---doOpEql: lv.T: %v, rv.T: %v \n", lv.T, rv.T) - debug.Printf("---doOpEql: lv.V: %v, rv.V: %v \n", lv.V, rv.V) - debug.Printf("---doOpEql: lv.N: %v, rv.N: %v \n", lv.N, rv.N) - var res bool if debug { - assertAssignable(lv.T, rv.T) + assertEqualityTypes(lv.T, rv.T) } - res = isEql(m.Store, lv, rv) + res := isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -98,12 +93,11 @@ func (m *Machine) doOpNeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result - var res bool if debug { - assertAssignable(lv.T, rv.T) + assertEqualityTypes(lv.T, rv.T) } - res = !isEql(m.Store, lv, rv) + res := !isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil lv.SetBool(res) @@ -340,7 +334,6 @@ func (m *Machine) doOpBandn() { // TODO: can be much faster. func isEql(store Store, lv, rv *TypedValue) bool { - debug.Printf("---isEql, lv: %v, rv: %v \n", lv, rv) // If one is undefined, the other must be as well. // Fields/items are set to defaultValue along the way. lvu := lv.IsUndefined() @@ -350,10 +343,9 @@ func isEql(store Store, lv, rv *TypedValue) bool { } else if rvu { return false } - if !isSameType(lv.T, rv.T) { + if !assertSameTypes2(lv.T, rv.T) { return false } - debug.Println("---assert to be same types") if lnt, ok := lv.T.(*NativeType); ok { if rnt, ok := rv.T.(*NativeType); ok { if lnt.Type != rnt.Type { diff --git a/gnovm/pkg/gnolang/op_exec.go b/gnovm/pkg/gnolang/op_exec.go index 5a7431799b3..300303135ad 100644 --- a/gnovm/pkg/gnolang/op_exec.go +++ b/gnovm/pkg/gnolang/op_exec.go @@ -957,7 +957,7 @@ func (m *Machine) doOpSwitchClauseCase() { // eval whether cv == tv. if debug { - assertAssignable(cv.T, tv.T) + assertEqualityTypes(cv.T, tv.T) } match := isEql(m.Store, cv, tv) if match { diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index a6141854fe0..0f107b84fc6 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -78,7 +78,6 @@ func (m *Machine) doOpIndex2() { func (m *Machine) doOpSelector() { sx := m.PopExpr().(*SelectorExpr) xv := m.PeekValue(1) - debug.Printf("---doOpSelector, xv:%v \n", xv) res := xv.GetPointerTo(m.Alloc, m.Store, sx.Path) *xv = res.Deref() // reuse as result } diff --git a/gnovm/pkg/gnolang/op_types.go b/gnovm/pkg/gnolang/op_types.go index d26c455cd88..6999af33680 100644 --- a/gnovm/pkg/gnolang/op_types.go +++ b/gnovm/pkg/gnolang/op_types.go @@ -231,8 +231,6 @@ func (m *Machine) doOpStaticTypeOf() { // NOTE: this code segment similar to that in op_types.go var dxt Type path := x.Path // mutable - debug.Printf("---SelectorExpr, path: %v \n", path) - debug.Printf("---SelectorExpr, path.Type: %v \n", path.Type) switch path.Type { case VPField: switch path.Depth { // see tests/selector_test.go for cases. diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 68499b7a674..592d47aaef3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -740,8 +740,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *BinaryExpr: - debug.Println("---BinaryExpr") - // TODO: improve readability lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) @@ -754,7 +752,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // check compatible n.checkShiftExpr(lt) // checkOrConvert RHS - if baseOf(rt) != UintType { // TODO: XXX, is it good for native? + if baseOf(rt) != UintType { // convert n.Right to (gno) uint type, rn := Expr(Call("uint", n.Right)) // reset/create n2 to preprocess right child. @@ -773,7 +771,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) - debug.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + if debug { + debug.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + } if lic { if ric { // Left const, Right const ---------------------- @@ -783,23 +783,18 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if !isShift { cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { - debug.Println("cmp < 0, ->") // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { - debug.Println("cmp == 0") // to typed-nil. refer to 0f46 - if lcx.T == nil { // TODO: make nil check happen in cmpSpecificity + if lcx.T == nil { checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if rcx.T == nil { checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } else { checkOrConvertType(store, last, &n.Left, rcx.T, false, false) - // do nothing, all compatibility is checked, - // e.g. int(1) == int8(1), will also conduct type check } } else { - debug.Println("cmp > 0, <-") // convert n.Right to left type. checkOrConvertType(store, last, &n.Right, lcx.T, false, false) } @@ -813,9 +808,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isShift { // RHS of shift should not be native panic("should not happen") } - debug.Printf("---n: %v \n", n) - debug.Printf("---rt: %v \n", rt) - debug.Printf("---rnt: %v \n", rnt) // get concrete native base type. pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) if !ok { @@ -828,10 +820,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, pt, false, false) // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) - debug.Printf("---rn : %v \n", rn) // and convert result back. tx := constType(n, rnt) - debug.Printf("---tx : %v \n", tx) // reset/create n2 to preprocess right child. n2 := &BinaryExpr{ Left: n.Left, @@ -840,7 +830,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} resn = Preprocess(store, last, resn) - debug.Printf("---resn : %v \n", resn) return resn, TRANS_CONTINUE // NOTE: binary operations are always computed in // gno, never with reflect. @@ -860,9 +849,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if isUntyped(rt) { // refer to 0_d.gno. e.g. int(1) + 1< native. it's reasonable for gno is a superset of go type, e.g. bigint if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. - debug.Println("---dt not native, go check") - // the reason why we need this is that the checkOperandWithOp() can not filter out all mismatch case, - // e.g. int(1) == int8(1), the pre check won't halt this kind of expr(with op ==, !=). - // we still need a safeguard before convertConst, which will conduct mandatory conversion from int(1) to int8(1). - // this is for binaryExpr that assignable has already been checked and cached - //if store.AssertAssignableExists(*x, t) { - // debug.Printf("---assignable already set for: %v => %v \n", cx, t) - //} else { - // still need for non-binary, like arg + // e.g. int(1) == int8(1) checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a - debug.Println("---check pass in checkOrConvertType!") - //} } } convertConst(store, last, cx, t) @@ -2461,18 +2423,18 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if debug { debug.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) } - var isUnnamed bool + var needConversion bool // for unnamed -> named if t != nil && !coerce { - isUnnamed = checkAssignableTo(xt, t, autoNative) + needConversion = checkAssignableTo(xt, t, autoNative) } if isUntyped(xt) { if _, ok := t.(*InterfaceType); ok || t == nil { t = defaultTypeOf(xt) } - debug.Printf("default type of t: %v \n", t) + if debug { + debug.Printf("default type of t: %v \n", t) + } // Push type into expr if qualifying binary expr. - // main logic for handling nested binary expr - // e.g. 1 << 2 + 1 << x, will be handled recursively until its type is determined. if bx, ok := (*x).(*BinaryExpr); ok { switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, @@ -2494,7 +2456,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } // unnamed to named - if isUnnamed { + if needConversion { cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx @@ -2510,11 +2472,9 @@ func convertIfConst(store Store, last BlockNode, x Expr) { } func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { - debug.Println("---convertConst") if t != nil && t.Kind() == InterfaceKind { if cx.IsUndefined() && cx.T == nil { // if cx is nil, not undefined interface if _, ok := t.(*NativeType); !ok { // bypass native nil interface, not support native interface(nil) now - debug.Println("---going to convert undefined interface") ConvertTo(nilAllocator, store, &cx.TypedValue, t) setConstAttrs(cx) return diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index 17510f180b3..24aff4936f3 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -24,8 +24,6 @@ type Store interface { SetCachePackage(*PackageValue) GetPackageRealm(pkgPath string) *Realm SetPackageRealm(*Realm) - AddAssignableCheckResult(key Expr, value Type) - AssertAssignableExists(key Expr, value Type) bool GetObject(oid ObjectID) Object GetObjectSafe(oid ObjectID) Object SetObject(Object) @@ -63,18 +61,17 @@ type Store interface { // Used to keep track of in-mem objects during tx. type defaultStore struct { - alloc *Allocator // for accounting for cached items - pkgGetter PackageGetter // non-realm packages - cacheObjects map[ObjectID]Object - cacheTypes map[TypeID]Type - cacheNodes map[Location]BlockNode - cacheNativeTypes map[reflect.Type]Type // go spec: reflect.Type are comparable - cacheAssignableCheck map[string]map[string]bool - baseStore store.Store // for objects, types, nodes - iavlStore store.Store // for escaped object hashes - pkgInjector PackageInjector // for injecting natives - go2gnoMap map[string]string // go pkgpath.name -> gno pkgpath.name - go2gnoStrict bool // if true, native->gno type conversion must be registered. + alloc *Allocator // for accounting for cached items + pkgGetter PackageGetter // non-realm packages + cacheObjects map[ObjectID]Object + cacheTypes map[TypeID]Type + cacheNodes map[Location]BlockNode + cacheNativeTypes map[reflect.Type]Type // go spec: reflect.Type are comparable + baseStore store.Store // for objects, types, nodes + iavlStore store.Store // for escaped object hashes + pkgInjector PackageInjector // for injecting natives + go2gnoMap map[string]string // go pkgpath.name -> gno pkgpath.name + go2gnoStrict bool // if true, native->gno type conversion must be registered. // transient opslog []StoreOp // for debugging and testing. @@ -83,18 +80,17 @@ type defaultStore struct { func NewStore(alloc *Allocator, baseStore, iavlStore store.Store) *defaultStore { ds := &defaultStore{ - alloc: alloc, - pkgGetter: nil, - cacheObjects: make(map[ObjectID]Object), - cacheTypes: make(map[TypeID]Type), - cacheNodes: make(map[Location]BlockNode), - cacheNativeTypes: make(map[reflect.Type]Type), - cacheAssignableCheck: make(map[string]map[string]bool), - baseStore: baseStore, - iavlStore: iavlStore, - go2gnoMap: make(map[string]string), - go2gnoStrict: true, - current: make(map[string]struct{}), + alloc: alloc, + pkgGetter: nil, + cacheObjects: make(map[ObjectID]Object), + cacheTypes: make(map[TypeID]Type), + cacheNodes: make(map[Location]BlockNode), + cacheNativeTypes: make(map[reflect.Type]Type), + baseStore: baseStore, + iavlStore: iavlStore, + go2gnoMap: make(map[string]string), + go2gnoStrict: true, + current: make(map[string]struct{}), } InitStoreCaches(ds) return ds @@ -202,33 +198,6 @@ func (ds *defaultStore) GetPackage(pkgPath string, isImport bool) *PackageValue return nil } -func (ds *defaultStore) AddAssignableCheckResult(key Expr, value Type) { - if ds.cacheAssignableCheck[key.String()] == nil { - ds.cacheAssignableCheck[key.String()] = make(map[string]bool) - } - var destTypeStr string - if value != nil { - destTypeStr = value.String() - } else { - destTypeStr = "" - } - ds.cacheAssignableCheck[key.String()][destTypeStr] = true -} - -func (ds *defaultStore) AssertAssignableExists(key Expr, value Type) bool { - if valSet, ok := ds.cacheAssignableCheck[key.String()]; ok { - // Check if the value exists in the set - var destTypeStr string - if value != nil { - destTypeStr = value.String() - } else { - destTypeStr = "" - } - return valSet[destTypeStr] - } - return false -} - // Used to set throwaway packages. func (ds *defaultStore) SetCachePackage(pv *PackageValue) { oid := ObjectIDFromPkgPath(pv.PkgPath) @@ -728,7 +697,6 @@ func (ds *defaultStore) ClearCache() { ds.cacheTypes = make(map[TypeID]Type) ds.cacheNodes = make(map[Location]BlockNode) ds.cacheNativeTypes = make(map[reflect.Type]Type) - ds.cacheAssignableCheck = make(map[string]map[string]bool) // restore builtin types to cache. InitStoreCaches(ds) } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index a9f7f0ce427..bcbf6c32a26 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -125,7 +125,6 @@ func isNumeric(t Type) bool { } } -// TODO: also compatible with 1.0, 2.0... func isIntNum(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: @@ -182,38 +181,33 @@ func assertSameTypes(lt, rt Type) { } } -func isSameType(lt, rt Type) bool { - debug.Printf("---isSameType, lt: %v, rt: %v \n", lt, rt) +// more strict, only for both typed and both nil +// use by isEql +func assertSameTypes2(lt, rt Type) bool { return lt == nil && rt == nil || // both are nil/undefined (lt != nil && rt != nil) && // both are defined (lt.TypeID() == rt.TypeID()) // and identical. } // runtime assert -// TODO: consider this!!! -func assertAssignable(lt, rt Type) { +func assertEqualityTypes(lt, rt Type) { if debug { - debug.Printf("assertAssignable, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) + debug.Printf("assertEqualityTypes, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) } - if isSameType(lt, rt) { - println("1") + if assertSameTypes2(lt, rt) { // both are nil/undefined or same type. } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil - println("2") // LHS is undefined } else if lt.Kind() == rt.Kind() && isUntyped(lt) || isUntyped(rt) { // one is untyped of same kind. - println("3") } else if lt.Kind() == rt.Kind() && isDataByte(lt) { // left is databyte of same kind, // specifically for assignments. // TODO: make another function // and remove this case? - println("4") } else { - //panic("---8") debug.Errorf( "incompatible operands in binary expression: %s and %s", lt.String(), @@ -273,7 +267,10 @@ func assertComparable(xt, dt Type) { if !cdt.Type.Comparable() { panic(fmt.Sprintf("%v is not comparable \n", dt)) } - case nil: // refer to 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. + case nil: // see 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. + if xt == nil { + panic(fmt.Sprintf("invalid operation, nil can not be compared to %s \n", "nil")) + } assertMaybeNil("invalid operation, nil can not be compared to", xt) default: panic(fmt.Sprintf("%v is not comparable \n", dt)) @@ -281,9 +278,6 @@ func assertComparable(xt, dt Type) { } func assertMaybeNil(msg string, t Type) { - if t == nil { - panic(fmt.Sprintf("%s %s \n", msg, "nil")) - } switch cxt := baseOf(t).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer case *NativeType: @@ -307,9 +301,6 @@ func assertMaybeNil(msg string, t Type) { // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general cases for primitives and composite. -// XXX. the name of checkAssignableTo should be considered. -// we have another func of assertAssignable for runtime check, that is a narrow version since we have all concrete types in runtime -// XXX: make it (t Type) CheckAssignableTo? func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { if debug { debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) @@ -578,7 +569,6 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // xt: any type but a *DeclaredType; could be native. // cdt: actual concrete native target type. // ie, if cdt can match against xt. - debug.Println("---going to check gno2go matches") if gno2GoTypeMatches(xt, cdt.Type) { return // ok } @@ -596,7 +586,6 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { // =========================================================== func (bx *BinaryExpr) checkShiftExpr(dt Type) { - debug.Printf("---checkShiftExpr: dt: %v \n", dt) var destKind interface{} if dt != nil { destKind = dt.Kind() @@ -616,7 +605,6 @@ func (bx *BinaryExpr) checkShiftExpr(dt Type) { // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { - debug.Printf("---AssertCompatible, bx: %v, lt: %v, rt: %v \n", bx, lt, rt) // we can't check compatible with native types at current stage, // so leave it to later operations(trans_leave on binaryExpr) // to be converted into gno(only for primitive types), and do @@ -684,7 +672,6 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } func (bx *BinaryExpr) checkCompatibility(store Store, xt, dt Type, checker func(t Type) bool, escapedOpStr string) { - debug.Printf("---checkCompatibility, op: %v, xt: %v, dt: %v\n", bx.Op, xt, dt) // cache it to be reused in later stage in checkOrConvertType var destKind interface{} if !checker(dt) { // lt not compatible with op @@ -696,15 +683,13 @@ func (bx *BinaryExpr) checkCompatibility(store Store, xt, dt Type, checker func( } func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { - debug.Printf("---AssertCompatible, ux: %v, xt: %v, dt: %v \n", ux, xt, dt) - var destKind interface{} + if nt, ok := xt.(*NativeType); ok { if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { return } } - // check compatible if checker, ok := unaryChecker[ux.Op]; ok { if dt == nil { @@ -722,8 +707,6 @@ func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { } func (idst *IncDecStmt) AssertCompatible(t Type) { - debug.Printf("---AssertCompatible, stmt: %v, t: %v, op: %v \n", idst, t, idst.Op) - var destKind interface{} if nt, ok := t.(*NativeType); ok { @@ -731,7 +714,6 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { return } } - // check compatible if checker, ok := IncDecStmtChecker[idst.Op]; ok { if !checker(t) { @@ -746,8 +728,6 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { } func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { - debug.Printf("---AssertCompatible, as: %v \n", as) - escapedOpStr := strings.Replace(wordTokenStrings[as.Op], "%", "%%", 1) var destKind interface{} @@ -768,7 +748,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } - debug.Printf("AssertCompatible,lt: %v, rt: %v,op: %v \n", lt, rt, as.Op) // check compatible if as.Op != ASSIGN { if checker, ok := AssignStmtChecker[as.Op]; ok { @@ -818,8 +797,6 @@ func isComparison(op Word) bool { } func cmpSpecificity(t1, t2 Type) int { - debug.Printf("comSpecificity, t1: %v, t2: %v \n", t1, t2) - if it1, ok := baseOf(t1).(*InterfaceType); ok { if it1.IsEmptyInterface() { return 1 // left empty interface diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 72a39a806d3..e829e3e8fcd 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1084,31 +1084,6 @@ type FuncType struct { bound *FuncType } -func (ft *FuncType) NumIn() int { - if len(ft.Params) >= 1 { - return len(ft.Params) - 1 // TODO: assert to be method - } - return 0 -} - -func (ft *FuncType) In(i int) Type { - if len(ft.Params) >= 1 { - return ft.Params[len(ft.Params)-1-i] - } - return nil -} - -func (ft *FuncType) Out(i int) Type { - if len(ft.Params) >= 1 { - return ft.Params[len(ft.Results)-1-i] - } - return nil -} - -func (ft *FuncType) NumOut() int { - return len(ft.Results) -} - // if ft is a method, returns whether method takes a pointer receiver. func (ft *FuncType) HasPointerReceiver() bool { if debug { @@ -2115,7 +2090,6 @@ func isDataByte(t Type) bool { // TODO move untyped const stuff to preprocess.go. // TODO associate with ConvertTo() in documentation. func defaultTypeOf(t Type) Type { - debug.Printf("---defaultTypeOf, t: %v \n", t) switch t { case UntypedBoolType: return BoolType @@ -2198,12 +2172,10 @@ func fillEmbeddedName(ft *FieldType) { // TODO: empty interface? refer to checkAssignableTo func IsImplementedBy(it Type, ot Type) bool { - debug.Printf("---IsImplementedBy, it: %v, ot: %v \n", it, ot) switch cbt := baseOf(it).(type) { case *InterfaceType: return cbt.IsImplementedBy(ot) case *NativeType: - debug.Println("---native type") return gno2GoTypeMatches(ot, cbt.Type) default: panic("should not happen") diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index a9af089433b..4cf944e5f2d 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -952,7 +952,6 @@ func (tv *TypedValue) IsUndefined() bool { func (tv *TypedValue) IsNilInterface() bool { if tv.T != nil && tv.T.Kind() == InterfaceKind { if tv.V == nil { - debug.Println("---isNilInterface") return true } if debug { diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 916d6bcda13..87771984088 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -14,10 +14,6 @@ import ( // the conversion is forced and overflow/underflow is ignored. // TODO: return error, and let caller also print the file and line. func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { - debug.Printf("---convertTo: tv: %v, t: %v \n", tv, t) - defer func() { - debug.Printf("---after convert: tv: %v \n", tv) - }() if debug { if t == nil { panic("ConvertTo() requires non-nil type") @@ -77,20 +73,10 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { } GNO_CASE: // special case for interface target - // TODO: consider interface{}(nil) - // var a interface, a == 1 - // seems the second case is not match with here - // the second case should be a empty interface - // that both type and data is nil, (0x00) - // look line 91 - // is it specified for nil to typed-nil? - // that nil is different with undefined? - - // XXX, go does not do this, see: go.dev/issue/13061 + // see: go.dev/issue/13061 if t.Kind() == InterfaceKind { if tv.IsUndefined() && tv.T == nil { // if tv.T == nil, nil T and nil Value. not a nil interface if _, ok := t.(*NativeType); !ok { // no support for native now - debug.Printf("t is interface and not native, t: %v \n", t) tv.T = t } } From a65be41384a8ce75e8eb12b12abd1c8406ebf353 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 4 Apr 2024 20:10:07 +0800 Subject: [PATCH 114/193] clean --- gnovm/pkg/gnolang/preprocess.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 592d47aaef3..b04b095e05d 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -166,11 +166,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } if rerr, ok := r.(error); ok { // NOTE: gotuna/gorilla expects error exceptions. - fmt.Println(errors.Wrap(rerr, loc.String())) panic(errors.Wrap(rerr, loc.String())) } else { // NOTE: gotuna/gorilla expects error exceptions. - fmt.Println(errors.New(fmt.Sprintf("%s: %v", loc.String(), r))) panic(errors.New(fmt.Sprintf("%s: %v", loc.String(), r))) } } @@ -1314,7 +1312,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // always computed in gno, never with reflect. } // Replace with *ConstExpr if const X. - if _, ok := n.X.(*ConstExpr); ok { + if isConst(n.X) { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } @@ -2383,6 +2381,11 @@ func anyValue(t Type) TypedValue { } } +func isConst(x Expr) bool { + _, ok := x.(*ConstExpr) + return ok +} + func isConstType(x Expr) bool { _, ok := x.(*constTypeExpr) return ok From 953765cb3bc17f6212f6e96ee8d138fea765beca Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 4 Apr 2024 23:09:08 +0800 Subject: [PATCH 115/193] clean --- gnovm/pkg/gnolang/type_check.go | 4 ---- gnovm/pkg/gnolang/values_conversions.go | 2 +- gnovm/tests/file_test.go | 5 ----- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index bcbf6c32a26..094f28484f7 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -311,10 +311,6 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { } // case3 if dt.Kind() == InterfaceKind { // note native interface - debug.Println("---dt: ", dt) - debug.Println("---baseOf dt: ", baseOf(dt)) - debug.Println("---dt.Kind: ", dt.Kind()) - debug.Printf("---xt: %v, baseOf(xt): %v \n", xt, baseOf(xt)) if idt, ok := baseOf(dt).(*InterfaceType); ok { if idt.IsEmptyInterface() { // XXX, can this be merged with IsImplementedBy? // if dt is an empty Gno interface, any x ok. diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 87771984088..65e609e6cc3 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -75,7 +75,7 @@ GNO_CASE: // special case for interface target // see: go.dev/issue/13061 if t.Kind() == InterfaceKind { - if tv.IsUndefined() && tv.T == nil { // if tv.T == nil, nil T and nil Value. not a nil interface + if tv.IsUndefined() && tv.T == nil { // see 0f47f if _, ok := t.(*NativeType); !ok { // no support for native now tv.T = t } diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index dffd2210c63..622ef274b5b 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -47,11 +47,6 @@ func TestTypesNative(t *testing.T) { runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) } -func TestTypes2(t *testing.T) { - baseDir := filepath.Join(".", "files/types2") - runFileTests(t, baseDir, nil) -} - func TestDebug(t *testing.T) { baseDir := filepath.Join(".", "debug") runFileTests(t, baseDir, []string{"*_native*"}) From 6f22a56215e2e1d9c2cd4ba31867dbfda8dd1cf5 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 5 Apr 2024 00:10:28 +0800 Subject: [PATCH 116/193] split type_compare(wtf) and type(nil) --- gnovm/pkg/gnolang/op_binary.go | 4 +- gnovm/pkg/gnolang/op_expressions.go | 19 +- gnovm/pkg/gnolang/preprocess.go | 41 ++-- gnovm/pkg/gnolang/type_check.go | 66 ------ gnovm/pkg/gnolang/types.go | 58 +++++ gnovm/pkg/gnolang/values_conversions.go | 5 - gnovm/tests/debug/zrealm1.gno | 203 ++++++++++++++++++ gnovm/tests/files/interface27b.gno | 2 +- gnovm/tests/files/interface28b.gno | 2 +- gnovm/tests/files/types/0f10_filetest.gno | 31 --- gnovm/tests/files/types/0f2_stdlibs.gno | 28 --- gnovm/tests/files/types/0f2a_filetest.gno | 29 --- gnovm/tests/files/types/0f36_filetest.gno | 35 --- .../files/types/0f38_stdlibs_filetest.gno | 31 --- .../files/types/0f39_stdlibs_filetest.gno | 28 --- .../files/types/0f47_nilcast_filetest.gno | 18 -- gnovm/tests/files/types/0f47a_filetest.gno | 10 - gnovm/tests/files/types/0f47f_filetest.gno | 2 +- gnovm/tests/files/types/0f49.gno | 78 ------- gnovm/tests/files/types/0f4_stdlibs.gno | 27 --- gnovm/tests/files/types/0f9_filetest.gno | 31 --- gnovm/tests/files/types/2b21_filetest.gno | 9 + gnovm/tests/files/zrealm1.gno | 16 +- 23 files changed, 297 insertions(+), 476 deletions(-) create mode 100644 gnovm/tests/debug/zrealm1.gno delete mode 100644 gnovm/tests/files/types/0f10_filetest.gno delete mode 100644 gnovm/tests/files/types/0f2_stdlibs.gno delete mode 100644 gnovm/tests/files/types/0f2a_filetest.gno delete mode 100644 gnovm/tests/files/types/0f36_filetest.gno delete mode 100644 gnovm/tests/files/types/0f38_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/0f39_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/0f47_nilcast_filetest.gno delete mode 100644 gnovm/tests/files/types/0f47a_filetest.gno delete mode 100644 gnovm/tests/files/types/0f49.gno delete mode 100644 gnovm/tests/files/types/0f4_stdlibs.gno delete mode 100644 gnovm/tests/files/types/0f9_filetest.gno create mode 100644 gnovm/tests/files/types/2b21_filetest.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 0f2b294f9d2..876791b05be 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -343,9 +343,7 @@ func isEql(store Store, lv, rv *TypedValue) bool { } else if rvu { return false } - if !assertSameTypes2(lv.T, rv.T) { - return false - } + if lnt, ok := lv.T.(*NativeType); ok { if rnt, ok := rv.T.(*NativeType); ok { if lnt.Type != rnt.Type { diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 0f107b84fc6..b0595cd5a78 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -113,16 +113,14 @@ func (m *Machine) doOpSlice() { high = xv.GetLength() } // all low:high:max cases - var sv TypedValue + //var sv TypedValue if max == -1 { - sv = xv.GetSlice(m.Alloc, low, high) + sv := xv.GetSlice(m.Alloc, low, high) + m.PushValue(sv) } else { - sv = xv.GetSlice2(m.Alloc, low, high, max) + sv := xv.GetSlice2(m.Alloc, low, high, max) + m.PushValue(sv) } - if isUntyped(sv.T) { - ConvertUntypedTo(&sv, defaultTypeOf(sv.T)) - } - m.PushValue(sv) } // If the referred value is undefined, and the pointer @@ -193,13 +191,8 @@ func (m *Machine) doOpRef() { nv.Value = rv2 } } - elt := xv.TV.T - if elt == DataByteType { - elt = xv.TV.V.(DataByteValue).ElemType - } m.PushValue(TypedValue{ - // T: m.Alloc.NewType(&PointerType{Elt: xv.TV.T}), - T: m.Alloc.NewType(&PointerType{Elt: elt}), + T: m.Alloc.NewType(&PointerType{Elt: xv.TV.T}), V: xv, }) } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index b04b095e05d..713b4b2c3e8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1030,21 +1030,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("type conversion requires single argument") } n.NumArgs = 1 - var dt Type - ct := evalStaticType(store, last, n.Func) //switch arg0 := n.Args[0].(type) { if arg0, ok := n.Args[0].(*ConstExpr); ok { - // check legal type for nil - if arg0.IsUndefined() { - switch ct.Kind() { // special case for nil conversion check. refer to 0f47a - case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind: - dt = ct // convert nil to typed-nil - default: - panic(fmt.Sprintf( - "cannot convert %v to %v", - arg0, ct.Kind())) - } - } + ct := evalStaticType(store, last, n.Func) // As a special case, if a decimal cannot // be represented as an integer, it cannot be converted to one, // and the error is handled here. @@ -1064,19 +1052,25 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TODO: consider this, need check? // (const) untyped decimal -> float64. // (const) untyped bigint -> int. - convertConst(store, last, arg0, dt) // convert to default type if dt is nil + //convertConst(store, last, arg0, dt) // convert to default type if dt is nil + convertConst(store, last, arg0, nil) // convert to default type if dt is nil // evaluate the new expression. cx := evalConst(store, last, n) // Though cx may be undefined if ct is interface, // the ATTR_TYPEOF_VALUE is still interface. - cx.SetAttribute(ATTR_TYPEOF_VALUE, dt) + //cx.SetAttribute(ATTR_TYPEOF_VALUE, dt) + cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE + } else { + ct := evalStaticType(store, last, n.Func) + n.SetAttribute(ATTR_TYPEOF_VALUE, ct) + return n, TRANS_CONTINUE } - // general case, for non-const untyped && no nested untyped shift - // after handling const, and special cases recursively, set the target node type - // ct := evalStaticType(store, last, n.Func) - n.SetAttribute(ATTR_TYPEOF_VALUE, ct) - return n, TRANS_CONTINUE + //// general case, for non-const untyped && no nested untyped shift + //// after handling const, and special cases recursively, set the target node type + //// ct := evalStaticType(store, last, n.Func) + //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) + //return n, TRANS_CONTINUE default: panic(fmt.Sprintf( "unexpected func type %v (%v)", @@ -2476,13 +2470,6 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { if t != nil && t.Kind() == InterfaceKind { - if cx.IsUndefined() && cx.T == nil { // if cx is nil, not undefined interface - if _, ok := t.(*NativeType); !ok { // bypass native nil interface, not support native interface(nil) now - ConvertTo(nilAllocator, store, &cx.TypedValue, t) - setConstAttrs(cx) - return - } - } t = nil } if isUntyped(cx.T) { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 094f28484f7..34735fef6b7 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -150,72 +150,6 @@ func isNumericOrString(t Type) bool { } // =========================================================== - -// main type-assertion functions. -// TODO: document what class of problems its for. -// One of them can be nil, and this lets uninitialized primitives -// and others serve as empty values. See doOpAdd() -// usage: if debug { assertSameTypes() } -func assertSameTypes(lt, rt Type) { - if lt == nil && rt == nil { - // both are nil. - } else if lt == nil || rt == nil { - // one is nil. see function comment. - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. - } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { - // left is databyte of same kind, - // specifically for assignments. - // TODO: make another function - // and remove this case? - } else if lt.TypeID() == rt.TypeID() { - // non-nil types are identical. - } else { - debug.Errorf( - "incompatible operands in binary expression: %s and %s", - lt.String(), - rt.String(), - ) - } -} - -// more strict, only for both typed and both nil -// use by isEql -func assertSameTypes2(lt, rt Type) bool { - return lt == nil && rt == nil || // both are nil/undefined - (lt != nil && rt != nil) && // both are defined - (lt.TypeID() == rt.TypeID()) // and identical. -} - -// runtime assert -func assertEqualityTypes(lt, rt Type) { - if debug { - debug.Printf("assertEqualityTypes, lt: %v, rt: %v, isLeftDataByte: %v, isRightDataByte: %v \n", lt, rt, isDataByte(lt), isDataByte(rt)) - } - if assertSameTypes2(lt, rt) { - // both are nil/undefined or same type. - } else if lt == nil || rt == nil { // has support (interface{}) typed-nil, yet support for (native interface{}) typed-nil - // LHS is undefined - } else if lt.Kind() == rt.Kind() && - isUntyped(lt) || isUntyped(rt) { - // one is untyped of same kind. - } else if lt.Kind() == rt.Kind() && - isDataByte(lt) { - // left is databyte of same kind, - // specifically for assignments. - // TODO: make another function - // and remove this case? - } else { - debug.Errorf( - "incompatible operands in binary expression: %s and %s", - lt.String(), - rt.String(), - ) - } -} - // assertComparable is used in preprocess. // assert value with dt is comparable // special case when both typed, check if type identical diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index e829e3e8fcd..48d3d8574d4 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2066,6 +2066,64 @@ func KindOf(t Type) Kind { } } +// ---------------------------------------- +// main type-assertion functions. + +// TODO: document what class of problems its for. +// One of them can be nil, and this lets uninitialized primitives +// and others serve as empty values. See doOpAdd() +// usage: if debug { assertSameTypes() } +func assertSameTypes(lt, rt Type) { + if lt == nil && rt == nil { + // both are nil. + } else if lt == nil || rt == nil { + // one is nil. see function comment. + } else if lt.Kind() == rt.Kind() && + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + } else if lt.Kind() == rt.Kind() && + isDataByte(lt) { + // left is databyte of same kind, + // specifically for assignments. + // TODO: make another function + // and remove this case? + } else if lt.TypeID() == rt.TypeID() { + // non-nil types are identical. + } else { + debug.Errorf( + "incompatible operands in binary expression: %s and %s", + lt.String(), + rt.String(), + ) + } +} + +// Like assertSameTypes(), but more relaxed, for == and !=. +func assertEqualityTypes(lt, rt Type) { + if lt == nil && rt == nil { + // both are nil. + } else if lt == nil || rt == nil { + // one is nil. see function comment. + } else if lt.Kind() == rt.Kind() && + isUntyped(lt) || isUntyped(rt) { + // one is untyped of same kind. + } else if lt.Kind() == InterfaceKind && + IsImplementedBy(lt, rt) { + // rt implements lt (and lt is nil interface). + } else if rt.Kind() == InterfaceKind && + IsImplementedBy(rt, lt) { + // lt implements rt (and rt is nil interface). + } else if lt.TypeID() == rt.TypeID() { + // non-nil types are identical. + } else { + debug.Errorf( + "incompatible operands in binary (eql/neq) expression: %s and %s", + lt.String(), + rt.String(), + ) + } +} + // ---------------------------------------- // misc diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 65e609e6cc3..5f127b62668 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -75,11 +75,6 @@ GNO_CASE: // special case for interface target // see: go.dev/issue/13061 if t.Kind() == InterfaceKind { - if tv.IsUndefined() && tv.T == nil { // see 0f47f - if _, ok := t.(*NativeType); !ok { // no support for native now - tv.T = t - } - } return } // special case for undefined/nil source diff --git a/gnovm/tests/debug/zrealm1.gno b/gnovm/tests/debug/zrealm1.gno new file mode 100644 index 00000000000..1dea983a49d --- /dev/null +++ b/gnovm/tests/debug/zrealm1.gno @@ -0,0 +1,203 @@ +// PKGPATH: gno.land/r/test +package test + +var root Node + +type ( + Node interface{} + Key interface{} +) + +type InnerNode struct { + Key Key + Left Node + Right Node +} + +func main() { + key := "somekey" + root = InnerNode{ + Key: key, + Left: nil, + Right: nil, + } +} + +// Realm: +// switchrealm["gno.land/r/test"] +// c[a8ada09dee16d791fd406d629fe29bb0ed084a30:4]={ +// "Fields": [ +// { +// "T": { +// "@type": "/gno.PrimitiveType", +// "value": "16" +// }, +// "V": { +// "@type": "/gno.StringValue", +// "value": "somekey" +// } +// }, +// {}, +// {} +// ], +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4", +// "ModTime": "0", +// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", +// "RefCount": "1" +// } +// } +// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:2]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", +// "IsEscaped": true, +// "ModTime": "3", +// "RefCount": "2" +// }, +// "Parent": null, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "", +// "Line": "0", +// "Nonce": "0", +// "PkgPath": "gno.land/r/test" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.InterfaceType", +// "Generic": "", +// "Methods": [], +// "PkgPath": "gno.land/r/test" +// }, +// "Methods": [], +// "Name": "Node", +// "PkgPath": "gno.land/r/test" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.InterfaceType", +// "Generic": "", +// "Methods": [], +// "PkgPath": "gno.land/r/test" +// }, +// "Methods": [], +// "Name": "Key", +// "PkgPath": "gno.land/r/test" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.StructType", +// "Fields": [ +// { +// "Embedded": false, +// "Name": "Key", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.Key" +// } +// }, +// { +// "Embedded": false, +// "Name": "Left", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.Node" +// } +// }, +// { +// "Embedded": false, +// "Name": "Right", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.Node" +// } +// } +// ], +// "PkgPath": "gno.land/r/test" +// }, +// "Methods": [], +// "Name": "InnerNode", +// "PkgPath": "gno.land/r/test" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:3" +// }, +// "FileName": "main.gno", +// "IsMethod": false, +// "Name": "main", +// "PkgPath": "gno.land/r/test", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "main.gno", +// "Line": "17", +// "Nonce": "0", +// "PkgPath": "gno.land/r/test" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/test.InnerNode" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "ae4e9e2d205cc0081d4ee249e1d188ebe270b220", +// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4" +// } +// } +// ] +// } diff --git a/gnovm/tests/files/interface27b.gno b/gnovm/tests/files/interface27b.gno index 7022b934b9f..4818db24e2c 100644 --- a/gnovm/tests/files/interface27b.gno +++ b/gnovm/tests/files/interface27b.gno @@ -7,4 +7,4 @@ func main() { } // Output: -// map{(0 int):(undefined) .uverse.error} +// map{(0 int):(undefined) nil} diff --git a/gnovm/tests/files/interface28b.gno b/gnovm/tests/files/interface28b.gno index 1a372943c09..4c4deb5d3c1 100644 --- a/gnovm/tests/files/interface28b.gno +++ b/gnovm/tests/files/interface28b.gno @@ -7,4 +7,4 @@ func main() { } // Output: -// slice[(undefined) .uverse.error] +// slice[(undefined) nil] diff --git a/gnovm/tests/files/types/0f10_filetest.gno b/gnovm/tests/files/types/0f10_filetest.gno deleted file mode 100644 index c2c99dea9c3..00000000000 --- a/gnovm/tests/files/types/0f10_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 == e2) -} - -// Output: -// false diff --git a/gnovm/tests/files/types/0f2_stdlibs.gno b/gnovm/tests/files/types/0f2_stdlibs.gno deleted file mode 100644 index 16b4e82476b..00000000000 --- a/gnovm/tests/files/types/0f2_stdlibs.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - if Error(0) == errCmp { // this would not convert, errCmp is interface - //if errCmp == 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/0f2a_filetest.gno b/gnovm/tests/files/types/0f2a_filetest.gno deleted file mode 100644 index 169e30a3bab..00000000000 --- a/gnovm/tests/files/types/0f2a_filetest.gno +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// typed -var errCmp error = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - const e Error = Error(0) // typed const - if e == errCmp { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/0f36_filetest.gno b/gnovm/tests/files/types/0f36_filetest.gno deleted file mode 100644 index bddb57b7ec5..00000000000 --- a/gnovm/tests/files/types/0f36_filetest.gno +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "fmt" - "strconv" -) - -type Error0 int64 - -func (e Error0) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - defer func() { - if r := recover(); r != nil { - if r == Error0(0) { - fmt.Println("recover Error0") - } else { - fmt.Println("recover Error1") - } - } - }() - - panic(Error1(0)) -} - -// Output: -// recover Error1 diff --git a/gnovm/tests/files/types/0f38_stdlibs_filetest.gno b/gnovm/tests/files/types/0f38_stdlibs_filetest.gno deleted file mode 100644 index fcba5dad752..00000000000 --- a/gnovm/tests/files/types/0f38_stdlibs_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("errCmp") - -func main() { - defer func() { - if r := recover(); r != nil { - if r == errCmp { - println("same error") - } else { - println("different error") - } - } - }() - - panic(Error1(0)) -} - -// Output: -// different error diff --git a/gnovm/tests/files/types/0f39_stdlibs_filetest.gno b/gnovm/tests/files/types/0f39_stdlibs_filetest.gno deleted file mode 100644 index d8831f7f9a4..00000000000 --- a/gnovm/tests/files/types/0f39_stdlibs_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" -) - -func get() interface{} { - return "hello" -} - -var errCmp = errors.New("errCmp") - -func main() { - defer func() { - if r := recover(); r != nil { - if r == errCmp { - println("same error") - } else { - println("different error") - } - } - }() - - panic(get()) -} - -// Output: -// different error diff --git a/gnovm/tests/files/types/0f47_nilcast_filetest.gno b/gnovm/tests/files/types/0f47_nilcast_filetest.gno deleted file mode 100644 index 2b850e53ce0..00000000000 --- a/gnovm/tests/files/types/0f47_nilcast_filetest.gno +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import "fmt" - -type integer int - -func main() { // TODO: same with 47a - // illegal conversion - // should not work - if integer(nil) == nil { - fmt.Println("integer is nil") - } else { - fmt.Println("integer is not nil") - } -} - -// Error: -// main/files/types/0f47_nilcast_filetest.gno:10: cannot convert (const (undefined) nil) to IntKind diff --git a/gnovm/tests/files/types/0f47a_filetest.gno b/gnovm/tests/files/types/0f47a_filetest.gno deleted file mode 100644 index 8faffefbee6..00000000000 --- a/gnovm/tests/files/types/0f47a_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -type integer int - -func main() { - println(integer(nil)) // preprocess, 1042 -} - -// Error: -// main/files/types/0f47a_filetest.gno:6: cannot convert (const (undefined) nil) to IntKind diff --git a/gnovm/tests/files/types/0f47f_filetest.gno b/gnovm/tests/files/types/0f47f_filetest.gno index b25b534f718..01c80bd8079 100644 --- a/gnovm/tests/files/types/0f47f_filetest.gno +++ b/gnovm/tests/files/types/0f47f_filetest.gno @@ -10,5 +10,5 @@ func main() { } // Output: -// false +// true // diff --git a/gnovm/tests/files/types/0f49.gno b/gnovm/tests/files/types/0f49.gno deleted file mode 100644 index 1e930f65345..00000000000 --- a/gnovm/tests/files/types/0f49.gno +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "fmt" -) - -// implicit type conversion and equality -// NOTE: the output type is incorrect, but the == eval is right -func main() { - { // case 1 with slices - type X []byte - var x interface{} = []byte("foo") - var xx interface{} = X(x.([]byte)) - fmt.Printf("%T, %v \n", x, x) // []uint8 [102 111 111] - fmt.Printf("%T, %v \n", xx, xx) // main.X [102 111 111] - fmt.Println(x == xx) // false - } - - { // case 2 with arrays - type X [3]byte - var x interface{} = [3]byte{102, 111, 111} - var xx interface{} = X(x.([3]byte)) - fmt.Printf("%T, %v \n", x, x) // [3]uint8 [102 111 111] - fmt.Printf("%T, %v \n", xx, xx) // main.X [102 111 111] - fmt.Println(x == xx) // false still. - } - { // switch without conversion - type X [3]byte - var x interface{} = [3]byte{102, 111, 111} - switch x { - case [3]byte{102, 111, 111}: - fmt.Println("ok") // ok - case [3]byte{102, 111, 112}: - panic("should not happen") - default: - panic("should not happen") - } - } - - { // case 1 switch with conversion no match - type X [3]byte - var x interface{} = X([3]byte{102, 111, 111}) - switch x { - case [3]byte{102, 111, 111}: - panic("should not happen") - case [3]byte{102, 111, 112}: - panic("should not happen") - default: - fmt.Println("no match") // no match - } - } - - { // case 2 switch with conversion match - type X [3]byte - var x interface{} = X([3]byte{102, 111, 111}) - switch x { - case [3]byte{102, 111, 111}: - panic("should not happen") - case X([3]byte{102, 111, 111}): - fmt.Println("ok") // ok - case X([3]byte{102, 111, 112}): - panic("should not happen") - default: - panic("should not happen") - } - } -} - -// Output: -// []uint8, [102 111 111] -// []uint8, [102 111 111] -// false -// [3]uint8, [102 111 111] -// [3]uint8, [102 111 111] -// false -// ok -// no match -// ok diff --git a/gnovm/tests/files/types/0f4_stdlibs.gno b/gnovm/tests/files/types/0f4_stdlibs.gno deleted file mode 100644 index e3f03cd76a2..00000000000 --- a/gnovm/tests/files/types/0f4_stdlibs.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if Error(0) != errCmp { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// what the firetruck? diff --git a/gnovm/tests/files/types/0f9_filetest.gno b/gnovm/tests/files/types/0f9_filetest.gno deleted file mode 100644 index 6abc84992ea..00000000000 --- a/gnovm/tests/files/types/0f9_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int64 - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 == e2) -} - -// Output: -// false diff --git a/gnovm/tests/files/types/2b21_filetest.gno b/gnovm/tests/files/types/2b21_filetest.gno new file mode 100644 index 00000000000..3795df8947a --- /dev/null +++ b/gnovm/tests/files/types/2b21_filetest.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("a" - 1) +} + +// Error: +// main/files/types/2b21_filetest.gno:5: cannot use untyped string as BigintKind diff --git a/gnovm/tests/files/zrealm1.gno b/gnovm/tests/files/zrealm1.gno index d93bf82c62e..1dea983a49d 100644 --- a/gnovm/tests/files/zrealm1.gno +++ b/gnovm/tests/files/zrealm1.gno @@ -37,18 +37,8 @@ func main() { // "value": "somekey" // } // }, -// { -// "T": { -// "@type": "/gno.RefType", -// "ID": "gno.land/r/test.Node" -// } -// }, -// { -// "T": { -// "@type": "/gno.RefType", -// "ID": "gno.land/r/test.Node" -// } -// } +// {}, +// {} // ], // "ObjectInfo": { // "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4", @@ -205,7 +195,7 @@ func main() { // }, // "V": { // "@type": "/gno.RefValue", -// "Hash": "5684cb2d35e7da2ec67cf7a389db879a44bb4d30", +// "Hash": "ae4e9e2d205cc0081d4ee249e1d188ebe270b220", // "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4" // } // } From 69089503366ab9749d18e99d2a35f79d924ca197 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 5 Apr 2024 00:12:07 +0800 Subject: [PATCH 117/193] restore --- examples/gno.land/r/demo/foo1155/foo1155_test.gno | 4 ++-- examples/gno.land/r/demo/foo721/foo721_test.gno | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/r/demo/foo1155/foo1155_test.gno b/examples/gno.land/r/demo/foo1155/foo1155_test.gno index 695c3f3bae4..30663ab2c95 100644 --- a/examples/gno.land/r/demo/foo1155/foo1155_test.gno +++ b/examples/gno.land/r/demo/foo1155/foo1155_test.gno @@ -18,8 +18,8 @@ func TestFoo721(t *testing.T) { expected interface{} fn func() interface{} }{ - {"BalanceOf(admin, tid1)", uint64(100), func() interface{} { return BalanceOf(admin, tid1) }}, - {"BalanceOf(bob, tid1)", uint64(0), func() interface{} { return BalanceOf(bob, tid1) }}, + {"BalanceOf(admin, tid1)", 100, func() interface{} { return BalanceOf(admin, tid1) }}, + {"BalanceOf(bob, tid1)", 0, func() interface{} { return BalanceOf(bob, tid1) }}, {"IsApprovedForAll(admin, bob)", false, func() interface{} { return IsApprovedForAll(admin, bob) }}, } { t.Run(tc.name, func(t *testing.T) { diff --git a/examples/gno.land/r/demo/foo721/foo721_test.gno b/examples/gno.land/r/demo/foo721/foo721_test.gno index 618cff55bc2..8fb5c6d4f94 100644 --- a/examples/gno.land/r/demo/foo721/foo721_test.gno +++ b/examples/gno.land/r/demo/foo721/foo721_test.gno @@ -16,8 +16,8 @@ func TestFoo721(t *testing.T) { expected interface{} fn func() interface{} }{ - {"BalanceOf(admin)", uint64(10), func() interface{} { return BalanceOf(admin) }}, - {"BalanceOf(hariom)", uint64(5), func() interface{} { return BalanceOf(hariom) }}, + {"BalanceOf(admin)", 10, func() interface{} { return BalanceOf(admin) }}, + {"BalanceOf(hariom)", 5, func() interface{} { return BalanceOf(hariom) }}, {"OwnerOf(0)", admin.Resolve(), func() interface{} { return OwnerOf(grc721.TokenID("0")) }}, {"IsApprovedForAll(admin, hariom)", false, func() interface{} { return IsApprovedForAll(admin, hariom) }}, } { From 0c79c67cfc4b2063b2e9e74d83aa4a0d20291f4a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 5 Apr 2024 00:41:42 +0800 Subject: [PATCH 118/193] split type def on pointer type & clean --- gnovm/pkg/gnolang/op_binary.go | 7 +++---- gnovm/pkg/gnolang/op_expressions.go | 1 - gnovm/pkg/gnolang/op_types.go | 9 --------- gnovm/pkg/gnolang/preprocess.go | 20 +++----------------- gnovm/pkg/gnolang/values_conversions.go | 1 - gnovm/tests/files/types/0f43a_filetest.gno | 16 ---------------- gnovm/tests/files/types/0f47b_filetest.gno | 11 ----------- gnovm/tests/files/types/0f47c_filetest.gno | 20 -------------------- 8 files changed, 6 insertions(+), 79 deletions(-) delete mode 100644 gnovm/tests/files/types/0f43a_filetest.gno delete mode 100644 gnovm/tests/files/types/0f47b_filetest.gno delete mode 100644 gnovm/tests/files/types/0f47c_filetest.gno diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 876791b05be..9162a710d7d 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -76,10 +76,11 @@ func (m *Machine) doOpEql() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - if debug { assertEqualityTypes(lv.T, rv.T) } + + // set result in lv. res := isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil @@ -92,11 +93,11 @@ func (m *Machine) doOpNeq() { // get right and left operands. rv := m.PopValue() lv := m.PeekValue(1) // also the result - if debug { assertEqualityTypes(lv.T, rv.T) } + // set result in lv. res := !isEql(m.Store, lv, rv) lv.T = UntypedBoolType lv.V = nil @@ -343,7 +344,6 @@ func isEql(store Store, lv, rv *TypedValue) bool { } else if rvu { return false } - if lnt, ok := lv.T.(*NativeType); ok { if rnt, ok := rv.T.(*NativeType); ok { if lnt.Type != rnt.Type { @@ -456,7 +456,6 @@ func isEql(store Store, lv, rv *TypedValue) bool { panic("function can only be compared with `nil`") } } - if _, ok := lv.V.(*BoundMethodValue); ok { // BoundMethodValues are objects so just compare. return lv.V == rv.V diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index b0595cd5a78..b46e343b00e 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -113,7 +113,6 @@ func (m *Machine) doOpSlice() { high = xv.GetLength() } // all low:high:max cases - //var sv TypedValue if max == -1 { sv := xv.GetSlice(m.Alloc, low, high) m.PushValue(sv) diff --git a/gnovm/pkg/gnolang/op_types.go b/gnovm/pkg/gnolang/op_types.go index 6999af33680..a38010bac4e 100644 --- a/gnovm/pkg/gnolang/op_types.go +++ b/gnovm/pkg/gnolang/op_types.go @@ -297,15 +297,6 @@ func (m *Machine) doOpStaticTypeOf() { } switch path.Type { - case VPUverse: - println("---case match vpuverse") - switch path.Depth { - case 0: - println("---depth is 0") - dxt = xt - default: - panic("should not happen") - } case VPBlock: switch dxt.(type) { case *PackageType: diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 713b4b2c3e8..d7ab02cb986 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -765,7 +765,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { n.AssertCompatible(store, lt, rt) } - // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) @@ -1030,7 +1029,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("type conversion requires single argument") } n.NumArgs = 1 - //switch arg0 := n.Args[0].(type) { if arg0, ok := n.Args[0].(*ConstExpr); ok { ct := evalStaticType(store, last, n.Func) // As a special case, if a decimal cannot @@ -1052,13 +1050,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TODO: consider this, need check? // (const) untyped decimal -> float64. // (const) untyped bigint -> int. - //convertConst(store, last, arg0, dt) // convert to default type if dt is nil - convertConst(store, last, arg0, nil) // convert to default type if dt is nil + convertConst(store, last, arg0, nil) // evaluate the new expression. cx := evalConst(store, last, n) // Though cx may be undefined if ct is interface, // the ATTR_TYPEOF_VALUE is still interface. - //cx.SetAttribute(ATTR_TYPEOF_VALUE, dt) cx.SetAttribute(ATTR_TYPEOF_VALUE, ct) return cx, TRANS_CONTINUE } else { @@ -1066,11 +1062,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.SetAttribute(ATTR_TYPEOF_VALUE, ct) return n, TRANS_CONTINUE } - //// general case, for non-const untyped && no nested untyped shift - //// after handling const, and special cases recursively, set the target node type - //// ct := evalStaticType(store, last, n.Func) - //n.SetAttribute(ATTR_TYPEOF_VALUE, ct) - //return n, TRANS_CONTINUE default: panic(fmt.Sprintf( "unexpected func type %v (%v)", @@ -1284,9 +1275,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: xt := evalStaticTypeOf(store, last, n.X) - n.AssertCompatible(xt, nil) - if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) @@ -2251,7 +2240,6 @@ func getResultTypedValues(cx *CallExpr) []TypedValue { // composite exprs/nodes that contain constant expression nodes (e.g. const // exprs in the rhs of AssignStmts). func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { - debug.Printf("---evalConst, x: %v \n", x) // TODO: some check or verification for ensuring x // is constant? From the machine? cv := NewMachine(".dontcare", store) @@ -2425,7 +2413,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative needConversion = checkAssignableTo(xt, t, autoNative) } if isUntyped(xt) { - if _, ok := t.(*InterfaceType); ok || t == nil { + if t == nil { t = defaultTypeOf(xt) } if debug { @@ -2470,7 +2458,7 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { if t != nil && t.Kind() == InterfaceKind { - t = nil + t = nil // signifies to convert to default type. } if isUntyped(cx.T) { ConvertUntypedTo(&cx.TypedValue, t) @@ -2924,8 +2912,6 @@ func tryPredefine(store Store, last BlockNode, d Decl) (un Name) { t = &MapType{} case *StructTypeExpr: t = &StructType{} - case *StarExpr: - t = &PointerType{} case *NameExpr: if tv := last.GetValueRef(store, tx.Name); tv != nil { // (file) block name diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 5f127b62668..d99f5417d34 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -73,7 +73,6 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { } GNO_CASE: // special case for interface target - // see: go.dev/issue/13061 if t.Kind() == InterfaceKind { return } diff --git a/gnovm/tests/files/types/0f43a_filetest.gno b/gnovm/tests/files/types/0f43a_filetest.gno deleted file mode 100644 index 49bb000d951..00000000000 --- a/gnovm/tests/files/types/0f43a_filetest.gno +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import "fmt" - -type myPointer *int - -func main() { - if myPointer(nil) == nil { - fmt.Println("Pointer is nil") - } else { - fmt.Println("Pointer is not nil") - } -} - -// Output: -// Pointer is nil diff --git a/gnovm/tests/files/types/0f47b_filetest.gno b/gnovm/tests/files/types/0f47b_filetest.gno deleted file mode 100644 index e8228c622e6..00000000000 --- a/gnovm/tests/files/types/0f47b_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -type integer *int - -// nil can be cast to pointer -func main() { - println(integer(nil) == nil) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/0f47c_filetest.gno b/gnovm/tests/files/types/0f47c_filetest.gno deleted file mode 100644 index 410bbff23f8..00000000000 --- a/gnovm/tests/files/types/0f47c_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import "fmt" - -type integer *int - -// TODO: this is go outputs, should check println and fmt.Printf -// 0x0 -// -// main.integer -func main() { - println(integer(nil)) - fmt.Println(integer(nil)) - fmt.Printf("%T \n", integer(nil)) -} - -// Output: -// (nil main.integer) -// -// *int From cc5c8c832cc307775e083655c271fc5c411cb45a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 5 Apr 2024 01:29:02 +0800 Subject: [PATCH 119/193] rm no use file --- gnovm/tests/debug/zrealm1.gno | 203 ---------------------------------- 1 file changed, 203 deletions(-) delete mode 100644 gnovm/tests/debug/zrealm1.gno diff --git a/gnovm/tests/debug/zrealm1.gno b/gnovm/tests/debug/zrealm1.gno deleted file mode 100644 index 1dea983a49d..00000000000 --- a/gnovm/tests/debug/zrealm1.gno +++ /dev/null @@ -1,203 +0,0 @@ -// PKGPATH: gno.land/r/test -package test - -var root Node - -type ( - Node interface{} - Key interface{} -) - -type InnerNode struct { - Key Key - Left Node - Right Node -} - -func main() { - key := "somekey" - root = InnerNode{ - Key: key, - Left: nil, - Right: nil, - } -} - -// Realm: -// switchrealm["gno.land/r/test"] -// c[a8ada09dee16d791fd406d629fe29bb0ed084a30:4]={ -// "Fields": [ -// { -// "T": { -// "@type": "/gno.PrimitiveType", -// "value": "16" -// }, -// "V": { -// "@type": "/gno.StringValue", -// "value": "somekey" -// } -// }, -// {}, -// {} -// ], -// "ObjectInfo": { -// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4", -// "ModTime": "0", -// "OwnerID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", -// "RefCount": "1" -// } -// } -// u[a8ada09dee16d791fd406d629fe29bb0ed084a30:2]={ -// "Blank": {}, -// "ObjectInfo": { -// "ID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:2", -// "IsEscaped": true, -// "ModTime": "3", -// "RefCount": "2" -// }, -// "Parent": null, -// "Source": { -// "@type": "/gno.RefNode", -// "BlockNode": null, -// "Location": { -// "File": "", -// "Line": "0", -// "Nonce": "0", -// "PkgPath": "gno.land/r/test" -// } -// }, -// "Values": [ -// { -// "T": { -// "@type": "/gno.TypeType" -// }, -// "V": { -// "@type": "/gno.TypeValue", -// "Type": { -// "@type": "/gno.DeclaredType", -// "Base": { -// "@type": "/gno.InterfaceType", -// "Generic": "", -// "Methods": [], -// "PkgPath": "gno.land/r/test" -// }, -// "Methods": [], -// "Name": "Node", -// "PkgPath": "gno.land/r/test" -// } -// } -// }, -// { -// "T": { -// "@type": "/gno.TypeType" -// }, -// "V": { -// "@type": "/gno.TypeValue", -// "Type": { -// "@type": "/gno.DeclaredType", -// "Base": { -// "@type": "/gno.InterfaceType", -// "Generic": "", -// "Methods": [], -// "PkgPath": "gno.land/r/test" -// }, -// "Methods": [], -// "Name": "Key", -// "PkgPath": "gno.land/r/test" -// } -// } -// }, -// { -// "T": { -// "@type": "/gno.TypeType" -// }, -// "V": { -// "@type": "/gno.TypeValue", -// "Type": { -// "@type": "/gno.DeclaredType", -// "Base": { -// "@type": "/gno.StructType", -// "Fields": [ -// { -// "Embedded": false, -// "Name": "Key", -// "Tag": "", -// "Type": { -// "@type": "/gno.RefType", -// "ID": "gno.land/r/test.Key" -// } -// }, -// { -// "Embedded": false, -// "Name": "Left", -// "Tag": "", -// "Type": { -// "@type": "/gno.RefType", -// "ID": "gno.land/r/test.Node" -// } -// }, -// { -// "Embedded": false, -// "Name": "Right", -// "Tag": "", -// "Type": { -// "@type": "/gno.RefType", -// "ID": "gno.land/r/test.Node" -// } -// } -// ], -// "PkgPath": "gno.land/r/test" -// }, -// "Methods": [], -// "Name": "InnerNode", -// "PkgPath": "gno.land/r/test" -// } -// } -// }, -// { -// "T": { -// "@type": "/gno.FuncType", -// "Params": [], -// "Results": [] -// }, -// "V": { -// "@type": "/gno.FuncValue", -// "Closure": { -// "@type": "/gno.RefValue", -// "Escaped": true, -// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:3" -// }, -// "FileName": "main.gno", -// "IsMethod": false, -// "Name": "main", -// "PkgPath": "gno.land/r/test", -// "Source": { -// "@type": "/gno.RefNode", -// "BlockNode": null, -// "Location": { -// "File": "main.gno", -// "Line": "17", -// "Nonce": "0", -// "PkgPath": "gno.land/r/test" -// } -// }, -// "Type": { -// "@type": "/gno.FuncType", -// "Params": [], -// "Results": [] -// } -// } -// }, -// { -// "T": { -// "@type": "/gno.RefType", -// "ID": "gno.land/r/test.InnerNode" -// }, -// "V": { -// "@type": "/gno.RefValue", -// "Hash": "ae4e9e2d205cc0081d4ee249e1d188ebe270b220", -// "ObjectID": "a8ada09dee16d791fd406d629fe29bb0ed084a30:4" -// } -// } -// ] -// } From 5f9a3622a67b735d431e4fe085d5f561e0480174 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 5 Apr 2024 09:44:12 +0800 Subject: [PATCH 120/193] clean --- gnovm/tests/note/1.gno | 12 ------------ gnovm/tests/note/2.gno | 10 ---------- gnovm/tests/note/iface.gno | 14 -------------- 3 files changed, 36 deletions(-) delete mode 100644 gnovm/tests/note/1.gno delete mode 100644 gnovm/tests/note/2.gno delete mode 100644 gnovm/tests/note/iface.gno diff --git a/gnovm/tests/note/1.gno b/gnovm/tests/note/1.gno deleted file mode 100644 index 4f2e7e03af1..00000000000 --- a/gnovm/tests/note/1.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -func main() { - var a interface{} - //var b = 1 - - //println(b == a) - println(1 == a) -} - -// Output: -// false diff --git a/gnovm/tests/note/2.gno b/gnovm/tests/note/2.gno deleted file mode 100644 index a3d30a3814d..00000000000 --- a/gnovm/tests/note/2.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -var e error - -func main() { - e = 1 // this check is currently happening in checkOrConvert, should be in assertCompatibility -} - -// Error: -// main/debug/2.gnoa:6: bigint does not implement .uverse.error diff --git a/gnovm/tests/note/iface.gno b/gnovm/tests/note/iface.gno deleted file mode 100644 index 80aae4d2774..00000000000 --- a/gnovm/tests/note/iface.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -type MyError struct { - error -} - -var err error - -func main() { - err = (*MyError)(nil) - println(err) -} - -// Output: From cb338ce3115f34966d51e65ca12b686ed52b3aa6 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 7 Apr 2024 17:10:33 +0800 Subject: [PATCH 121/193] for binaryExpr, also check xt --- gnovm/pkg/gnolang/type_check.go | 20 ++++++++++++++++--- gnovm/tests/debug/bigdec.gno | 11 ++++++++++ .../tests/files/types/11a8_LAND_filetest.gno | 2 +- gnovm/tests/files/types/20a4_filetest.gno | 2 +- gnovm/tests/files/types/2b21_filetest.gno | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 gnovm/tests/debug/bigdec.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 34735fef6b7..b419fcb9ddc 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -602,14 +602,28 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } func (bx *BinaryExpr) checkCompatibility(store Store, xt, dt Type, checker func(t Type) bool, escapedOpStr string) { - // cache it to be reused in later stage in checkOrConvertType var destKind interface{} - if !checker(dt) { // lt not compatible with op - if dt != nil { // return error on left side that is checked first + + if !checker(dt) { + if dt != nil { destKind = dt.Kind() } panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) } + + defer func() { // rewrite err msg + if r := recover(); r != nil { + if xt != nil { + destKind = xt.Kind() + } + panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + } + }() + + // e.g. 1%1e9 + if !checker(xt) { // lt not compatible with op + checkAssignableTo(xt, dt, false) // XXX, cache this? + } } func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { diff --git a/gnovm/tests/debug/bigdec.gno b/gnovm/tests/debug/bigdec.gno new file mode 100644 index 00000000000..baa3d4d6309 --- /dev/null +++ b/gnovm/tests/debug/bigdec.gno @@ -0,0 +1,11 @@ +package main + +var a uint64 + +func main() { + a = 1 + println(a % 1e9) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/11a8_LAND_filetest.gno b/gnovm/tests/files/types/11a8_LAND_filetest.gno index 379adcca6f6..5c2ad0296f0 100644 --- a/gnovm/tests/files/types/11a8_LAND_filetest.gno +++ b/gnovm/tests/files/types/11a8_LAND_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/11a8_LAND_filetest.gno:4: cannot use untyped Bigint as BoolKind +// main/files/types/11a8_LAND_filetest.gno:4: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/20a4_filetest.gno b/gnovm/tests/files/types/20a4_filetest.gno index 7339ac40893..b7b70e42fe9 100644 --- a/gnovm/tests/files/types/20a4_filetest.gno +++ b/gnovm/tests/files/types/20a4_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/20a4_filetest.gno:4: cannot use untyped bool as BigintKind +// main/files/types/20a4_filetest.gno:4: operator < not defined on: BoolKind diff --git a/gnovm/tests/files/types/2b21_filetest.gno b/gnovm/tests/files/types/2b21_filetest.gno index 3795df8947a..559ebb61d8f 100644 --- a/gnovm/tests/files/types/2b21_filetest.gno +++ b/gnovm/tests/files/types/2b21_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/2b21_filetest.gno:5: cannot use untyped string as BigintKind +// main/files/types/2b21_filetest.gno:5: operator - not defined on: StringKind From d3af8c3eae9d8b8320ec4e4079018cd04139df60 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 7 Apr 2024 17:56:38 +0800 Subject: [PATCH 122/193] split implicit type conversion feat --- gnovm/pkg/gnolang/preprocess.go | 11 +---- gnovm/pkg/gnolang/type_check.go | 26 +++++----- gnovm/tests/files/types/22a10_filetest.gno | 21 -------- gnovm/tests/files/types/22a11_filetest.gno | 22 --------- gnovm/tests/files/types/22a11a_filetest.gno | 21 -------- gnovm/tests/files/types/22a12_filetest.gno | 20 -------- gnovm/tests/files/types/22a12a_filetest.gno | 24 ---------- gnovm/tests/files/types/22a12b_filetest.gno | 22 --------- gnovm/tests/files/types/22a12c_filetest.gno | 25 ---------- gnovm/tests/files/types/22a13_filetest.gno | 20 -------- gnovm/tests/files/types/22a14_filetest.gnoa | 21 -------- gnovm/tests/files/types/22a15_filetest.gno | 18 ------- gnovm/tests/files/types/22a16_filetest.gno | 25 ---------- gnovm/tests/files/types/22a17_filetest.gno | 15 ------ gnovm/tests/files/types/22a17a_filetest.gno | 15 ------ gnovm/tests/files/types/22a17b_filetest.gno | 16 ------- gnovm/tests/files/types/22a17c_filetest.gno | 20 -------- gnovm/tests/files/types/22a17d_filetest.gno | 20 -------- gnovm/tests/files/types/22a17e_filetest.gno | 23 --------- gnovm/tests/files/types/22a17f_filetest.gno | 26 ---------- gnovm/tests/files/types/22a17g_filetest.gno | 36 -------------- gnovm/tests/files/types/22a17h_filetest.gno | 30 ------------ gnovm/tests/files/types/22a17i_filetest.gno | 48 ------------------- gnovm/tests/files/types/22a17j_filetest.gno | 28 ----------- gnovm/tests/files/types/22a18_filetest.gno | 12 ----- .../files/types/22a1_IMPLICIT_filetest.gno | 17 ------- gnovm/tests/files/types/22a1a_filetest.gno | 29 ----------- gnovm/tests/files/types/22a2_filetest.gno | 25 ---------- gnovm/tests/files/types/22a3_filetest.gno | 25 ---------- gnovm/tests/files/types/22a4_filetest.gno | 25 ---------- gnovm/tests/files/types/22a5_filetest.gno | 24 ---------- gnovm/tests/files/types/22a6_filetest.gno | 20 -------- gnovm/tests/files/types/22a7_filetest.gno | 20 -------- gnovm/tests/files/types/22a8_filetest.gno | 24 ---------- gnovm/tests/files/types/22a9_filetest.gno | 20 -------- gnovm/tests/{debug => files/types}/bigdec.gno | 0 36 files changed, 13 insertions(+), 781 deletions(-) delete mode 100644 gnovm/tests/files/types/22a10_filetest.gno delete mode 100644 gnovm/tests/files/types/22a11_filetest.gno delete mode 100644 gnovm/tests/files/types/22a11a_filetest.gno delete mode 100644 gnovm/tests/files/types/22a12_filetest.gno delete mode 100644 gnovm/tests/files/types/22a12a_filetest.gno delete mode 100644 gnovm/tests/files/types/22a12b_filetest.gno delete mode 100644 gnovm/tests/files/types/22a12c_filetest.gno delete mode 100644 gnovm/tests/files/types/22a13_filetest.gno delete mode 100644 gnovm/tests/files/types/22a14_filetest.gnoa delete mode 100644 gnovm/tests/files/types/22a15_filetest.gno delete mode 100644 gnovm/tests/files/types/22a16_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17a_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17b_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17c_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17d_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17e_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17f_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17g_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17h_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17i_filetest.gno delete mode 100644 gnovm/tests/files/types/22a17j_filetest.gno delete mode 100644 gnovm/tests/files/types/22a18_filetest.gno delete mode 100644 gnovm/tests/files/types/22a1_IMPLICIT_filetest.gno delete mode 100644 gnovm/tests/files/types/22a1a_filetest.gno delete mode 100644 gnovm/tests/files/types/22a2_filetest.gno delete mode 100644 gnovm/tests/files/types/22a3_filetest.gno delete mode 100644 gnovm/tests/files/types/22a4_filetest.gno delete mode 100644 gnovm/tests/files/types/22a5_filetest.gno delete mode 100644 gnovm/tests/files/types/22a6_filetest.gno delete mode 100644 gnovm/tests/files/types/22a7_filetest.gno delete mode 100644 gnovm/tests/files/types/22a8_filetest.gno delete mode 100644 gnovm/tests/files/types/22a9_filetest.gno rename gnovm/tests/{debug => files/types}/bigdec.gno (100%) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index d7ab02cb986..ac329d4710c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -747,7 +747,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // special case of shift if isShift { // check LHS type compatibility - // check compatible n.checkShiftExpr(lt) // checkOrConvert RHS if baseOf(rt) != UintType { @@ -2408,9 +2407,8 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if debug { debug.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) } - var needConversion bool // for unnamed -> named if t != nil && !coerce { - needConversion = checkAssignableTo(xt, t, autoNative) + checkAssignableTo(xt, t, autoNative) } if isUntyped(xt) { if t == nil { @@ -2439,13 +2437,6 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative cx = Preprocess(store, last, cx).(Expr) *x = cx } - - // unnamed to named - if needConversion { - cx := Expr(Call(constType(nil, t), *x)) - cx = Preprocess(store, last, cx).(Expr) - *x = cx - } } } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index b419fcb9ddc..0e5c7b07e02 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -235,7 +235,7 @@ func assertMaybeNil(msg string, t Type) { // case 2. unnamed to named // case 3. dt is interface, xt satisfied dt // case 4. general cases for primitives and composite. -func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { +func checkAssignableTo(xt, dt Type, autoNative bool) { if debug { debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) } @@ -357,8 +357,7 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { dt.String())) } else { // carry on with baseOf(dxt) - xt = dxt.Base // set as base to do the rest check - conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass + xt = dxt.Base // set as base to do the rest check } } } else if ddt, ok := dt.(*DeclaredType); ok { @@ -379,7 +378,6 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { } } else { dt = ddt.Base - conversionNeeded = true // conduct a type conversion from unnamed to named, it below checks pass } } @@ -449,24 +447,24 @@ func checkAssignableTo(xt, dt Type, autoNative bool) (conversionNeeded bool) { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - cdt := checkAssignableTo(pt.Elt, cdt.Elt, false) - return cdt || conversionNeeded + checkAssignableTo(pt.Elt, cdt.Elt, false) } + return case *ArrayType: if at, ok := xt.(*ArrayType); ok { - cdt := checkAssignableTo(at.Elt, cdt.Elt, false) - return cdt || conversionNeeded + checkAssignableTo(at.Elt, cdt.Elt, false) + return } case *SliceType: if st, ok := xt.(*SliceType); ok { - cdt := checkAssignableTo(st.Elt, cdt.Elt, false) - return cdt || conversionNeeded + checkAssignableTo(st.Elt, cdt.Elt, false) + return } case *MapType: if mt, ok := xt.(*MapType); ok { - cn1 := checkAssignableTo(mt.Key, cdt.Key, false) - cn2 := checkAssignableTo(mt.Value, cdt.Value, false) - return cn1 || cn2 || conversionNeeded + checkAssignableTo(mt.Key, cdt.Key, false) + checkAssignableTo(mt.Value, cdt.Value, false) + return } case *FuncType: if xt.TypeID() == cdt.TypeID() { @@ -621,7 +619,7 @@ func (bx *BinaryExpr) checkCompatibility(store Store, xt, dt Type, checker func( }() // e.g. 1%1e9 - if !checker(xt) { // lt not compatible with op + if !checker(xt) { checkAssignableTo(xt, dt, false) // XXX, cache this? } } diff --git a/gnovm/tests/files/types/22a10_filetest.gno b/gnovm/tests/files/types/22a10_filetest.gno deleted file mode 100644 index cf1bf1c1759..00000000000 --- a/gnovm/tests/files/types/22a10_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add(x, y nat) bool { - return true -} - -// parameter -func main() { - var abs nat - abs = []word{0} - x := []word{1} - y := []word{2} - - println(abs.add(x, y)) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a11_filetest.gno b/gnovm/tests/files/types/22a11_filetest.gno deleted file mode 100644 index e99eb493d7e..00000000000 --- a/gnovm/tests/files/types/22a11_filetest.gno +++ /dev/null @@ -1,22 +0,0 @@ -package main - -type BasicFunc func(int, int) int -type MyFunc BasicFunc - -func (f MyFunc) Apply(a, b int) int { - return f(a, b) -} - -func main() { - basicAdd := func(a, b int) int { - return a + b - } - var myAdd MyFunc - myAdd = basicAdd - - result := myAdd.Apply(2, 3) - println(result) -} - -// Output: -// 5 diff --git a/gnovm/tests/files/types/22a11a_filetest.gno b/gnovm/tests/files/types/22a11a_filetest.gno deleted file mode 100644 index fd79fa9fc47..00000000000 --- a/gnovm/tests/files/types/22a11a_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -type MyFunc func(int, int) int - -func (f MyFunc) Apply(a, b int) int { - return f(a, b) -} - -func main() { - basicAdd := func(a, b int) int { - return a + b - } - var myAdd MyFunc - myAdd = basicAdd - - result := myAdd.Apply(2, 3) - println(result) -} - -// Output: -// 5 diff --git a/gnovm/tests/files/types/22a12_filetest.gno b/gnovm/tests/files/types/22a12_filetest.gno deleted file mode 100644 index 6173afd0c01..00000000000 --- a/gnovm/tests/files/types/22a12_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type c uint -type word c -type nat []word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - - abs = []c{0} - - println(abs.add()) -} - -// Error: -// main/files/types/22a12_filetest.gno:14: cannot use main.c as main.word without explicit conversion diff --git a/gnovm/tests/files/types/22a12a_filetest.gno b/gnovm/tests/files/types/22a12a_filetest.gno deleted file mode 100644 index 7c757ff6347..00000000000 --- a/gnovm/tests/files/types/22a12a_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import "fmt" - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - abs = []word{0} // unname-Composit to named DeclaredTypes - println(abs.add()) - - var s []word - s = abs - fmt.Printf("%T", s) -} - -// Output: -// true -// []uint diff --git a/gnovm/tests/files/types/22a12b_filetest.gno b/gnovm/tests/files/types/22a12b_filetest.gno deleted file mode 100644 index ab2b0d969ad..00000000000 --- a/gnovm/tests/files/types/22a12b_filetest.gno +++ /dev/null @@ -1,22 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// TODO: improve err, like :s.add undefined (type []word has no field or method add) -func main() { - var abs nat - abs = []word{0} // unname-Composit to named DeclaredTypes - println(abs.add()) - - var s []word - s = abs - println(s.add()) -} - -// Error: -// main/files/types/22a12b_filetest.gno:18: unexpected selector expression type *gnolang.SliceType diff --git a/gnovm/tests/files/types/22a12c_filetest.gno b/gnovm/tests/files/types/22a12c_filetest.gno deleted file mode 100644 index df2dc499c85..00000000000 --- a/gnovm/tests/files/types/22a12c_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import "fmt" - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// TODO: seems fmt prints the underlying type, this is another problem to fix. -func main() { - var abs nat - abs = []word{0} // unname-Composit to named DeclaredTypes - fmt.Printf("%T \n", abs) - - var s []word - s = abs - fmt.Printf("%T \n", s) -} - -// Output: -// []uint -// []uint diff --git a/gnovm/tests/files/types/22a13_filetest.gno b/gnovm/tests/files/types/22a13_filetest.gno deleted file mode 100644 index 8c143338cee..00000000000 --- a/gnovm/tests/files/types/22a13_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type c uint -type word c -type nat []word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - - abs = []uint{0} - - println(abs.add()) -} - -// Error: -// main/files/types/22a13_filetest.gno:14: cannot use uint as main.word without explicit conversion diff --git a/gnovm/tests/files/types/22a14_filetest.gnoa b/gnovm/tests/files/types/22a14_filetest.gnoa deleted file mode 100644 index 2385623808b..00000000000 --- a/gnovm/tests/files/types/22a14_filetest.gnoa +++ /dev/null @@ -1,21 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// parameter -// TODO: should fix in another place, this should not work -func main() { - des := make([]nat, 2) - src := make([][]word, 2) - - src[0] = []word{0} - - copy(des, src) -} - -// Error: diff --git a/gnovm/tests/files/types/22a15_filetest.gno b/gnovm/tests/files/types/22a15_filetest.gno deleted file mode 100644 index bf307296caa..00000000000 --- a/gnovm/tests/files/types/22a15_filetest.gno +++ /dev/null @@ -1,18 +0,0 @@ -package main - -type word uint -type nat map[string]word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - abs = map[string]word{"test": word(0)} // unname-Composit to named DeclaredTypes - - println(abs.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a16_filetest.gno b/gnovm/tests/files/types/22a16_filetest.gno deleted file mode 100644 index b6a3088bd86..00000000000 --- a/gnovm/tests/files/types/22a16_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -type nat []int - -func main() { - - var a nat - a = []int{0} - b := []int{1} - - println(a) - println(b) - - a = nat{0} - b = a - - println(a) - println(b) -} - -// Output: -// (slice[(0 int)] main.nat) -// slice[(1 int)] -// (slice[(0 int)] main.nat) -// slice[(0 int)] diff --git a/gnovm/tests/files/types/22a17_filetest.gno b/gnovm/tests/files/types/22a17_filetest.gno deleted file mode 100644 index d47b1c83f8d..00000000000 --- a/gnovm/tests/files/types/22a17_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -type Int int8 - -func Add(a, b Int) Int { - return a + b -} - -func main() { - r := Add(0, 1) - println(r) -} - -// Output: -// (1 main.Int) diff --git a/gnovm/tests/files/types/22a17a_filetest.gno b/gnovm/tests/files/types/22a17a_filetest.gno deleted file mode 100644 index 907d10807ef..00000000000 --- a/gnovm/tests/files/types/22a17a_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -type Int int8 - -func Add(a, b Int) Int { - return a + b -} - -// No binaryExpr or unaryExpr, no op related, still need checkType -func main() { - println(Add(0, int8(1))) -} - -// Error: -// main/files/types/22a17a_filetest.gno:11: cannot use int8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/22a17b_filetest.gno b/gnovm/tests/files/types/22a17b_filetest.gno deleted file mode 100644 index d9724e67ad6..00000000000 --- a/gnovm/tests/files/types/22a17b_filetest.gno +++ /dev/null @@ -1,16 +0,0 @@ -package main - -type i8 int8 -type Int i8 - -func Add(a, b Int) Int { - return a + b -} - -func main() { - r := Add(0, i8(1)) - println(r) -} - -// Error: -// main/files/types/22a17b_filetest.gno:11: cannot use main.i8 as main.Int without explicit conversion diff --git a/gnovm/tests/files/types/22a17c_filetest.gno b/gnovm/tests/files/types/22a17c_filetest.gno deleted file mode 100644 index 7231e33f9b6..00000000000 --- a/gnovm/tests/files/types/22a17c_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type word uint -type nat []word - -func Add(n1, n2 nat) bool { - return true -} - -// mapLit -func main() { - n0 := []word{0} - n1 := []word{1} - - r := Add(n0, n1) - println(r) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a17d_filetest.gno b/gnovm/tests/files/types/22a17d_filetest.gno deleted file mode 100644 index ffd8e4c3c27..00000000000 --- a/gnovm/tests/files/types/22a17d_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type word uint -type nat []word - -func Add(n1, n2 nat) int { - return len(n1) + len(n2) -} - -// mapLit -func main() { - n0 := []word{0} - n1 := []word{1} - - r := Add(n0, n1) - println(r) -} - -// Output: -// 2 diff --git a/gnovm/tests/files/types/22a17e_filetest.gno b/gnovm/tests/files/types/22a17e_filetest.gno deleted file mode 100644 index bd46a6f9d7a..00000000000 --- a/gnovm/tests/files/types/22a17e_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { - return true -} - -func Gen() nat { - n := []word{0} - return n -} - -// mapLit -func main() { - r := Gen() - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a17f_filetest.gno b/gnovm/tests/files/types/22a17f_filetest.gno deleted file mode 100644 index bf82d9fea0d..00000000000 --- a/gnovm/tests/files/types/22a17f_filetest.gno +++ /dev/null @@ -1,26 +0,0 @@ -package main - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { - return true -} - -func Gen2() (nat, nat) { - n0 := []word{0} - n1 := []word{1} - return n0, n1 -} - -// mapLit -func main() { - r1, r2 := Gen2() - println(r1.add()) - println(r2.add()) -} - -// Output: -// true -// true diff --git a/gnovm/tests/files/types/22a17g_filetest.gno b/gnovm/tests/files/types/22a17g_filetest.gno deleted file mode 100644 index 7676395b252..00000000000 --- a/gnovm/tests/files/types/22a17g_filetest.gno +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import "fmt" - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { - return true -} - -func Gen() interface{} { - n := []word{0} - return n -} - -// mapLit -func main() { - r := Gen() - - fmt.Printf("%T \n", r) - - switch r.(type) { - case nat: - println("nat") - case []word: - println("[]word") - default: - panic("should not happen") - } -} - -// Output: -// []uint -// []word diff --git a/gnovm/tests/files/types/22a17h_filetest.gno b/gnovm/tests/files/types/22a17h_filetest.gno deleted file mode 100644 index 9b7f2c80a64..00000000000 --- a/gnovm/tests/files/types/22a17h_filetest.gno +++ /dev/null @@ -1,30 +0,0 @@ -package main - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { - return true -} - -func Gen() nat { - n := []word{0} - return n -} - -// mapLit -func main() { - r := Gen() - switch r.(type) { - case nat: - println("nat") - println(r.add()) - default: - println("should not happen") - } -} - -// Output: -// nat -// true diff --git a/gnovm/tests/files/types/22a17i_filetest.gno b/gnovm/tests/files/types/22a17i_filetest.gno deleted file mode 100644 index e9c4c395a77..00000000000 --- a/gnovm/tests/files/types/22a17i_filetest.gno +++ /dev/null @@ -1,48 +0,0 @@ -package main - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { - return true -} - -func Gen() interface{} { - n := []word{0} - return n -} - -func Gen2() interface{} { - n := nat([]word{0}) - return n -} - -func main() { - r := Gen() - switch t := r.(type) { - case nat: - println("nat") - println(t.add()) - case []word: - println("[]word") - default: - println("should not happen") - } - - r2 := Gen2() - switch t := r2.(type) { - case nat: - println("nat") - println(t.add()) - case []word: - println("[]word") - default: - println("should not happen") - } -} - -// Output: -// []word -// nat -// true diff --git a/gnovm/tests/files/types/22a17j_filetest.gno b/gnovm/tests/files/types/22a17j_filetest.gno deleted file mode 100644 index 507b5ca7051..00000000000 --- a/gnovm/tests/files/types/22a17j_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import "fmt" - -type nat []int - -func main() { - - var a nat - a = []int{0} - b := []int{1} - - fmt.Printf("%v \n ", a) - fmt.Printf("%v \n ", b) - - a = nat{0} - b = a - - fmt.Printf("%v \n ", a) - fmt.Printf("%v \n ", b) - -} - -// Output: -// [0] -// [1] -// [0] -// [0] diff --git a/gnovm/tests/files/types/22a18_filetest.gno b/gnovm/tests/files/types/22a18_filetest.gno deleted file mode 100644 index 88aae826e85..00000000000 --- a/gnovm/tests/files/types/22a18_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -type s1 struct { - foo int -} - -func main() { - println(s1{foo: 1} == 1) -} - -// Error: -// main/files/types/22a18_filetest.gno:8: cannot use bigint as struct{foo int} diff --git a/gnovm/tests/files/types/22a1_IMPLICIT_filetest.gno b/gnovm/tests/files/types/22a1_IMPLICIT_filetest.gno deleted file mode 100644 index 52250bc4393..00000000000 --- a/gnovm/tests/files/types/22a1_IMPLICIT_filetest.gno +++ /dev/null @@ -1,17 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - abs = []word{0} // unname-Composit to named DeclaredTypes - println(abs.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a1a_filetest.gno b/gnovm/tests/files/types/22a1a_filetest.gno deleted file mode 100644 index 3c9bc4d1e03..00000000000 --- a/gnovm/tests/files/types/22a1a_filetest.gno +++ /dev/null @@ -1,29 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -func main() { - var abs nat - abs = []word{0} // unname-Composit to named DeclaredTypes - println(abs.add()) - - var w []word - w = abs - println(w) - switch w.(type) { - case []word: - println("[]word") - case nat: - println("should not happen") - } -} - -// Output: -// true -// slice[(0 main.word)] -// []word diff --git a/gnovm/tests/files/types/22a2_filetest.gno b/gnovm/tests/files/types/22a2_filetest.gno deleted file mode 100644 index 62a38acbe20..00000000000 --- a/gnovm/tests/files/types/22a2_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -type word uint -type nat []word - -// structLit -type Int struct { - neg bool - abs nat -} - -func (n nat) add() bool { - return true -} - -func main() { - z := &Int{ - neg: true, - abs: []word{0}, - } - println(z.abs.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a3_filetest.gno b/gnovm/tests/files/types/22a3_filetest.gno deleted file mode 100644 index 5b49241ae8b..00000000000 --- a/gnovm/tests/files/types/22a3_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -type word uint -type nat []word - -type Int struct { - neg bool - abs nat -} - -func (n nat) add() bool { - return true -} - -func main() { - z := &Int{ - neg: true, - } - - z.abs = []word{0} - println(z.abs.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a4_filetest.gno b/gnovm/tests/files/types/22a4_filetest.gno deleted file mode 100644 index f66dcfe2ace..00000000000 --- a/gnovm/tests/files/types/22a4_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -type word uint -type nat []word - -// receiver -func (n nat) add() bool { - return true -} - -// map -func main() { - items := map[string]nat{} - - n := []word{0} - - items["test"] = n - - r := items["test"] - - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a5_filetest.gno b/gnovm/tests/files/types/22a5_filetest.gno deleted file mode 100644 index 3352f38083d..00000000000 --- a/gnovm/tests/files/types/22a5_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// mapLit -func main() { - n := []word{0} - - items := map[string]nat{ - "test": n, - } - - r := items["test"] - - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a6_filetest.gno b/gnovm/tests/files/types/22a6_filetest.gno deleted file mode 100644 index f5beceec159..00000000000 --- a/gnovm/tests/files/types/22a6_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// sliceLit -func main() { - items := []nat{[]word{0}, []word{1}} - - r := items[0] - - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a7_filetest.gno b/gnovm/tests/files/types/22a7_filetest.gno deleted file mode 100644 index 5b91ac72cc3..00000000000 --- a/gnovm/tests/files/types/22a7_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// sliceLit2 -func main() { - items := []nat{1: []word{0}, 2: []word{1}} - - r := items[1] - - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a8_filetest.gno b/gnovm/tests/files/types/22a8_filetest.gno deleted file mode 100644 index a6bc0f251a5..00000000000 --- a/gnovm/tests/files/types/22a8_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// slice append -func main() { - var items []nat - - n := []word{0} - - items = append(items, n) - - r := items[0] - - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/22a9_filetest.gno b/gnovm/tests/files/types/22a9_filetest.gno deleted file mode 100644 index b10c2f9ab8a..00000000000 --- a/gnovm/tests/files/types/22a9_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -type word uint -type nat []word - -func (n nat) add() bool { - return true -} - -// ArrayLit -func main() { - items := [3]nat{[]word{0}, []word{1}} - - r := items[0] - - println(r.add()) -} - -// Output: -// true diff --git a/gnovm/tests/debug/bigdec.gno b/gnovm/tests/files/types/bigdec.gno similarity index 100% rename from gnovm/tests/debug/bigdec.gno rename to gnovm/tests/files/types/bigdec.gno From 5b83cdbfdbfd6e95e41b126b46ac5d62f5fe0088 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 8 Apr 2024 14:41:18 +0800 Subject: [PATCH 123/193] add test --- gnovm/tests/files/types/0a02.gno | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 gnovm/tests/files/types/0a02.gno diff --git a/gnovm/tests/files/types/0a02.gno b/gnovm/tests/files/types/0a02.gno new file mode 100644 index 00000000000..8fc6c37d9fa --- /dev/null +++ b/gnovm/tests/files/types/0a02.gno @@ -0,0 +1,11 @@ +package main + +func main() { + intPtr := new(int) + *intPtr = 5 + s := "hello" + println(intPtr == s) +} + +// Error: +// main/files/types/0a02.gno:7: cannot use *int as string From 3d148f6d3df828e3621c6670f743e312e73001a6 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 8 Apr 2024 14:44:20 +0800 Subject: [PATCH 124/193] add test --- gnovm/tests/files/types/0a03.gno | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 gnovm/tests/files/types/0a03.gno diff --git a/gnovm/tests/files/types/0a03.gno b/gnovm/tests/files/types/0a03.gno new file mode 100644 index 00000000000..243ecc4d2f5 --- /dev/null +++ b/gnovm/tests/files/types/0a03.gno @@ -0,0 +1,12 @@ +package main + +func main() { + intPtr := new(int8) + *intPtr = 5 + + i := 0 + println(intPtr == &i) +} + +// Error: +// main/files/types/0a03.gno:8: cannot use int8 as int From 79252024356b5a41558cea4f6e0b879cd994bc48 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 8 Apr 2024 16:17:13 +0800 Subject: [PATCH 125/193] check bigdec, add comments --- gnovm/pkg/gnolang/type_check.go | 10 +++++++--- gnovm/tests/files/types/0a5_rune_filetest.gno | 2 ++ gnovm/tests/files/types/0d0_filetest.gno | 2 ++ gnovm/tests/files/types/bigdec2.gno | 11 +++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 gnovm/tests/files/types/bigdec2.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 0e5c7b07e02..0d954e4433b 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -402,8 +402,12 @@ func checkAssignableTo(xt, dt Type, autoNative bool) { "cannot use untyped string as %s", dt.Kind())) } - - case UntypedBigdecType: // can bigdec assign to bigint? + // XXX, this is a loose check, we don't have the context + // to check if it is an exact integer, e.g. 1.2 or 1.0(1.0 can be converted to int). + // this ensure expr like (a % 1.0) pass check, while + // expr like (a % 1.2) panic at ConvertUntypedTo, which is a delayed assertion when const evaluated. + // assignable does not guarantee convertable. + case UntypedBigdecType: switch dt.Kind() { case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind, UintKind, Uint8Kind, Uint16Kind, @@ -418,7 +422,7 @@ func checkAssignableTo(xt, dt Type, autoNative bool) { switch dt.Kind() { case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind, UintKind, Uint8Kind, Uint16Kind, - Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: + Uint32Kind, Uint64Kind, BigintKind, BigdecKind, Float32Kind, Float64Kind: // see 0d0 return // ok default: panic(fmt.Sprintf( diff --git a/gnovm/tests/files/types/0a5_rune_filetest.gno b/gnovm/tests/files/types/0a5_rune_filetest.gno index fe05f7c1124..7c1e8742fd4 100644 --- a/gnovm/tests/files/types/0a5_rune_filetest.gno +++ b/gnovm/tests/files/types/0a5_rune_filetest.gno @@ -8,9 +8,11 @@ func main() { println(r) println(float32(r)) println(float64(r)) + println(string(r)) } // Output: // 97 // 97 // 97 +// a diff --git a/gnovm/tests/files/types/0d0_filetest.gno b/gnovm/tests/files/types/0d0_filetest.gno index ac965bef23e..6890d450bab 100644 --- a/gnovm/tests/files/types/0d0_filetest.gno +++ b/gnovm/tests/files/types/0d0_filetest.gno @@ -4,8 +4,10 @@ package main func main() { println(1.0 == 1) println(1.0 == 0) + println(float32(1.0) == 0) } // Output: // true // false +// false diff --git a/gnovm/tests/files/types/bigdec2.gno b/gnovm/tests/files/types/bigdec2.gno new file mode 100644 index 00000000000..60048151a31 --- /dev/null +++ b/gnovm/tests/files/types/bigdec2.gno @@ -0,0 +1,11 @@ +package main + +var a uint64 + +func main() { + a = 1 + println(a % 1.2) +} + +// Error: +// main/files/types/bigdec2.gno:7: cannot convert untyped bigdec to integer -- 1.2 not an exact integer From 2f780d5e05077ab1615bce56bc47295fc64c214d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 10 Apr 2024 09:56:24 +0800 Subject: [PATCH 126/193] clean --- gnovm/pkg/gnolang/type_check.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 0d954e4433b..6fb97c2a75f 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -295,8 +295,6 @@ func checkAssignableTo(xt, dt Type, autoNative bool) { if gno2GoTypeMatches(baseOf(xdt), ndt.Type) { return } // not check against native interface - //debug.Println("---matches!") - //return } else { panic(fmt.Sprintf( "unexpected type pair: cannot use %s as %s", @@ -536,7 +534,7 @@ func (bx *BinaryExpr) checkShiftExpr(dt Type) { // e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. -func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { +func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { // we can't check compatible with native types at current stage, // so leave it to later operations(trans_leave on binaryExpr) // to be converted into gno(only for primitive types), and do @@ -573,7 +571,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { assertComparable(xt, dt) // only check if dest type is comparable case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(store, xt, dt, checker, escapedOpStr) + bx.checkCompatibility(xt, dt, checker, escapedOpStr) } else { panic("should not happen") } @@ -582,7 +580,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } } else { if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(store, xt, dt, checker, escapedOpStr) + bx.checkCompatibility(xt, dt, checker, escapedOpStr) } else { panic("should not happen") } @@ -603,7 +601,7 @@ func (bx *BinaryExpr) AssertCompatible(store Store, lt, rt Type) { } } -func (bx *BinaryExpr) checkCompatibility(store Store, xt, dt Type, checker func(t Type) bool, escapedOpStr string) { +func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, escapedOpStr string) { var destKind interface{} if !checker(dt) { From a89aea36be43dc8918940086ce954f33105a04af Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 11 Apr 2024 23:35:03 +0800 Subject: [PATCH 127/193] type check for assignStmt --- gnovm/pkg/gnolang/preprocess.go | 58 +------ gnovm/pkg/gnolang/type_check.go | 150 ++++++++++++++++-- gnovm/tests/debug/assign_call.gno | 14 ++ gnovm/tests/debug/assign_index.gno | 14 ++ gnovm/tests/debug/assign_index_1.gno | 12 ++ gnovm/tests/debug/assign_index_a.gno | 12 ++ gnovm/tests/debug/assign_literal.gno | 8 + gnovm/tests/debug/assign_literal10.gno | 21 +++ gnovm/tests/debug/assign_literal10a.gno | 20 +++ gnovm/tests/debug/assign_literal11.gno | 11 ++ gnovm/tests/debug/assign_literal2.gno | 9 ++ gnovm/tests/debug/assign_literal2_a.gno | 9 ++ gnovm/tests/debug/assign_literal3.gno | 8 + gnovm/tests/debug/assign_literal4.gno | 8 + gnovm/tests/debug/assign_literal4_a.gno | 8 + gnovm/tests/debug/assign_literal5.gno | 8 + gnovm/tests/debug/assign_literal6.gno | 8 + gnovm/tests/debug/assign_literal7.gno | 10 ++ gnovm/tests/debug/assign_literal7a.gno | 10 ++ gnovm/tests/debug/assign_literal7b.gno | 10 ++ gnovm/tests/debug/assign_literal7c.gno | 13 ++ gnovm/tests/debug/assign_literal7d.gno | 14 ++ gnovm/tests/debug/assign_literal8.gno | 11 ++ gnovm/tests/debug/assign_literal9.gno | 14 ++ gnovm/tests/debug/assign_literal_a.gno | 8 + gnovm/tests/debug/assign_type_assertion.gno | 22 +++ gnovm/tests/debug/assign_type_assertion_a.gno | 33 ++++ gnovm/tests/debug/assign_type_assertion_b.gno | 32 ++++ gnovm/tests/debug_temp/bigdec3.gno | 11 ++ gnovm/tests/debug_temp/bigdec4.gno | 11 ++ gnovm/tests/debug_temp/bigdec5.gno | 11 ++ 31 files changed, 522 insertions(+), 66 deletions(-) create mode 100644 gnovm/tests/debug/assign_call.gno create mode 100644 gnovm/tests/debug/assign_index.gno create mode 100644 gnovm/tests/debug/assign_index_1.gno create mode 100644 gnovm/tests/debug/assign_index_a.gno create mode 100644 gnovm/tests/debug/assign_literal.gno create mode 100644 gnovm/tests/debug/assign_literal10.gno create mode 100644 gnovm/tests/debug/assign_literal10a.gno create mode 100644 gnovm/tests/debug/assign_literal11.gno create mode 100644 gnovm/tests/debug/assign_literal2.gno create mode 100644 gnovm/tests/debug/assign_literal2_a.gno create mode 100644 gnovm/tests/debug/assign_literal3.gno create mode 100644 gnovm/tests/debug/assign_literal4.gno create mode 100644 gnovm/tests/debug/assign_literal4_a.gno create mode 100644 gnovm/tests/debug/assign_literal5.gno create mode 100644 gnovm/tests/debug/assign_literal6.gno create mode 100644 gnovm/tests/debug/assign_literal7.gno create mode 100644 gnovm/tests/debug/assign_literal7a.gno create mode 100644 gnovm/tests/debug/assign_literal7b.gno create mode 100644 gnovm/tests/debug/assign_literal7c.gno create mode 100644 gnovm/tests/debug/assign_literal7d.gno create mode 100644 gnovm/tests/debug/assign_literal8.gno create mode 100644 gnovm/tests/debug/assign_literal9.gno create mode 100644 gnovm/tests/debug/assign_literal_a.gno create mode 100644 gnovm/tests/debug/assign_type_assertion.gno create mode 100644 gnovm/tests/debug/assign_type_assertion_a.gno create mode 100644 gnovm/tests/debug/assign_type_assertion_b.gno create mode 100644 gnovm/tests/debug_temp/bigdec3.gno create mode 100644 gnovm/tests/debug_temp/bigdec4.gno create mode 100644 gnovm/tests/debug_temp/bigdec5.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ac329d4710c..394736eba5d 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -762,7 +762,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return resn, TRANS_CONTINUE } } else { - n.AssertCompatible(store, lt, rt) + n.AssertCompatible(lt, rt) } // General case. lcx, lic := n.Left.(*ConstExpr) @@ -1577,22 +1577,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: does nothing if rx is "nil". convertIfConst(store, last, rx) } + + n.AssertCompatible(store, last) if len(n.Lhs) > len(n.Rhs) { - // Unpack n.Rhs[0] to n.Lhs[:] - if len(n.Rhs) != 1 { - panic("should not happen") - } switch cx := n.Rhs[0].(type) { case *CallExpr: // Call case: a, b := x(...) ift := evalStaticTypeOf(store, last, cx.Func) cft := getGnoFuncTypeOf(store, ift) - if len(n.Lhs) != len(cft.Results) { - panic(fmt.Sprintf( - "assignment mismatch: "+ - "%d variables but %s returns %d values", - len(n.Lhs), cx.Func.String(), len(cft.Results))) - } for i, lx := range n.Lhs { ln := lx.(*NameExpr).Name rf := cft.Results[i] @@ -1600,10 +1592,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(ln, anyValue(rf.Type)) } case *TypeAssertExpr: - // Type-assert case: a, ok := x.(type) - if len(n.Lhs) != 2 { - panic("should not happen") - } cx.HasOK = true lhs0 := n.Lhs[0].(*NameExpr).Name lhs1 := n.Lhs[1].(*NameExpr).Name @@ -1612,10 +1600,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(lhs0, anyValue(tt)) last.Define(lhs1, anyValue(BoolType)) case *IndexExpr: - // Index case: v, ok := x[k], x is map. - if len(n.Lhs) != 2 { - panic("should not happen") - } cx.HasOK = true lhs0 := n.Lhs[0].(*NameExpr).Name lhs1 := n.Lhs[1].(*NameExpr).Name @@ -1645,41 +1629,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // ASSIGN. // NOTE: Keep in sync with DEFINE above. + n.AssertCompatible(store, last) if len(n.Lhs) > len(n.Rhs) { - // TODO dry code w/ above. - // Unpack n.Rhs[0] to n.Lhs[:] - if len(n.Rhs) != 1 { - panic("should not happen") - } - switch cx := n.Rhs[0].(type) { - // TODO: check compatible with this case? a, b = x(...) - case *CallExpr: - // Call case: a, b = x(...) - ift := evalStaticTypeOf(store, last, cx.Func) - cft := getGnoFuncTypeOf(store, ift) - if len(n.Lhs) != len(cft.Results) { - panic(fmt.Sprintf( - "assignment mismatch: "+ - "%d variables but %s returns %d values", - len(n.Lhs), cx.Func.String(), len(cft.Results))) - } - case *TypeAssertExpr: - // Type-assert case: a, ok := x.(type) - if len(n.Lhs) != 2 { - panic("should not happen") - } - cx.HasOK = true - case *IndexExpr: - // Index case: v, ok := x[k], x is map. - if len(n.Lhs) != 2 { - panic("should not happen") - } - cx.HasOK = true - default: - panic("should not happen") - } + // check is done in assertCompatible } else { - n.AssertCompatible(store, last) + debug.Println("---assignStmt, assign") if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { if len(n.Lhs) != 1 || len(n.Rhs) != 1 { panic("should not happen") diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 6fb97c2a75f..216a790c5d1 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -675,25 +675,138 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { escapedOpStr := strings.Replace(wordTokenStrings[as.Op], "%", "%%", 1) var destKind interface{} - // XXX, assume lhs length is same with of rhs - // Call case: a, b = x(...) - for i, x := range as.Lhs { - lt := evalStaticTypeOf(store, last, x) - rt := evalStaticTypeOf(store, last, as.Rhs[i]) + if as.Op == ASSIGN || as.Op == DEFINE { + if len(as.Lhs) > len(as.Rhs) { + if len(as.Rhs) != 1 { + panic("should not happen") + } + switch cx := as.Rhs[0].(type) { + case *CallExpr: + // Call case: a, b = x(...) + ift := evalStaticTypeOf(store, last, cx.Func) + cft := getGnoFuncTypeOf(store, ift) + if len(as.Lhs) != len(cft.Results) { + panic(fmt.Sprintf( + "assignment mismatch: "+ + "%d variables but %s returns %d values", + len(as.Lhs), cx.Func.String(), len(cft.Results))) + } + // check assignable + for i, lx := range as.Lhs { + lxt := evalStaticTypeOf(store, last, lx) + checkAssignableTo(cft.Results[i].Type, lxt, false) // TODO: autoNative? + } + case *TypeAssertExpr: + // Type-assert case: a, ok := x.(type) + if len(as.Lhs) != 2 { + panic("should not happen") + } + debug.Println("---type assertion, assert type, reflect type of at: ", cx.Type, reflect.TypeOf(cx.Type)) + if ctex, ok := cx.Type.(*constTypeExpr); ok { + // check assignable + dt := evalStaticTypeOf(store, last, as.Lhs[0]) + checkAssignableTo(ctex.Type, dt, false) + } else if _, ok := cx.Type.(*InterfaceTypeExpr); ok { + dt := evalStaticTypeOf(store, last, as.Lhs[0]) + if isBlankIdentifier(as.Lhs[0]) { // see composite3.gno + debug.Println("---blank") + } else if dt != nil && dt.Kind() == InterfaceKind { + // do nothing + } else { + panic(fmt.Sprintf("cannot assign to %v \n", as.Lhs[0])) + } + } + cx.HasOK = true + case *IndexExpr: + if len(as.Lhs) != 2 { + panic("should not happen") + } + lt := evalStaticTypeOf(store, last, as.Lhs[0]) + debug.Println("---cx.X, type of: ", cx.X, reflect.TypeOf(cx.X)) + if nx, ok := cx.X.(*NameExpr); ok { + rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() + debug.Println("---rx, type of rx: ", rx, reflect.TypeOf(rx)) + debug.Println("---rx.T: ", rx.T) + debug.Println("---rx.V: ", rx.V) + + if mt, ok := rx.T.(*MapType); ok { + debug.Println("---mt: ", mt) + debug.Println("---type of value of map type: ", mt.Value) + checkAssignableTo(mt.Value, lt, false) + } + } else if _, ok := cx.X.(*CompositeLitExpr); ok { + cpt := evalStaticTypeOf(store, last, cx.X) + debug.Println("---cpt: ", cpt) + if mt, ok := cpt.(*MapType); ok { + debug.Println("---mt: ", mt) + checkAssignableTo(mt.Value, lt, false) + } + } + cx.HasOK = true + default: + panic("should not happen") + } + } else { + if as.Op == ASSIGN { + for i, lx := range as.Lhs { + rt := evalStaticTypeOf(store, last, as.Rhs[i]) - if lnt, ok := lt.(*NativeType); ok { - if _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType); ok { - return + debug.Println("lx, type of lx: ", lx, reflect.TypeOf(lx)) + + // check native cases + if rnt, ok := rt.(*NativeType); ok { + if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { + return + } + } + + shouldPanic := true + switch clx := lx.(type) { + case *NameExpr, *StarExpr, *SelectorExpr: + shouldPanic = false + case *IndexExpr: + debug.Println("---ix.X, type of ix.X: ", clx.X, reflect.TypeOf(clx.X)) + xt := evalStaticTypeOf(store, last, clx.X) + shouldPanic = xt != nil && xt.Kind() == StringKind + default: + } + if shouldPanic { + panic(fmt.Sprintf("cannot assign to %v \n", lx)) + } + } + } else { + // NOTE: this is already checked while parsing file + for i, lx := range as.Lhs { + rt := evalStaticTypeOf(store, last, as.Rhs[i]) + if rnt, ok := rt.(*NativeType); ok { + if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { + return + } + } + switch lx.(type) { + case *NameExpr: + default: + panic(fmt.Sprintf("non-name %v on left side of := \n", lx)) + } + } } } - if rnt, ok := rt.(*NativeType); ok { - if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { - return + } else { + for i, lx := range as.Lhs { + lt := evalStaticTypeOf(store, last, lx) + rt := evalStaticTypeOf(store, last, as.Rhs[i]) + + if lnt, ok := lt.(*NativeType); ok { + if _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType); ok { + return + } + } + if rnt, ok := rt.(*NativeType); ok { + if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { + return + } } - } - // check compatible - if as.Op != ASSIGN { if checker, ok := AssignStmtChecker[as.Op]; ok { if !checker(lt) { if lt != nil { @@ -775,3 +888,12 @@ func cmpSpecificity(t1, t2 Type) int { return -1 } } + +func isBlankIdentifier(x Expr) bool { + if nx, ok := x.(*NameExpr); ok { + if nx.Path.Depth == 0 && nx.Path.Index == 0 && nx.Name == "_" { + return true + } + } + return false +} diff --git a/gnovm/tests/debug/assign_call.gno b/gnovm/tests/debug/assign_call.gno new file mode 100644 index 00000000000..e739f8f1994 --- /dev/null +++ b/gnovm/tests/debug/assign_call.gno @@ -0,0 +1,14 @@ +package main + +func foo() (int, float32) { + return 1, 1.0 +} + +func main() { + var s, s1 string + s, s1 = foo() + println(s) +} + +// Error: +// main/debug/assign_call.gno:9: cannot use int as string diff --git a/gnovm/tests/debug/assign_index.gno b/gnovm/tests/debug/assign_index.gno new file mode 100644 index 00000000000..a5e6b7b8bca --- /dev/null +++ b/gnovm/tests/debug/assign_index.gno @@ -0,0 +1,14 @@ +package main + +func main() { + m := map[string]int{"a": 1, "b": 2, "c": 3} + + var s string + var ok bool + s, ok = m["a"] + println(s) + println(ok) +} + +// Error: +// main/debug/assign_index.gno:8: cannot use int as string \ No newline at end of file diff --git a/gnovm/tests/debug/assign_index_1.gno b/gnovm/tests/debug/assign_index_1.gno new file mode 100644 index 00000000000..2c01eab1548 --- /dev/null +++ b/gnovm/tests/debug/assign_index_1.gno @@ -0,0 +1,12 @@ +package main + +func main() { + s := []int{1, 2, 3} + + var s1 string + s1 = s[0] + println(s) +} + +// Error: +// main/debug/assign_index_1.gno:7: cannot use int as string diff --git a/gnovm/tests/debug/assign_index_a.gno b/gnovm/tests/debug/assign_index_a.gno new file mode 100644 index 00000000000..c3aa9088e91 --- /dev/null +++ b/gnovm/tests/debug/assign_index_a.gno @@ -0,0 +1,12 @@ +package main + +func main() { + var s string + var ok bool + s, ok = map[string]int{"a": 1, "b": 2, "c": 3}["a"] + println(s) + println(ok) +} + +// Error: +// main/debug/assign_index_a.gno:6: cannot use int as string diff --git a/gnovm/tests/debug/assign_literal.gno b/gnovm/tests/debug/assign_literal.gno new file mode 100644 index 00000000000..d2d172b0322 --- /dev/null +++ b/gnovm/tests/debug/assign_literal.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 = 6 +} + +// Error: +// main/debug/assign_literal.gno:4: cannot assign to (const (1 bigint)) diff --git a/gnovm/tests/debug/assign_literal10.gno b/gnovm/tests/debug/assign_literal10.gno new file mode 100644 index 00000000000..d7b29f91aec --- /dev/null +++ b/gnovm/tests/debug/assign_literal10.gno @@ -0,0 +1,21 @@ +package main + +type foo struct { + a int +} + +var n int + +func (f foo) add() *int { return &n } + +func main() { + s := &foo{} + *(s.add()) = 1 + println((*s).a) + + println(n) +} + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/debug/assign_literal10a.gno b/gnovm/tests/debug/assign_literal10a.gno new file mode 100644 index 00000000000..b1a2c9c113a --- /dev/null +++ b/gnovm/tests/debug/assign_literal10a.gno @@ -0,0 +1,20 @@ +package main + +type foo struct { + a int +} + +var n int + +func (f foo) add() *int { return &n } + +func main() { + s := &foo{} + s.add() = 1 + println((*s).a) + + println(n) +} + +// Error: +// main/debug/assign_literal10a.gno:13: cannot assign to s.add() diff --git a/gnovm/tests/debug/assign_literal11.gno b/gnovm/tests/debug/assign_literal11.gno new file mode 100644 index 00000000000..50f1d20ddfc --- /dev/null +++ b/gnovm/tests/debug/assign_literal11.gno @@ -0,0 +1,11 @@ +package main + +const Pi = 3.14 + +func main() { + Pi = 3.14159 + println(Pi) +} + +// Error: +// main/debug/assign_literal11.gno:6: cannot assign to (const (3.14 bigdec)) diff --git a/gnovm/tests/debug/assign_literal2.gno b/gnovm/tests/debug/assign_literal2.gno new file mode 100644 index 00000000000..f0a076bd52e --- /dev/null +++ b/gnovm/tests/debug/assign_literal2.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var a int + a, 2 = 6, 6 +} + +// Error: +// main/debug/assign_literal2.gno:5: cannot assign to (const (2 bigint)) \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal2_a.gno b/gnovm/tests/debug/assign_literal2_a.gno new file mode 100644 index 00000000000..14f1aea1d2d --- /dev/null +++ b/gnovm/tests/debug/assign_literal2_a.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var a int + a, 2 := 6, 6 +} + +// Error: +// debug/assign_literal2_a.gno:5:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal3.gno b/gnovm/tests/debug/assign_literal3.gno new file mode 100644 index 00000000000..5ef63b5ff5e --- /dev/null +++ b/gnovm/tests/debug/assign_literal3.gno @@ -0,0 +1,8 @@ +package main + +func main() { + true = false +} + +// Error: +// main/debug/assign_literal3.gno:4: cannot assign to (const (true bool)) \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal4.gno b/gnovm/tests/debug/assign_literal4.gno new file mode 100644 index 00000000000..e38b04b2e39 --- /dev/null +++ b/gnovm/tests/debug/assign_literal4.gno @@ -0,0 +1,8 @@ +package main + +func main() { + []int{1, 2} = []int{3, 4} +} + +// Error: +// main/debug/assign_literal4.gno:4: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal4_a.gno b/gnovm/tests/debug/assign_literal4_a.gno new file mode 100644 index 00000000000..0150b73a656 --- /dev/null +++ b/gnovm/tests/debug/assign_literal4_a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + []int{1, 2} := []int{3, 4} +} + +// Error: +// debug/assign_literal4_a.gno:4:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal5.gno b/gnovm/tests/debug/assign_literal5.gno new file mode 100644 index 00000000000..f1dd446e47d --- /dev/null +++ b/gnovm/tests/debug/assign_literal5.gno @@ -0,0 +1,8 @@ +package main + +func main() { + map[string]int{"a": 1, "b": 2} = map[string]int{"a": 1, "b": 2} +} + +// Error: +// main/debug/assign_literal5.gno:4: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} diff --git a/gnovm/tests/debug/assign_literal6.gno b/gnovm/tests/debug/assign_literal6.gno new file mode 100644 index 00000000000..41dec2ab5c1 --- /dev/null +++ b/gnovm/tests/debug/assign_literal6.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 + 2 = 6 +} + +// Error: +// main/debug/assign_literal6.gno:4: cannot assign to (const (3 bigint)) \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal7.gno b/gnovm/tests/debug/assign_literal7.gno new file mode 100644 index 00000000000..56308cdbbfc --- /dev/null +++ b/gnovm/tests/debug/assign_literal7.gno @@ -0,0 +1,10 @@ +package main + +func main() { + s := []int{1, 2, 3} + s[0] = 0 + println(s) +} + +// Output: +// slice[(0 int),(2 int),(3 int)] diff --git a/gnovm/tests/debug/assign_literal7a.gno b/gnovm/tests/debug/assign_literal7a.gno new file mode 100644 index 00000000000..8be126c49de --- /dev/null +++ b/gnovm/tests/debug/assign_literal7a.gno @@ -0,0 +1,10 @@ +package main + +func main() { + m := map[string]int{"a": 1, "b": 2, "c": 3} + m["a"] = 0 + println(m) +} + +// Output: +// map{("a" string):(0 int),("b" string):(2 int),("c" string):(3 int)} diff --git a/gnovm/tests/debug/assign_literal7b.gno b/gnovm/tests/debug/assign_literal7b.gno new file mode 100644 index 00000000000..dc61467e07c --- /dev/null +++ b/gnovm/tests/debug/assign_literal7b.gno @@ -0,0 +1,10 @@ +package main + +func main() { + s := [2]int{} + s[0] = 0 + println(s) +} + +// Output: +// array[(0 int),(0 int)] diff --git a/gnovm/tests/debug/assign_literal7c.gno b/gnovm/tests/debug/assign_literal7c.gno new file mode 100644 index 00000000000..4314308959a --- /dev/null +++ b/gnovm/tests/debug/assign_literal7c.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + str := "hello" + str[0] = 'y' + fmt.Println(str[0]) + fmt.Printf("%c\n", str[0]) +} + +// Error: +// main/debug/assign_literal7c.gno:7: cannot assign to str[(const (0 int))] diff --git a/gnovm/tests/debug/assign_literal7d.gno b/gnovm/tests/debug/assign_literal7d.gno new file mode 100644 index 00000000000..f56c304b3d3 --- /dev/null +++ b/gnovm/tests/debug/assign_literal7d.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + bs := []byte("hello") + bs[0] = 'y' + fmt.Println(bs[0]) + fmt.Printf("%c\n", bs[0]) +} + +// Output: +// 121 +// y diff --git a/gnovm/tests/debug/assign_literal8.gno b/gnovm/tests/debug/assign_literal8.gno new file mode 100644 index 00000000000..d652efc0874 --- /dev/null +++ b/gnovm/tests/debug/assign_literal8.gno @@ -0,0 +1,11 @@ +package main + +func main() { + var a int + p := &a + *p = 1 + println(*p) +} + +// Output: +// 1 diff --git a/gnovm/tests/debug/assign_literal9.gno b/gnovm/tests/debug/assign_literal9.gno new file mode 100644 index 00000000000..843cb5a67fc --- /dev/null +++ b/gnovm/tests/debug/assign_literal9.gno @@ -0,0 +1,14 @@ +package main + +type foo struct { + a int +} + +func main() { + s := &foo{} + s.a = 1 + println(s) +} + +// Output: +// &0x14000189110.(*main.foo) diff --git a/gnovm/tests/debug/assign_literal_a.gno b/gnovm/tests/debug/assign_literal_a.gno new file mode 100644 index 00000000000..9486f4068ba --- /dev/null +++ b/gnovm/tests/debug/assign_literal_a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 := 6 +} + +// Error: +// debug/assign_literal_a.gno:4:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug/assign_type_assertion.gno b/gnovm/tests/debug/assign_type_assertion.gno new file mode 100644 index 00000000000..a6d6373426f --- /dev/null +++ b/gnovm/tests/debug/assign_type_assertion.gno @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" +) + +func main() { + var i interface{} = "Hello, world!" + + // Attempt to assert the type of i to string + var n int + var ok bool + n, ok = i.(string) + if ok { + fmt.Println("i contains a string:", n) + } else { + fmt.Println("i does not contain a string") + } +} + +// Error: +// main/debug/assign_type_assertion.gno:13: cannot use string as int diff --git a/gnovm/tests/debug/assign_type_assertion_a.gno b/gnovm/tests/debug/assign_type_assertion_a.gno new file mode 100644 index 00000000000..1b28408d309 --- /dev/null +++ b/gnovm/tests/debug/assign_type_assertion_a.gno @@ -0,0 +1,33 @@ +package main + +import "fmt" + +type MyError struct{} + +func (e MyError) Error() string { + return "my error" +} + +func (e MyError) IsSet() bool { + return true +} + +func main() { + var err error = MyError{} + + var assertedErr interface{ IsSet() bool } // Define a variable of the interface type + var ok bool + + // Perform the assertion and assign the result to assertedErr + assertedErr, ok = err.(interface{ IsSet() bool }) + if ok { + fmt.Println("Assertion succeeded:", ok) + fmt.Println("IsSet:", assertedErr.IsSet()) + } else { + fmt.Println("Assertion failed:", ok) + } +} + +// Output: +// Assertion succeeded: true +// IsSet: true diff --git a/gnovm/tests/debug/assign_type_assertion_b.gno b/gnovm/tests/debug/assign_type_assertion_b.gno new file mode 100644 index 00000000000..de4944465b9 --- /dev/null +++ b/gnovm/tests/debug/assign_type_assertion_b.gno @@ -0,0 +1,32 @@ +package main + +import "fmt" + +type MyError struct{} + +func (e MyError) Error() string { + return "my error" +} + +func (e MyError) IsSet() bool { + return true +} + +func main() { + var err error = MyError{} + + var assertedErr int // Define a variable of the interface type + var ok bool + + // Perform the assertion and assign the result to assertedErr + assertedErr, ok = err.(interface{ IsSet() bool }) + if ok { + fmt.Println("Assertion succeeded:", ok) + fmt.Println("IsSet:", assertedErr.IsSet()) + } else { + fmt.Println("Assertion failed:", ok) + } +} + +// Error: +// main/debug/assign_type_assertion_b.gno:22: cannot assign to assertedErr diff --git a/gnovm/tests/debug_temp/bigdec3.gno b/gnovm/tests/debug_temp/bigdec3.gno new file mode 100644 index 00000000000..0e0effa7cbb --- /dev/null +++ b/gnovm/tests/debug_temp/bigdec3.gno @@ -0,0 +1,11 @@ +package main + +var a uint64 + +func main() { + a = 1 + println(1.0 % a) +} + +// Output: +// 0 diff --git a/gnovm/tests/debug_temp/bigdec4.gno b/gnovm/tests/debug_temp/bigdec4.gno new file mode 100644 index 00000000000..88cbe894020 --- /dev/null +++ b/gnovm/tests/debug_temp/bigdec4.gno @@ -0,0 +1,11 @@ +package main + +var a uint64 + +func main() { + a = 1.0 + println(a) +} + +// Output: +// 1 diff --git a/gnovm/tests/debug_temp/bigdec5.gno b/gnovm/tests/debug_temp/bigdec5.gno new file mode 100644 index 00000000000..4f0a01ddfa0 --- /dev/null +++ b/gnovm/tests/debug_temp/bigdec5.gno @@ -0,0 +1,11 @@ +package main + +var a uint64 + +func main() { + a = 1.2 + println(a) +} + +// Error: +// main/debug/bigdec5.gno:6: cannot convert untyped bigdec to integer -- 1.2 not an exact integer From cfe75b7e2dd592ea0f8824307dca9f28dab11d3a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 12 Apr 2024 00:25:59 +0800 Subject: [PATCH 128/193] type check for assignStmt, fixup assertion --- gnovm/pkg/gnolang/preprocess.go | 7 ++-- gnovm/pkg/gnolang/type_check.go | 25 +++++--------- gnovm/tests/debug/assign_literal.gno | 8 ----- gnovm/tests/debug/assign_literal11.gno | 11 ------- gnovm/tests/debug/assign_literal2.gno | 9 ----- gnovm/tests/debug/assign_literal2_a.gno | 9 ----- gnovm/tests/debug/assign_literal3.gno | 8 ----- gnovm/tests/debug/assign_literal4.gno | 8 ----- gnovm/tests/debug/assign_literal4_a.gno | 8 ----- gnovm/tests/debug/assign_literal5.gno | 8 ----- gnovm/tests/debug/assign_literal6.gno | 8 ----- gnovm/tests/debug/assign_literal_a.gno | 8 ----- gnovm/tests/debug_temp/bigdec5.gno | 11 ------- .../{debug => files/types}/assign_call.gno | 2 +- .../{debug => files/types}/assign_index.gno | 2 +- .../{debug => files/types}/assign_index_1.gno | 2 +- .../{debug => files/types}/assign_index_a.gno | 2 +- gnovm/tests/files/types/assign_literal.gno | 8 +++++ .../types}/assign_literal10.gno | 0 .../types}/assign_literal10a.gno | 2 +- gnovm/tests/files/types/assign_literal11.gno | 11 +++++++ gnovm/tests/files/types/assign_literal2.gno | 9 +++++ gnovm/tests/files/types/assign_literal2_a.gno | 9 +++++ gnovm/tests/files/types/assign_literal3.gno | 8 +++++ gnovm/tests/files/types/assign_literal4.gno | 8 +++++ gnovm/tests/files/types/assign_literal4_a.gno | 8 +++++ gnovm/tests/files/types/assign_literal5.gno | 8 +++++ gnovm/tests/files/types/assign_literal6.gno | 8 +++++ .../types}/assign_literal7.gno | 0 .../types}/assign_literal7a.gno | 0 .../types}/assign_literal7b.gno | 0 .../types}/assign_literal7c.gno | 2 +- .../types}/assign_literal7d.gno | 0 .../types}/assign_literal8.gno | 0 .../types}/assign_literal9.gno | 2 +- gnovm/tests/files/types/assign_literal_a.gno | 8 +++++ .../types}/assign_type_assertion.gno | 2 +- .../types}/assign_type_assertion_a.gno | 0 .../types}/assign_type_assertion_b.gno | 2 +- .../files/types/assign_type_assertion_c.gno | 33 +++++++++++++++++++ .../{debug_temp => files/types}/bigdec3.gno | 0 .../{debug_temp => files/types}/bigdec4.gno | 0 gnovm/tests/files/types/bigdec5.gno | 11 +++++++ 43 files changed, 150 insertions(+), 125 deletions(-) delete mode 100644 gnovm/tests/debug/assign_literal.gno delete mode 100644 gnovm/tests/debug/assign_literal11.gno delete mode 100644 gnovm/tests/debug/assign_literal2.gno delete mode 100644 gnovm/tests/debug/assign_literal2_a.gno delete mode 100644 gnovm/tests/debug/assign_literal3.gno delete mode 100644 gnovm/tests/debug/assign_literal4.gno delete mode 100644 gnovm/tests/debug/assign_literal4_a.gno delete mode 100644 gnovm/tests/debug/assign_literal5.gno delete mode 100644 gnovm/tests/debug/assign_literal6.gno delete mode 100644 gnovm/tests/debug/assign_literal_a.gno delete mode 100644 gnovm/tests/debug_temp/bigdec5.gno rename gnovm/tests/{debug => files/types}/assign_call.gno (67%) rename gnovm/tests/{debug => files/types}/assign_index.gno (70%) rename gnovm/tests/{debug => files/types}/assign_index_1.gno (60%) rename gnovm/tests/{debug => files/types}/assign_index_a.gno (68%) create mode 100644 gnovm/tests/files/types/assign_literal.gno rename gnovm/tests/{debug => files/types}/assign_literal10.gno (100%) rename gnovm/tests/{debug => files/types}/assign_literal10a.gno (67%) create mode 100644 gnovm/tests/files/types/assign_literal11.gno create mode 100644 gnovm/tests/files/types/assign_literal2.gno create mode 100644 gnovm/tests/files/types/assign_literal2_a.gno create mode 100644 gnovm/tests/files/types/assign_literal3.gno create mode 100644 gnovm/tests/files/types/assign_literal4.gno create mode 100644 gnovm/tests/files/types/assign_literal4_a.gno create mode 100644 gnovm/tests/files/types/assign_literal5.gno create mode 100644 gnovm/tests/files/types/assign_literal6.gno rename gnovm/tests/{debug => files/types}/assign_literal7.gno (100%) rename gnovm/tests/{debug => files/types}/assign_literal7a.gno (100%) rename gnovm/tests/{debug => files/types}/assign_literal7b.gno (100%) rename gnovm/tests/{debug => files/types}/assign_literal7c.gno (58%) rename gnovm/tests/{debug => files/types}/assign_literal7d.gno (100%) rename gnovm/tests/{debug => files/types}/assign_literal8.gno (100%) rename gnovm/tests/{debug => files/types}/assign_literal9.gno (77%) create mode 100644 gnovm/tests/files/types/assign_literal_a.gno rename gnovm/tests/{debug => files/types}/assign_type_assertion.gno (79%) rename gnovm/tests/{debug => files/types}/assign_type_assertion_a.gno (100%) rename gnovm/tests/{debug => files/types}/assign_type_assertion_b.gno (85%) create mode 100644 gnovm/tests/files/types/assign_type_assertion_c.gno rename gnovm/tests/{debug_temp => files/types}/bigdec3.gno (100%) rename gnovm/tests/{debug_temp => files/types}/bigdec4.gno (100%) create mode 100644 gnovm/tests/files/types/bigdec5.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 394736eba5d..aaccaed434d 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,9 +2,10 @@ package gnolang import ( "fmt" - "github.com/gnolang/gno/tm2/pkg/errors" "math/big" "reflect" + + "github.com/gnolang/gno/tm2/pkg/errors" ) // In the case of a *FileSet, some declaration steps have to happen @@ -1572,13 +1573,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *AssignStmt: // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { + n.AssertCompatible(store, last) // Rhs consts become default *ConstExprs. for _, rx := range n.Rhs { // NOTE: does nothing if rx is "nil". convertIfConst(store, last, rx) } - n.AssertCompatible(store, last) if len(n.Lhs) > len(n.Rhs) { switch cx := n.Rhs[0].(type) { case *CallExpr: @@ -1592,7 +1593,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(ln, anyValue(rf.Type)) } case *TypeAssertExpr: - cx.HasOK = true lhs0 := n.Lhs[0].(*NameExpr).Name lhs1 := n.Lhs[1].(*NameExpr).Name tt := evalStaticType(store, last, cx.Type) @@ -1600,7 +1600,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(lhs0, anyValue(tt)) last.Define(lhs1, anyValue(BoolType)) case *IndexExpr: - cx.HasOK = true lhs0 := n.Lhs[0].(*NameExpr).Name lhs1 := n.Lhs[1].(*NameExpr).Name diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 216a790c5d1..629f73c35b2 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -674,7 +674,6 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { escapedOpStr := strings.Replace(wordTokenStrings[as.Op], "%", "%%", 1) var destKind interface{} - if as.Op == ASSIGN || as.Op == DEFINE { if len(as.Lhs) > len(as.Rhs) { if len(as.Rhs) != 1 { @@ -701,7 +700,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if len(as.Lhs) != 2 { panic("should not happen") } - debug.Println("---type assertion, assert type, reflect type of at: ", cx.Type, reflect.TypeOf(cx.Type)) if ctex, ok := cx.Type.(*constTypeExpr); ok { // check assignable dt := evalStaticTypeOf(store, last, as.Lhs[0]) @@ -709,9 +707,14 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } else if _, ok := cx.Type.(*InterfaceTypeExpr); ok { dt := evalStaticTypeOf(store, last, as.Lhs[0]) if isBlankIdentifier(as.Lhs[0]) { // see composite3.gno - debug.Println("---blank") - } else if dt != nil && dt.Kind() == InterfaceKind { // do nothing + } else if dt != nil && dt.Kind() == InterfaceKind { + ift := evalStaticTypeOf(store, last, cx) + debug.Println("---ift, type of: ", ift, reflect.TypeOf(ift)) + idt := dt.(*InterfaceType) + if !idt.IsImplementedBy(ift) { + panic(fmt.Sprintf("cannot assign to %v \n", as.Lhs[0])) + } } else { panic(fmt.Sprintf("cannot assign to %v \n", as.Lhs[0])) } @@ -722,24 +725,17 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } lt := evalStaticTypeOf(store, last, as.Lhs[0]) - debug.Println("---cx.X, type of: ", cx.X, reflect.TypeOf(cx.X)) if nx, ok := cx.X.(*NameExpr); ok { rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() - debug.Println("---rx, type of rx: ", rx, reflect.TypeOf(rx)) - debug.Println("---rx.T: ", rx.T) - debug.Println("---rx.V: ", rx.V) - if mt, ok := rx.T.(*MapType); ok { - debug.Println("---mt: ", mt) - debug.Println("---type of value of map type: ", mt.Value) checkAssignableTo(mt.Value, lt, false) } } else if _, ok := cx.X.(*CompositeLitExpr); ok { cpt := evalStaticTypeOf(store, last, cx.X) - debug.Println("---cpt: ", cpt) if mt, ok := cpt.(*MapType); ok { - debug.Println("---mt: ", mt) checkAssignableTo(mt.Value, lt, false) + } else { + panic("should not happen") } } cx.HasOK = true @@ -751,8 +747,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { for i, lx := range as.Lhs { rt := evalStaticTypeOf(store, last, as.Rhs[i]) - debug.Println("lx, type of lx: ", lx, reflect.TypeOf(lx)) - // check native cases if rnt, ok := rt.(*NativeType); ok { if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { @@ -765,7 +759,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { case *NameExpr, *StarExpr, *SelectorExpr: shouldPanic = false case *IndexExpr: - debug.Println("---ix.X, type of ix.X: ", clx.X, reflect.TypeOf(clx.X)) xt := evalStaticTypeOf(store, last, clx.X) shouldPanic = xt != nil && xt.Kind() == StringKind default: diff --git a/gnovm/tests/debug/assign_literal.gno b/gnovm/tests/debug/assign_literal.gno deleted file mode 100644 index d2d172b0322..00000000000 --- a/gnovm/tests/debug/assign_literal.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - 1 = 6 -} - -// Error: -// main/debug/assign_literal.gno:4: cannot assign to (const (1 bigint)) diff --git a/gnovm/tests/debug/assign_literal11.gno b/gnovm/tests/debug/assign_literal11.gno deleted file mode 100644 index 50f1d20ddfc..00000000000 --- a/gnovm/tests/debug/assign_literal11.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -const Pi = 3.14 - -func main() { - Pi = 3.14159 - println(Pi) -} - -// Error: -// main/debug/assign_literal11.gno:6: cannot assign to (const (3.14 bigdec)) diff --git a/gnovm/tests/debug/assign_literal2.gno b/gnovm/tests/debug/assign_literal2.gno deleted file mode 100644 index f0a076bd52e..00000000000 --- a/gnovm/tests/debug/assign_literal2.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - var a int - a, 2 = 6, 6 -} - -// Error: -// main/debug/assign_literal2.gno:5: cannot assign to (const (2 bigint)) \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal2_a.gno b/gnovm/tests/debug/assign_literal2_a.gno deleted file mode 100644 index 14f1aea1d2d..00000000000 --- a/gnovm/tests/debug/assign_literal2_a.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - var a int - a, 2 := 6, 6 -} - -// Error: -// debug/assign_literal2_a.gno:5:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal3.gno b/gnovm/tests/debug/assign_literal3.gno deleted file mode 100644 index 5ef63b5ff5e..00000000000 --- a/gnovm/tests/debug/assign_literal3.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - true = false -} - -// Error: -// main/debug/assign_literal3.gno:4: cannot assign to (const (true bool)) \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal4.gno b/gnovm/tests/debug/assign_literal4.gno deleted file mode 100644 index e38b04b2e39..00000000000 --- a/gnovm/tests/debug/assign_literal4.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - []int{1, 2} = []int{3, 4} -} - -// Error: -// main/debug/assign_literal4.gno:4: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal4_a.gno b/gnovm/tests/debug/assign_literal4_a.gno deleted file mode 100644 index 0150b73a656..00000000000 --- a/gnovm/tests/debug/assign_literal4_a.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - []int{1, 2} := []int{3, 4} -} - -// Error: -// debug/assign_literal4_a.gno:4:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal5.gno b/gnovm/tests/debug/assign_literal5.gno deleted file mode 100644 index f1dd446e47d..00000000000 --- a/gnovm/tests/debug/assign_literal5.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - map[string]int{"a": 1, "b": 2} = map[string]int{"a": 1, "b": 2} -} - -// Error: -// main/debug/assign_literal5.gno:4: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} diff --git a/gnovm/tests/debug/assign_literal6.gno b/gnovm/tests/debug/assign_literal6.gno deleted file mode 100644 index 41dec2ab5c1..00000000000 --- a/gnovm/tests/debug/assign_literal6.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - 1 + 2 = 6 -} - -// Error: -// main/debug/assign_literal6.gno:4: cannot assign to (const (3 bigint)) \ No newline at end of file diff --git a/gnovm/tests/debug/assign_literal_a.gno b/gnovm/tests/debug/assign_literal_a.gno deleted file mode 100644 index 9486f4068ba..00000000000 --- a/gnovm/tests/debug/assign_literal_a.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - 1 := 6 -} - -// Error: -// debug/assign_literal_a.gno:4:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug_temp/bigdec5.gno b/gnovm/tests/debug_temp/bigdec5.gno deleted file mode 100644 index 4f0a01ddfa0..00000000000 --- a/gnovm/tests/debug_temp/bigdec5.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -var a uint64 - -func main() { - a = 1.2 - println(a) -} - -// Error: -// main/debug/bigdec5.gno:6: cannot convert untyped bigdec to integer -- 1.2 not an exact integer diff --git a/gnovm/tests/debug/assign_call.gno b/gnovm/tests/files/types/assign_call.gno similarity index 67% rename from gnovm/tests/debug/assign_call.gno rename to gnovm/tests/files/types/assign_call.gno index e739f8f1994..a94b4a0b126 100644 --- a/gnovm/tests/debug/assign_call.gno +++ b/gnovm/tests/files/types/assign_call.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/debug/assign_call.gno:9: cannot use int as string +// main/files/types/assign_call.gno:9: cannot use int as string diff --git a/gnovm/tests/debug/assign_index.gno b/gnovm/tests/files/types/assign_index.gno similarity index 70% rename from gnovm/tests/debug/assign_index.gno rename to gnovm/tests/files/types/assign_index.gno index a5e6b7b8bca..93f4cf0a3c1 100644 --- a/gnovm/tests/debug/assign_index.gno +++ b/gnovm/tests/files/types/assign_index.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/debug/assign_index.gno:8: cannot use int as string \ No newline at end of file +// main/files/types/assign_index.gno:8: cannot use int as string diff --git a/gnovm/tests/debug/assign_index_1.gno b/gnovm/tests/files/types/assign_index_1.gno similarity index 60% rename from gnovm/tests/debug/assign_index_1.gno rename to gnovm/tests/files/types/assign_index_1.gno index 2c01eab1548..c9c68fa91fd 100644 --- a/gnovm/tests/debug/assign_index_1.gno +++ b/gnovm/tests/files/types/assign_index_1.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/debug/assign_index_1.gno:7: cannot use int as string +// main/files/types/assign_index_1.gno:7: cannot use int as string diff --git a/gnovm/tests/debug/assign_index_a.gno b/gnovm/tests/files/types/assign_index_a.gno similarity index 68% rename from gnovm/tests/debug/assign_index_a.gno rename to gnovm/tests/files/types/assign_index_a.gno index c3aa9088e91..dd92220b1fe 100644 --- a/gnovm/tests/debug/assign_index_a.gno +++ b/gnovm/tests/files/types/assign_index_a.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/debug/assign_index_a.gno:6: cannot use int as string +// main/files/types/assign_index_a.gno:6: cannot use int as string diff --git a/gnovm/tests/files/types/assign_literal.gno b/gnovm/tests/files/types/assign_literal.gno new file mode 100644 index 00000000000..61c128fbe1f --- /dev/null +++ b/gnovm/tests/files/types/assign_literal.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 = 6 +} + +// Error: +// main/files/types/assign_literal.gno:4: cannot assign to (const (1 bigint)) diff --git a/gnovm/tests/debug/assign_literal10.gno b/gnovm/tests/files/types/assign_literal10.gno similarity index 100% rename from gnovm/tests/debug/assign_literal10.gno rename to gnovm/tests/files/types/assign_literal10.gno diff --git a/gnovm/tests/debug/assign_literal10a.gno b/gnovm/tests/files/types/assign_literal10a.gno similarity index 67% rename from gnovm/tests/debug/assign_literal10a.gno rename to gnovm/tests/files/types/assign_literal10a.gno index b1a2c9c113a..f6963d926ee 100644 --- a/gnovm/tests/debug/assign_literal10a.gno +++ b/gnovm/tests/files/types/assign_literal10a.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/debug/assign_literal10a.gno:13: cannot assign to s.add() +// main/files/types/assign_literal10a.gno:13: cannot assign to s.add() diff --git a/gnovm/tests/files/types/assign_literal11.gno b/gnovm/tests/files/types/assign_literal11.gno new file mode 100644 index 00000000000..821f95422a0 --- /dev/null +++ b/gnovm/tests/files/types/assign_literal11.gno @@ -0,0 +1,11 @@ +package main + +const Pi = 3.14 + +func main() { + Pi = 3.14159 + println(Pi) +} + +// Error: +// main/files/types/assign_literal11.gno:6: cannot assign to (const (3.14 bigdec)) diff --git a/gnovm/tests/files/types/assign_literal2.gno b/gnovm/tests/files/types/assign_literal2.gno new file mode 100644 index 00000000000..2e495b6fb78 --- /dev/null +++ b/gnovm/tests/files/types/assign_literal2.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var a int + a, 2 = 6, 6 +} + +// Error: +// main/files/types/assign_literal2.gno:5: cannot assign to (const (2 bigint)) diff --git a/gnovm/tests/files/types/assign_literal2_a.gno b/gnovm/tests/files/types/assign_literal2_a.gno new file mode 100644 index 00000000000..f66868ab842 --- /dev/null +++ b/gnovm/tests/files/types/assign_literal2_a.gno @@ -0,0 +1,9 @@ +package main + +func main() { + var a int + a, 2 := 6, 6 +} + +// Error: +// files/types/assign_literal2_a.gno:5:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/files/types/assign_literal3.gno b/gnovm/tests/files/types/assign_literal3.gno new file mode 100644 index 00000000000..67d4877cd5a --- /dev/null +++ b/gnovm/tests/files/types/assign_literal3.gno @@ -0,0 +1,8 @@ +package main + +func main() { + true = false +} + +// Error: +// main/files/types/assign_literal3.gno:4: cannot assign to (const (true bool)) diff --git a/gnovm/tests/files/types/assign_literal4.gno b/gnovm/tests/files/types/assign_literal4.gno new file mode 100644 index 00000000000..bdae4fa39a5 --- /dev/null +++ b/gnovm/tests/files/types/assign_literal4.gno @@ -0,0 +1,8 @@ +package main + +func main() { + []int{1, 2} = []int{3, 4} +} + +// Error: +// main/files/types/assign_literal4.gno:4: cannot assign to [](const-type int){(const (1 int)), (const (2 int))} diff --git a/gnovm/tests/files/types/assign_literal4_a.gno b/gnovm/tests/files/types/assign_literal4_a.gno new file mode 100644 index 00000000000..054ae227b32 --- /dev/null +++ b/gnovm/tests/files/types/assign_literal4_a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + []int{1, 2} := []int{3, 4} +} + +// Error: +// files/types/assign_literal4_a.gno:4:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/files/types/assign_literal5.gno b/gnovm/tests/files/types/assign_literal5.gno new file mode 100644 index 00000000000..da382b8ac1c --- /dev/null +++ b/gnovm/tests/files/types/assign_literal5.gno @@ -0,0 +1,8 @@ +package main + +func main() { + map[string]int{"a": 1, "b": 2} = map[string]int{"a": 1, "b": 2} +} + +// Error: +// main/files/types/assign_literal5.gno:4: cannot assign to map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))} diff --git a/gnovm/tests/files/types/assign_literal6.gno b/gnovm/tests/files/types/assign_literal6.gno new file mode 100644 index 00000000000..dfcf9cbb80a --- /dev/null +++ b/gnovm/tests/files/types/assign_literal6.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 + 2 = 6 +} + +// Error: +// main/files/types/assign_literal6.gno:4: cannot assign to (const (3 bigint)) diff --git a/gnovm/tests/debug/assign_literal7.gno b/gnovm/tests/files/types/assign_literal7.gno similarity index 100% rename from gnovm/tests/debug/assign_literal7.gno rename to gnovm/tests/files/types/assign_literal7.gno diff --git a/gnovm/tests/debug/assign_literal7a.gno b/gnovm/tests/files/types/assign_literal7a.gno similarity index 100% rename from gnovm/tests/debug/assign_literal7a.gno rename to gnovm/tests/files/types/assign_literal7a.gno diff --git a/gnovm/tests/debug/assign_literal7b.gno b/gnovm/tests/files/types/assign_literal7b.gno similarity index 100% rename from gnovm/tests/debug/assign_literal7b.gno rename to gnovm/tests/files/types/assign_literal7b.gno diff --git a/gnovm/tests/debug/assign_literal7c.gno b/gnovm/tests/files/types/assign_literal7c.gno similarity index 58% rename from gnovm/tests/debug/assign_literal7c.gno rename to gnovm/tests/files/types/assign_literal7c.gno index 4314308959a..989dcca6699 100644 --- a/gnovm/tests/debug/assign_literal7c.gno +++ b/gnovm/tests/files/types/assign_literal7c.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/debug/assign_literal7c.gno:7: cannot assign to str[(const (0 int))] +// main/files/types/assign_literal7c.gno:7: cannot assign to str[(const (0 int))] diff --git a/gnovm/tests/debug/assign_literal7d.gno b/gnovm/tests/files/types/assign_literal7d.gno similarity index 100% rename from gnovm/tests/debug/assign_literal7d.gno rename to gnovm/tests/files/types/assign_literal7d.gno diff --git a/gnovm/tests/debug/assign_literal8.gno b/gnovm/tests/files/types/assign_literal8.gno similarity index 100% rename from gnovm/tests/debug/assign_literal8.gno rename to gnovm/tests/files/types/assign_literal8.gno diff --git a/gnovm/tests/debug/assign_literal9.gno b/gnovm/tests/files/types/assign_literal9.gno similarity index 77% rename from gnovm/tests/debug/assign_literal9.gno rename to gnovm/tests/files/types/assign_literal9.gno index 843cb5a67fc..e0efc7e071b 100644 --- a/gnovm/tests/debug/assign_literal9.gno +++ b/gnovm/tests/files/types/assign_literal9.gno @@ -11,4 +11,4 @@ func main() { } // Output: -// &0x14000189110.(*main.foo) +// &0x140002f85a0.(*main.foo) diff --git a/gnovm/tests/files/types/assign_literal_a.gno b/gnovm/tests/files/types/assign_literal_a.gno new file mode 100644 index 00000000000..dd17e97c466 --- /dev/null +++ b/gnovm/tests/files/types/assign_literal_a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + 1 := 6 +} + +// Error: +// files/types/assign_literal_a.gno:4:2: no new variables on left side of := \ No newline at end of file diff --git a/gnovm/tests/debug/assign_type_assertion.gno b/gnovm/tests/files/types/assign_type_assertion.gno similarity index 79% rename from gnovm/tests/debug/assign_type_assertion.gno rename to gnovm/tests/files/types/assign_type_assertion.gno index a6d6373426f..6bc2b4b26c8 100644 --- a/gnovm/tests/debug/assign_type_assertion.gno +++ b/gnovm/tests/files/types/assign_type_assertion.gno @@ -19,4 +19,4 @@ func main() { } // Error: -// main/debug/assign_type_assertion.gno:13: cannot use string as int +// main/files/types/assign_type_assertion.gno:13: cannot use string as int diff --git a/gnovm/tests/debug/assign_type_assertion_a.gno b/gnovm/tests/files/types/assign_type_assertion_a.gno similarity index 100% rename from gnovm/tests/debug/assign_type_assertion_a.gno rename to gnovm/tests/files/types/assign_type_assertion_a.gno diff --git a/gnovm/tests/debug/assign_type_assertion_b.gno b/gnovm/tests/files/types/assign_type_assertion_b.gno similarity index 85% rename from gnovm/tests/debug/assign_type_assertion_b.gno rename to gnovm/tests/files/types/assign_type_assertion_b.gno index de4944465b9..da6af231a21 100644 --- a/gnovm/tests/debug/assign_type_assertion_b.gno +++ b/gnovm/tests/files/types/assign_type_assertion_b.gno @@ -29,4 +29,4 @@ func main() { } // Error: -// main/debug/assign_type_assertion_b.gno:22: cannot assign to assertedErr +// main/files/types/assign_type_assertion_b.gno:22: cannot assign to assertedErr diff --git a/gnovm/tests/files/types/assign_type_assertion_c.gno b/gnovm/tests/files/types/assign_type_assertion_c.gno new file mode 100644 index 00000000000..48fd0181f27 --- /dev/null +++ b/gnovm/tests/files/types/assign_type_assertion_c.gno @@ -0,0 +1,33 @@ +package main + +import "fmt" + +type MyError struct{} + +func (e MyError) Error() string { + return "my error" +} + +func (e MyError) IsSet() bool { + return true +} + +func main() { + var err error = MyError{} + + var assertedErr interface{ IsNotSet() bool } // Define a variable of the interface type + + var ok bool + + // Perform the assertion and assign the result to assertedErr + assertedErr, ok = err.(interface{ IsSet() bool }) // not impl lhs + if ok { + fmt.Println("Assertion succeeded:", ok) + fmt.Println("IsSet:", assertedErr.IsSet()) + } else { + fmt.Println("Assertion failed:", ok) + } +} + +// Error: +// main/files/types/assign_type_assertion_c.gno:23: cannot assign to assertedErr diff --git a/gnovm/tests/debug_temp/bigdec3.gno b/gnovm/tests/files/types/bigdec3.gno similarity index 100% rename from gnovm/tests/debug_temp/bigdec3.gno rename to gnovm/tests/files/types/bigdec3.gno diff --git a/gnovm/tests/debug_temp/bigdec4.gno b/gnovm/tests/files/types/bigdec4.gno similarity index 100% rename from gnovm/tests/debug_temp/bigdec4.gno rename to gnovm/tests/files/types/bigdec4.gno diff --git a/gnovm/tests/files/types/bigdec5.gno b/gnovm/tests/files/types/bigdec5.gno new file mode 100644 index 00000000000..e3f64e0a8ce --- /dev/null +++ b/gnovm/tests/files/types/bigdec5.gno @@ -0,0 +1,11 @@ +package main + +var a uint64 + +func main() { + a = 1.2 + println(a) +} + +// Error: +// main/files/types/bigdec5.gno:6: cannot convert untyped bigdec to integer -- 1.2 not an exact integer From d427e79ad4d78bffe7315703d77fb2c21080eff5 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 12 Apr 2024 16:34:49 +0800 Subject: [PATCH 129/193] fix render issure with % --- gnovm/pkg/gnolang/type_check.go | 17 ++++++++--------- gnovm/tests/file.go | 9 ++++----- gnovm/tests/files/types/assign_literal9.gno | 4 ++-- tm2/pkg/errors/errors.go | 3 +++ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 629f73c35b2..efa584c2df3 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -3,7 +3,6 @@ package gnolang import ( "fmt" "reflect" - "strings" ) // here are a range of rules predefined for preprocessor to check the compatibility between operands and operators @@ -553,7 +552,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } - escapedOpStr := strings.Replace(wordTokenStrings[bx.Op], "%", "%%", 1) + OpStr := wordTokenStrings[bx.Op] var xt, dt Type cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion @@ -571,7 +570,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { assertComparable(xt, dt) // only check if dest type is comparable case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(xt, dt, checker, escapedOpStr) + bx.checkCompatibility(xt, dt, checker, OpStr) } else { panic("should not happen") } @@ -580,7 +579,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } else { if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(xt, dt, checker, escapedOpStr) + bx.checkCompatibility(xt, dt, checker, OpStr) } else { panic("should not happen") } @@ -601,14 +600,14 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } -func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, escapedOpStr string) { +func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, OpStr string) { var destKind interface{} if !checker(dt) { if dt != nil { destKind = dt.Kind() } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind)) } defer func() { // rewrite err msg @@ -616,7 +615,7 @@ func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, if xt != nil { destKind = xt.Kind() } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind)) } }() @@ -672,7 +671,7 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { } func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { - escapedOpStr := strings.Replace(wordTokenStrings[as.Op], "%", "%%", 1) + Opstr := wordTokenStrings[as.Op] var destKind interface{} if as.Op == ASSIGN || as.Op == DEFINE { if len(as.Lhs) > len(as.Rhs) { @@ -805,7 +804,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if lt != nil { destKind = lt.Kind() } - panic(fmt.Sprintf("operator %s not defined on: %v", escapedOpStr, destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, destKind)) } switch as.Op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 451bf0677dc..e44dd87e579 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -262,11 +262,9 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { errstr = strings.TrimSpace(fmt.Sprintf("%v", pnc)) } // check tip line, write to file - ctl := fmt.Sprintf( - errstr + - "\n*** CHECK THE ERR MESSAGES ABOVE, MAKE SURE IT'S WHAT YOU EXPECTED, " + - "DELETE THIS LINE AND RUN TEST AGAIN ***", - ) + ctl := errstr + + "\n*** CHECK THE ERR MESSAGES ABOVE, MAKE SURE IT'S WHAT YOU EXPECTED, " + + "DELETE THIS LINE AND RUN TEST AGAIN ***" replaceWantedInPlace(path, "Error", ctl) panic(fmt.Sprintf("fail on %s: err recorded, check the message and run test again", path)) } @@ -424,6 +422,7 @@ func readComments(cg *ast.CommentGroup) string { // Replace comment in file with given output given directive. func replaceWantedInPlace(path string, directive string, output string) { + fmt.Println("---replace...: ", directive, output) bz := osm.MustReadFile(path) body := string(bz) lines := strings.Split(body, "\n") diff --git a/gnovm/tests/files/types/assign_literal9.gno b/gnovm/tests/files/types/assign_literal9.gno index e0efc7e071b..1d672ae46ce 100644 --- a/gnovm/tests/files/types/assign_literal9.gno +++ b/gnovm/tests/files/types/assign_literal9.gno @@ -7,8 +7,8 @@ type foo struct { func main() { s := &foo{} s.a = 1 - println(s) + println(s.a) } // Output: -// &0x140002f85a0.(*main.foo) +// 1 diff --git a/tm2/pkg/errors/errors.go b/tm2/pkg/errors/errors.go index c07356f0b06..c72d9c64680 100644 --- a/tm2/pkg/errors/errors.go +++ b/tm2/pkg/errors/errors.go @@ -237,6 +237,9 @@ type FmtError struct { } func (fe FmtError) Error() string { + if len(fe.args) == 0 { + return fe.format + } return fmt.Sprintf(fe.format, fe.args...) } From 4fb88d83925797b44c16b8b0cc05bf4fe220fd9c Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Sat, 13 Apr 2024 08:37:23 +0800 Subject: [PATCH 130/193] Update gnovm/pkg/gnolang/type_check.go Co-authored-by: Morgan --- gnovm/pkg/gnolang/type_check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index efa584c2df3..0157c8d41a6 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -202,7 +202,7 @@ func assertComparable(xt, dt Type) { } case nil: // see 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. if xt == nil { - panic(fmt.Sprintf("invalid operation, nil can not be compared to %s \n", "nil")) + panic("invalid operation, nil can not be compared to nil") } assertMaybeNil("invalid operation, nil can not be compared to", xt) default: From ac6d5cb747a5123c5564b42949937cfecbc0f0b8 Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Sat, 13 Apr 2024 08:39:47 +0800 Subject: [PATCH 131/193] Update gnovm/pkg/gnolang/type_check.go Co-authored-by: Morgan --- gnovm/pkg/gnolang/type_check.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 0157c8d41a6..ad0d158b69a 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -227,7 +227,6 @@ func assertMaybeNil(msg string, t Type) { // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. - // check if xt can be assigned to dt. conversionNeeded indicates further conversion needed especially from unnamed -> named // case 0. nil check // case 1. untyped const to typed const with same kind From 83cacc62498daf7e2034a5668ec48fd3aae2abce Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Sat, 13 Apr 2024 08:42:07 +0800 Subject: [PATCH 132/193] Update gnovm/pkg/gnolang/type_check.go Co-authored-by: Morgan --- gnovm/pkg/gnolang/type_check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index ad0d158b69a..f9a97ce40ac 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -551,7 +551,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } - OpStr := wordTokenStrings[bx.Op] + OpStr := bx.Op.TokenString() var xt, dt Type cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion From 0cfe9b839c8ca9a16684fcc6c9355e963119ba1a Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Mon, 15 Apr 2024 23:00:29 +0800 Subject: [PATCH 133/193] Update gnovm/Makefile Co-authored-by: Morgan --- gnovm/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gnovm/Makefile b/gnovm/Makefile index 9f3033dc511..f06de4168bc 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -60,6 +60,8 @@ _test.gnolang.native:; go test tests/*.go -test.short -run "TestFilesNativ _test.gnolang.stdlibs:; go test tests/*.go -test.short -run 'TestFiles$$/' $(GOTEST_FLAGS) _test.gnolang.native.sync:; go test tests/*.go -test.short -run "TestFilesNative/" --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.stdlibs.sync:; go test tests/*.go -test.short -run 'TestFiles$$/' --update-golden-tests $(GOTEST_FLAGS) +# NOTE: challenges are current GnoVM bugs which are supposed to fail. +# If any of these tests pass, it should be moved to a normal test. _test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallenges$$/' $(GOTEST_FLAGS) _test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' --update-golden-tests $(GOTEST_FLAGS) From bed7e3cd69d7e67dffdfedab3277edec09843c22 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Apr 2024 01:39:50 +0800 Subject: [PATCH 134/193] clean --- gnovm/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/gnovm/Makefile b/gnovm/Makefile index 9f3033dc511..8ce4dac72f1 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -63,8 +63,6 @@ _test.gnolang.stdlibs.sync:; go test tests/*.go -test.short -run 'TestFiles$$/' _test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallenges$$/' $(GOTEST_FLAGS) _test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' --update-golden-tests $(GOTEST_FLAGS) _test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' --update-golden-tests $(GOTEST_FLAGS) -_test.gnolang.debug:; go test tests/*.go -test.short -run 'TestDebug$$/' --update-golden-tests $(GOTEST_FLAGS) -_test.gnolang.debug.native:; go test tests/*.go -test.short -run 'TestDebugNative$$/' --update-golden-tests $(GOTEST_FLAGS) ######################################## # Code gen From b7e6f5a5916cf1271dacf469253492ee3a9abe7a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Apr 2024 15:41:32 +0800 Subject: [PATCH 135/193] update --- gnovm/pkg/gnolang/preprocess.go | 18 +- gnovm/pkg/gnolang/type_check.go | 213 +++++++++++----------- gnovm/tests/files/types/0f20_filetest.gno | 2 +- 3 files changed, 110 insertions(+), 123 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index aaccaed434d..f8ef08e08ae 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -750,7 +750,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // check LHS type compatibility n.checkShiftExpr(lt) // checkOrConvert RHS - if baseOf(rt) != UintType { + if baseOf(rt) != UintType { // convert rhs of shift expr to uint // convert n.Right to (gno) uint type, rn := Expr(Call("uint", n.Right)) // reset/create n2 to preprocess right child. @@ -777,20 +777,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. // refer to 0a0_filetest - if !isShift { + if !isShift { // rhs of shift expr has already been converted to uint cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else if cmp == 0 { - // to typed-nil. refer to 0f46 - if lcx.T == nil { - checkOrConvertType(store, last, &n.Left, rcx.T, false, false) - } else if rcx.T == nil { - checkOrConvertType(store, last, &n.Right, lcx.T, false, false) - } else { - checkOrConvertType(store, last, &n.Left, rcx.T, false, false) - } + checkOrConvertType(store, last, &n.Left, rcx.T, false, false) } else { // convert n.Right to left type. checkOrConvertType(store, last, &n.Right, lcx.T, false, false) @@ -800,7 +793,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cx := evalConst(store, last, n) return cx, TRANS_CONTINUE } else if isUntyped(lcx.T) { // left untyped const -> right not const - // Left untyped const, Right not const ---------------- if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native), e.g. 1*time.Second if isShift { // RHS of shift should not be native panic("should not happen") @@ -842,7 +834,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false, false) } } else { // left is typed const, right not const - if !isShift { + if !isShift { // rhs of shift expr has already been converted to uint if isUntyped(rt) { // refer to 0_d.gno. e.g. int(1) + 1< 0 { + xt, dt = dt, xt } if isComparison(bx.Op) { @@ -600,33 +603,20 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, OpStr string) { - var destKind interface{} - if !checker(dt) { - if dt != nil { - destKind = dt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind(dt))) } - defer func() { // rewrite err msg - if r := recover(); r != nil { - if xt != nil { - destKind = xt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind)) - } - }() - // e.g. 1%1e9 if !checker(xt) { - checkAssignableTo(xt, dt, false) // XXX, cache this? + err := tryCheckAssignableTo(xt, dt, false) // XXX, cache this? + if err != nil { + panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind(xt))) + } } } func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { - var destKind interface{} - if nt, ok := xt.(*NativeType); ok { if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { return @@ -638,10 +628,7 @@ func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { dt = xt } if !checker(dt) { - if dt != nil { - destKind = dt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[ux.Op], destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", ux.Op.TokenString(), destKind(dt))) } } else { panic("should not happen") @@ -649,8 +636,6 @@ func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { } func (idst *IncDecStmt) AssertCompatible(t Type) { - var destKind interface{} - if nt, ok := t.(*NativeType); ok { if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { return @@ -659,10 +644,7 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { // check compatible if checker, ok := IncDecStmtChecker[idst.Op]; ok { if !checker(t) { - if t != nil { - destKind = t.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[idst.Op], destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", idst.Op.TokenString(), destKind(t))) } } else { panic("should not happen") @@ -671,7 +653,6 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { Opstr := wordTokenStrings[as.Op] - var destKind interface{} if as.Op == ASSIGN || as.Op == DEFINE { if len(as.Lhs) > len(as.Rhs) { if len(as.Rhs) != 1 { @@ -711,10 +692,10 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { debug.Println("---ift, type of: ", ift, reflect.TypeOf(ift)) idt := dt.(*InterfaceType) if !idt.IsImplementedBy(ift) { - panic(fmt.Sprintf("cannot assign to %v \n", as.Lhs[0])) + panic(fmt.Sprintf("cannot assign to %v", as.Lhs[0])) } } else { - panic(fmt.Sprintf("cannot assign to %v \n", as.Lhs[0])) + panic(fmt.Sprintf("cannot assign to %v", as.Lhs[0])) } } cx.HasOK = true @@ -762,7 +743,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { default: } if shouldPanic { - panic(fmt.Sprintf("cannot assign to %v \n", lx)) + panic(fmt.Sprintf("cannot assign to %v", lx)) } } } else { @@ -777,7 +758,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { switch lx.(type) { case *NameExpr: default: - panic(fmt.Sprintf("non-name %v on left side of := \n", lx)) + panic(fmt.Sprintf("non-name %v on left side of :=", lx)) } } } @@ -800,10 +781,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if checker, ok := AssignStmtChecker[as.Op]; ok { if !checker(lt) { - if lt != nil { - destKind = lt.Kind() - } - panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, destKind(lt))) } switch as.Op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: @@ -811,7 +789,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet if lt != nil && rt != nil { if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v \n", lt, rt)) + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", lt, rt)) } } } @@ -826,6 +804,14 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } // misc +func destKind(xt Type) Kind { + var dk Kind + if xt != nil { + dk = xt.Kind() + } + return dk +} + func isQuoOrRem(op Word) bool { switch op { case QUO, QUO_ASSIGN, REM, REM_ASSIGN: @@ -845,6 +831,14 @@ func isComparison(op Word) bool { } func cmpSpecificity(t1, t2 Type) int { + // check nil + if t1 == nil { // see test file 0f46 + return -1 // also with both nil + } else if t2 == nil { + return 1 + } + + // check interface if it1, ok := baseOf(t1).(*InterfaceType); ok { if it1.IsEmptyInterface() { return 1 // left empty interface @@ -863,6 +857,7 @@ func cmpSpecificity(t1, t2 Type) int { return -1 // left not interface, right is interface } + // primitive types t1s, t2s := 0, 0 if t1p, ok := t1.(PrimitiveType); ok { t1s = t1p.Specificity() diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index 5184d635afc..d42aceef7e4 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types/0f20_filetest.gno:9: invalid operation, nil can not be compared to [2]main.f +// main/files/types/0f20_filetest.gno:9: and [2]main.f cannot be compared From 0d767a469c294b9ab6c857ffb3dfa488a335924d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Apr 2024 18:18:48 +0800 Subject: [PATCH 136/193] fix assertComparable --- gnovm/pkg/gnolang/type_check.go | 29 +++++++++++---- gnovm/tests/files/types/0a02.gno | 2 +- gnovm/tests/files/types/0f14_filetest.gno | 2 +- gnovm/tests/files/types/cmp_array.gno | 16 +++++++++ gnovm/tests/files/types/cmp_array_a.gno | 21 +++++++++++ gnovm/tests/files/types/cmp_array_b.gno | 15 ++++++++ gnovm/tests/files/types/cmp_array_c.gno | 15 ++++++++ gnovm/tests/files/types/cmp_poiner.gno | 23 ++++++++++++ gnovm/tests/files/types/cmp_struct.gno | 23 ++++++++++++ gnovm/tests/files/types/cmp_struct_a.gno | 20 +++++++++++ gnovm/tests/files/types/cmp_struct_b.gno | 19 ++++++++++ gnovm/tests/files/types/cmp_struct_c.gno | 19 ++++++++++ gnovm/tests/files/types/cmp_struct_d.gno | 19 ++++++++++ gnovm/tests/files/types/cmp_struct_e.gno | 15 ++++++++ gnovm/tests/files/types/cmp_struct_f.gno | 43 +++++++++++++++++++++++ 15 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 gnovm/tests/files/types/cmp_array.gno create mode 100644 gnovm/tests/files/types/cmp_array_a.gno create mode 100644 gnovm/tests/files/types/cmp_array_b.gno create mode 100644 gnovm/tests/files/types/cmp_array_c.gno create mode 100644 gnovm/tests/files/types/cmp_poiner.gno create mode 100644 gnovm/tests/files/types/cmp_struct.gno create mode 100644 gnovm/tests/files/types/cmp_struct_a.gno create mode 100644 gnovm/tests/files/types/cmp_struct_b.gno create mode 100644 gnovm/tests/files/types/cmp_struct_c.gno create mode 100644 gnovm/tests/files/types/cmp_struct_d.gno create mode 100644 gnovm/tests/files/types/cmp_struct_e.gno create mode 100644 gnovm/tests/files/types/cmp_struct_f.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index b1348ce4260..657c4940e2d 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -169,24 +169,41 @@ func assertComparable(xt, dt Type) { } } } - case *ArrayType: // NOTE: no recursive allowed + // assert xt is primitive type + if _, ok := baseOf(xt).(PrimitiveType); !ok { + panic(fmt.Sprintf("%v and %v cannot be compared", baseOf(xt), cdt)) + } + case *ArrayType: switch baseOf(cdt.Elem()).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType: // NOTE: nativeType? + case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: // NOTE: nativeType? switch cxt := baseOf(xt).(type) { case *ArrayType: if cxt.Len != cdt.Len { // check length panic(fmt.Sprintf("%v and %v cannot be compared", cxt, cdt)) + } else if cxt.TypeID() != cdt.TypeID() { // see 0f14_filetest.gno + panic("comparison on arrays of unequal type") } + // assert elem comparable + assertComparable(cxt.Elem(), cdt.Elem()) default: panic(fmt.Sprintf("%v and %v cannot be compared", cxt, cdt)) } default: panic(fmt.Sprintf("%v and %v cannot be compared", xt, cdt)) } - case *StructType: - for _, f := range cdt.Fields { - switch baseOf(f.Type).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType: + case *StructType: // struct type, not pointer type + for i, f := range cdt.Fields { + switch cft := baseOf(f.Type).(type) { + case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: + if cxt, ok := baseOf(xt).(*StructType); ok { // if xt is also a struct type + if cxt.TypeID() != cdt.TypeID() { + panic("comparison on structs of unequal types") + } + if len(cxt.Fields) != len(cdt.Fields) { + panic("comparison on structs of unequal size") + } + assertComparable(cxt.Fields[i].Type, cft) + } default: panic(fmt.Sprintf("%v and %v cannot be compared", xt, cdt)) } diff --git a/gnovm/tests/files/types/0a02.gno b/gnovm/tests/files/types/0a02.gno index 8fc6c37d9fa..1ab0bbc622f 100644 --- a/gnovm/tests/files/types/0a02.gno +++ b/gnovm/tests/files/types/0a02.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/0a02.gno:7: cannot use *int as string +// main/files/types/0a02.gno:7: *int and string cannot be compared diff --git a/gnovm/tests/files/types/0f14_filetest.gno b/gnovm/tests/files/types/0f14_filetest.gno index 92037364f85..39b960ace7d 100644 --- a/gnovm/tests/files/types/0f14_filetest.gno +++ b/gnovm/tests/files/types/0f14_filetest.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/types/0f14_filetest.gno:10: cannot use string as int +// main/files/types/0f14_filetest.gno:10: comparison on arrays of unequal type diff --git a/gnovm/tests/files/types/cmp_array.gno b/gnovm/tests/files/types/cmp_array.gno new file mode 100644 index 00000000000..52fea95b034 --- /dev/null +++ b/gnovm/tests/files/types/cmp_array.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func main() { + a := [2][2]int{{1, 2}, {3, 4}} + b := [2][2]int{{1, 2}, {3, 4}} + c := [2][2]int{{5, 6}, {7, 8}} + + fmt.Println("a == b:", a == b) // True because the elements match exactly + fmt.Println("a == c:", a == c) // False because the elements do not match +} + +// Output: +// a == b: true +// a == c: false diff --git a/gnovm/tests/files/types/cmp_array_a.gno b/gnovm/tests/files/types/cmp_array_a.gno new file mode 100644 index 00000000000..1d30f7c51eb --- /dev/null +++ b/gnovm/tests/files/types/cmp_array_a.gno @@ -0,0 +1,21 @@ +package main + +import "fmt" + +// Define a struct that embeds an array +type Matrix struct { + data [2]int +} + +func main() { + a := [2]Matrix{{data: [2]int{1, 2}}, {data: [2]int{3, 4}}} + b := [2]Matrix{{data: [2]int{1, 2}}, {data: [2]int{3, 4}}} + c := [2]Matrix{{data: [2]int{5, 6}}, {data: [2]int{7, 8}}} + + fmt.Println("a == b:", a == b) // True because the elements match exactly + fmt.Println("a == c:", a == c) // False because the elements do not match +} + +// Output: +// a == b: true +// a == c: false diff --git a/gnovm/tests/files/types/cmp_array_b.gno b/gnovm/tests/files/types/cmp_array_b.gno new file mode 100644 index 00000000000..d3f81f7670b --- /dev/null +++ b/gnovm/tests/files/types/cmp_array_b.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + a := [2][]int{{1, 2}, {3, 4}} + b := [2][]int{{1, 2}, {3, 4}} + c := [2][]int{{5, 6}, {7, 8}} + + fmt.Println("a == b:", a == b) // True because the elements match exactly + fmt.Println("a == c:", a == c) // False because the elements do not match +} + +// Error: +// main/files/types/cmp_array_b.gno:10: [2][]int and [2][]int cannot be compared diff --git a/gnovm/tests/files/types/cmp_array_c.gno b/gnovm/tests/files/types/cmp_array_c.gno new file mode 100644 index 00000000000..8eddee0ea3d --- /dev/null +++ b/gnovm/tests/files/types/cmp_array_c.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + a := [2][2][]int{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}} + b := [2][2][]int{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}} + c := [2][2][]int{{{5, 6}, {7, 8}}, {{1, 2}, {3, 4}}} + + fmt.Println("a == b:", a == b) + fmt.Println("a == c:", a == c) +} + +// Error: +// main/files/types/cmp_array_c.gno:10: [2][]int and [2][]int cannot be compared diff --git a/gnovm/tests/files/types/cmp_poiner.gno b/gnovm/tests/files/types/cmp_poiner.gno new file mode 100644 index 00000000000..0d7625a878d --- /dev/null +++ b/gnovm/tests/files/types/cmp_poiner.gno @@ -0,0 +1,23 @@ +package main + +import "fmt" + +// Define a Person struct +type Person struct { + Name string + Age int +} + +type Worker string + +func main() { + // Create two pointers to Person instances + p1 := &Person{Name: "Alice", Age: 30} + p2 := Worker("a") + p2Ptr := &p2 + + fmt.Println("p1 == p2:", p1 == p2Ptr) +} + +// Error: +// main/files/types/cmp_poiner.gno:19: cannot use main.Person as main.Worker without explicit conversion diff --git a/gnovm/tests/files/types/cmp_struct.gno b/gnovm/tests/files/types/cmp_struct.gno new file mode 100644 index 00000000000..c3ead1510a4 --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct.gno @@ -0,0 +1,23 @@ +package main + +import "fmt" + +// Define a struct that contains an array field +type Matrix struct { + data [2]int +} + +func main() { + // Create two instances of the struct + m1 := Matrix{data: [2]int{1, 2}} + m2 := Matrix{data: [2]int{1, 2}} + m3 := Matrix{data: [2]int{3, 4}} + + // Compare the instances + fmt.Println("m1 == m2:", m1 == m2) // True because the data fields are identical + fmt.Println("m1 == m3:", m1 == m3) // False because the data fields are different +} + +// Output: +// m1 == m2: true +// m1 == m3: false diff --git a/gnovm/tests/files/types/cmp_struct_a.gno b/gnovm/tests/files/types/cmp_struct_a.gno new file mode 100644 index 00000000000..738d3f1d94b --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_a.gno @@ -0,0 +1,20 @@ +package main + +import "fmt" + +// Define a struct that wraps the three-dimensional data structure +type Matrix struct { + data [2][2][]int +} + +func main() { + a := Matrix{data: [2][2][]int{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}} + b := Matrix{data: [2][2][]int{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}} + c := Matrix{data: [2][2][]int{{{5, 6}, {7, 8}}, {{1, 2}, {3, 4}}}} + + fmt.Println("a == b:", a == b) + fmt.Println("a == c:", a == c) +} + +// Error: +// main/files/types/cmp_struct_a.gno:15: [2][]int and [2][]int cannot be compared diff --git a/gnovm/tests/files/types/cmp_struct_b.gno b/gnovm/tests/files/types/cmp_struct_b.gno new file mode 100644 index 00000000000..7bed790a7b5 --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_b.gno @@ -0,0 +1,19 @@ +package main + +type foo struct { + a int +} + +type bar struct { + b int +} + +func main() { + fa := foo{} + bb := bar{} + + println(fa == bb) +} + +// Error: +// main/files/types/cmp_struct_b.gno:15: comparison on structs of unequal types diff --git a/gnovm/tests/files/types/cmp_struct_c.gno b/gnovm/tests/files/types/cmp_struct_c.gno new file mode 100644 index 00000000000..d94ce945036 --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_c.gno @@ -0,0 +1,19 @@ +package main + +type foo struct { + a int +} + +type bar struct { + b []int +} + +func main() { + fa := foo{} + bb := bar{} + + println(fa == bb) +} + +// Error: +// main/files/types/cmp_struct_c.gno:15: main.foo and struct{b []int} cannot be compared diff --git a/gnovm/tests/files/types/cmp_struct_d.gno b/gnovm/tests/files/types/cmp_struct_d.gno new file mode 100644 index 00000000000..abe324f263b --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_d.gno @@ -0,0 +1,19 @@ +package main + +type foo struct { + a []int +} + +type bar struct { + b []int +} + +func main() { + fa := foo{} + bb := bar{} + + println(fa == bb) +} + +// Error: +// main/files/types/cmp_struct_d.gno:15: main.foo and struct{b []int} cannot be compared diff --git a/gnovm/tests/files/types/cmp_struct_e.gno b/gnovm/tests/files/types/cmp_struct_e.gno new file mode 100644 index 00000000000..3f302a1393a --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_e.gno @@ -0,0 +1,15 @@ +package main + +type foo struct { + a []int +} + +func main() { + fa := foo{} + fb := foo{} + + println(fa == fb) +} + +// Error: +// main/files/types/cmp_struct_e.gno:11: main.foo and struct{a []int} cannot be compared diff --git a/gnovm/tests/files/types/cmp_struct_f.gno b/gnovm/tests/files/types/cmp_struct_f.gno new file mode 100644 index 00000000000..20366b625e9 --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_f.gno @@ -0,0 +1,43 @@ +package main + +import "fmt" + +// Define a Person struct +type Person struct { + Name string + Age int +} + +// Define an Employee struct that embeds Person +type Employee struct { + Person + Department string + ID int +} + +func main() { + emp1 := Employee{ + Person: Person{Name: "John Doe", Age: 30}, + Department: "Engineering", + ID: 12345, + } + + emp2 := Employee{ + Person: Person{Name: "John Doe", Age: 30}, + Department: "Engineering", + ID: 12345, + } + + emp3 := Employee{ + Person: Person{Name: "Jane Doe", Age: 29}, + Department: "Marketing", + ID: 67890, + } + + fmt.Println("emp1 == emp2:", emp1 == emp2) // True because all fields match + fmt.Println("emp1 == emp3:", emp1 == emp3) // False because some fields differ +} + +// Output: +// emp1 == emp2: true +// emp1 == emp3: false From 7fe0504a800f0dedc40426ea9dd468962470cfbe Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 17 Apr 2024 22:31:32 +0800 Subject: [PATCH 137/193] simplify assertComparable logic --- gnovm/pkg/gnolang/type_check.go | 90 +++++++------------- gnovm/tests/files/types/0a01_filetest.gno | 2 +- gnovm/tests/files/types/0a02.gno | 2 +- gnovm/tests/files/types/0a0_EQL_filetest.gno | 2 +- gnovm/tests/files/types/0a1_filetest.gno | 2 +- gnovm/tests/files/types/0a1a0_filetest.gno | 2 +- gnovm/tests/files/types/0a1a1_filetest.gno | 2 +- gnovm/tests/files/types/0a1f_filetest.gno | 2 +- gnovm/tests/files/types/0a2_filetest.gno | 2 +- gnovm/tests/files/types/0a3_filetest.gno | 2 +- gnovm/tests/files/types/0a4_filetest.gno | 2 +- gnovm/tests/files/types/0e0_filetest.gno | 2 +- gnovm/tests/files/types/0e1_filetest.gno | 2 +- gnovm/tests/files/types/0f14_filetest.gno | 2 +- gnovm/tests/files/types/0f16_filetest.gno | 2 +- gnovm/tests/files/types/0f20_filetest.gno | 2 +- gnovm/tests/files/types/0f21_filetest.gno | 3 +- gnovm/tests/files/types/0f21a_filetest.gno | 13 +++ gnovm/tests/files/types/0f30f_filetest.gno | 2 +- gnovm/tests/files/types/cmp_array_b.gno | 2 +- gnovm/tests/files/types/cmp_array_c.gno | 2 +- gnovm/tests/files/types/cmp_array_d.gno | 13 +++ gnovm/tests/files/types/cmp_struct_a.gno | 2 +- gnovm/tests/files/types/cmp_struct_b.gno | 2 +- gnovm/tests/files/types/cmp_struct_c.gno | 2 +- gnovm/tests/files/types/cmp_struct_c1.gno | 19 +++++ gnovm/tests/files/types/cmp_struct_d.gno | 2 +- gnovm/tests/files/types/cmp_struct_e.gno | 2 +- gnovm/tests/files/types/cmp_struct_g.gno | 21 +++++ 29 files changed, 122 insertions(+), 83 deletions(-) create mode 100644 gnovm/tests/files/types/0f21a_filetest.gno create mode 100644 gnovm/tests/files/types/cmp_array_d.gno create mode 100644 gnovm/tests/files/types/cmp_struct_c1.gno create mode 100644 gnovm/tests/files/types/cmp_struct_g.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 657c4940e2d..a6eddc2165a 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -153,92 +153,55 @@ func isNumericOrString(t Type) bool { // assertComparable is used in preprocess. // assert value with dt is comparable // special case when both typed, check if type identical -func assertComparable(xt, dt Type) { +func assertComparable(dt Type) { if debug { - debug.Printf("--- assertComparable---, xt: %v, dt: %v \n", xt, dt) + debug.Printf("--- assertComparable---, dt: %v \n", dt) } + switch cdt := baseOf(dt).(type) { case PrimitiveType: - // both typed primitive types - if _, ok := baseOf(xt).(PrimitiveType); ok { - if !isUntyped(xt) && !isUntyped(dt) { // in this stage, lt or rt maybe untyped, not converted yet - if xt != nil && dt != nil { - if xt.TypeID() != dt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", xt, dt)) - } - } - } - } - // assert xt is primitive type - if _, ok := baseOf(xt).(PrimitiveType); !ok { - panic(fmt.Sprintf("%v and %v cannot be compared", baseOf(xt), cdt)) - } case *ArrayType: switch baseOf(cdt.Elem()).(type) { - case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: // NOTE: nativeType? - switch cxt := baseOf(xt).(type) { - case *ArrayType: - if cxt.Len != cdt.Len { // check length - panic(fmt.Sprintf("%v and %v cannot be compared", cxt, cdt)) - } else if cxt.TypeID() != cdt.TypeID() { // see 0f14_filetest.gno - panic("comparison on arrays of unequal type") - } - // assert elem comparable - assertComparable(cxt.Elem(), cdt.Elem()) - default: - panic(fmt.Sprintf("%v and %v cannot be compared", cxt, cdt)) - } + case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: + assertComparable(cdt.Elem()) default: - panic(fmt.Sprintf("%v and %v cannot be compared", xt, cdt)) + panic(fmt.Sprintf("%v is not comparable", dt)) } case *StructType: // struct type, not pointer type - for i, f := range cdt.Fields { + for _, f := range cdt.Fields { switch cft := baseOf(f.Type).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: - if cxt, ok := baseOf(xt).(*StructType); ok { // if xt is also a struct type - if cxt.TypeID() != cdt.TypeID() { - panic("comparison on structs of unequal types") - } - if len(cxt.Fields) != len(cdt.Fields) { - panic("comparison on structs of unequal size") - } - assertComparable(cxt.Fields[i].Type, cft) - } + assertComparable(cft) default: - panic(fmt.Sprintf("%v and %v cannot be compared", xt, cdt)) + panic(fmt.Sprintf("%v is not comparable", dt)) } } case *PointerType: // &a == &b case *InterfaceType: // var a, b interface{} - case *SliceType, *FuncType, *MapType: - if xt != nil { - panic(fmt.Sprintf("%v can only be compared to nil", dt)) - } + case *SliceType, *FuncType, *MapType: // xt is not nil here + panic(fmt.Sprintf("%v can only be compared to nil", dt)) case *NativeType: if !cdt.Type.Comparable() { panic(fmt.Sprintf("%v is not comparable \n", dt)) } - case nil: // see 0a01, or that can be identified earlier in cmpSpecificity? to remove this check. - if xt == nil { - panic("invalid operation, nil can not be compared to nil") - } - assertMaybeNil("invalid operation, nil can not be compared to", xt) default: panic(fmt.Sprintf("%v is not comparable", dt)) } } -func assertMaybeNil(msg string, t Type) { +func assertMaybeNil(t Type) bool { switch cxt := baseOf(t).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer + return true case *NativeType: switch nk := cxt.Type.Kind(); nk { case reflect.Slice, reflect.Func, reflect.Map, reflect.Interface, reflect.Pointer: + return true default: - panic(fmt.Sprintf("%s %s \n", msg, nk)) + return false } default: - panic(fmt.Sprintf("%s %s \n", msg, t)) + return false } } @@ -426,7 +389,7 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { // to check if it is an exact integer, e.g. 1.2 or 1.0(1.0 can be converted to int). // this ensure expr like (a % 1.0) pass check, while // expr like (a % 1.2) panic at ConvertUntypedTo, which is a delayed assertion when const evaluated. - // assignable does not guarantee convertable. + // assignable does not guarantee convertible. case UntypedBigdecType: switch dt.Kind() { case IntKind, Int8Kind, Int16Kind, Int32Kind, @@ -476,6 +439,12 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { return nil case *ArrayType: if at, ok := xt.(*ArrayType); ok { + if at.Len != cdt.Len { + return fmt.Errorf( + "cannot use %s as %s", + at.String(), + cdt.String()) + } checkAssignableTo(at.Elt, cdt.Elt, false) return nil } @@ -497,9 +466,7 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { case *InterfaceType: return errors.New("should not happen") case *DeclaredType: - // do nothing, untyped to declared type - return nil - // panic("should not happen") + panic("should not happen") case *StructType, *PackageType, *ChanType: if xt.TypeID() == cdt.TypeID() { return nil // ok @@ -586,7 +553,14 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { if isComparison(bx.Op) { switch bx.Op { case EQL, NEQ: - assertComparable(xt, dt) // only check if dest type is comparable + // special case when xt is nil + if xt == nil { + if !assertMaybeNil(dt) { + panic(fmt.Sprintf("invalid operation, nil can not be compared to %v", dt)) + } + } else { + assertComparable(dt) // only check if dest type is comparable + } case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[bx.Op]; ok { bx.checkCompatibility(xt, dt, checker, OpStr) diff --git a/gnovm/tests/files/types/0a01_filetest.gno b/gnovm/tests/files/types/0a01_filetest.gno index 37d4f381901..4aa4110898d 100644 --- a/gnovm/tests/files/types/0a01_filetest.gno +++ b/gnovm/tests/files/types/0a01_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/0a01_filetest.gno:4: invalid operation, nil can not be compared to nil +// main/files/types/0a01_filetest.gno:4: invalid operation, nil can not be compared to diff --git a/gnovm/tests/files/types/0a02.gno b/gnovm/tests/files/types/0a02.gno index 1ab0bbc622f..8fc6c37d9fa 100644 --- a/gnovm/tests/files/types/0a02.gno +++ b/gnovm/tests/files/types/0a02.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/0a02.gno:7: *int and string cannot be compared +// main/files/types/0a02.gno:7: cannot use *int as string diff --git a/gnovm/tests/files/types/0a0_EQL_filetest.gno b/gnovm/tests/files/types/0a0_EQL_filetest.gno index ea0eba7fbbe..6ddb8b993c0 100644 --- a/gnovm/tests/files/types/0a0_EQL_filetest.gno +++ b/gnovm/tests/files/types/0a0_EQL_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a0_EQL_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/0a0_EQL_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/0a1_filetest.gno b/gnovm/tests/files/types/0a1_filetest.gno index dda07879f27..10373e92992 100644 --- a/gnovm/tests/files/types/0a1_filetest.gno +++ b/gnovm/tests/files/types/0a1_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a1_filetest.gno:5: invalid operation: mismatched types int and int8 +// main/files/types/0a1_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/0a1a0_filetest.gno b/gnovm/tests/files/types/0a1a0_filetest.gno index 9b5d953e013..f10b0cf599a 100644 --- a/gnovm/tests/files/types/0a1a0_filetest.gno +++ b/gnovm/tests/files/types/0a1a0_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a1a0_filetest.gno:5: invalid operation: mismatched types uint64 and uint +// main/files/types/0a1a0_filetest.gno:5: cannot use uint64 as uint diff --git a/gnovm/tests/files/types/0a1a1_filetest.gno b/gnovm/tests/files/types/0a1a1_filetest.gno index 64df0d47913..996950e6092 100644 --- a/gnovm/tests/files/types/0a1a1_filetest.gno +++ b/gnovm/tests/files/types/0a1a1_filetest.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/0a1a1_filetest.gno:5: invalid operation: mismatched types uint and uint64 +// main/files/types/0a1a1_filetest.gno:5: cannot use uint64 as uint diff --git a/gnovm/tests/files/types/0a1f_filetest.gno b/gnovm/tests/files/types/0a1f_filetest.gno index 984edb9e8b5..4861fe84c03 100644 --- a/gnovm/tests/files/types/0a1f_filetest.gno +++ b/gnovm/tests/files/types/0a1f_filetest.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/0a1f_filetest.gno:6: invalid operation: mismatched types int and string +// main/files/types/0a1f_filetest.gno:6: cannot use int as string diff --git a/gnovm/tests/files/types/0a2_filetest.gno b/gnovm/tests/files/types/0a2_filetest.gno index b6a940f5e10..3c28a8eb12c 100644 --- a/gnovm/tests/files/types/0a2_filetest.gno +++ b/gnovm/tests/files/types/0a2_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/0a2_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/0a2_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0a3_filetest.gno b/gnovm/tests/files/types/0a3_filetest.gno index ecba7d40f74..6767d7aae9f 100644 --- a/gnovm/tests/files/types/0a3_filetest.gno +++ b/gnovm/tests/files/types/0a3_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/0a3_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/0a3_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0a4_filetest.gno b/gnovm/tests/files/types/0a4_filetest.gno index 5ae407e5add..f44f895a779 100644 --- a/gnovm/tests/files/types/0a4_filetest.gno +++ b/gnovm/tests/files/types/0a4_filetest.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/0a4_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/0a4_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0e0_filetest.gno b/gnovm/tests/files/types/0e0_filetest.gno index 30af49f7f2a..fc845f73e1e 100644 --- a/gnovm/tests/files/types/0e0_filetest.gno +++ b/gnovm/tests/files/types/0e0_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 \ No newline at end of file +// main/files/types/0e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0e1_filetest.gno b/gnovm/tests/files/types/0e1_filetest.gno index a07aa1f433f..ba937d9a110 100644 --- a/gnovm/tests/files/types/0e1_filetest.gno +++ b/gnovm/tests/files/types/0e1_filetest.gno @@ -24,4 +24,4 @@ func main() { } // Error: -// main/files/types/0e1_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 +// main/files/types/0e1_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/0f14_filetest.gno b/gnovm/tests/files/types/0f14_filetest.gno index 39b960ace7d..92037364f85 100644 --- a/gnovm/tests/files/types/0f14_filetest.gno +++ b/gnovm/tests/files/types/0f14_filetest.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/types/0f14_filetest.gno:10: comparison on arrays of unequal type +// main/files/types/0f14_filetest.gno:10: cannot use string as int diff --git a/gnovm/tests/files/types/0f16_filetest.gno b/gnovm/tests/files/types/0f16_filetest.gno index f4229190382..9a148067cba 100644 --- a/gnovm/tests/files/types/0f16_filetest.gno +++ b/gnovm/tests/files/types/0f16_filetest.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/types/0f16_filetest.gno:16: [2]main.word and [2]main.word cannot be compared +// main/files/types/0f16_filetest.gno:16: [2]main.word is not comparable diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index d42aceef7e4..5184d635afc 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types/0f20_filetest.gno:9: and [2]main.f cannot be compared +// main/files/types/0f20_filetest.gno:9: invalid operation, nil can not be compared to [2]main.f diff --git a/gnovm/tests/files/types/0f21_filetest.gno b/gnovm/tests/files/types/0f21_filetest.gno index fa6606b512d..6959680a0c5 100644 --- a/gnovm/tests/files/types/0f21_filetest.gno +++ b/gnovm/tests/files/types/0f21_filetest.gno @@ -5,10 +5,9 @@ type f func() bool var a [2]f var b [2]f -// TODO: review where it happens func main() { println(a == b) } // Error: -// main/files/types/0f21_filetest.gno:10: [2]main.f and [2]main.f cannot be compared +// main/files/types/0f21_filetest.gno:9: [2]main.f is not comparable diff --git a/gnovm/tests/files/types/0f21a_filetest.gno b/gnovm/tests/files/types/0f21a_filetest.gno new file mode 100644 index 00000000000..075149d264f --- /dev/null +++ b/gnovm/tests/files/types/0f21a_filetest.gno @@ -0,0 +1,13 @@ +package main + +type f func() bool + +var a [2]*f +var b [2]*f + +func main() { + println(a == b) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/0f30f_filetest.gno b/gnovm/tests/files/types/0f30f_filetest.gno index 62cf24182df..e9e236e4c82 100644 --- a/gnovm/tests/files/types/0f30f_filetest.gno +++ b/gnovm/tests/files/types/0f30f_filetest.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/0f30f_filetest.gno:7: [2]int and [3]int cannot be compared +// main/files/types/0f30f_filetest.gno:7: cannot use [2]int as [3]int diff --git a/gnovm/tests/files/types/cmp_array_b.gno b/gnovm/tests/files/types/cmp_array_b.gno index d3f81f7670b..490a3424965 100644 --- a/gnovm/tests/files/types/cmp_array_b.gno +++ b/gnovm/tests/files/types/cmp_array_b.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/types/cmp_array_b.gno:10: [2][]int and [2][]int cannot be compared +// main/files/types/cmp_array_b.gno:10: [2][]int is not comparable diff --git a/gnovm/tests/files/types/cmp_array_c.gno b/gnovm/tests/files/types/cmp_array_c.gno index 8eddee0ea3d..f23ef6c9a78 100644 --- a/gnovm/tests/files/types/cmp_array_c.gno +++ b/gnovm/tests/files/types/cmp_array_c.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/types/cmp_array_c.gno:10: [2][]int and [2][]int cannot be compared +// main/files/types/cmp_array_c.gno:10: [2][]int is not comparable diff --git a/gnovm/tests/files/types/cmp_array_d.gno b/gnovm/tests/files/types/cmp_array_d.gno new file mode 100644 index 00000000000..78f9527f819 --- /dev/null +++ b/gnovm/tests/files/types/cmp_array_d.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + a := [2]int{1, 2} + b := [2]int{1, 2} + + fmt.Println("a == b:", a == b) +} + +// Output: +// a == b: true diff --git a/gnovm/tests/files/types/cmp_struct_a.gno b/gnovm/tests/files/types/cmp_struct_a.gno index 738d3f1d94b..5e8add9f1d6 100644 --- a/gnovm/tests/files/types/cmp_struct_a.gno +++ b/gnovm/tests/files/types/cmp_struct_a.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/types/cmp_struct_a.gno:15: [2][]int and [2][]int cannot be compared +// main/files/types/cmp_struct_a.gno:15: [2][]int is not comparable diff --git a/gnovm/tests/files/types/cmp_struct_b.gno b/gnovm/tests/files/types/cmp_struct_b.gno index 7bed790a7b5..f767fec16d5 100644 --- a/gnovm/tests/files/types/cmp_struct_b.gno +++ b/gnovm/tests/files/types/cmp_struct_b.gno @@ -16,4 +16,4 @@ func main() { } // Error: -// main/files/types/cmp_struct_b.gno:15: comparison on structs of unequal types +// main/files/types/cmp_struct_b.gno:15: cannot use main.foo as main.bar without explicit conversion diff --git a/gnovm/tests/files/types/cmp_struct_c.gno b/gnovm/tests/files/types/cmp_struct_c.gno index d94ce945036..4894e32d0e5 100644 --- a/gnovm/tests/files/types/cmp_struct_c.gno +++ b/gnovm/tests/files/types/cmp_struct_c.gno @@ -16,4 +16,4 @@ func main() { } // Error: -// main/files/types/cmp_struct_c.gno:15: main.foo and struct{b []int} cannot be compared +// main/files/types/cmp_struct_c.gno:15: main.bar is not comparable \ No newline at end of file diff --git a/gnovm/tests/files/types/cmp_struct_c1.gno b/gnovm/tests/files/types/cmp_struct_c1.gno new file mode 100644 index 00000000000..3cb4b835dcd --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_c1.gno @@ -0,0 +1,19 @@ +package main + +type foo struct { + a int +} + +type bar struct { + b []int +} + +func main() { + fa := foo{} + bb := bar{} + + println(bb == fa) +} + +// Error: +// main/files/types/cmp_struct_c1.gno:15: cannot use main.bar as main.foo without explicit conversion diff --git a/gnovm/tests/files/types/cmp_struct_d.gno b/gnovm/tests/files/types/cmp_struct_d.gno index abe324f263b..4c2f6eb848f 100644 --- a/gnovm/tests/files/types/cmp_struct_d.gno +++ b/gnovm/tests/files/types/cmp_struct_d.gno @@ -16,4 +16,4 @@ func main() { } // Error: -// main/files/types/cmp_struct_d.gno:15: main.foo and struct{b []int} cannot be compared +// main/files/types/cmp_struct_d.gno:15: main.bar is not comparable diff --git a/gnovm/tests/files/types/cmp_struct_e.gno b/gnovm/tests/files/types/cmp_struct_e.gno index 3f302a1393a..4640c0e4252 100644 --- a/gnovm/tests/files/types/cmp_struct_e.gno +++ b/gnovm/tests/files/types/cmp_struct_e.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/types/cmp_struct_e.gno:11: main.foo and struct{a []int} cannot be compared +// main/files/types/cmp_struct_e.gno:11: main.foo is not comparable diff --git a/gnovm/tests/files/types/cmp_struct_g.gno b/gnovm/tests/files/types/cmp_struct_g.gno new file mode 100644 index 00000000000..05224000f05 --- /dev/null +++ b/gnovm/tests/files/types/cmp_struct_g.gno @@ -0,0 +1,21 @@ +package main + +import "fmt" + +type Person struct { + age int +} + +type Dog struct { + age int +} + +func main() { + a := Person{} + b := Dog{} + + fmt.Println("a == b:", a == b) +} + +// Error: +// main/files/types/cmp_struct_g.gno:17: cannot use main.Person as main.Dog without explicit conversion From 681f285f855f0348bf5ef91ce7071722ba09eb42 Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Thu, 18 Apr 2024 15:02:52 +0800 Subject: [PATCH 138/193] Update gnovm/pkg/gnolang/preprocess.go Co-authored-by: Morgan --- gnovm/pkg/gnolang/preprocess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index f8ef08e08ae..1f2b1815518 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2340,7 +2340,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if !coerce { if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. // e.g. int(1) == int8(1) - checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a + checkAssignableTo(cx.T, t, autoNative) } } convertConst(store, last, cx, t) From 603c39aab0a2b9fbb6bf1c18d01a65b1efc2d9ad Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Thu, 18 Apr 2024 15:44:44 +0800 Subject: [PATCH 139/193] Update gnovm/pkg/gnolang/type_check.go Co-authored-by: Morgan --- gnovm/pkg/gnolang/type_check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index a6eddc2165a..c33b1fea20a 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -514,7 +514,7 @@ func (bx *BinaryExpr) checkShiftExpr(dt Type) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) } } else { - panic("should not happen") + panic(fmt.Sprintf("binary checker for %s does not exist", bx.Op)) } } From 1919aa304b1c91f4072395f723b571f59fec0a1e Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Thu, 18 Apr 2024 15:50:02 +0800 Subject: [PATCH 140/193] Update gnovm/pkg/gnolang/type_check.go Co-authored-by: Morgan --- gnovm/pkg/gnolang/type_check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index c33b1fea20a..9cecd2e004a 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -504,7 +504,7 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { } // =========================================================== -func (bx *BinaryExpr) checkShiftExpr(dt Type) { +func (bx *BinaryExpr) checkShiftLhs(dt Type) { var destKind interface{} if dt != nil { destKind = dt.Kind() From 7699ab0841f8f85e31a6d3b70fc2b7c5a8dc88d1 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Apr 2024 15:54:55 +0800 Subject: [PATCH 141/193] decouple checkOrConvertType --- gnovm/pkg/gnolang/preprocess.go | 133 ++++++++++++++++---------------- gnovm/pkg/gnolang/type_check.go | 31 ++++---- 2 files changed, 81 insertions(+), 83 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index f8ef08e08ae..fdd12454121 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -450,7 +450,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, cx := range n.Cases { cx = Preprocess( store, last, cx).(Expr) - checkOrConvertType(store, last, &cx, tt, false, false) // #nosec G601 + checkOrConvertType(store, last, &cx, tt, false) // #nosec G601 n.Cases[i] = cx } } @@ -781,12 +781,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rcx.T, false, false) + checkOrConvertType(store, last, &n.Left, rcx.T, false) } else if cmp == 0 { - checkOrConvertType(store, last, &n.Left, rcx.T, false, false) + checkOrConvertType(store, last, &n.Left, rcx.T, false) } else { // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lcx.T, false, false) + checkOrConvertType(store, last, &n.Right, lcx.T, false) } } // Then, evaluate the expression. @@ -806,7 +806,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { rnt.String())) } // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, false, false) + checkOrConvertType(store, last, &n.Left, pt, false) // if check pass, convert n.Right to (gno) pt type, rn := Expr(Call(pt.String(), n.Right)) // and convert result back. @@ -825,20 +825,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { if !isShift { // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, false, false) + checkOrConvertType(store, last, &n.Left, rt, false) } } } else if lcx.T == nil { // LHS is nil. XXX, should this be located in isUntyped? if !isShift { // convert n.Left to typed-nil type. - checkOrConvertType(store, last, &n.Left, rt, false, false) + checkOrConvertType(store, last, &n.Left, rt, false) } } else { // left is typed const, right not const if !isShift { // rhs of shift expr has already been converted to uint - if isUntyped(rt) { // refer to 0_d.gno. e.g. int(1) + 1<>=. - convertConstType(store, last, &n.Rhs[0], UintType, false) // bypass check + convertType(store, last, &n.Rhs[0], UintType, false) // bypass check } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, // TODO: assert length lt := evalStaticTypeOf(store, last, n.Lhs[0]) - checkOrConvertType(store, last, &n.Rhs[0], lt, true, false) + checkOrConvertType(store, last, &n.Rhs[0], lt, true) } else { // all else, like BAND_ASSIGN, etc // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) // if lt is interface, nothing will happen - checkOrConvertType(store, last, &n.Rhs[i], lt, true, false) + checkOrConvertType(store, last, &n.Rhs[i], lt, true) } } } @@ -1681,12 +1681,12 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *ForStmt: // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, false, false) + checkOrConvertType(store, last, &n.Cond, BoolType, false) // TRANS_LEAVE ----------------------- case *IfStmt: // Cond consts become bool *ConstExprs. - checkOrConvertType(store, last, &n.Cond, BoolType, false, false) + checkOrConvertType(store, last, &n.Cond, BoolType, false) // TRANS_LEAVE ----------------------- case *RangeStmt: @@ -1741,7 +1741,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // XXX how to deal? panic("not yet implemented") } else { - checkOrConvertType(store, last, &n.Results[i], rt, false, false) + checkOrConvertType(store, last, &n.Results[i], rt, false) } } } @@ -1749,7 +1749,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *SendStmt: // Value consts become default *ConstExprs. - checkOrConvertType(store, last, &n.Value, nil, false, false) + checkOrConvertType(store, last, &n.Value, nil, false) // TRANS_LEAVE ----------------------- case *SelectCaseStmt: @@ -1837,7 +1837,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // convert if const to nt. for i := range n.Values { - checkOrConvertType(store, last, &n.Values[i], nt, false, false) + checkOrConvertType(store, last, &n.Values[i], nt, false) } } else if n.Const { // derive static type from values. @@ -2317,11 +2317,26 @@ func isConstType(x Expr) bool { return ok } -// for special case to bypass check for typed -> typed conversion, e.g. array index conversion -func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { +// check before convert type +func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { + if debug { + debug.Printf("checkOrConvertType, *x: %v:, t:%v \n", *x, t) + } if cx, ok := (*x).(*ConstExpr); ok { - convertConst(store, last, cx, t) + if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. + // e.g. int(1) == int8(1) + checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a + } + } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { + // "push" expected type into shift binary's left operand. recursively. + checkOrConvertType(store, last, &bx.Left, t, autoNative) + } else if *x != nil { // XXX if x != nil && t != nil { + xt := evalStaticTypeOf(store, last, *x) + if t != nil { + checkAssignableTo(xt, t, autoNative) + } } + convertType(store, last, x, t, autoNative) } // 1. convert x to t if x is *ConstExpr. @@ -2330,31 +2345,17 @@ func convertConstType(store Store, last BlockNode, x *Expr, t Type, autoNative b // for native function calls, where gno values are // automatically converted to native go types. // NOTE: also see checkOrConvertIntegerType() -// coerce implies a mandatory convert, it happens with explicit conversion, uint64(int(1)), or RHS of a -// shift expr, or key of slice/array. -func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool, coerce bool) { +func convertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) { if debug { - debug.Printf("checkOrConvertType, *x: %v:, t:%v, coerce: %v \n", *x, t, coerce) + debug.Printf("convertType, *x: %v:, t:%v \n", *x, t) } if cx, ok := (*x).(*ConstExpr); ok { - if !coerce { - if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. - // e.g. int(1) == int8(1) - checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a - } - } convertConst(store, last, cx, t) - } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // "push" expected type into shift binary's left operand. - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - } else if *x != nil { // XXX if x != nil && t != nil { + } else if *x != nil { xt := evalStaticTypeOf(store, last, *x) if debug { debug.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) } - if t != nil && !coerce { - checkAssignableTo(xt, t, autoNative) - } if isUntyped(xt) { if t == nil { t = defaultTypeOf(xt) @@ -2368,11 +2369,9 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: // push t into bx.Left and bx.Right, recursively - checkOrConvertType(store, last, &bx.Left, t, autoNative, coerce) - checkOrConvertType(store, last, &bx.Right, t, autoNative, coerce) + convertType(store, last, &bx.Left, t, autoNative) + convertType(store, last, &bx.Right, t, autoNative) return - case EQL, LSS, GTR, NEQ, LEQ, GEQ: - // nothing to do, quick forward default: // do nothing } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index a6eddc2165a..2b6ae73da35 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -36,7 +36,7 @@ var ( XOR: isIntNum, NOT: isBoolean, } - IncDecStmtChecker = map[Word]func(t Type) bool{ // NOTE: to be consistent with op_inc_dec.go, line3, no float support for now(while go does). + IncDecStmtChecker = map[Word]func(t Type) bool{ INC: isNumeric, DEC: isNumeric, } @@ -514,7 +514,7 @@ func (bx *BinaryExpr) checkShiftExpr(dt Type) { panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) } } else { - panic("should not happen") + panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) } } @@ -565,7 +565,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { if checker, ok := binaryChecker[bx.Op]; ok { bx.checkCompatibility(xt, dt, checker, OpStr) } else { - panic("should not happen") + panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) } default: panic("invalid comparison operator") @@ -574,7 +574,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { if checker, ok := binaryChecker[bx.Op]; ok { bx.checkCompatibility(xt, dt, checker, OpStr) } else { - panic("should not happen") + panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) } switch bx.Op { @@ -595,14 +595,14 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, OpStr string) { if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind(dt))) + panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, kindString(dt))) } // e.g. 1%1e9 if !checker(xt) { err := tryCheckAssignableTo(xt, dt, false) // XXX, cache this? if err != nil { - panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, destKind(xt))) + panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, kindString(xt))) } } } @@ -619,10 +619,10 @@ func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { dt = xt } if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", ux.Op.TokenString(), destKind(dt))) + panic(fmt.Sprintf("operator %s not defined on: %v", ux.Op.TokenString(), kindString(dt))) } } else { - panic("should not happen") + panic(fmt.Sprintf("checker for %s does not exist", ux.Op)) } } @@ -635,10 +635,10 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { // check compatible if checker, ok := IncDecStmtChecker[idst.Op]; ok { if !checker(t) { - panic(fmt.Sprintf("operator %s not defined on: %v", idst.Op.TokenString(), destKind(t))) + panic(fmt.Sprintf("operator %s not defined on: %v", idst.Op.TokenString(), kindString(t))) } } else { - panic("should not happen") + panic(fmt.Sprintf("checker for %s does not exist", idst.Op)) } } @@ -772,7 +772,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if checker, ok := AssignStmtChecker[as.Op]; ok { if !checker(lt) { - panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, destKind(lt))) + panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, kindString(lt))) } switch as.Op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: @@ -788,19 +788,18 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { // do nothing } } else { - panic("should not happen") + panic(fmt.Sprintf("checker for %s does not exist", as.Op)) } } } } // misc -func destKind(xt Type) Kind { - var dk Kind +func kindString(xt Type) string { if xt != nil { - dk = xt.Kind() + return xt.Kind().String() } - return dk + return "nil" } func isQuoOrRem(op Word) bool { From 5f95c6c9ee648644232b4288d7edca33b1646cc4 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Apr 2024 23:23:36 +0800 Subject: [PATCH 142/193] improve assertComparable, rm interface{}(nil) test file --- gnovm/pkg/gnolang/type_check.go | 54 +++++++++++----------- gnovm/tests/files/types/0a01_filetest.gno | 2 +- gnovm/tests/files/types/0f20_filetest.gno | 2 +- gnovm/tests/files/types/0f47d_filetest.gno | 17 ------- gnovm/tests/files/types/0f47e_filetest.gno | 17 ------- gnovm/tests/files/types/0f47f_filetest.gno | 14 ------ gnovm/tests/files/types/cmp_poiner2.gno | 10 ++++ gnovm/tests/files/types/nil.gno | 9 ++++ 8 files changed, 47 insertions(+), 78 deletions(-) delete mode 100644 gnovm/tests/files/types/0f47d_filetest.gno delete mode 100644 gnovm/tests/files/types/0f47e_filetest.gno delete mode 100644 gnovm/tests/files/types/0f47f_filetest.gno create mode 100644 gnovm/tests/files/types/cmp_poiner2.gno create mode 100644 gnovm/tests/files/types/nil.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 5d246f0ebe2..683811af5cd 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -150,46 +150,52 @@ func isNumericOrString(t Type) bool { } // =========================================================== -// assertComparable is used in preprocess. +func assertComparable(xt, dt Type) { + switch baseOf(dt).(type) { + case *SliceType, *FuncType, *MapType: + if xt != nil { + panic(fmt.Sprintf("%v can only be compared to nil", dt)) + } + } + assertComparable2(dt) +} + // assert value with dt is comparable -// special case when both typed, check if type identical -func assertComparable(dt Type) { +func assertComparable2(dt Type) { if debug { - debug.Printf("--- assertComparable---, dt: %v \n", dt) + debug.Printf("---assertComparable2 dt: %v \n", dt) } - switch cdt := baseOf(dt).(type) { case PrimitiveType: case *ArrayType: switch baseOf(cdt.Elem()).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: - assertComparable(cdt.Elem()) + assertComparable2(cdt.Elem()) default: panic(fmt.Sprintf("%v is not comparable", dt)) } - case *StructType: // struct type, not pointer type + case *StructType: for _, f := range cdt.Fields { switch cft := baseOf(f.Type).(type) { case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: - assertComparable(cft) + assertComparable2(cft) default: panic(fmt.Sprintf("%v is not comparable", dt)) } } case *PointerType: // &a == &b - case *InterfaceType: // var a, b interface{} - case *SliceType, *FuncType, *MapType: // xt is not nil here - panic(fmt.Sprintf("%v can only be compared to nil", dt)) + case *InterfaceType: + case *SliceType, *FuncType, *MapType: case *NativeType: if !cdt.Type.Comparable() { - panic(fmt.Sprintf("%v is not comparable \n", dt)) + panic(fmt.Sprintf("%v is not comparable", dt)) } default: panic(fmt.Sprintf("%v is not comparable", dt)) } } -func assertMaybeNil(t Type) bool { +func maybeNil(t Type) bool { switch cxt := baseOf(t).(type) { case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType: // we don't have unsafePointer return true @@ -215,18 +221,17 @@ func checkAssignableTo(xt, dt Type, autoNative bool) { // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -// check if xt can be assigned to dt. conversionNeeded indicates further conversion needed especially from unnamed -> named -// case 0. nil check -// case 1. untyped const to typed const with same kind -// case 2. unnamed to named -// case 3. dt is interface, xt satisfied dt -// case 4. general cases for primitives and composite. func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { if debug { debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) } // case0 - if xt == nil || dt == nil { // see 0f18, assign8.gno + if xt == nil { // see test/files/types/0f18 + if !maybeNil(dt) { + panic(fmt.Sprintf("invalid operation, nil can not be compared to %v", dt)) + } + return nil + } else if dt == nil { // _ = xxx, assign8.gno, 0f31. else cases? return nil } // case3 @@ -553,14 +558,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { if isComparison(bx.Op) { switch bx.Op { case EQL, NEQ: - // special case when xt is nil - if xt == nil { - if !assertMaybeNil(dt) { - panic(fmt.Sprintf("invalid operation, nil can not be compared to %v", dt)) - } - } else { - assertComparable(dt) // only check if dest type is comparable - } + assertComparable(xt, dt) case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[bx.Op]; ok { bx.checkCompatibility(xt, dt, checker, OpStr) diff --git a/gnovm/tests/files/types/0a01_filetest.gno b/gnovm/tests/files/types/0a01_filetest.gno index 4aa4110898d..cbe430fadc4 100644 --- a/gnovm/tests/files/types/0a01_filetest.gno +++ b/gnovm/tests/files/types/0a01_filetest.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/0a01_filetest.gno:4: invalid operation, nil can not be compared to +// main/files/types/0a01_filetest.gno:4: is not comparable diff --git a/gnovm/tests/files/types/0f20_filetest.gno b/gnovm/tests/files/types/0f20_filetest.gno index 5184d635afc..d9f1ac78935 100644 --- a/gnovm/tests/files/types/0f20_filetest.gno +++ b/gnovm/tests/files/types/0f20_filetest.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/types/0f20_filetest.gno:9: invalid operation, nil can not be compared to [2]main.f +// main/files/types/0f20_filetest.gno:9: [2]main.f is not comparable diff --git a/gnovm/tests/files/types/0f47d_filetest.gno b/gnovm/tests/files/types/0f47d_filetest.gno deleted file mode 100644 index 22b8b5db220..00000000000 --- a/gnovm/tests/files/types/0f47d_filetest.gno +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import "fmt" - -type integer interface{} - -// note, cast untyped nil to interface{}, hence comparable, special case -// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false -func main() { - //println(integer(nil) == nil) - println(interface{}(nil) == nil) // refer to convertConst and convertTo - fmt.Printf("%T \n", interface{}(nil)) -} - -// Output: -// true -// diff --git a/gnovm/tests/files/types/0f47e_filetest.gno b/gnovm/tests/files/types/0f47e_filetest.gno deleted file mode 100644 index d195aed98d9..00000000000 --- a/gnovm/tests/files/types/0f47e_filetest.gno +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import "fmt" - -type integer interface{} - -// note, cast untyped nil to interface{}, hence comparable, special case -// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false -func main() { - //println(integer(nil) == nil) - println(integer(nil) == nil) - fmt.Printf("%T \n", integer(nil)) -} - -// Output: -// true -// diff --git a/gnovm/tests/files/types/0f47f_filetest.gno b/gnovm/tests/files/types/0f47f_filetest.gno deleted file mode 100644 index 01c80bd8079..00000000000 --- a/gnovm/tests/files/types/0f47f_filetest.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import "fmt" - -// note, cast untyped nil to interface{}, hence comparable, special case -// ---BinaryExpr---, OP: EQL, lx: (const (undefined)), rx: (const (undefined)), lt: interface{}, rt: , isLeftConstExpr: true, isRightConstExpr true, isLeftUntyped: false, isRightUntyped: false -func main() { - println(interface{}(nil) == (*int)(nil)) // refer to convertConst and convertTo - fmt.Printf("%T \n", interface{}(nil)) -} - -// Output: -// true -// diff --git a/gnovm/tests/files/types/cmp_poiner2.gno b/gnovm/tests/files/types/cmp_poiner2.gno new file mode 100644 index 00000000000..6899803075f --- /dev/null +++ b/gnovm/tests/files/types/cmp_poiner2.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := []int{1, 2} + b := []int{1, 2} + println(&a == &b) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/nil.gno b/gnovm/tests/files/types/nil.gno new file mode 100644 index 00000000000..a836d328dfe --- /dev/null +++ b/gnovm/tests/files/types/nil.gno @@ -0,0 +1,9 @@ +package main + +func main() { + + println(nil + nil) +} + +// Error: +// main/files/types/nil.gno:5: operator + not defined on: nil From 1caac46e5aec23a123aad005d6bff61c6d04cf4d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Apr 2024 23:27:38 +0800 Subject: [PATCH 143/193] fix CI --- .github/workflows/gnovm.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/gnovm.yml b/.github/workflows/gnovm.yml index 5fa68ac305a..a1448436a54 100644 --- a/.github/workflows/gnovm.yml +++ b/.github/workflows/gnovm.yml @@ -60,6 +60,8 @@ jobs: - _test.pkg - _test.gnolang.native - _test.gnolang.stdlibs + - _test.gnolang.types + - _test.gnolang.types.native - _test.gnolang.realm - _test.gnolang.pkg0 - _test.gnolang.pkg1 From f4c9e668fbb283f9d55b5450d654e9f19e136ae1 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 18 Apr 2024 23:50:56 +0800 Subject: [PATCH 144/193] revert unuseful logic --- gnovm/pkg/gnolang/type_check.go | 13 +++++-------- gnovm/pkg/gnolang/values_string.go | 8 +------- gnovm/tests/files/addr0b_stdlibs.gno | 2 +- gnovm/tests/files/interface27b.gno | 2 +- gnovm/tests/files/interface28b.gno | 2 +- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 683811af5cd..f7ac320cd23 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -324,8 +324,8 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { if ddt, ok := dt.(*DeclaredType); ok { // types must match exactly. if !dxt.sealed && !ddt.sealed && - dxt.PkgPath == ddt.PkgPath && - dxt.Name == ddt.Name { // not yet sealed + dxt.PkgPath == ddt.PkgPath && + dxt.Name == ddt.Name { // not yet sealed return nil // ok } else if dxt.TypeID() == ddt.TypeID() { return nil // ok @@ -529,11 +529,8 @@ func (bx *BinaryExpr) checkShiftLhs(dt Type) { // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { - // we can't check compatible with native types at current stage, - // so leave it to later operations(trans_leave on binaryExpr) - // to be converted into gno(only for primitive types), and do - // this check again. (AssertCompatible would be invoked again) - // non-primitive types is a special case that is not handled. + // native type will be converted to gno in latter logic, + // this check logic will be conduct again if lnt, ok := lt.(*NativeType); ok { _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) if ok { @@ -655,7 +652,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if len(as.Lhs) != len(cft.Results) { panic(fmt.Sprintf( "assignment mismatch: "+ - "%d variables but %s returns %d values", + "%d variables but %s returns %d values", len(as.Lhs), cx.Func.String(), len(cft.Results))) } // check assignable diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index b00ab352fde..dc1dcda9cc0 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -281,13 +281,7 @@ func printNilOrValue(tv *TypedValue, valueType interface{}) string { // For gno debugging/testing. func (tv TypedValue) String() string { if tv.IsUndefined() { - var n string - if tv.T == nil { - n = "nil" - } else { - n = tv.T.String() - } - return "(undefined)" + " " + n + return "(undefined)" } vs := "" if tv.V == nil { diff --git a/gnovm/tests/files/addr0b_stdlibs.gno b/gnovm/tests/files/addr0b_stdlibs.gno index 324a30f8140..2ec6782c7f0 100644 --- a/gnovm/tests/files/addr0b_stdlibs.gno +++ b/gnovm/tests/files/addr0b_stdlibs.gno @@ -20,4 +20,4 @@ func main() { } // Output: -// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined) nil,(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) +// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined),(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) diff --git a/gnovm/tests/files/interface27b.gno b/gnovm/tests/files/interface27b.gno index 4818db24e2c..97c7127e315 100644 --- a/gnovm/tests/files/interface27b.gno +++ b/gnovm/tests/files/interface27b.gno @@ -7,4 +7,4 @@ func main() { } // Output: -// map{(0 int):(undefined) nil} +// map{(0 int):(undefined)} diff --git a/gnovm/tests/files/interface28b.gno b/gnovm/tests/files/interface28b.gno index 4c4deb5d3c1..1fdcab58905 100644 --- a/gnovm/tests/files/interface28b.gno +++ b/gnovm/tests/files/interface28b.gno @@ -7,4 +7,4 @@ func main() { } // Output: -// slice[(undefined) nil] +// slice[(undefined)] From 850e4e34c31808f136b5ae59d00b6d85b5b037b6 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 19 Apr 2024 16:40:21 +0800 Subject: [PATCH 145/193] more check --- gnovm/pkg/gnolang/preprocess.go | 1 + gnovm/pkg/gnolang/type_check.go | 114 ++++++++++++------ gnovm/tests/files/types/assign_index_b.gno | 14 +++ ...{assign_index_1.gno => assign_index_c.gno} | 2 +- gnovm/tests/files/types/assign_range.gno | 42 +++++++ gnovm/tests/files/types/assign_range_a.gno | 22 ++++ gnovm/tests/files/types/assign_range_b.gno | 20 +++ gnovm/tests/files/types/assign_range_b1.gno | 20 +++ gnovm/tests/files/types/assign_range_c.gno | 20 +++ gnovm/tests/files/types/assign_range_d.gno | 14 +++ gnovm/tests/files/types/assign_range_e.gno | 15 +++ .../files/types/assign_type_assertion_b.gno | 2 +- .../files/types/assign_type_assertion_c.gno | 2 +- .../files/types/assign_type_assertion_d.gno | 25 ++++ .../files/types/assign_type_assertion_e.gno | 27 +++++ .../files/types/assign_type_assertion_f.gno | 25 ++++ .../files/types/assign_type_assertion_g.gno | 27 +++++ 17 files changed, 353 insertions(+), 39 deletions(-) create mode 100644 gnovm/tests/files/types/assign_index_b.gno rename gnovm/tests/files/types/{assign_index_1.gno => assign_index_c.gno} (61%) create mode 100644 gnovm/tests/files/types/assign_range.gno create mode 100644 gnovm/tests/files/types/assign_range_a.gno create mode 100644 gnovm/tests/files/types/assign_range_b.gno create mode 100644 gnovm/tests/files/types/assign_range_b1.gno create mode 100644 gnovm/tests/files/types/assign_range_c.gno create mode 100644 gnovm/tests/files/types/assign_range_d.gno create mode 100644 gnovm/tests/files/types/assign_range_e.gno create mode 100644 gnovm/tests/files/types/assign_type_assertion_d.gno create mode 100644 gnovm/tests/files/types/assign_type_assertion_e.gno create mode 100644 gnovm/tests/files/types/assign_type_assertion_f.gno create mode 100644 gnovm/tests/files/types/assign_type_assertion_g.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index efb3fa89447..1cdd545b8cf 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1691,6 +1691,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *RangeStmt: // NOTE: k,v already defined @ TRANS_BLOCK. + n.AssertCompatible(store, last) // TRANS_LEAVE ----------------------- case *ReturnStmt: diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index f7ac320cd23..f1ca3d62ea8 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -324,8 +324,8 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { if ddt, ok := dt.(*DeclaredType); ok { // types must match exactly. if !dxt.sealed && !ddt.sealed && - dxt.PkgPath == ddt.PkgPath && - dxt.Name == ddt.Name { // not yet sealed + dxt.PkgPath == ddt.PkgPath && + dxt.Name == ddt.Name { // not yet sealed return nil // ok } else if dxt.TypeID() == ddt.TypeID() { return nil // ok @@ -516,7 +516,7 @@ func (bx *BinaryExpr) checkShiftLhs(dt Type) { } if checker, ok := binaryChecker[bx.Op]; ok { if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", wordTokenStrings[bx.Op], destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", bx.Op.TokenString(), destKind)) } } else { panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) @@ -637,8 +637,44 @@ func (idst *IncDecStmt) AssertCompatible(t Type) { } } +func (rs *RangeStmt) AssertCompatible(store Store, last BlockNode) { + if rs.Op == ASSIGN { + if isBlankIdentifier(rs.Key) && isBlankIdentifier(rs.Value) { + // both "_" + } else { + kt := evalStaticTypeOf(store, last, rs.Key) + vt := evalStaticTypeOf(store, last, rs.Value) + xt := evalStaticTypeOf(store, last, rs.X) + switch cxt := xt.(type) { + case *MapType: + checkAssignableTo(cxt.Key, kt, false) + checkAssignableTo(cxt.Value, vt, false) + case *SliceType: + if kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } + checkAssignableTo(cxt.Elt, vt, false) + case *ArrayType: + if kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } + checkAssignableTo(cxt.Elt, vt, false) + case PrimitiveType: + if cxt.Kind() == StringKind { + if kt != nil && kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } + if vt != nil && vt.Kind() != Int32Kind { // rune + panic(fmt.Sprintf("value type should be int32, but got %v", kt)) + } + } + } + } + } +} + func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { - Opstr := wordTokenStrings[as.Op] + Opstr := as.Op.TokenString() if as.Op == ASSIGN || as.Op == DEFINE { if len(as.Lhs) > len(as.Rhs) { if len(as.Rhs) != 1 { @@ -652,55 +688,60 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if len(as.Lhs) != len(cft.Results) { panic(fmt.Sprintf( "assignment mismatch: "+ - "%d variables but %s returns %d values", + "%d variables but %s returns %d values", len(as.Lhs), cx.Func.String(), len(cft.Results))) } // check assignable for i, lx := range as.Lhs { - lxt := evalStaticTypeOf(store, last, lx) - checkAssignableTo(cft.Results[i].Type, lxt, false) // TODO: autoNative? + if !isBlankIdentifier(lx) { // see composite3.gno + lxt := evalStaticTypeOf(store, last, lx) + checkAssignableTo(cft.Results[i].Type, lxt, false) + } } case *TypeAssertExpr: // Type-assert case: a, ok := x.(type) if len(as.Lhs) != 2 { panic("should not happen") } - if ctex, ok := cx.Type.(*constTypeExpr); ok { - // check assignable - dt := evalStaticTypeOf(store, last, as.Lhs[0]) - checkAssignableTo(ctex.Type, dt, false) - } else if _, ok := cx.Type.(*InterfaceTypeExpr); ok { + // check assignable to first value + if !isBlankIdentifier(as.Lhs[0]) { // see composite3.gno dt := evalStaticTypeOf(store, last, as.Lhs[0]) - if isBlankIdentifier(as.Lhs[0]) { // see composite3.gno - // do nothing - } else if dt != nil && dt.Kind() == InterfaceKind { - ift := evalStaticTypeOf(store, last, cx) - debug.Println("---ift, type of: ", ift, reflect.TypeOf(ift)) - idt := dt.(*InterfaceType) - if !idt.IsImplementedBy(ift) { - panic(fmt.Sprintf("cannot assign to %v", as.Lhs[0])) - } - } else { - panic(fmt.Sprintf("cannot assign to %v", as.Lhs[0])) + ift := evalStaticTypeOf(store, last, cx) + checkAssignableTo(ift, dt, false) + } + if !isBlankIdentifier(as.Lhs[1]) { // see composite3.gno + dt := evalStaticTypeOf(store, last, as.Lhs[1]) + if dt != nil && dt.Kind() != BoolKind { // typed, not bool + panic(fmt.Sprintf("want bool type got %v", dt)) } } + cx.HasOK = true - case *IndexExpr: + case *IndexExpr: // must be with map type when len(Lhs) > len(Rhs) if len(as.Lhs) != 2 { panic("should not happen") } - lt := evalStaticTypeOf(store, last, as.Lhs[0]) - if nx, ok := cx.X.(*NameExpr); ok { - rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() - if mt, ok := rx.T.(*MapType); ok { - checkAssignableTo(mt.Value, lt, false) + // check first value + if !isBlankIdentifier(as.Lhs[0]) { + lt := evalStaticTypeOf(store, last, as.Lhs[0]) + if nx, ok := cx.X.(*NameExpr); ok { + rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() + if mt, ok := rx.T.(*MapType); ok { + checkAssignableTo(mt.Value, lt, false) + } + } else if _, ok := cx.X.(*CompositeLitExpr); ok { + cpt := evalStaticTypeOf(store, last, cx.X) + if mt, ok := cpt.(*MapType); ok { + checkAssignableTo(mt.Value, lt, false) + } else { + panic("should not happen") + } } - } else if _, ok := cx.X.(*CompositeLitExpr); ok { - cpt := evalStaticTypeOf(store, last, cx.X) - if mt, ok := cpt.(*MapType); ok { - checkAssignableTo(mt.Value, lt, false) - } else { - panic("should not happen") + } + if !isBlankIdentifier(as.Lhs[1]) { + dt := evalStaticTypeOf(store, last, as.Lhs[1]) + if dt != nil && dt.Kind() != BoolKind { // typed, not bool + panic(fmt.Sprintf("want bool type got %v", dt)) } } cx.HasOK = true @@ -732,7 +773,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic(fmt.Sprintf("cannot assign to %v", lx)) } } - } else { + } else { // define // NOTE: this is already checked while parsing file for i, lx := range as.Lhs { rt := evalStaticTypeOf(store, last, as.Rhs[i]) @@ -750,6 +791,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } else { + // TODO: check length of expression for i, lx := range as.Lhs { lt := evalStaticTypeOf(store, last, lx) rt := evalStaticTypeOf(store, last, as.Rhs[i]) diff --git a/gnovm/tests/files/types/assign_index_b.gno b/gnovm/tests/files/types/assign_index_b.gno new file mode 100644 index 00000000000..d8900759cb2 --- /dev/null +++ b/gnovm/tests/files/types/assign_index_b.gno @@ -0,0 +1,14 @@ +package main + +func main() { + m := map[string]int{"a": 1, "b": 2, "c": 3} + + var s int + var ok int + s, ok = m["a"] + println(s) + println(ok) +} + +// Error: +// main/files/types/assign_index_b.gno:8: want bool type got int diff --git a/gnovm/tests/files/types/assign_index_1.gno b/gnovm/tests/files/types/assign_index_c.gno similarity index 61% rename from gnovm/tests/files/types/assign_index_1.gno rename to gnovm/tests/files/types/assign_index_c.gno index c9c68fa91fd..592191189a2 100644 --- a/gnovm/tests/files/types/assign_index_1.gno +++ b/gnovm/tests/files/types/assign_index_c.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/types/assign_index_1.gno:7: cannot use int as string +// main/files/types/assign_index_c.gno:7: cannot use int as string diff --git a/gnovm/tests/files/types/assign_range.gno b/gnovm/tests/files/types/assign_range.gno new file mode 100644 index 00000000000..5ee1c49a2e9 --- /dev/null +++ b/gnovm/tests/files/types/assign_range.gno @@ -0,0 +1,42 @@ +package main + +import "fmt" + +func main() { + // Creating a map where keys are strings and values are integers + scores := map[string]int{ + "Alice": 92, + "Bob": 89, + "Charlie": 95, + } + + // Using range to iterate over the map + // k is the key and v is the value for each pair in the map + for k, v := range scores { + fmt.Printf("%s has a score of %d\n", k, v) + } + + // Modifying values during iteration + for k := range scores { + scores[k] += 5 // Adding 5 to each score + } + fmt.Println("Updated scores:", scores) + + // Collecting keys and values into slices + var keys []string + var values []int + for k, v := range scores { + keys = append(keys, k) + values = append(values, v) + } + fmt.Println("Keys:", keys) + fmt.Println("Values:", values) +} + +// Output: +// Alice has a score of 92 +// Bob has a score of 89 +// Charlie has a score of 95 +// Updated scores: map[Alice:97 Bob:94 Charlie:100] +// Keys: [Alice Bob Charlie] +// Values: [97 94 100] diff --git a/gnovm/tests/files/types/assign_range_a.gno b/gnovm/tests/files/types/assign_range_a.gno new file mode 100644 index 00000000000..72115771e52 --- /dev/null +++ b/gnovm/tests/files/types/assign_range_a.gno @@ -0,0 +1,22 @@ +package main + +import "fmt" + +func main() { + // Creating a map where keys are strings and values are integers + scores := map[string]int{ + "Alice": 92, + "Bob": 89, + "Charlie": 95, + } + + // Using range to iterate over the map + // k is the key and v is the value for each pair in the map + var k, v int + for k, v = range scores { + fmt.Printf("%s has a score of %d\n", k, v) + } +} + +// Error: +// main/files/types/assign_range_a.gno:16: cannot use string as int diff --git a/gnovm/tests/files/types/assign_range_b.gno b/gnovm/tests/files/types/assign_range_b.gno new file mode 100644 index 00000000000..df7fbeb8158 --- /dev/null +++ b/gnovm/tests/files/types/assign_range_b.gno @@ -0,0 +1,20 @@ +package main + +import "fmt" + +func main() { + // Creating a map where keys are strings and values are integers + scores := []string{ + "a", "b", "c", + } + + // Using range to iterate over the map + // k is the key and v is the value for each pair in the map + var k, v int + for k, v = range scores { + fmt.Printf("%d has a score of %s\n", k, v) + } +} + +// Error: +// main/files/types/assign_range_b.gno:14: cannot use string as int diff --git a/gnovm/tests/files/types/assign_range_b1.gno b/gnovm/tests/files/types/assign_range_b1.gno new file mode 100644 index 00000000000..4632b79b6f0 --- /dev/null +++ b/gnovm/tests/files/types/assign_range_b1.gno @@ -0,0 +1,20 @@ +package main + +import "fmt" + +func main() { + // Creating a map where keys are strings and values are integers + scores := [3]string{ + "a", "b", "c", + } + + // Using range to iterate over the map + // k is the key and v is the value for each pair in the map + var k, v int + for k, v = range scores { + fmt.Printf("%d has a score of %s\n", k, v) + } +} + +// Error: +// main/files/types/assign_range_b1.gno:14: cannot use string as int diff --git a/gnovm/tests/files/types/assign_range_c.gno b/gnovm/tests/files/types/assign_range_c.gno new file mode 100644 index 00000000000..783534bebb4 --- /dev/null +++ b/gnovm/tests/files/types/assign_range_c.gno @@ -0,0 +1,20 @@ +package main + +import "fmt" + +func main() { + // Creating a map where keys are strings and values are integers + scores := []string{ + "a", "b", "c", + } + + // Using range to iterate over the map + // k is the key and v is the value for each pair in the map + var k, v float32 + for k, v = range scores { + fmt.Printf("%d has a score of %s\n", k, v) + } +} + +// Error: +// main/files/types/assign_range_c.gno:14: index type should be int, but got float32 diff --git a/gnovm/tests/files/types/assign_range_d.gno b/gnovm/tests/files/types/assign_range_d.gno new file mode 100644 index 00000000000..4a84ff215ae --- /dev/null +++ b/gnovm/tests/files/types/assign_range_d.gno @@ -0,0 +1,14 @@ +package main + +func main() { + s := "hello" + + var index float32 + var value rune + for index, rune = range s { + println(index) + } +} + +// Error: +// main/files/types/assign_range_d.gno:8: index type should be int, but got float32 diff --git a/gnovm/tests/files/types/assign_range_e.gno b/gnovm/tests/files/types/assign_range_e.gno new file mode 100644 index 00000000000..7f7f15c5c23 --- /dev/null +++ b/gnovm/tests/files/types/assign_range_e.gno @@ -0,0 +1,15 @@ +package main + +func main() { + s := "hello" + + var index int + var value int + for index, value = range s { + println(index) + println(value) + } +} + +// Error: +// main/files/types/assign_range_e.gno:8: value type should be int32, but got int diff --git a/gnovm/tests/files/types/assign_type_assertion_b.gno b/gnovm/tests/files/types/assign_type_assertion_b.gno index da6af231a21..4f68751667d 100644 --- a/gnovm/tests/files/types/assign_type_assertion_b.gno +++ b/gnovm/tests/files/types/assign_type_assertion_b.gno @@ -29,4 +29,4 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_b.gno:22: cannot assign to assertedErr +// main/files/types/assign_type_assertion_b.gno:22: cannot use interface{IsSet func()(bool)} as int diff --git a/gnovm/tests/files/types/assign_type_assertion_c.gno b/gnovm/tests/files/types/assign_type_assertion_c.gno index 48fd0181f27..044154dadfd 100644 --- a/gnovm/tests/files/types/assign_type_assertion_c.gno +++ b/gnovm/tests/files/types/assign_type_assertion_c.gno @@ -30,4 +30,4 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_c.gno:23: cannot assign to assertedErr +// main/files/types/assign_type_assertion_c.gno:23: interface{IsSet func()(bool)} does not implement interface{IsNotSet func()(bool)} diff --git a/gnovm/tests/files/types/assign_type_assertion_d.gno b/gnovm/tests/files/types/assign_type_assertion_d.gno new file mode 100644 index 00000000000..4ab24f36aac --- /dev/null +++ b/gnovm/tests/files/types/assign_type_assertion_d.gno @@ -0,0 +1,25 @@ +package main + +type Animal interface { + eat() +} + +type Robot struct { +} + +type Dog struct{} + +func (Dog) eat() {} + +func main() { + var animal Animal = Dog{} + + var r Robot + + r = animal.(Dog) + + println(r) +} + +// Error: +// main/files/types/assign_type_assertion_d.gno:19: cannot use main.Dog as main.Robot without explicit conversion diff --git a/gnovm/tests/files/types/assign_type_assertion_e.gno b/gnovm/tests/files/types/assign_type_assertion_e.gno new file mode 100644 index 00000000000..fbe91031667 --- /dev/null +++ b/gnovm/tests/files/types/assign_type_assertion_e.gno @@ -0,0 +1,27 @@ +package main + +type Animal interface { + eat() +} + +type Robot struct { +} + +type Dog struct{} + +func (Dog) eat() {} + +func main() { + var animal Animal = Dog{} + + var r Robot + var ok bool + + r, ok = animal.(Dog) + + println(r) + println(ok) +} + +// Error: +// main/files/types/assign_type_assertion_e.gno:20: cannot use main.Dog as main.Robot without explicit conversion diff --git a/gnovm/tests/files/types/assign_type_assertion_f.gno b/gnovm/tests/files/types/assign_type_assertion_f.gno new file mode 100644 index 00000000000..3b9a87fd5dc --- /dev/null +++ b/gnovm/tests/files/types/assign_type_assertion_f.gno @@ -0,0 +1,25 @@ +package main + +type Animal interface { + eat() +} + +type Robot struct { +} + +type Dog struct{} + +func (Dog) eat() {} + +func main() { + var animal Animal = Dog{} + + var ok bool + + 1, ok = animal.(Dog) + + println(ok) +} + +// Error: +// main/files/types/assign_type_assertion_f.gno:19: cannot use main.Dog as bigint without explicit conversion diff --git a/gnovm/tests/files/types/assign_type_assertion_g.gno b/gnovm/tests/files/types/assign_type_assertion_g.gno new file mode 100644 index 00000000000..2d3d61c561d --- /dev/null +++ b/gnovm/tests/files/types/assign_type_assertion_g.gno @@ -0,0 +1,27 @@ +package main + +type Animal interface { + eat() +} + +type Robot struct { +} + +type Dog struct{} + +func (Dog) eat() {} + +func main() { + var animal Animal = Dog{} + + var a Animal + var ok int + + a, ok = animal.(Dog) + + println(a) + println(ok) +} + +// Error: +// main/files/types/assign_type_assertion_g.gno:20: want bool type got int From 7467a2d93d74672d79ce9fbf0b519f3e89ccf86c Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 19 Apr 2024 16:49:45 +0800 Subject: [PATCH 146/193] clean --- gnovm/tests/file_test.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index 622ef274b5b..4d8c4176f8d 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -47,16 +47,6 @@ func TestTypesNative(t *testing.T) { runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) } -func TestDebug(t *testing.T) { - baseDir := filepath.Join(".", "debug") - runFileTests(t, baseDir, []string{"*_native*"}) -} - -func TestDebugNative(t *testing.T) { - baseDir := filepath.Join(".", "debug") - runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) -} - func filterFileTests(t *testing.T, files []fs.DirEntry, ignore []string) []fs.DirEntry { t.Helper() From 4b139809d70d2280c3bc17d8d216b448f97830d0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sat, 20 Apr 2024 08:07:42 +0800 Subject: [PATCH 147/193] not check on define in assignment --- gnovm/pkg/gnolang/type_check.go | 80 ++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index f1ca3d62ea8..daf9d8f75ff 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -691,11 +691,13 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { "%d variables but %s returns %d values", len(as.Lhs), cx.Func.String(), len(cft.Results))) } - // check assignable - for i, lx := range as.Lhs { - if !isBlankIdentifier(lx) { // see composite3.gno - lxt := evalStaticTypeOf(store, last, lx) - checkAssignableTo(cft.Results[i].Type, lxt, false) + if as.Op == ASSIGN { + // check assignable + for i, lx := range as.Lhs { + if !isBlankIdentifier(lx) { // see composite3.gno + lxt := evalStaticTypeOf(store, last, lx) + checkAssignableTo(cft.Results[i].Type, lxt, false) + } } } case *TypeAssertExpr: @@ -703,53 +705,57 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if len(as.Lhs) != 2 { panic("should not happen") } - // check assignable to first value - if !isBlankIdentifier(as.Lhs[0]) { // see composite3.gno - dt := evalStaticTypeOf(store, last, as.Lhs[0]) - ift := evalStaticTypeOf(store, last, cx) - checkAssignableTo(ift, dt, false) - } - if !isBlankIdentifier(as.Lhs[1]) { // see composite3.gno - dt := evalStaticTypeOf(store, last, as.Lhs[1]) - if dt != nil && dt.Kind() != BoolKind { // typed, not bool - panic(fmt.Sprintf("want bool type got %v", dt)) + if as.Op == ASSIGN { + // check assignable to first value + if !isBlankIdentifier(as.Lhs[0]) { // see composite3.gno + dt := evalStaticTypeOf(store, last, as.Lhs[0]) + ift := evalStaticTypeOf(store, last, cx) + checkAssignableTo(ift, dt, false) + } + if !isBlankIdentifier(as.Lhs[1]) { // see composite3.gno + dt := evalStaticTypeOf(store, last, as.Lhs[1]) + if dt != nil && dt.Kind() != BoolKind { // typed, not bool + panic(fmt.Sprintf("want bool type got %v", dt)) + } } } - cx.HasOK = true case *IndexExpr: // must be with map type when len(Lhs) > len(Rhs) if len(as.Lhs) != 2 { panic("should not happen") } - // check first value - if !isBlankIdentifier(as.Lhs[0]) { - lt := evalStaticTypeOf(store, last, as.Lhs[0]) - if nx, ok := cx.X.(*NameExpr); ok { - rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() - if mt, ok := rx.T.(*MapType); ok { - checkAssignableTo(mt.Value, lt, false) - } - } else if _, ok := cx.X.(*CompositeLitExpr); ok { - cpt := evalStaticTypeOf(store, last, cx.X) - if mt, ok := cpt.(*MapType); ok { - checkAssignableTo(mt.Value, lt, false) - } else { - panic("should not happen") + if as.Op == ASSIGN { + // check first value + if !isBlankIdentifier(as.Lhs[0]) { + lt := evalStaticTypeOf(store, last, as.Lhs[0]) + if nx, ok := cx.X.(*NameExpr); ok { + rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() + if mt, ok := rx.T.(*MapType); ok { + checkAssignableTo(mt.Value, lt, false) + } + } else if _, ok := cx.X.(*CompositeLitExpr); ok { + cpt := evalStaticTypeOf(store, last, cx.X) + if mt, ok := cpt.(*MapType); ok { + checkAssignableTo(mt.Value, lt, false) + } else { + panic("should not happen") + } } } - } - if !isBlankIdentifier(as.Lhs[1]) { - dt := evalStaticTypeOf(store, last, as.Lhs[1]) - if dt != nil && dt.Kind() != BoolKind { // typed, not bool - panic(fmt.Sprintf("want bool type got %v", dt)) + if !isBlankIdentifier(as.Lhs[1]) { + dt := evalStaticTypeOf(store, last, as.Lhs[1]) + if dt != nil && dt.Kind() != BoolKind { // typed, not bool + panic(fmt.Sprintf("want bool type got %v", dt)) + } } } cx.HasOK = true default: panic("should not happen") } - } else { + } else { // len(Lhs) == len(Rhs) if as.Op == ASSIGN { + // check lhs for i, lx := range as.Lhs { rt := evalStaticTypeOf(store, last, as.Rhs[i]) @@ -790,7 +796,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } - } else { + } else { // else op other than assign and define // TODO: check length of expression for i, lx := range as.Lhs { lt := evalStaticTypeOf(store, last, lx) From 63fd8cc1fae3da8203b70e2dea2f69924680de43 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 21 Apr 2024 21:21:51 +0800 Subject: [PATCH 148/193] rm similar test file with multi operators --- gnovm/tests/files/types/0c0_filetest.gno | 23 ---------- gnovm/tests/files/types/0c1_filetest.gno | 23 ---------- gnovm/tests/files/types/0f11_filetest.gno | 24 ---------- gnovm/tests/files/types/0f13_filetest.gno | 15 ------- gnovm/tests/files/types/0f22_filetest.gno | 1 - .../files/types/0f26_stdlibs_filetest.gno | 27 ----------- gnovm/tests/files/types/0f30c_filetest.gno | 1 - gnovm/tests/files/types/0f3_stdlibs.gno | 27 ----------- gnovm/tests/files/types/0f5_stdlibs.gno | 27 ----------- gnovm/tests/files/types/0f7_stdlibs.gno | 27 ----------- .../tests/files/types/11a0_LAND_filetest.gno | 9 ---- gnovm/tests/files/types/11a1_filetest.gno | 9 ---- gnovm/tests/files/types/11a2_filetest.gno | 9 ---- gnovm/tests/files/types/11a3_filetest.gno | 15 ------- .../tests/files/types/11a4_LAND_filetest.gno | 8 ---- .../tests/files/types/11a5_LAND_filetest.gno | 8 ---- .../tests/files/types/11a6_LAND_filetest.gno | 8 ---- .../tests/files/types/11a7_LAND_filetest.gno | 8 ---- .../tests/files/types/11a8_LAND_filetest.gno | 8 ---- gnovm/tests/files/types/12a0_LOR_filetest.gno | 9 ---- gnovm/tests/files/types/12a1_filetest.gno | 9 ---- gnovm/tests/files/types/12a2_filetest.gno | 9 ---- gnovm/tests/files/types/12a3_filetest.gno | 15 ------- .../files/types/14a0_SUB_ASSIGN_filetest.gno | 9 ---- gnovm/tests/files/types/14a1_filetest.gno | 25 ----------- gnovm/tests/files/types/14b0_filetest.gno | 13 ------ gnovm/tests/files/types/14b1_filetest.gno | 13 ------ gnovm/tests/files/types/14b2_filetest.gno | 10 ----- gnovm/tests/files/types/14d0_filetest.gno | 12 ----- gnovm/tests/files/types/14e0_filetest.gno | 28 ------------ gnovm/tests/files/types/14e1_filetest.gno | 20 --------- gnovm/tests/files/types/14e_filetest.gno | 21 --------- .../files/types/14f0_stdlibs_filetest.gno | 25 ----------- .../files/types/14f1_stdlibs_filetest.gno | 22 --------- .../files/types/14f2_stdlibs_filetest.gno | 45 ------------------- gnovm/tests/files/types/14f3_filetest.gno | 32 ------------- gnovm/tests/files/types/14f4_filetest.gno | 9 ---- gnovm/tests/files/types/14f5_filetest.gno | 10 ----- gnovm/tests/files/types/15a01_filetest.gno | 10 ----- gnovm/tests/files/types/15a02_filetest.gno | 10 ----- gnovm/tests/files/types/15a03_filetest.gno | 10 ----- gnovm/tests/files/types/15a04_filetest.gno | 10 ----- .../files/types/15a0_REM_ASSIGN_filetest.gno | 10 ----- .../files/types/18a0_AND_ASSIGN_filetest.gno | 10 ----- gnovm/tests/files/types/18a1_filetest.gno | 10 ----- gnovm/tests/files/types/18a2_filetest.gno | 10 ----- gnovm/tests/files/types/18a3_filetest.gno | 10 ----- gnovm/tests/files/types/18a4_filetest.gno | 10 ----- gnovm/tests/files/types/20a0_LSS_filetest.gno | 8 ---- gnovm/tests/files/types/20a1_filetest.gno | 8 ---- gnovm/tests/files/types/20a2_filetest.gno | 8 ---- gnovm/tests/files/types/20a3_filetest.gno | 8 ---- gnovm/tests/files/types/20a4_filetest.gno | 8 ---- gnovm/tests/files/types/20a5_filetest.gno | 8 ---- gnovm/tests/files/types/2a0_SUB_filetest.gno | 9 ---- gnovm/tests/files/types/2a1_filetest.gno | 25 ----------- gnovm/tests/files/types/2b0_filetest.gno | 13 ------ gnovm/tests/files/types/2b1_filetest.gno | 21 --------- gnovm/tests/files/types/2b21_filetest.gno | 9 ---- gnovm/tests/files/types/2b2_filetest.gno | 9 ---- gnovm/tests/files/types/2b3_filetest.gno | 9 ---- gnovm/tests/files/types/2d0_filetest.gno | 12 ----- gnovm/tests/files/types/2d1_filetest.gno | 10 ----- gnovm/tests/files/types/2d2_filetest.gno | 13 ------ gnovm/tests/files/types/2d3_filetest.gno | 15 ------- gnovm/tests/files/types/2e0_filetest.gno | 27 ----------- .../files/types/2f0_stdlibs_filetest.gno | 23 ---------- .../files/types/2f1_stdlibs_filetest.gno | 23 ---------- gnovm/tests/files/types/2f2_filetest.gno | 31 ------------- gnovm/tests/files/types/3a0_MUL_filetest.gno | 9 ---- gnovm/tests/files/types/3a1_filetest.gno | 25 ----------- gnovm/tests/files/types/3b0_filetest.gno | 13 ------ gnovm/tests/files/types/3b1_filetest.gno | 21 --------- gnovm/tests/files/types/3b2_filetest.gno | 9 ---- gnovm/tests/files/types/3b3_filetest.gno | 9 ---- gnovm/tests/files/types/3d0_filetest.gno | 12 ----- gnovm/tests/files/types/3d1_filetest.gno | 10 ----- gnovm/tests/files/types/3d2_filetest.gno | 13 ------ gnovm/tests/files/types/3d3_filetest.gno | 15 ------- gnovm/tests/files/types/3e0_filetest.gno | 27 ----------- .../files/types/3f0_stdlibs_filetest.gno | 23 ---------- .../files/types/3f1_stdlibs_filetest.gno | 23 ---------- gnovm/tests/files/types/3f2_filetest.gno | 31 ------------- gnovm/tests/files/types/4a0_QUO_filetest.gno | 9 ---- gnovm/tests/files/types/4a1_filetest.gno | 25 ----------- gnovm/tests/files/types/4b0_filetest.gno | 13 ------ gnovm/tests/files/types/4b1_filetest.gno | 21 --------- gnovm/tests/files/types/4b2_filetest.gno | 9 ---- gnovm/tests/files/types/4b3_filetest.gno | 9 ---- gnovm/tests/files/types/4d0_filetest.gno | 11 ----- gnovm/tests/files/types/4d1_filetest.gno | 10 ----- gnovm/tests/files/types/4d2_filetest.gno | 13 ------ gnovm/tests/files/types/4d3_filetest.gno | 15 ------- gnovm/tests/files/types/4d4_filetest.gno | 10 ----- gnovm/tests/files/types/4d5_filetest.gno | 11 ----- gnovm/tests/files/types/4d6_filetest.gno | 11 ----- gnovm/tests/files/types/4e01_filetest.gno | 21 --------- gnovm/tests/files/types/4e0_filetest.gno | 27 ----------- gnovm/tests/files/types/4f0_filetest.gno | 9 ---- .../files/types/4f0_stdlibs_filetest.gno | 23 ---------- .../files/types/4f1_stdlibs_filetest.gno | 23 ---------- gnovm/tests/files/types/4f2_filetest.gno | 31 ------------- gnovm/tests/files/types/5b1_filetest.gno | 21 --------- gnovm/tests/files/types/5b2_filetest.gno | 9 ---- gnovm/tests/files/types/5b3_filetest.gno | 9 ---- gnovm/tests/files/types/5d0_filetest.gno | 10 ----- gnovm/tests/files/types/5d1_filetest.gno | 10 ----- gnovm/tests/files/types/5d2_filetest.gno | 13 ------ gnovm/tests/files/types/5d3_filetest.gno | 15 ------- gnovm/tests/files/types/5d4_filetest.gno | 10 ----- gnovm/tests/files/types/5e0_filetest.gno | 27 ----------- .../files/types/5f0_stdlibs_filetest.gno | 23 ---------- .../files/types/5f1_stdlibs_filetest.gno | 23 ---------- gnovm/tests/files/types/5f2_filetest.gno | 31 ------------- gnovm/tests/files/types/8a0_XOR_filetest.gno | 9 ---- gnovm/tests/files/types/8a1_filetest.gno | 25 ----------- gnovm/tests/files/types/8b0_filetest.gno | 13 ------ gnovm/tests/files/types/8b1_filetest.gno | 21 --------- gnovm/tests/files/types/8b2_filetest.gno | 9 ---- gnovm/tests/files/types/8b3_filetest.gno | 9 ---- gnovm/tests/files/types/8b4_filetest.gno | 9 ---- gnovm/tests/files/types/8d0_filetest.gno | 10 ----- gnovm/tests/files/types/8d1_filetest.gno | 10 ----- gnovm/tests/files/types/8d2_filetest.gno | 13 ------ gnovm/tests/files/types/8d3_filetest.gno | 15 ------- gnovm/tests/files/types/8d4_filetest.gno | 10 ----- gnovm/tests/files/types/8e0_filetest.gno | 27 ----------- .../files/types/8f0_stdlibs_filetest.gno | 23 ---------- .../files/types/8f1_stdlibs_filetest.gno | 23 ---------- gnovm/tests/files/types/8f2_filetest.gno | 31 ------------- .../tests/files/types/9a0_ANDNOT_filetest.gno | 9 ---- gnovm/tests/files/types/9a1_filetest.gno | 25 ----------- gnovm/tests/files/types/9b0_filetest.gno | 13 ------ gnovm/tests/files/types/9b1_filetest.gno | 21 --------- gnovm/tests/files/types/9b2_filetest.gno | 9 ---- gnovm/tests/files/types/9b3_filetest.gno | 9 ---- gnovm/tests/files/types/9b4_filetest.gno | 9 ---- gnovm/tests/files/types/9d0_filetest.gno | 10 ----- gnovm/tests/files/types/9d1_filetest.gno | 10 ----- gnovm/tests/files/types/9d2_filetest.gno | 13 ------ gnovm/tests/files/types/9d3_filetest.gno | 15 ------- gnovm/tests/files/types/9d4_filetest.gno | 10 ----- gnovm/tests/files/types/9e0_filetest.gno | 27 ----------- .../files/types/9f0_stdlibs_filetest.gno | 23 ---------- .../files/types/9f1_stdlibs_filetest.gno | 23 ---------- gnovm/tests/files/types/9f2_filetest.gno | 31 ------------- ...{0a5_rune_filetest.gno => assign_rune.gno} | 0 ...a6_rune_filetest.gno => assign_rune_a.gno} | 2 +- 148 files changed, 1 insertion(+), 2267 deletions(-) delete mode 100644 gnovm/tests/files/types/0c0_filetest.gno delete mode 100644 gnovm/tests/files/types/0c1_filetest.gno delete mode 100644 gnovm/tests/files/types/0f11_filetest.gno delete mode 100644 gnovm/tests/files/types/0f13_filetest.gno delete mode 100644 gnovm/tests/files/types/0f26_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/0f3_stdlibs.gno delete mode 100644 gnovm/tests/files/types/0f5_stdlibs.gno delete mode 100644 gnovm/tests/files/types/0f7_stdlibs.gno delete mode 100644 gnovm/tests/files/types/11a0_LAND_filetest.gno delete mode 100644 gnovm/tests/files/types/11a1_filetest.gno delete mode 100644 gnovm/tests/files/types/11a2_filetest.gno delete mode 100644 gnovm/tests/files/types/11a3_filetest.gno delete mode 100644 gnovm/tests/files/types/11a4_LAND_filetest.gno delete mode 100644 gnovm/tests/files/types/11a5_LAND_filetest.gno delete mode 100644 gnovm/tests/files/types/11a6_LAND_filetest.gno delete mode 100644 gnovm/tests/files/types/11a7_LAND_filetest.gno delete mode 100644 gnovm/tests/files/types/11a8_LAND_filetest.gno delete mode 100644 gnovm/tests/files/types/12a0_LOR_filetest.gno delete mode 100644 gnovm/tests/files/types/12a1_filetest.gno delete mode 100644 gnovm/tests/files/types/12a2_filetest.gno delete mode 100644 gnovm/tests/files/types/12a3_filetest.gno delete mode 100644 gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/files/types/14a1_filetest.gno delete mode 100644 gnovm/tests/files/types/14b0_filetest.gno delete mode 100644 gnovm/tests/files/types/14b1_filetest.gno delete mode 100644 gnovm/tests/files/types/14b2_filetest.gno delete mode 100644 gnovm/tests/files/types/14d0_filetest.gno delete mode 100644 gnovm/tests/files/types/14e0_filetest.gno delete mode 100644 gnovm/tests/files/types/14e1_filetest.gno delete mode 100644 gnovm/tests/files/types/14e_filetest.gno delete mode 100644 gnovm/tests/files/types/14f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/14f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/14f2_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/14f3_filetest.gno delete mode 100644 gnovm/tests/files/types/14f4_filetest.gno delete mode 100644 gnovm/tests/files/types/14f5_filetest.gno delete mode 100644 gnovm/tests/files/types/15a01_filetest.gno delete mode 100644 gnovm/tests/files/types/15a02_filetest.gno delete mode 100644 gnovm/tests/files/types/15a03_filetest.gno delete mode 100644 gnovm/tests/files/types/15a04_filetest.gno delete mode 100644 gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/files/types/18a0_AND_ASSIGN_filetest.gno delete mode 100644 gnovm/tests/files/types/18a1_filetest.gno delete mode 100644 gnovm/tests/files/types/18a2_filetest.gno delete mode 100644 gnovm/tests/files/types/18a3_filetest.gno delete mode 100644 gnovm/tests/files/types/18a4_filetest.gno delete mode 100644 gnovm/tests/files/types/20a0_LSS_filetest.gno delete mode 100644 gnovm/tests/files/types/20a1_filetest.gno delete mode 100644 gnovm/tests/files/types/20a2_filetest.gno delete mode 100644 gnovm/tests/files/types/20a3_filetest.gno delete mode 100644 gnovm/tests/files/types/20a4_filetest.gno delete mode 100644 gnovm/tests/files/types/20a5_filetest.gno delete mode 100644 gnovm/tests/files/types/2a0_SUB_filetest.gno delete mode 100644 gnovm/tests/files/types/2a1_filetest.gno delete mode 100644 gnovm/tests/files/types/2b0_filetest.gno delete mode 100644 gnovm/tests/files/types/2b1_filetest.gno delete mode 100644 gnovm/tests/files/types/2b21_filetest.gno delete mode 100644 gnovm/tests/files/types/2b2_filetest.gno delete mode 100644 gnovm/tests/files/types/2b3_filetest.gno delete mode 100644 gnovm/tests/files/types/2d0_filetest.gno delete mode 100644 gnovm/tests/files/types/2d1_filetest.gno delete mode 100644 gnovm/tests/files/types/2d2_filetest.gno delete mode 100644 gnovm/tests/files/types/2d3_filetest.gno delete mode 100644 gnovm/tests/files/types/2e0_filetest.gno delete mode 100644 gnovm/tests/files/types/2f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/2f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/2f2_filetest.gno delete mode 100644 gnovm/tests/files/types/3a0_MUL_filetest.gno delete mode 100644 gnovm/tests/files/types/3a1_filetest.gno delete mode 100644 gnovm/tests/files/types/3b0_filetest.gno delete mode 100644 gnovm/tests/files/types/3b1_filetest.gno delete mode 100644 gnovm/tests/files/types/3b2_filetest.gno delete mode 100644 gnovm/tests/files/types/3b3_filetest.gno delete mode 100644 gnovm/tests/files/types/3d0_filetest.gno delete mode 100644 gnovm/tests/files/types/3d1_filetest.gno delete mode 100644 gnovm/tests/files/types/3d2_filetest.gno delete mode 100644 gnovm/tests/files/types/3d3_filetest.gno delete mode 100644 gnovm/tests/files/types/3e0_filetest.gno delete mode 100644 gnovm/tests/files/types/3f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/3f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/3f2_filetest.gno delete mode 100644 gnovm/tests/files/types/4a0_QUO_filetest.gno delete mode 100644 gnovm/tests/files/types/4a1_filetest.gno delete mode 100644 gnovm/tests/files/types/4b0_filetest.gno delete mode 100644 gnovm/tests/files/types/4b1_filetest.gno delete mode 100644 gnovm/tests/files/types/4b2_filetest.gno delete mode 100644 gnovm/tests/files/types/4b3_filetest.gno delete mode 100644 gnovm/tests/files/types/4d0_filetest.gno delete mode 100644 gnovm/tests/files/types/4d1_filetest.gno delete mode 100644 gnovm/tests/files/types/4d2_filetest.gno delete mode 100644 gnovm/tests/files/types/4d3_filetest.gno delete mode 100644 gnovm/tests/files/types/4d4_filetest.gno delete mode 100644 gnovm/tests/files/types/4d5_filetest.gno delete mode 100644 gnovm/tests/files/types/4d6_filetest.gno delete mode 100644 gnovm/tests/files/types/4e01_filetest.gno delete mode 100644 gnovm/tests/files/types/4e0_filetest.gno delete mode 100644 gnovm/tests/files/types/4f0_filetest.gno delete mode 100644 gnovm/tests/files/types/4f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/4f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/4f2_filetest.gno delete mode 100644 gnovm/tests/files/types/5b1_filetest.gno delete mode 100644 gnovm/tests/files/types/5b2_filetest.gno delete mode 100644 gnovm/tests/files/types/5b3_filetest.gno delete mode 100644 gnovm/tests/files/types/5d0_filetest.gno delete mode 100644 gnovm/tests/files/types/5d1_filetest.gno delete mode 100644 gnovm/tests/files/types/5d2_filetest.gno delete mode 100644 gnovm/tests/files/types/5d3_filetest.gno delete mode 100644 gnovm/tests/files/types/5d4_filetest.gno delete mode 100644 gnovm/tests/files/types/5e0_filetest.gno delete mode 100644 gnovm/tests/files/types/5f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/5f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/5f2_filetest.gno delete mode 100644 gnovm/tests/files/types/8a0_XOR_filetest.gno delete mode 100644 gnovm/tests/files/types/8a1_filetest.gno delete mode 100644 gnovm/tests/files/types/8b0_filetest.gno delete mode 100644 gnovm/tests/files/types/8b1_filetest.gno delete mode 100644 gnovm/tests/files/types/8b2_filetest.gno delete mode 100644 gnovm/tests/files/types/8b3_filetest.gno delete mode 100644 gnovm/tests/files/types/8b4_filetest.gno delete mode 100644 gnovm/tests/files/types/8d0_filetest.gno delete mode 100644 gnovm/tests/files/types/8d1_filetest.gno delete mode 100644 gnovm/tests/files/types/8d2_filetest.gno delete mode 100644 gnovm/tests/files/types/8d3_filetest.gno delete mode 100644 gnovm/tests/files/types/8d4_filetest.gno delete mode 100644 gnovm/tests/files/types/8e0_filetest.gno delete mode 100644 gnovm/tests/files/types/8f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/8f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/8f2_filetest.gno delete mode 100644 gnovm/tests/files/types/9a0_ANDNOT_filetest.gno delete mode 100644 gnovm/tests/files/types/9a1_filetest.gno delete mode 100644 gnovm/tests/files/types/9b0_filetest.gno delete mode 100644 gnovm/tests/files/types/9b1_filetest.gno delete mode 100644 gnovm/tests/files/types/9b2_filetest.gno delete mode 100644 gnovm/tests/files/types/9b3_filetest.gno delete mode 100644 gnovm/tests/files/types/9b4_filetest.gno delete mode 100644 gnovm/tests/files/types/9d0_filetest.gno delete mode 100644 gnovm/tests/files/types/9d1_filetest.gno delete mode 100644 gnovm/tests/files/types/9d2_filetest.gno delete mode 100644 gnovm/tests/files/types/9d3_filetest.gno delete mode 100644 gnovm/tests/files/types/9d4_filetest.gno delete mode 100644 gnovm/tests/files/types/9e0_filetest.gno delete mode 100644 gnovm/tests/files/types/9f0_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/9f1_stdlibs_filetest.gno delete mode 100644 gnovm/tests/files/types/9f2_filetest.gno rename gnovm/tests/files/types/{0a5_rune_filetest.gno => assign_rune.gno} (100%) rename gnovm/tests/files/types/{0a6_rune_filetest.gno => assign_rune_a.gno} (50%) diff --git a/gnovm/tests/files/types/0c0_filetest.gno b/gnovm/tests/files/types/0c0_filetest.gno deleted file mode 100644 index c1692c8019c..00000000000 --- a/gnovm/tests/files/types/0c0_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is typed const, right is untyped const -func main() { - if Error(1) == 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// what the firetruck? diff --git a/gnovm/tests/files/types/0c1_filetest.gno b/gnovm/tests/files/types/0c1_filetest.gno deleted file mode 100644 index 5c597e8482c..00000000000 --- a/gnovm/tests/files/types/0c1_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// left is typed const, right is untyped const -func main() { - if Error(1) != 1 { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/0f11_filetest.gno b/gnovm/tests/files/types/0f11_filetest.gno deleted file mode 100644 index a4ae0463291..00000000000 --- a/gnovm/tests/files/types/0f11_filetest.gno +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var l interface{} - if l == Error(0) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/0f13_filetest.gno b/gnovm/tests/files/types/0f13_filetest.gno deleted file mode 100644 index 0ae088c05b0..00000000000 --- a/gnovm/tests/files/types/0f13_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -var a [2]string -var b [2]string -var c [2]int - -func main() { - - a = [2]string{"hello", "world"} - b = [2]string{"hello", "world"} - println(a == b) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/0f22_filetest.gno b/gnovm/tests/files/types/0f22_filetest.gno index 02d78481b57..75891def307 100644 --- a/gnovm/tests/files/types/0f22_filetest.gno +++ b/gnovm/tests/files/types/0f22_filetest.gno @@ -3,7 +3,6 @@ package main var a int = 0 var b int = 1 -// TODO: review where it happens func main() { println(&a == &b) } diff --git a/gnovm/tests/files/types/0f26_stdlibs_filetest.gno b/gnovm/tests/files/types/0f26_stdlibs_filetest.gno deleted file mode 100644 index a786ee6563c..00000000000 --- a/gnovm/tests/files/types/0f26_stdlibs_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if 1 > errCmp { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Error: -// main/files/types/0f26_stdlibs_filetest.gno:19: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0f30c_filetest.gno b/gnovm/tests/files/types/0f30c_filetest.gno index 63e9d04fb7f..ffa8c7c96e7 100644 --- a/gnovm/tests/files/types/0f30c_filetest.gno +++ b/gnovm/tests/files/types/0f30c_filetest.gno @@ -1,7 +1,6 @@ package main var f1 func() -var f2 func() func main() { println(f1 == nil) diff --git a/gnovm/tests/files/types/0f3_stdlibs.gno b/gnovm/tests/files/types/0f3_stdlibs.gno deleted file mode 100644 index 9c4cb0e5ea0..00000000000 --- a/gnovm/tests/files/types/0f3_stdlibs.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if Error(1) == errCmp { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/0f5_stdlibs.gno b/gnovm/tests/files/types/0f5_stdlibs.gno deleted file mode 100644 index 72e3eaac1b7..00000000000 --- a/gnovm/tests/files/types/0f5_stdlibs.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if Error(1) != errCmp { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// what the firetruck? diff --git a/gnovm/tests/files/types/0f7_stdlibs.gno b/gnovm/tests/files/types/0f7_stdlibs.gno deleted file mode 100644 index 29a6061cd77..00000000000 --- a/gnovm/tests/files/types/0f7_stdlibs.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// special case: -// one is interface -func main() { - if errCmp == Error(1) { - println("what the firetruck?") - } else { - println("something else") - } -} - -// Output: -// something else diff --git a/gnovm/tests/files/types/11a0_LAND_filetest.gno b/gnovm/tests/files/types/11a0_LAND_filetest.gno deleted file mode 100644 index abe396dd650..00000000000 --- a/gnovm/tests/files/types/11a0_LAND_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(1) && int(1)) -} - -// Error: -// main/files/types/11a0_LAND_filetest.gno:5: operator && not defined on: IntKind diff --git a/gnovm/tests/files/types/11a1_filetest.gno b/gnovm/tests/files/types/11a1_filetest.gno deleted file mode 100644 index c04341a309e..00000000000 --- a/gnovm/tests/files/types/11a1_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(1 && 1) -} - -// Error: -// main/files/types/11a1_filetest.gno:5: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a2_filetest.gno b/gnovm/tests/files/types/11a2_filetest.gno deleted file mode 100644 index a502575a27b..00000000000 --- a/gnovm/tests/files/types/11a2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(true && 1) -} - -// Error: -// main/files/types/11a2_filetest.gno:5: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a3_filetest.gno b/gnovm/tests/files/types/11a3_filetest.gno deleted file mode 100644 index c6f03efb164..00000000000 --- a/gnovm/tests/files/types/11a3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(true && true) - println(true && false) - println(1 == 1 && true) - println(1 == 1 && false) -} - -// Output: -// true -// false -// true -// false diff --git a/gnovm/tests/files/types/11a4_LAND_filetest.gno b/gnovm/tests/files/types/11a4_LAND_filetest.gno deleted file mode 100644 index ba0333b4eb1..00000000000 --- a/gnovm/tests/files/types/11a4_LAND_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(true && false) -} - -// Output: -// false diff --git a/gnovm/tests/files/types/11a5_LAND_filetest.gno b/gnovm/tests/files/types/11a5_LAND_filetest.gno deleted file mode 100644 index e2a8e10897c..00000000000 --- a/gnovm/tests/files/types/11a5_LAND_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(true && 0) -} - -// Error: -// main/files/types/11a5_LAND_filetest.gno:4: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a6_LAND_filetest.gno b/gnovm/tests/files/types/11a6_LAND_filetest.gno deleted file mode 100644 index d9b0702a5c7..00000000000 --- a/gnovm/tests/files/types/11a6_LAND_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(0 && true) -} - -// Error: -// main/files/types/11a6_LAND_filetest.gno:4: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/11a7_LAND_filetest.gno b/gnovm/tests/files/types/11a7_LAND_filetest.gno deleted file mode 100644 index d27742cf32d..00000000000 --- a/gnovm/tests/files/types/11a7_LAND_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(0) && true) // left typed, right untyped -} - -// Error: -// main/files/types/11a7_LAND_filetest.gno:4: operator && not defined on: IntKind diff --git a/gnovm/tests/files/types/11a8_LAND_filetest.gno b/gnovm/tests/files/types/11a8_LAND_filetest.gno deleted file mode 100644 index 5c2ad0296f0..00000000000 --- a/gnovm/tests/files/types/11a8_LAND_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(bool(true) && 0) // left typed, right untyped -} - -// Error: -// main/files/types/11a8_LAND_filetest.gno:4: operator && not defined on: BigintKind diff --git a/gnovm/tests/files/types/12a0_LOR_filetest.gno b/gnovm/tests/files/types/12a0_LOR_filetest.gno deleted file mode 100644 index f1be388ff6c..00000000000 --- a/gnovm/tests/files/types/12a0_LOR_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(1) || int(1)) -} - -// Error: -// main/files/types/12a0_LOR_filetest.gno:5: operator || not defined on: IntKind diff --git a/gnovm/tests/files/types/12a1_filetest.gno b/gnovm/tests/files/types/12a1_filetest.gno deleted file mode 100644 index 367d8f98631..00000000000 --- a/gnovm/tests/files/types/12a1_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(1 || 1) -} - -// Error: -// main/files/types/12a1_filetest.gno:5: operator || not defined on: BigintKind diff --git a/gnovm/tests/files/types/12a2_filetest.gno b/gnovm/tests/files/types/12a2_filetest.gno deleted file mode 100644 index 529639a2d54..00000000000 --- a/gnovm/tests/files/types/12a2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(true || 1) -} - -// Error: -// main/files/types/12a2_filetest.gno:5: operator || not defined on: BigintKind diff --git a/gnovm/tests/files/types/12a3_filetest.gno b/gnovm/tests/files/types/12a3_filetest.gno deleted file mode 100644 index 7bd3d97b019..00000000000 --- a/gnovm/tests/files/types/12a3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(true || true) - println(true || false) - println(1 == 1 || true) - println(1 == 1 || false) -} - -// Output: -// true -// true -// true -// true diff --git a/gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno b/gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno deleted file mode 100644 index 6f8845190fa..00000000000 --- a/gnovm/tests/files/types/14a0_SUB_ASSIGN_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - int(0) -= int8(1) -} - -// Error: -// main/files/types/14a0_SUB_ASSIGN_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/14a1_filetest.gno b/gnovm/tests/files/types/14a1_filetest.gno deleted file mode 100644 index 02c7c952268..00000000000 --- a/gnovm/tests/files/types/14a1_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - Error1(0) -= Error2(0) -} - -// Error: -// main/files/types/14a1_filetest.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/14b0_filetest.gno b/gnovm/tests/files/types/14b0_filetest.gno deleted file mode 100644 index 3ca7463828f..00000000000 --- a/gnovm/tests/files/types/14b0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - r := 1 - r -= Error(1) - println(r) -} - -// Error: -// main/files/types/14b0_filetest.gno:8: invalid operation: mismatched types int and main.Error diff --git a/gnovm/tests/files/types/14b1_filetest.gno b/gnovm/tests/files/types/14b1_filetest.gno deleted file mode 100644 index 60daad58194..00000000000 --- a/gnovm/tests/files/types/14b1_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - r := Error(1) - r -= 1 - println(r) -} - -// Output: -// (0 main.Error) diff --git a/gnovm/tests/files/types/14b2_filetest.gno b/gnovm/tests/files/types/14b2_filetest.gno deleted file mode 100644 index c351754d256..00000000000 --- a/gnovm/tests/files/types/14b2_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - r := 1 - r -= 'a' - println(r) -} - -// Output: -// -96 diff --git a/gnovm/tests/files/types/14d0_filetest.gno b/gnovm/tests/files/types/14d0_filetest.gno deleted file mode 100644 index e830d7d269d..00000000000 --- a/gnovm/tests/files/types/14d0_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - r := 1.0 - r -= 1 - println(r) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/14e0_filetest.gno b/gnovm/tests/files/types/14e0_filetest.gno deleted file mode 100644 index 0b9d0baa96e..00000000000 --- a/gnovm/tests/files/types/14e0_filetest.gno +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - e1 -= e2 - println(e1) -} - -// Error: -// main/files/types/14e0_filetest.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/14e1_filetest.gno b/gnovm/tests/files/types/14e1_filetest.gno deleted file mode 100644 index a351bb7af8b..00000000000 --- a/gnovm/tests/files/types/14e1_filetest.gno +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 = Error1(0) - e1 -= 1 - println(e1) -} - -// Output: -// error: -1 diff --git a/gnovm/tests/files/types/14e_filetest.gno b/gnovm/tests/files/types/14e_filetest.gno deleted file mode 100644 index 1696128422e..00000000000 --- a/gnovm/tests/files/types/14e_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -func main() { - var e1 Error1 = Error1(0) - var e2 int64 = 1 - e1 -= Error1(e2) - println(e1) -} - -// Output: -// error: -1 diff --git a/gnovm/tests/files/types/14f0_stdlibs_filetest.gno b/gnovm/tests/files/types/14f0_stdlibs_filetest.gno deleted file mode 100644 index 4177a20d602..00000000000 --- a/gnovm/tests/files/types/14f0_stdlibs_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - r := 1 - r -= errCmp - println(r) -} - -// Error: -// main/files/types/14f0_stdlibs_filetest.gno:20: invalid operation: mismatched types int and .uverse.error diff --git a/gnovm/tests/files/types/14f1_stdlibs_filetest.gno b/gnovm/tests/files/types/14f1_stdlibs_filetest.gno deleted file mode 100644 index a26fdf054ba..00000000000 --- a/gnovm/tests/files/types/14f1_stdlibs_filetest.gno +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -func main() { - r := Error(0) - r -= errCmp // in case of this, should panic mismatch on operand, except RHS is untyped -} - -// Error: -// main/files/types/14f1_stdlibs_filetest.gno:18: invalid operation: mismatched types main.Error and .uverse.error diff --git a/gnovm/tests/files/types/14f2_stdlibs_filetest.gno b/gnovm/tests/files/types/14f2_stdlibs_filetest.gno deleted file mode 100644 index 29636e76aba..00000000000 --- a/gnovm/tests/files/types/14f2_stdlibs_filetest.gno +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// NOTE: in golang, this won't compile by type mismatch -// code like this : won't compile by : "invalid operation: operator + not defined on err1 (variable of type error)" -// which indicates that golang will check type match first, and operand legality secondly -// that is, for op =+, first check type match, second check operand -// in our condition, should check convert first, after that, check operand? - -//package main -// -//import ( -//"errors" -//) -// -//var err1 = errors.New("XXXX") -//var err2 = errors.New("XXXX") -// -//func main() { -// err1 += err2 -// println(err1) -//} - -// specil case: -// one is interface -func main() { - r := Error(0) - errCmp -= r - println(errCmp) -} - -// Error: -// main/files/types/14f2_stdlibs_filetest.gno:40: operator -= not defined on: InterfaceKind \ No newline at end of file diff --git a/gnovm/tests/files/types/14f3_filetest.gno b/gnovm/tests/files/types/14f3_filetest.gno deleted file mode 100644 index 60458f50050..00000000000 --- a/gnovm/tests/files/types/14f3_filetest.gno +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - e1 -= e2 - println(e1) -} - -// Error: -// main/files/types/14f3_filetest.gno:27: operator -= not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/14f4_filetest.gno b/gnovm/tests/files/types/14f4_filetest.gno deleted file mode 100644 index f847ac07805..00000000000 --- a/gnovm/tests/files/types/14f4_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both not const, and both interface -func main() { - "a" -= "b" -} - -// Error: -// main/files/types/14f4_filetest.gno:5: operator -= not defined on: StringKind diff --git a/gnovm/tests/files/types/14f5_filetest.gno b/gnovm/tests/files/types/14f5_filetest.gno deleted file mode 100644 index 787f2be03d8..00000000000 --- a/gnovm/tests/files/types/14f5_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both not const, and both interface -func main() { - var a string = "a" - a -= "b" -} - -// Error: -// main/files/types/14f5_filetest.gno:6: operator -= not defined on: StringKind diff --git a/gnovm/tests/files/types/15a01_filetest.gno b/gnovm/tests/files/types/15a01_filetest.gno deleted file mode 100644 index e866e059361..00000000000 --- a/gnovm/tests/files/types/15a01_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 10 - a %= 3.0 - println(a) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/15a02_filetest.gno b/gnovm/tests/files/types/15a02_filetest.gno deleted file mode 100644 index a401fd97cab..00000000000 --- a/gnovm/tests/files/types/15a02_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := "hello" - a %= 3 - println(a) -} - -// Error: -// main/files/types/15a02_filetest.gno:5: operator %= not defined on: StringKind diff --git a/gnovm/tests/files/types/15a03_filetest.gno b/gnovm/tests/files/types/15a03_filetest.gno deleted file mode 100644 index 918b47fb31c..00000000000 --- a/gnovm/tests/files/types/15a03_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 10 - a %= "a" - println(a) -} - -// Error: -// main/files/types/15a03_filetest.gno:5: cannot use untyped string as IntKind diff --git a/gnovm/tests/files/types/15a04_filetest.gno b/gnovm/tests/files/types/15a04_filetest.gno deleted file mode 100644 index a465f75f1ac..00000000000 --- a/gnovm/tests/files/types/15a04_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 10.0 - a %= 3.0 - println(a) -} - -// Error: -// main/files/types/15a04_filetest.gno:5: operator %= not defined on: Float64Kind diff --git a/gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno b/gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno deleted file mode 100644 index 363252d58e0..00000000000 --- a/gnovm/tests/files/types/15a0_REM_ASSIGN_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - a := 10 - a %= 3 - println(a) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/18a0_AND_ASSIGN_filetest.gno b/gnovm/tests/files/types/18a0_AND_ASSIGN_filetest.gno deleted file mode 100644 index 31d88639bd8..00000000000 --- a/gnovm/tests/files/types/18a0_AND_ASSIGN_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - r := int(1) - r &= int(1) - println(r) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/18a1_filetest.gno b/gnovm/tests/files/types/18a1_filetest.gno deleted file mode 100644 index c3b080cabf1..00000000000 --- a/gnovm/tests/files/types/18a1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - r := int(1) - r &= 1 - println(r) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/18a2_filetest.gno b/gnovm/tests/files/types/18a2_filetest.gno deleted file mode 100644 index c6c825b1ac9..00000000000 --- a/gnovm/tests/files/types/18a2_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - r := int(1) - r &= int8(1) - println(r) -} - -// Error: -// main/files/types/18a2_filetest.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/18a3_filetest.gno b/gnovm/tests/files/types/18a3_filetest.gno deleted file mode 100644 index aa3de3b8944..00000000000 --- a/gnovm/tests/files/types/18a3_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - r := int(1) - r &= 'a' - println(r) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/18a4_filetest.gno b/gnovm/tests/files/types/18a4_filetest.gno deleted file mode 100644 index 96c90100417..00000000000 --- a/gnovm/tests/files/types/18a4_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -func main() { - r := "a" - r &= "b" - println(r) -} - -// Error: -// main/files/types/18a4_filetest.gno:5: operator &= not defined on: StringKind diff --git a/gnovm/tests/files/types/20a0_LSS_filetest.gno b/gnovm/tests/files/types/20a0_LSS_filetest.gno deleted file mode 100644 index f11bda7fd5c..00000000000 --- a/gnovm/tests/files/types/20a0_LSS_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(1) < int8(2)) -} - -// Error: -// main/files/types/20a0_LSS_filetest.gno:4: cannot use int as int8 diff --git a/gnovm/tests/files/types/20a1_filetest.gno b/gnovm/tests/files/types/20a1_filetest.gno deleted file mode 100644 index 770bbc61d12..00000000000 --- a/gnovm/tests/files/types/20a1_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(1) < 2) -} - -// Output: -// true diff --git a/gnovm/tests/files/types/20a2_filetest.gno b/gnovm/tests/files/types/20a2_filetest.gno deleted file mode 100644 index 887f23c13e0..00000000000 --- a/gnovm/tests/files/types/20a2_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(1) < 'a') -} - -// Output: -// true diff --git a/gnovm/tests/files/types/20a3_filetest.gno b/gnovm/tests/files/types/20a3_filetest.gno deleted file mode 100644 index 8afe6a84a5f..00000000000 --- a/gnovm/tests/files/types/20a3_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(int(1) < "a") -} - -// Error: -// main/files/types/20a3_filetest.gno:4: cannot use untyped string as IntKind diff --git a/gnovm/tests/files/types/20a4_filetest.gno b/gnovm/tests/files/types/20a4_filetest.gno deleted file mode 100644 index b7b70e42fe9..00000000000 --- a/gnovm/tests/files/types/20a4_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println(true < 1) -} - -// Error: -// main/files/types/20a4_filetest.gno:4: operator < not defined on: BoolKind diff --git a/gnovm/tests/files/types/20a5_filetest.gno b/gnovm/tests/files/types/20a5_filetest.gno deleted file mode 100644 index f89ed14eddb..00000000000 --- a/gnovm/tests/files/types/20a5_filetest.gno +++ /dev/null @@ -1,8 +0,0 @@ -package main - -func main() { - println("a" < "b") -} - -// Output: -// true diff --git a/gnovm/tests/files/types/2a0_SUB_filetest.gno b/gnovm/tests/files/types/2a0_SUB_filetest.gno deleted file mode 100644 index cb3de0548db..00000000000 --- a/gnovm/tests/files/types/2a0_SUB_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(1) - int8(1)) -} - -// Error: -// main/files/types/2a0_SUB_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/2a1_filetest.gno b/gnovm/tests/files/types/2a1_filetest.gno deleted file mode 100644 index 53ef6bf03db..00000000000 --- a/gnovm/tests/files/types/2a1_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - println(Error1(0) - Error2(0)) -} - -// Error: -// main/files/types/2a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/2b0_filetest.gno b/gnovm/tests/files/types/2b0_filetest.gno deleted file mode 100644 index e629f077bbf..00000000000 --- a/gnovm/tests/files/types/2b0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - println(1 - Error(1)) - println(Error(1) - 1) -} - -// Output: -// (0 main.Error) -// (0 main.Error) diff --git a/gnovm/tests/files/types/2b1_filetest.gno b/gnovm/tests/files/types/2b1_filetest.gno deleted file mode 100644 index 9b1f8975d6b..00000000000 --- a/gnovm/tests/files/types/2b1_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// one untyped const, one typed const -func main() { - println(1 - Error(1)) - println(Error(1) - 1) -} - -// Output: -// error: 0 -// error: 0 diff --git a/gnovm/tests/files/types/2b21_filetest.gno b/gnovm/tests/files/types/2b21_filetest.gno deleted file mode 100644 index 559ebb61d8f..00000000000 --- a/gnovm/tests/files/types/2b21_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("a" - 1) -} - -// Error: -// main/files/types/2b21_filetest.gno:5: operator - not defined on: StringKind diff --git a/gnovm/tests/files/types/2b2_filetest.gno b/gnovm/tests/files/types/2b2_filetest.gno deleted file mode 100644 index d5a0eff3c7b..00000000000 --- a/gnovm/tests/files/types/2b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 - "a") -} - -// Error: -// main/files/types/2b2_filetest.gno:5: operator - not defined on: StringKind diff --git a/gnovm/tests/files/types/2b3_filetest.gno b/gnovm/tests/files/types/2b3_filetest.gno deleted file mode 100644 index 2a040667102..00000000000 --- a/gnovm/tests/files/types/2b3_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("b" - "a") -} - -// Error: -// main/files/types/2b3_filetest.gno:5: operator - not defined on: StringKind diff --git a/gnovm/tests/files/types/2d0_filetest.gno b/gnovm/tests/files/types/2d0_filetest.gno deleted file mode 100644 index d70c28a49ae..00000000000 --- a/gnovm/tests/files/types/2d0_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 - 1) - println(1.0 - 0) -} - -// Output: -// 0 -// 1 diff --git a/gnovm/tests/files/types/2d1_filetest.gno b/gnovm/tests/files/types/2d1_filetest.gno deleted file mode 100644 index b8e6b5d690a..00000000000 --- a/gnovm/tests/files/types/2d1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println('a' - 'b') -} - -// Output: -// -1 diff --git a/gnovm/tests/files/types/2d2_filetest.gno b/gnovm/tests/files/types/2d2_filetest.gno deleted file mode 100644 index 033d27cab6a..00000000000 --- a/gnovm/tests/files/types/2d2_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r rune - -func main() { - r = 'a' - println(r - 'b') -} - -// Output: -// -1 diff --git a/gnovm/tests/files/types/2d3_filetest.gno b/gnovm/tests/files/types/2d3_filetest.gno deleted file mode 100644 index a24b404a39d..00000000000 --- a/gnovm/tests/files/types/2d3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r1 rune -var r2 rune - -func main() { - r1 = 'a' - r2 = 'b' - println(r1 - r2) -} - -// Output: -// -1 diff --git a/gnovm/tests/files/types/2e0_filetest.gno b/gnovm/tests/files/types/2e0_filetest.gno deleted file mode 100644 index 42d9b638e12..00000000000 --- a/gnovm/tests/files/types/2e0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 - e2) -} - -// Error: -// main/files/types/2e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/2f0_stdlibs_filetest.gno b/gnovm/tests/files/types/2f0_stdlibs_filetest.gno deleted file mode 100644 index 0d88cd45a58..00000000000 --- a/gnovm/tests/files/types/2f0_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(1 - errCmp) -} - -// Error: -// main/files/types/2f0_stdlibs_filetest.gno:19: operator - not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/2f1_stdlibs_filetest.gno b/gnovm/tests/files/types/2f1_stdlibs_filetest.gno deleted file mode 100644 index 5edb48288d0..00000000000 --- a/gnovm/tests/files/types/2f1_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(Error(0) - errCmp) -} - -// Error: -// main/files/types/2f1_stdlibs_filetest.gno:19: operator - not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/2f2_filetest.gno b/gnovm/tests/files/types/2f2_filetest.gno deleted file mode 100644 index 895e3d5eb17..00000000000 --- a/gnovm/tests/files/types/2f2_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 - e2) -} - -// Error: -// main/files/types/2f2_filetest.gno:27: operator - not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/3a0_MUL_filetest.gno b/gnovm/tests/files/types/3a0_MUL_filetest.gno deleted file mode 100644 index 45674e75a08..00000000000 --- a/gnovm/tests/files/types/3a0_MUL_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(1) * int8(1)) -} - -// Error: -// main/files/types/3a0_MUL_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/3a1_filetest.gno b/gnovm/tests/files/types/3a1_filetest.gno deleted file mode 100644 index 0244780e786..00000000000 --- a/gnovm/tests/files/types/3a1_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - println(Error1(0) * Error2(0)) -} - -// Error: -// main/files/types/3a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/3b0_filetest.gno b/gnovm/tests/files/types/3b0_filetest.gno deleted file mode 100644 index 47e63fc0239..00000000000 --- a/gnovm/tests/files/types/3b0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - println(1 * Error(1)) - println(Error(1) * 1) -} - -// Output: -// (1 main.Error) -// (1 main.Error) diff --git a/gnovm/tests/files/types/3b1_filetest.gno b/gnovm/tests/files/types/3b1_filetest.gno deleted file mode 100644 index 83287928d2c..00000000000 --- a/gnovm/tests/files/types/3b1_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// one untyped const, one typed const -func main() { - println(1 * Error(1)) - println(Error(1) * 1) -} - -// Output: -// error: 1 -// error: 1 diff --git a/gnovm/tests/files/types/3b2_filetest.gno b/gnovm/tests/files/types/3b2_filetest.gno deleted file mode 100644 index 2cf6d721528..00000000000 --- a/gnovm/tests/files/types/3b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 * "a") -} - -// Error: -// main/files/types/3b2_filetest.gno:5: operator * not defined on: StringKind diff --git a/gnovm/tests/files/types/3b3_filetest.gno b/gnovm/tests/files/types/3b3_filetest.gno deleted file mode 100644 index cef4efb3c8a..00000000000 --- a/gnovm/tests/files/types/3b3_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("b" * "a") -} - -// Error: -// main/files/types/3b3_filetest.gno:5: operator * not defined on: StringKind diff --git a/gnovm/tests/files/types/3d0_filetest.gno b/gnovm/tests/files/types/3d0_filetest.gno deleted file mode 100644 index 3744115197e..00000000000 --- a/gnovm/tests/files/types/3d0_filetest.gno +++ /dev/null @@ -1,12 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 * 1) - println(1.0 * 0) -} - -// Output: -// 1 -// 0 diff --git a/gnovm/tests/files/types/3d1_filetest.gno b/gnovm/tests/files/types/3d1_filetest.gno deleted file mode 100644 index b8929345e2b..00000000000 --- a/gnovm/tests/files/types/3d1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println('a' * 'b') -} - -// Output: -// 9506 diff --git a/gnovm/tests/files/types/3d2_filetest.gno b/gnovm/tests/files/types/3d2_filetest.gno deleted file mode 100644 index b45d9d99b4c..00000000000 --- a/gnovm/tests/files/types/3d2_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r rune - -func main() { - r = 'a' - println(r * 'b') -} - -// Output: -// 9506 diff --git a/gnovm/tests/files/types/3d3_filetest.gno b/gnovm/tests/files/types/3d3_filetest.gno deleted file mode 100644 index a24b404a39d..00000000000 --- a/gnovm/tests/files/types/3d3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r1 rune -var r2 rune - -func main() { - r1 = 'a' - r2 = 'b' - println(r1 - r2) -} - -// Output: -// -1 diff --git a/gnovm/tests/files/types/3e0_filetest.gno b/gnovm/tests/files/types/3e0_filetest.gno deleted file mode 100644 index 0916d0acede..00000000000 --- a/gnovm/tests/files/types/3e0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 * e2) -} - -// Error: -// main/files/types/3e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/3f0_stdlibs_filetest.gno b/gnovm/tests/files/types/3f0_stdlibs_filetest.gno deleted file mode 100644 index c58261583aa..00000000000 --- a/gnovm/tests/files/types/3f0_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(1 * errCmp) -} - -// Error: -// main/files/types/3f0_stdlibs_filetest.gno:19: operator * not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/3f1_stdlibs_filetest.gno b/gnovm/tests/files/types/3f1_stdlibs_filetest.gno deleted file mode 100644 index 708571493ac..00000000000 --- a/gnovm/tests/files/types/3f1_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(Error(0) * errCmp) -} - -// Error: -// main/files/types/3f1_stdlibs_filetest.gno:19: operator * not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/3f2_filetest.gno b/gnovm/tests/files/types/3f2_filetest.gno deleted file mode 100644 index 229b7c89479..00000000000 --- a/gnovm/tests/files/types/3f2_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 * e2) -} - -// Error: -// main/files/types/3f2_filetest.gno:27: operator * not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/4a0_QUO_filetest.gno b/gnovm/tests/files/types/4a0_QUO_filetest.gno deleted file mode 100644 index 65cc7d0a438..00000000000 --- a/gnovm/tests/files/types/4a0_QUO_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(1) / int8(1)) -} - -// Error: -// main/files/types/4a0_QUO_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/4a1_filetest.gno b/gnovm/tests/files/types/4a1_filetest.gno deleted file mode 100644 index 44630848b9c..00000000000 --- a/gnovm/tests/files/types/4a1_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - println(Error1(0) / Error2(0)) -} - -// Error: -// main/files/types/4a1_filetest.gno:21: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4b0_filetest.gno b/gnovm/tests/files/types/4b0_filetest.gno deleted file mode 100644 index 00b5091f9f7..00000000000 --- a/gnovm/tests/files/types/4b0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - println(1 / Error(1)) - println(Error(1) / 1) -} - -// Output: -// (1 main.Error) -// (1 main.Error) diff --git a/gnovm/tests/files/types/4b1_filetest.gno b/gnovm/tests/files/types/4b1_filetest.gno deleted file mode 100644 index af2b1839164..00000000000 --- a/gnovm/tests/files/types/4b1_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// one untyped const, one typed const -func main() { - println(1 / Error(1)) - println(Error(1) / 1) -} - -// Output: -// error: 1 -// error: 1 diff --git a/gnovm/tests/files/types/4b2_filetest.gno b/gnovm/tests/files/types/4b2_filetest.gno deleted file mode 100644 index 26568836778..00000000000 --- a/gnovm/tests/files/types/4b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 / "a") -} - -// Error: -// main/files/types/4b2_filetest.gno:5: operator / not defined on: StringKind diff --git a/gnovm/tests/files/types/4b3_filetest.gno b/gnovm/tests/files/types/4b3_filetest.gno deleted file mode 100644 index 2d3ce9b3656..00000000000 --- a/gnovm/tests/files/types/4b3_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("b" / "a") -} - -// Error: -// main/files/types/4b3_filetest.gno:5: operator / not defined on: StringKind diff --git a/gnovm/tests/files/types/4d0_filetest.gno b/gnovm/tests/files/types/4d0_filetest.gno deleted file mode 100644 index fde15376a6a..00000000000 --- a/gnovm/tests/files/types/4d0_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 / 1) - //println(1.0 / 0) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/4d1_filetest.gno b/gnovm/tests/files/types/4d1_filetest.gno deleted file mode 100644 index 3ace2671ecc..00000000000 --- a/gnovm/tests/files/types/4d1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println('a' / 'b') -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/4d2_filetest.gno b/gnovm/tests/files/types/4d2_filetest.gno deleted file mode 100644 index 5098fda2662..00000000000 --- a/gnovm/tests/files/types/4d2_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r rune - -func main() { - r = 'a' - println(r / 'b') -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/4d3_filetest.gno b/gnovm/tests/files/types/4d3_filetest.gno deleted file mode 100644 index 0234f80b846..00000000000 --- a/gnovm/tests/files/types/4d3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r1 rune -var r2 rune - -func main() { - r1 = 'a' - r2 = 'b' - println(r1 / r2) -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/4d4_filetest.gno b/gnovm/tests/files/types/4d4_filetest.gno deleted file mode 100644 index b01f3fb24ce..00000000000 --- a/gnovm/tests/files/types/4d4_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 / 0) -} - -// Error: -// main/files/types/4d4_filetest.gno:6: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4d5_filetest.gno b/gnovm/tests/files/types/4d5_filetest.gno deleted file mode 100644 index ef2140a7abd..00000000000 --- a/gnovm/tests/files/types/4d5_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - a := 1 / 0 - println(a) -} - -// Error: -// main/files/types/4d5_filetest.gno:6: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4d6_filetest.gno b/gnovm/tests/files/types/4d6_filetest.gno deleted file mode 100644 index a6c020b17eb..00000000000 --- a/gnovm/tests/files/types/4d6_filetest.gno +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - a := 1 / 0.0 - println(a) -} - -// Error: -// main/files/types/4d6_filetest.gno:6: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4e01_filetest.gno b/gnovm/tests/files/types/4e01_filetest.gno deleted file mode 100644 index 41f8befcafa..00000000000 --- a/gnovm/tests/files/types/4e01_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error1 = Error1(0) - println(e1 / e2) -} - -// Error: -// runtime error: integer divide by zero diff --git a/gnovm/tests/files/types/4e0_filetest.gno b/gnovm/tests/files/types/4e0_filetest.gno deleted file mode 100644 index ebea41b40a7..00000000000 --- a/gnovm/tests/files/types/4e0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 / e2) -} - -// Error: -// main/files/types/4e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion \ No newline at end of file diff --git a/gnovm/tests/files/types/4f0_filetest.gno b/gnovm/tests/files/types/4f0_filetest.gno deleted file mode 100644 index 7db1773913e..00000000000 --- a/gnovm/tests/files/types/4f0_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - a := 1 - println(a / 0) -} - -// Error: -// main/files/types/4f0_filetest.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/4f0_stdlibs_filetest.gno b/gnovm/tests/files/types/4f0_stdlibs_filetest.gno deleted file mode 100644 index 1ce0906baa9..00000000000 --- a/gnovm/tests/files/types/4f0_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(1 / errCmp) -} - -// Error: -// main/files/types/4f0_stdlibs_filetest.gno:19: operator / not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/4f1_stdlibs_filetest.gno b/gnovm/tests/files/types/4f1_stdlibs_filetest.gno deleted file mode 100644 index 788ab7e312c..00000000000 --- a/gnovm/tests/files/types/4f1_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(Error(0) / errCmp) -} - -// Error: -// main/files/types/4f1_stdlibs_filetest.gno:19: operator / not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/4f2_filetest.gno b/gnovm/tests/files/types/4f2_filetest.gno deleted file mode 100644 index 45f176eca15..00000000000 --- a/gnovm/tests/files/types/4f2_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 / e2) -} - -// Error: -// main/files/types/4f2_filetest.gno:27: operator / not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/5b1_filetest.gno b/gnovm/tests/files/types/5b1_filetest.gno deleted file mode 100644 index 0d8f1d097ee..00000000000 --- a/gnovm/tests/files/types/5b1_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// one untyped const, one typed const -func main() { - println(1 % Error(1)) - println(Error(1) % 1) -} - -// Output: -// error: 0 -// error: 0 diff --git a/gnovm/tests/files/types/5b2_filetest.gno b/gnovm/tests/files/types/5b2_filetest.gno deleted file mode 100644 index 928d24ce205..00000000000 --- a/gnovm/tests/files/types/5b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 % "a") -} - -// Error: -// main/files/types/5b2_filetest.gno:5: operator % not defined on: StringKind diff --git a/gnovm/tests/files/types/5b3_filetest.gno b/gnovm/tests/files/types/5b3_filetest.gno deleted file mode 100644 index 340291d63df..00000000000 --- a/gnovm/tests/files/types/5b3_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("b" % "a") -} - -// Error: -// main/files/types/5b3_filetest.gno:5: operator % not defined on: StringKind diff --git a/gnovm/tests/files/types/5d0_filetest.gno b/gnovm/tests/files/types/5d0_filetest.gno deleted file mode 100644 index 0077e6375e5..00000000000 --- a/gnovm/tests/files/types/5d0_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1.0 % 1) -} - -// Error: -// main/files/types/5d0_filetest.gno:6: operator % not defined on: BigdecKind diff --git a/gnovm/tests/files/types/5d1_filetest.gno b/gnovm/tests/files/types/5d1_filetest.gno deleted file mode 100644 index c05134707fb..00000000000 --- a/gnovm/tests/files/types/5d1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println('a' % 'b') -} - -// Output: -// 97 diff --git a/gnovm/tests/files/types/5d2_filetest.gno b/gnovm/tests/files/types/5d2_filetest.gno deleted file mode 100644 index fdd38eb3001..00000000000 --- a/gnovm/tests/files/types/5d2_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r rune - -func main() { - r = 'a' - println(r % 'b') -} - -// Output: -// 97 diff --git a/gnovm/tests/files/types/5d3_filetest.gno b/gnovm/tests/files/types/5d3_filetest.gno deleted file mode 100644 index 4759fffe865..00000000000 --- a/gnovm/tests/files/types/5d3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r1 rune -var r2 rune - -func main() { - r1 = 'a' - r2 = 'b' - println(r1 % r2) -} - -// Output: -// 97 diff --git a/gnovm/tests/files/types/5d4_filetest.gno b/gnovm/tests/files/types/5d4_filetest.gno deleted file mode 100644 index cc010c97978..00000000000 --- a/gnovm/tests/files/types/5d4_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 % 0) -} - -// Error: -// main/files/types/5d4_filetest.gno:6: operator % not defined on: BigdecKind diff --git a/gnovm/tests/files/types/5e0_filetest.gno b/gnovm/tests/files/types/5e0_filetest.gno deleted file mode 100644 index 3dc5ebc4dd8..00000000000 --- a/gnovm/tests/files/types/5e0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 % e2) -} - -// Error: -// main/files/types/5e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/5f0_stdlibs_filetest.gno b/gnovm/tests/files/types/5f0_stdlibs_filetest.gno deleted file mode 100644 index 8d934bc4d14..00000000000 --- a/gnovm/tests/files/types/5f0_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(1 % errCmp) -} - -// Error: -// main/files/types/5f0_stdlibs_filetest.gno:19: operator % not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/5f1_stdlibs_filetest.gno b/gnovm/tests/files/types/5f1_stdlibs_filetest.gno deleted file mode 100644 index ff841fefaa6..00000000000 --- a/gnovm/tests/files/types/5f1_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(Error(0) % errCmp) -} - -// Error: -// main/files/types/5f1_stdlibs_filetest.gno:19: operator % not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/5f2_filetest.gno b/gnovm/tests/files/types/5f2_filetest.gno deleted file mode 100644 index b982c34ebbd..00000000000 --- a/gnovm/tests/files/types/5f2_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 % e2) -} - -// Error: -// main/files/types/5f2_filetest.gno:27: operator % not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/8a0_XOR_filetest.gno b/gnovm/tests/files/types/8a0_XOR_filetest.gno deleted file mode 100644 index 3fcdbcc18e6..00000000000 --- a/gnovm/tests/files/types/8a0_XOR_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(0) ^ int8(1)) -} - -// Error: -// main/files/types/8a0_XOR_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/8a1_filetest.gno b/gnovm/tests/files/types/8a1_filetest.gno deleted file mode 100644 index c4e63ba9986..00000000000 --- a/gnovm/tests/files/types/8a1_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - println(Error1(0) ^ Error2(0)) -} - -// Error: -// main/files/types/8a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/8b0_filetest.gno b/gnovm/tests/files/types/8b0_filetest.gno deleted file mode 100644 index ef10ee9f93f..00000000000 --- a/gnovm/tests/files/types/8b0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - println(1 ^ Error(1)) - println(Error(1) ^ 1) -} - -// Output: -// (0 main.Error) -// (0 main.Error) diff --git a/gnovm/tests/files/types/8b1_filetest.gno b/gnovm/tests/files/types/8b1_filetest.gno deleted file mode 100644 index 7c192b72ad4..00000000000 --- a/gnovm/tests/files/types/8b1_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// one untyped const, one typed const -func main() { - println(1 ^ Error(1)) - println(Error(1) ^ 1) -} - -// Output: -// error: 0 -// error: 0 diff --git a/gnovm/tests/files/types/8b2_filetest.gno b/gnovm/tests/files/types/8b2_filetest.gno deleted file mode 100644 index f260a4b3078..00000000000 --- a/gnovm/tests/files/types/8b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 ^ "a") -} - -// Error: -// main/files/types/8b2_filetest.gno:5: operator ^ not defined on: StringKind diff --git a/gnovm/tests/files/types/8b3_filetest.gno b/gnovm/tests/files/types/8b3_filetest.gno deleted file mode 100644 index 70c3cb4af6d..00000000000 --- a/gnovm/tests/files/types/8b3_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("b" ^ "a") -} - -// Error: -// main/files/types/8b3_filetest.gno:5: operator ^ not defined on: StringKind diff --git a/gnovm/tests/files/types/8b4_filetest.gno b/gnovm/tests/files/types/8b4_filetest.gno deleted file mode 100644 index a0aaee98542..00000000000 --- a/gnovm/tests/files/types/8b4_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 ^ 'a') -} - -// Output: -// 96 diff --git a/gnovm/tests/files/types/8d0_filetest.gno b/gnovm/tests/files/types/8d0_filetest.gno deleted file mode 100644 index 3b4d4177df7..00000000000 --- a/gnovm/tests/files/types/8d0_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1.0 ^ 1) -} - -// Error: -// main/files/types/8d0_filetest.gno:6: operator ^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/8d1_filetest.gno b/gnovm/tests/files/types/8d1_filetest.gno deleted file mode 100644 index eeb35c7ad3c..00000000000 --- a/gnovm/tests/files/types/8d1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println('a' ^ 'b') -} - -// Output: -// 3 diff --git a/gnovm/tests/files/types/8d2_filetest.gno b/gnovm/tests/files/types/8d2_filetest.gno deleted file mode 100644 index 169cf12aba5..00000000000 --- a/gnovm/tests/files/types/8d2_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r rune - -func main() { - r = 'a' - println(r ^ 'b') -} - -// Output: -// 3 diff --git a/gnovm/tests/files/types/8d3_filetest.gno b/gnovm/tests/files/types/8d3_filetest.gno deleted file mode 100644 index feffa8aca21..00000000000 --- a/gnovm/tests/files/types/8d3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r1 rune -var r2 rune - -func main() { - r1 = 'a' - r2 = 'b' - println(r1 ^ r2) -} - -// Output: -// 3 diff --git a/gnovm/tests/files/types/8d4_filetest.gno b/gnovm/tests/files/types/8d4_filetest.gno deleted file mode 100644 index 4b0e57515ea..00000000000 --- a/gnovm/tests/files/types/8d4_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 ^ 0) -} - -// Error: -// main/files/types/8d4_filetest.gno:6: operator ^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/8e0_filetest.gno b/gnovm/tests/files/types/8e0_filetest.gno deleted file mode 100644 index 393c2d9be3d..00000000000 --- a/gnovm/tests/files/types/8e0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 ^ e2) -} - -// Error: -// main/files/types/8e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/8f0_stdlibs_filetest.gno b/gnovm/tests/files/types/8f0_stdlibs_filetest.gno deleted file mode 100644 index 0a62300b46a..00000000000 --- a/gnovm/tests/files/types/8f0_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(1 ^ errCmp) -} - -// Error: -// main/files/types/8f0_stdlibs_filetest.gno:19: operator ^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/8f1_stdlibs_filetest.gno b/gnovm/tests/files/types/8f1_stdlibs_filetest.gno deleted file mode 100644 index ab19520e10a..00000000000 --- a/gnovm/tests/files/types/8f1_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(Error(0) ^ errCmp) -} - -// Error: -// main/files/types/8f1_stdlibs_filetest.gno:19: operator ^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/8f2_filetest.gno b/gnovm/tests/files/types/8f2_filetest.gno deleted file mode 100644 index 1ee42c37283..00000000000 --- a/gnovm/tests/files/types/8f2_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 ^ e2) -} - -// Error: -// main/files/types/8f2_filetest.gno:27: operator ^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno b/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno deleted file mode 100644 index 8cdb7bae8cd..00000000000 --- a/gnovm/tests/files/types/9a0_ANDNOT_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// both typed(different) const -func main() { - println(int(0) &^ int8(1)) -} - -// Error: -// main/files/types/9a0_ANDNOT_filetest.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/9a1_filetest.gno b/gnovm/tests/files/types/9a1_filetest.gno deleted file mode 100644 index 2a426d60e53..00000000000 --- a/gnovm/tests/files/types/9a1_filetest.gno +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both typed(different) const -func main() { - println(Error1(0) &^ Error2(0)) -} - -// Error: -// main/files/types/9a1_filetest.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/9b0_filetest.gno b/gnovm/tests/files/types/9b0_filetest.gno deleted file mode 100644 index 835aae4de9a..00000000000 --- a/gnovm/tests/files/types/9b0_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -type Error int8 - -// one untyped const, one typed const -func main() { - println(1 &^ Error(1)) - println(Error(1) &^ 1) -} - -// Output: -// (0 main.Error) -// (0 main.Error) diff --git a/gnovm/tests/files/types/9b1_filetest.gno b/gnovm/tests/files/types/9b1_filetest.gno deleted file mode 100644 index caabd382658..00000000000 --- a/gnovm/tests/files/types/9b1_filetest.gno +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error int8 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// one untyped const, one typed const -func main() { - println(1 &^ Error(1)) - println(Error(1) &^ 1) -} - -// Output: -// error: 0 -// error: 0 diff --git a/gnovm/tests/files/types/9b2_filetest.gno b/gnovm/tests/files/types/9b2_filetest.gno deleted file mode 100644 index b1dd347071b..00000000000 --- a/gnovm/tests/files/types/9b2_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 &^ "a") -} - -// Error: -// main/files/types/9b2_filetest.gno:5: operator &^ not defined on: StringKind diff --git a/gnovm/tests/files/types/9b3_filetest.gno b/gnovm/tests/files/types/9b3_filetest.gno deleted file mode 100644 index 65f64da6b25..00000000000 --- a/gnovm/tests/files/types/9b3_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println("b" &^ "a") -} - -// Error: -// main/files/types/9b3_filetest.gno:5: operator &^ not defined on: StringKind diff --git a/gnovm/tests/files/types/9b4_filetest.gno b/gnovm/tests/files/types/9b4_filetest.gno deleted file mode 100644 index 10d4b05e7ab..00000000000 --- a/gnovm/tests/files/types/9b4_filetest.gno +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// one untyped const, one typed const -func main() { - println(1 &^ 'a') -} - -// Output: -// 0 diff --git a/gnovm/tests/files/types/9d0_filetest.gno b/gnovm/tests/files/types/9d0_filetest.gno deleted file mode 100644 index 604252b0f46..00000000000 --- a/gnovm/tests/files/types/9d0_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation, and this should happen in process stage!!! -func main() { - println(1.0 &^ 1) -} - -// Error: -// main/files/types/9d0_filetest.gno:6: operator &^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/9d1_filetest.gno b/gnovm/tests/files/types/9d1_filetest.gno deleted file mode 100644 index cebcd08fb73..00000000000 --- a/gnovm/tests/files/types/9d1_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println('a' &^ 'b') -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/9d2_filetest.gno b/gnovm/tests/files/types/9d2_filetest.gno deleted file mode 100644 index fc38bfcf907..00000000000 --- a/gnovm/tests/files/types/9d2_filetest.gno +++ /dev/null @@ -1,13 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r rune - -func main() { - r = 'a' - println(r &^ 'b') -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/9d3_filetest.gno b/gnovm/tests/files/types/9d3_filetest.gno deleted file mode 100644 index 64f0efc651a..00000000000 --- a/gnovm/tests/files/types/9d3_filetest.gno +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -var r1 rune -var r2 rune - -func main() { - r1 = 'a' - r2 = 'b' - println(r1 &^ r2) -} - -// Output: -// 1 diff --git a/gnovm/tests/files/types/9d4_filetest.gno b/gnovm/tests/files/types/9d4_filetest.gno deleted file mode 100644 index c59d62ef1e2..00000000000 --- a/gnovm/tests/files/types/9d4_filetest.gno +++ /dev/null @@ -1,10 +0,0 @@ -package main - -// both untyped const -// TODO: dec value representation -func main() { - println(1.0 &^ 0) -} - -// Error: -// main/files/types/9d4_filetest.gno:6: operator &^ not defined on: BigdecKind diff --git a/gnovm/tests/files/types/9e0_filetest.gno b/gnovm/tests/files/types/9e0_filetest.gno deleted file mode 100644 index 7f8d83a5f4e..00000000000 --- a/gnovm/tests/files/types/9e0_filetest.gno +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "strconv" -) - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, typed -func main() { - var e1 Error1 = Error1(0) - var e2 Error2 = Error2(0) - println(e1 &^ e2) -} - -// Error: -// main/files/types/9e0_filetest.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/9f0_stdlibs_filetest.gno b/gnovm/tests/files/types/9f0_stdlibs_filetest.gno deleted file mode 100644 index b98b56900e5..00000000000 --- a/gnovm/tests/files/types/9f0_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(1 &^ errCmp) -} - -// Error: -// main/files/types/9f0_stdlibs_filetest.gno:19: operator &^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/9f1_stdlibs_filetest.gno b/gnovm/tests/files/types/9f1_stdlibs_filetest.gno deleted file mode 100644 index 0233a763acb..00000000000 --- a/gnovm/tests/files/types/9f1_stdlibs_filetest.gno +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "errors" - "strconv" -) - -type Error int64 - -func (e Error) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -var errCmp = errors.New("XXXX") - -// specil case: -// one is interface -func main() { - println(Error(0) &^ errCmp) -} - -// Error: -// main/files/types/9f1_stdlibs_filetest.gno:19: operator &^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/9f2_filetest.gno b/gnovm/tests/files/types/9f2_filetest.gno deleted file mode 100644 index aff0e9773cb..00000000000 --- a/gnovm/tests/files/types/9f2_filetest.gno +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "strconv" -) - -type E interface { - Error() string -} - -type Error1 int64 - -func (e Error1) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -type Error2 int - -func (e Error2) Error() string { - return "error: " + strconv.Itoa(int(e)) -} - -// both not const, and both interface -func main() { - var e1 E = Error1(0) - var e2 E = Error2(0) - println(e1 &^ e2) -} - -// Error: -// main/files/types/9f2_filetest.gno:27: operator &^ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/0a5_rune_filetest.gno b/gnovm/tests/files/types/assign_rune.gno similarity index 100% rename from gnovm/tests/files/types/0a5_rune_filetest.gno rename to gnovm/tests/files/types/assign_rune.gno diff --git a/gnovm/tests/files/types/0a6_rune_filetest.gno b/gnovm/tests/files/types/assign_rune_a.gno similarity index 50% rename from gnovm/tests/files/types/0a6_rune_filetest.gno rename to gnovm/tests/files/types/assign_rune_a.gno index 9171d738d07..13321fd8b08 100644 --- a/gnovm/tests/files/types/0a6_rune_filetest.gno +++ b/gnovm/tests/files/types/assign_rune_a.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/types/0a6_rune_filetest.gno:7: cannot use untyped string as Int32Kind +// main/files/types/assign_rune_a.gno:7: cannot use untyped string as Int32Kind From abc16778a4a93aecc85c03953761dc9b1e496489 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Sun, 21 Apr 2024 23:22:17 +0800 Subject: [PATCH 149/193] clean --- gnovm/Makefile | 5 +++-- gnovm/pkg/gnolang/preprocess.go | 13 ++++--------- gnovm/pkg/gnolang/values_conversions.go | 2 +- gnovm/pkg/gnolang/values_string.go | 3 --- gnovm/tests/file.go | 1 - gnovm/tests/file_test.go | 5 +++++ 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/gnovm/Makefile b/gnovm/Makefile index d19067e1c62..1fd16b4f699 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -63,9 +63,10 @@ _test.gnolang.stdlibs.sync:; go test tests/*.go -test.short -run 'TestFiles$$/' # NOTE: challenges are current GnoVM bugs which are supposed to fail. # If any of these tests pass, it should be moved to a normal test. _test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallenges$$/' $(GOTEST_FLAGS) -_test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' --update-golden-tests $(GOTEST_FLAGS) -_test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' --update-golden-tests $(GOTEST_FLAGS) +_test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' $(GOTEST_FLAGS) +_test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' $(GOTEST_FLAGS) +_test.gnolang.debug:; go test tests/*.go -test.short -run 'TestDebug$$/' $(GOTEST_FLAGS) ######################################## # Code gen stringer_cmd=$(rundep) golang.org/x/tools/cmd/stringer diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 1cdd545b8cf..74faa71cde7 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -622,7 +622,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // The main TRANS_LEAVE switch. switch n := n.(type) { // TRANS_LEAVE ----------------------- - case *NameExpr: // e.g. var a int, a is NameExpr + case *NameExpr: // Validity: check that name isn't reserved. if isReservedName(n.Name) { panic(fmt.Sprintf( @@ -750,7 +750,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // check LHS type compatibility n.checkShiftLhs(lt) // checkOrConvert RHS - if baseOf(rt) != UintType { // convert rhs of shift expr to uint + if baseOf(rt) != UintType { // convert n.Right to (gno) uint type, rn := Expr(Call("uint", n.Right)) // reset/create n2 to preprocess right child. @@ -763,20 +763,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return resn, TRANS_CONTINUE } } else { - n.AssertCompatible(lt, rt) + n.AssertCompatible(lt, rt) // check compatibility against binaryExpr other ths shift expr } // General case. lcx, lic := n.Left.(*ConstExpr) rcx, ric := n.Right.(*ConstExpr) if debug { - debug.Printf("---BinaryExpr---, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + debug.Printf("Trans_leave, BinaryExpr, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) } if lic { if ric { // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. - // refer to 0a0_filetest if !isShift { // rhs of shift expr has already been converted to uint cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { @@ -1624,7 +1623,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if len(n.Lhs) > len(n.Rhs) { // check is done in assertCompatible } else { - debug.Println("---assignStmt, assign") if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { if len(n.Lhs) != 1 || len(n.Rhs) != 1 { panic("should not happen") @@ -2354,9 +2352,6 @@ func convertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) convertConst(store, last, cx, t) } else if *x != nil { xt := evalStaticTypeOf(store, last, *x) - if debug { - debug.Printf("else expr, xt not nil,x: %v, xt: %v, t: %v, isUntyped: %v \n", *x, xt, t, isUntyped(xt)) - } if isUntyped(xt) { if t == nil { t = defaultTypeOf(xt) diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index d99f5417d34..30783b340c0 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -882,7 +882,7 @@ GNO_CASE: func ConvertUntypedTo(tv *TypedValue, t Type) { if debug { defer func() { - debug.Printf("---after ConvertUntypedTo---, tv:%v \n", tv) + debug.Printf("ConvertUntypedTo done, tv: %v \n", tv) }() } if debug { diff --git a/gnovm/pkg/gnolang/values_string.go b/gnovm/pkg/gnolang/values_string.go index dc1dcda9cc0..b64b491cbb8 100644 --- a/gnovm/pkg/gnolang/values_string.go +++ b/gnovm/pkg/gnolang/values_string.go @@ -266,9 +266,6 @@ func (tv *TypedValue) Sprint(m *Machine) string { } func printNilOrValue(tv *TypedValue, valueType interface{}) string { - if debug { - debug.Printf("printNilOrValue: tv: %v, T:%v, V:%v \n", *tv, (*tv).T, (*tv).V) - } if tv.V == nil { return nilStr + " " + tv.T.String() } diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index e44dd87e579..a0e133cae9e 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -422,7 +422,6 @@ func readComments(cg *ast.CommentGroup) string { // Replace comment in file with given output given directive. func replaceWantedInPlace(path string, directive string, output string) { - fmt.Println("---replace...: ", directive, output) bz := osm.MustReadFile(path) body := string(bz) lines := strings.Split(body, "\n") diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index 4d8c4176f8d..c1a4ac0a876 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -42,6 +42,11 @@ func TestTypes(t *testing.T) { runFileTests(t, baseDir, []string{"*_native*"}) } +func TestDebug(t *testing.T) { + baseDir := filepath.Join(".", "debug") + runFileTests(t, baseDir, []string{"*_native*"}) +} + func TestTypesNative(t *testing.T) { baseDir := filepath.Join(".", "files/types") runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) From 3c3d939ceaabcb12281d3f47ee7993b40b3eb981 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 22 Apr 2024 11:44:02 +0800 Subject: [PATCH 150/193] simplify binary type check --- gnovm/Makefile | 1 - gnovm/pkg/gnolang/preprocess.go | 163 +++++++++++------------- gnovm/pkg/gnolang/type_check.go | 11 +- gnovm/tests/files/types/0a1g_.gno | 10 ++ gnovm/tests/files/types/time_native.gno | 13 ++ 5 files changed, 102 insertions(+), 96 deletions(-) create mode 100644 gnovm/tests/files/types/0a1g_.gno create mode 100644 gnovm/tests/files/types/time_native.gno diff --git a/gnovm/Makefile b/gnovm/Makefile index 1fd16b4f699..a5906ad95e0 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -66,7 +66,6 @@ _test.gnolang.challenges:; go test tests/*.go -test.short -run 'TestChallen _test.gnolang.types:; go test tests/*.go -test.short -run 'TestTypes$$/' $(GOTEST_FLAGS) _test.gnolang.types.native:; go test tests/*.go -test.short -run 'TestTypesNative$$/' $(GOTEST_FLAGS) -_test.gnolang.debug:; go test tests/*.go -test.short -run 'TestDebug$$/' $(GOTEST_FLAGS) ######################################## # Code gen stringer_cmd=$(rundep) golang.org/x/tools/cmd/stringer diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 74faa71cde7..f5249e7a054 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -743,9 +743,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { lt := evalStaticTypeOf(store, last, n.Left) rt := evalStaticTypeOf(store, last, n.Right) + lcx, lic := n.Left.(*ConstExpr) + rcx, ric := n.Right.(*ConstExpr) + + if debug { + debug.Printf("Trans_leave, BinaryExpr, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) + } + // Special (recursive) case if shift and right isn't uint. isShift := n.Op == SHL || n.Op == SHR - // special case of shift if isShift { // check LHS type compatibility n.checkShiftLhs(lt) @@ -762,21 +768,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { resn := Preprocess(store, last, n2) return resn, TRANS_CONTINUE } + // Then, evaluate the expression. + if lic && ric { + cx := evalConst(store, last, n) + return cx, TRANS_CONTINUE + } + return n, TRANS_CONTINUE } else { n.AssertCompatible(lt, rt) // check compatibility against binaryExpr other ths shift expr - } - // General case. - lcx, lic := n.Left.(*ConstExpr) - rcx, ric := n.Right.(*ConstExpr) - if debug { - debug.Printf("Trans_leave, BinaryExpr, OP: %v, lx: %v, rx: %v, lt: %v, rt: %v, isLeftConstExpr: %v, isRightConstExpr %v, isLeftUntyped: %v, isRightUntyped: %v \n", n.Op, n.Left, n.Right, lt, rt, lic, ric, isUntyped(lt), isUntyped(rt)) - } - if lic { - if ric { - // Left const, Right const ---------------------- - // Replace with *ConstExpr if const operands. - // First, convert untyped as necessary. - if !isShift { // rhs of shift expr has already been converted to uint + // General case. + if lic { + if ric { + // Left const, Right const ---------------------- + // Replace with *ConstExpr if const operands. + // First, convert untyped as necessary. cmp := cmpSpecificity(lcx.T, rcx.T) if cmp < 0 { // convert n.Left to right type. @@ -787,64 +792,56 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // convert n.Right to left type. checkOrConvertType(store, last, &n.Right, lcx.T, false) } - } - // Then, evaluate the expression. - cx := evalConst(store, last, n) - return cx, TRANS_CONTINUE - } else if isUntyped(lcx.T) { // left untyped const -> right not const - if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native), e.g. 1*time.Second - if isShift { // RHS of shift should not be native - panic("should not happen") - } - // get concrete native base type. - pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) - if !ok { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - lt.String(), - rnt.String())) - } - // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, false) - // if check pass, convert n.Right to (gno) pt type, - rn := Expr(Call(pt.String(), n.Right)) - // and convert result back. - tx := constType(n, rnt) - // reset/create n2 to preprocess right child. - n2 := &BinaryExpr{ - Left: n.Left, - Op: n.Op, - Right: rn, - } - resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} - resn = Preprocess(store, last, resn) - return resn, TRANS_CONTINUE - // NOTE: binary operations are always computed in - // gno, never with reflect. - } else { - if !isShift { + // Then, evaluate the expression. + cx := evalConst(store, last, n) + return cx, TRANS_CONTINUE + } else if isUntyped(lcx.T) { // left untyped const -> right not const + if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native), e.g. 1*time.Second + if isShift { // RHS of shift should not be native + panic("should not happen") + } + // get concrete native base type. + pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + lt.String(), + rnt.String())) + } + // convert n.Left to pt type, + checkOrConvertType(store, last, &n.Left, pt, false) + // if check pass, convert n.Right to (gno) pt type, + rn := Expr(Call(pt.String(), n.Right)) + // and convert result back. + tx := constType(n, rnt) + // reset/create n2 to preprocess right child. + n2 := &BinaryExpr{ + Left: n.Left, + Op: n.Op, + Right: rn, + } + resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} + resn = Preprocess(store, last, resn) + return resn, TRANS_CONTINUE + // NOTE: binary operations are always computed in + // gno, never with reflect. + } else { // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rt, false) } - } - } else if lcx.T == nil { // LHS is nil. XXX, should this be located in isUntyped? - if !isShift { + } else if lcx.T == nil { // LHS is nil. // convert n.Left to typed-nil type. checkOrConvertType(store, last, &n.Left, rt, false) - } - } else { // left is typed const, right not const - if !isShift { // rhs of shift expr has already been converted to uint + } else { // left is typed const, right not const if isUntyped(rt) { // e.g. int(1) + 1< float64. // (const) untyped bigint -> int. convertConst(store, last, arg0, nil) @@ -1061,7 +1048,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Handle special cases. // NOTE: these appear to be actually special cases in go. - // In general, a string is not checkAssignableTo to []bytes + // In general, a string is not assignableTo to []bytes // without conversion. if cx, ok := n.Func.(*ConstExpr); ok { fv := cx.GetFunc() @@ -1266,7 +1253,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: xt := evalStaticTypeOf(store, last, n.X) - n.AssertCompatible(xt, nil) + n.AssertCompatible(xt) if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index daf9d8f75ff..8e1a99fded9 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -602,19 +602,16 @@ func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, } } -func (ux *UnaryExpr) AssertCompatible(xt, dt Type) { - if nt, ok := xt.(*NativeType); ok { +func (ux *UnaryExpr) AssertCompatible(t Type) { + if nt, ok := t.(*NativeType); ok { if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { return } } // check compatible if checker, ok := unaryChecker[ux.Op]; ok { - if dt == nil { - dt = xt - } - if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", ux.Op.TokenString(), kindString(dt))) + if !checker(t) { + panic(fmt.Sprintf("operator %s not defined on: %v", ux.Op.TokenString(), kindString(t))) } } else { panic(fmt.Sprintf("checker for %s does not exist", ux.Op)) diff --git a/gnovm/tests/files/types/0a1g_.gno b/gnovm/tests/files/types/0a1g_.gno new file mode 100644 index 00000000000..3cb934b5653 --- /dev/null +++ b/gnovm/tests/files/types/0a1g_.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var a int = 1 + var b float32 = 1.0 + println(a == b) // both typed +} + +// Error: +// main/files/types/0a1g_.gno:6: cannot use int as float32 diff --git a/gnovm/tests/files/types/time_native.gno b/gnovm/tests/files/types/time_native.gno new file mode 100644 index 00000000000..ef1c3daaf44 --- /dev/null +++ b/gnovm/tests/files/types/time_native.gno @@ -0,0 +1,13 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + fmt.Println(time.Second + time.Second) +} + +// Output: +// 2s From f6764d93eee767f917f1a8e7b8b7af485f3263c4 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 22 Apr 2024 11:45:27 +0800 Subject: [PATCH 151/193] clear --- gnovm/tests/file_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gnovm/tests/file_test.go b/gnovm/tests/file_test.go index c1a4ac0a876..4d8c4176f8d 100644 --- a/gnovm/tests/file_test.go +++ b/gnovm/tests/file_test.go @@ -42,11 +42,6 @@ func TestTypes(t *testing.T) { runFileTests(t, baseDir, []string{"*_native*"}) } -func TestDebug(t *testing.T) { - baseDir := filepath.Join(".", "debug") - runFileTests(t, baseDir, []string{"*_native*"}) -} - func TestTypesNative(t *testing.T) { baseDir := filepath.Join(".", "files/types") runFileTests(t, baseDir, []string{"*_stdlibs*"}, WithNativeLibs()) From 986d8ec2a0963e2ab198d2f9488227798174a1c2 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 22 Apr 2024 17:17:32 +0800 Subject: [PATCH 152/193] fixup --- gnovm/pkg/gnolang/gonative.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 28 ++++++------- gnovm/pkg/gnolang/type_check.go | 40 ++++++++++--------- gnovm/pkg/gnolang/types.go | 6 +-- gnovm/tests/files/types/13a_01.gno | 12 ++++++ .../files/types/13f2_stdlibs_filetest.gno | 22 +--------- 6 files changed, 50 insertions(+), 60 deletions(-) create mode 100644 gnovm/tests/files/types/13a_01.gno diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index b34ffc86c05..583c697c56f 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -901,7 +901,7 @@ func gno2GoType(t Type) reflect.Type { // If gno2GoTypeMatches(t, rt) is true, a t value can // be converted to an rt native value using gno2GoValue(v, rv). -// This is called when autoNative is true in checkAssignableTo(). +// This is called when autoNative is true in assertAssignableTo(). // This is used for all native function calls, and also // for testing whether a native value implements a gno interface. func gno2GoTypeMatches(t Type, rt reflect.Type) (result bool) { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index f5249e7a054..48fc638ce4c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -910,7 +910,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // check assignable, if pass, convert right to gno first // XXX, can we just check on native type? - checkAssignableTo(lpt, rpt, false) // both primitive types + assertAssignableTo(lpt, rpt, false) // both primitive types rn = Expr(Call(rpt.String(), n.Right)) // checkOrCovertType should happen in future when both sides to be gno'd } else { // rt not native @@ -986,7 +986,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { checkOrConvertType(store, last, &n.Left, rt, false) } else if cmp == 1 { checkOrConvertType(store, last, &n.Right, lt, false) - } else { // cmp 0, both typed, checkAssignableTo + } else { // cmp 0, both typed, assertAssignableTo checkOrConvertType(store, last, &n.Left, rt, false) } } @@ -1048,7 +1048,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Handle special cases. // NOTE: these appear to be actually special cases in go. - // In general, a string is not assignableTo to []bytes + // In general, a string is not assignable to []bytes // without conversion. if cx, ok := n.Func.(*ConstExpr); ok { fv := cx.GetFunc() @@ -1177,16 +1177,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { for i, tv := range argTVs { if hasVarg { if (len(spts) - 1) <= i { - checkAssignableTo(tv.T, spts[len(spts)-1].Type.Elem(), true) + assertAssignableTo(tv.T, spts[len(spts)-1].Type.Elem(), true) } else { - checkAssignableTo(tv.T, spts[i].Type, true) + assertAssignableTo(tv.T, spts[i].Type, true) } } else { - checkAssignableTo(tv.T, spts[i].Type, true) + assertAssignableTo(tv.T, spts[i].Type, true) } } } else { - for i := range n.Args { // iterate args + for i := range n.Args { if hasVarg { if (len(spts) - 1) <= i { if isVarg { @@ -1301,13 +1301,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } case *ArrayType: for i := 0; i < len(n.Elts); i++ { - // bypass check as a special case convertType(store, last, &n.Elts[i].Key, IntType, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { - // bypass check as a special case convertType(store, last, &n.Elts[i].Key, IntType, false) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } @@ -1549,9 +1547,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *AssignStmt: + n.AssertCompatible(store, last) // NOTE: keep DEFINE and ASSIGN in sync. if n.Op == DEFINE { - n.AssertCompatible(store, last) // Rhs consts become default *ConstExprs. for _, rx := range n.Rhs { // NOTE: does nothing if rx is "nil". @@ -1606,19 +1604,17 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } else { // ASSIGN. // NOTE: Keep in sync with DEFINE above. - n.AssertCompatible(store, last) if len(n.Lhs) > len(n.Rhs) { // check is done in assertCompatible - } else { + } else { // len(Lhs) == len(Rhs) if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { if len(n.Lhs) != 1 || len(n.Rhs) != 1 { panic("should not happen") } // Special case if shift assign <<= or >>=. - convertType(store, last, &n.Rhs[0], UintType, false) // bypass check + convertType(store, last, &n.Rhs[0], UintType, false) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { // e.g. a += b, single value for lhs and rhs, - // TODO: assert length lt := evalStaticTypeOf(store, last, n.Lhs[0]) checkOrConvertType(store, last, &n.Rhs[0], lt, true) } else { // all else, like BAND_ASSIGN, etc @@ -2311,7 +2307,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if cx, ok := (*x).(*ConstExpr); ok { if _, ok := t.(*NativeType); !ok { // not native type, refer to time4_native.gno. // e.g. int(1) == int8(1) - checkAssignableTo(cx.T, t, autoNative) // refer to 22a17a + assertAssignableTo(cx.T, t, autoNative) } } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { // "push" expected type into shift binary's left operand. recursively. @@ -2319,7 +2315,7 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative } else if *x != nil { // XXX if x != nil && t != nil { xt := evalStaticTypeOf(store, last, *x) if t != nil { - checkAssignableTo(xt, t, autoNative) + assertAssignableTo(xt, t, autoNative) } } convertType(store, last, x, t, autoNative) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 8e1a99fded9..cee48ed8279 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -211,8 +211,8 @@ func maybeNil(t Type) bool { } } -func checkAssignableTo(xt, dt Type, autoNative bool) { - err := tryCheckAssignableTo(xt, dt, autoNative) +func assertAssignableTo(xt, dt Type, autoNative bool) { + err := checkAssignableTo(xt, dt, autoNative) if err != nil { panic(err.Error()) } @@ -221,9 +221,9 @@ func checkAssignableTo(xt, dt Type, autoNative bool) { // Assert that xt can be assigned as dt (dest type). // If autoNative is true, a broad range of xt can match against // a target native dt type, if and only if dt is a native type. -func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { +func checkAssignableTo(xt, dt Type, autoNative bool) error { if debug { - debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) + debug.Printf("assertAssignableTo, xt: %v dt: %v \n", xt, dt) } // case0 if xt == nil { // see test/files/types/0f18 @@ -439,7 +439,7 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - checkAssignableTo(pt.Elt, cdt.Elt, false) + assertAssignableTo(pt.Elt, cdt.Elt, false) } return nil case *ArrayType: @@ -450,18 +450,18 @@ func tryCheckAssignableTo(xt, dt Type, autoNative bool) error { at.String(), cdt.String()) } - checkAssignableTo(at.Elt, cdt.Elt, false) + assertAssignableTo(at.Elt, cdt.Elt, false) return nil } case *SliceType: if st, ok := xt.(*SliceType); ok { - checkAssignableTo(st.Elt, cdt.Elt, false) + assertAssignableTo(st.Elt, cdt.Elt, false) return nil } case *MapType: if mt, ok := xt.(*MapType); ok { - checkAssignableTo(mt.Key, cdt.Key, false) - checkAssignableTo(mt.Value, cdt.Value, false) + assertAssignableTo(mt.Key, cdt.Key, false) + assertAssignableTo(mt.Value, cdt.Value, false) return nil } case *FuncType: @@ -595,7 +595,7 @@ func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, // e.g. 1%1e9 if !checker(xt) { - err := tryCheckAssignableTo(xt, dt, false) // XXX, cache this? + err := checkAssignableTo(xt, dt, false) // XXX, cache this? if err != nil { panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, kindString(xt))) } @@ -644,18 +644,18 @@ func (rs *RangeStmt) AssertCompatible(store Store, last BlockNode) { xt := evalStaticTypeOf(store, last, rs.X) switch cxt := xt.(type) { case *MapType: - checkAssignableTo(cxt.Key, kt, false) - checkAssignableTo(cxt.Value, vt, false) + assertAssignableTo(cxt.Key, kt, false) + assertAssignableTo(cxt.Value, vt, false) case *SliceType: if kt.Kind() != IntKind { panic(fmt.Sprintf("index type should be int, but got %v", kt)) } - checkAssignableTo(cxt.Elt, vt, false) + assertAssignableTo(cxt.Elt, vt, false) case *ArrayType: if kt.Kind() != IntKind { panic(fmt.Sprintf("index type should be int, but got %v", kt)) } - checkAssignableTo(cxt.Elt, vt, false) + assertAssignableTo(cxt.Elt, vt, false) case PrimitiveType: if cxt.Kind() == StringKind { if kt != nil && kt.Kind() != IntKind { @@ -693,7 +693,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { for i, lx := range as.Lhs { if !isBlankIdentifier(lx) { // see composite3.gno lxt := evalStaticTypeOf(store, last, lx) - checkAssignableTo(cft.Results[i].Type, lxt, false) + assertAssignableTo(cft.Results[i].Type, lxt, false) } } } @@ -707,7 +707,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if !isBlankIdentifier(as.Lhs[0]) { // see composite3.gno dt := evalStaticTypeOf(store, last, as.Lhs[0]) ift := evalStaticTypeOf(store, last, cx) - checkAssignableTo(ift, dt, false) + assertAssignableTo(ift, dt, false) } if !isBlankIdentifier(as.Lhs[1]) { // see composite3.gno dt := evalStaticTypeOf(store, last, as.Lhs[1]) @@ -728,12 +728,12 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if nx, ok := cx.X.(*NameExpr); ok { rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() if mt, ok := rx.T.(*MapType); ok { - checkAssignableTo(mt.Value, lt, false) + assertAssignableTo(mt.Value, lt, false) } } else if _, ok := cx.X.(*CompositeLitExpr); ok { cpt := evalStaticTypeOf(store, last, cx.X) if mt, ok := cpt.(*MapType); ok { - checkAssignableTo(mt.Value, lt, false) + assertAssignableTo(mt.Value, lt, false) } else { panic("should not happen") } @@ -794,7 +794,9 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } else { // else op other than assign and define - // TODO: check length of expression + if len(as.Lhs) != 1 || len(as.Rhs) != 1 { + panic("length of lhs and rhs should not > 1") + } for i, lx := range as.Lhs { lt := evalStaticTypeOf(store, last, lx) rt := evalStaticTypeOf(store, last, as.Rhs[i]) diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 48d3d8574d4..6ec60919806 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -2228,7 +2228,7 @@ func fillEmbeddedName(ft *FieldType) { ft.Embedded = true } -// TODO: empty interface? refer to checkAssignableTo +// TODO: empty interface? refer to assertAssignableTo func IsImplementedBy(it Type, ot Type) bool { switch cbt := baseOf(it).(type) { case *InterfaceType: @@ -2363,7 +2363,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy generic := ct.Generic[:len(ct.Generic)-len(".Elem()")] match, ok := lookup[generic] if ok { - checkAssignableTo(spec, match.Elem(), false) + assertAssignableTo(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -2377,7 +2377,7 @@ func specifyType(store Store, lookup map[Name]Type, tmpl Type, spec Type, specTy } else { match, ok := lookup[ct.Generic] if ok { - checkAssignableTo(spec, match, false) + assertAssignableTo(spec, match, false) return // ok } else { if isUntyped(spec) { diff --git a/gnovm/tests/files/types/13a_01.gno b/gnovm/tests/files/types/13a_01.gno new file mode 100644 index 00000000000..1ebb43cdad1 --- /dev/null +++ b/gnovm/tests/files/types/13a_01.gno @@ -0,0 +1,12 @@ +package main + +func main() { + a := 1 + b := 1 + a, b += 1, 1 + println(a) + println(b) +} + +// Error: +// main/files/types/13a_01.gno:6: length of lhs and rhs should not > 1 diff --git a/gnovm/tests/files/types/13f2_stdlibs_filetest.gno b/gnovm/tests/files/types/13f2_stdlibs_filetest.gno index 765aa172456..8d7f38b2311 100644 --- a/gnovm/tests/files/types/13f2_stdlibs_filetest.gno +++ b/gnovm/tests/files/types/13f2_stdlibs_filetest.gno @@ -13,26 +13,6 @@ func (e Error) Error() string { var errCmp = errors.New("XXXX") -// NOTE: in golang, this won't compile by type mismatch -// code like this : won't compile by : "invalid operation: operator + not defined on err1 (variable of type error)" -// which indicates that golang will check type match first, and operand legality secondly -// that is, for op =+, first check type match, second check operand -// in our condition, should check convert first, after that, check operand? - -//package main -// -//import ( -//"errors" -//) -// -//var err1 = errors.New("XXXX") -//var err2 = errors.New("XXXX") -// -//func main() { -// err1 += err2 -// println(err1) -//} - // specil case: // one is interface func main() { @@ -42,4 +22,4 @@ func main() { } // Error: -// main/files/types/13f2_stdlibs_filetest.gno:40: operator += not defined on: InterfaceKind +// main/files/types/13f2_stdlibs_filetest.gno:20: operator += not defined on: InterfaceKind From 97f46cd36865b920272c0bd71e8a4d8e1ba0345e Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 22 Apr 2024 17:50:57 +0800 Subject: [PATCH 153/193] fixup --- gnovm/pkg/gnolang/type_check.go | 50 +++++---------------------------- 1 file changed, 7 insertions(+), 43 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index cee48ed8279..fc1a8c54fc4 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -691,7 +691,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if as.Op == ASSIGN { // check assignable for i, lx := range as.Lhs { - if !isBlankIdentifier(lx) { // see composite3.gno + if !isBlankIdentifier(lx) { lxt := evalStaticTypeOf(store, last, lx) assertAssignableTo(cft.Results[i].Type, lxt, false) } @@ -722,12 +722,11 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } if as.Op == ASSIGN { - // check first value if !isBlankIdentifier(as.Lhs[0]) { lt := evalStaticTypeOf(store, last, as.Lhs[0]) - if nx, ok := cx.X.(*NameExpr); ok { - rx := last.GetStaticBlock().GetBlock().GetPointerTo(store, nx.Path).Deref() - if mt, ok := rx.T.(*MapType); ok { + if _, ok := cx.X.(*NameExpr); ok { + rt := evalStaticTypeOf(store, last, cx.X) + if mt, ok := rt.(*MapType); ok { assertAssignableTo(mt.Value, lt, false) } } else if _, ok := cx.X.(*CompositeLitExpr); ok { @@ -752,17 +751,8 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } else { // len(Lhs) == len(Rhs) if as.Op == ASSIGN { - // check lhs - for i, lx := range as.Lhs { - rt := evalStaticTypeOf(store, last, as.Rhs[i]) - - // check native cases - if rnt, ok := rt.(*NativeType); ok { - if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { - return - } - } - + // assert valid left value + for _, lx := range as.Lhs { shouldPanic := true switch clx := lx.(type) { case *NameExpr, *StarExpr, *SelectorExpr: @@ -776,24 +766,9 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic(fmt.Sprintf("cannot assign to %v", lx)) } } - } else { // define - // NOTE: this is already checked while parsing file - for i, lx := range as.Lhs { - rt := evalStaticTypeOf(store, last, as.Rhs[i]) - if rnt, ok := rt.(*NativeType); ok { - if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { - return - } - } - switch lx.(type) { - case *NameExpr: - default: - panic(fmt.Sprintf("non-name %v on left side of :=", lx)) - } - } } } - } else { // else op other than assign and define + } else { // Ops other than assign and define if len(as.Lhs) != 1 || len(as.Rhs) != 1 { panic("length of lhs and rhs should not > 1") } @@ -801,17 +776,6 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { lt := evalStaticTypeOf(store, last, lx) rt := evalStaticTypeOf(store, last, as.Rhs[i]) - if lnt, ok := lt.(*NativeType); ok { - if _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType); ok { - return - } - } - if rnt, ok := rt.(*NativeType); ok { - if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { - return - } - } - if checker, ok := AssignStmtChecker[as.Op]; ok { if !checker(lt) { panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, kindString(lt))) From 1819db745efcacdef3f4128d3c197304e0a95545 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 22 Apr 2024 18:06:16 +0800 Subject: [PATCH 154/193] assert valie left value --- gnovm/pkg/gnolang/type_check.go | 32 ++++++++++++--------- gnovm/tests/files/types/assign_range_a1.gno | 22 ++++++++++++++ 2 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 gnovm/tests/files/types/assign_range_a1.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index fc1a8c54fc4..a2e2f03dec1 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -8,7 +8,7 @@ import ( // here are a range of rules predefined for preprocessor to check the compatibility between operands and operators // e,g. for binary expr x + y, x, y can only be numeric or string, 1+2, "a" + "b" -// this is used in checkOperandWithOp(). +// this is used in assertCompatible()s. var ( binaryChecker = map[Word]func(t Type) bool{ ADD: isNumericOrString, @@ -639,6 +639,8 @@ func (rs *RangeStmt) AssertCompatible(store Store, last BlockNode) { if isBlankIdentifier(rs.Key) && isBlankIdentifier(rs.Value) { // both "_" } else { + assertValidLeftValue(store, last, rs.Key) + // if is valid left value kt := evalStaticTypeOf(store, last, rs.Key) vt := evalStaticTypeOf(store, last, rs.Value) xt := evalStaticTypeOf(store, last, rs.X) @@ -753,18 +755,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { if as.Op == ASSIGN { // assert valid left value for _, lx := range as.Lhs { - shouldPanic := true - switch clx := lx.(type) { - case *NameExpr, *StarExpr, *SelectorExpr: - shouldPanic = false - case *IndexExpr: - xt := evalStaticTypeOf(store, last, clx.X) - shouldPanic = xt != nil && xt.Kind() == StringKind - default: - } - if shouldPanic { - panic(fmt.Sprintf("cannot assign to %v", lx)) - } + assertValidLeftValue(store, last, lx) } } } @@ -801,6 +792,21 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } // misc +func assertValidLeftValue(store Store, last BlockNode, lx Expr) { + shouldPanic := true + switch clx := lx.(type) { + case *NameExpr, *StarExpr, *SelectorExpr: + shouldPanic = false + case *IndexExpr: + xt := evalStaticTypeOf(store, last, clx.X) + shouldPanic = xt != nil && xt.Kind() == StringKind + default: + } + if shouldPanic { + panic(fmt.Sprintf("cannot assign to %v", lx)) + } +} + func kindString(xt Type) string { if xt != nil { return xt.Kind().String() diff --git a/gnovm/tests/files/types/assign_range_a1.gno b/gnovm/tests/files/types/assign_range_a1.gno new file mode 100644 index 00000000000..4e6ede4ffda --- /dev/null +++ b/gnovm/tests/files/types/assign_range_a1.gno @@ -0,0 +1,22 @@ +package main + +import "fmt" + +func main() { + // Creating a map where keys are strings and values are integers + scores := map[string]int{ + "Alice": 92, + "Bob": 89, + "Charlie": 95, + } + + // Using range to iterate over the map + // k is the key and v is the value for each pair in the map + var v int + for 6, v = range scores { + fmt.Printf("%s has a score of %d\n", "a", v) + } +} + +// Error: +// main/files/types/assign_range_a1.gno:16: cannot assign to (const (6 bigint)) From a16747840a5d16f58ef2cd1f4d79c88640f4e008 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 25 Apr 2024 20:26:09 +0800 Subject: [PATCH 155/193] fix linter --- gnovm/pkg/gnolang/type_check.go | 128 ++++++++++++++++---------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 1df580fcd56..e70de60848b 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -509,17 +509,17 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { } // =========================================================== -func (bx *BinaryExpr) checkShiftLhs(dt Type) { +func (x *BinaryExpr) checkShiftLhs(dt Type) { var destKind interface{} if dt != nil { destKind = dt.Kind() } - if checker, ok := binaryChecker[bx.Op]; ok { + if checker, ok := binaryChecker[x.Op]; ok { if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", bx.Op.TokenString(), destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), destKind)) } } else { - panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } } @@ -528,7 +528,7 @@ func (bx *BinaryExpr) checkShiftLhs(dt Type) { // e.g. "a" << 1, the left hand operand is not compatible with <<, it will fail the check. // Overall,it efficiently filters out incompatible expressions, stopping before the next // checkOrConvertType() operation to optimize performance. -func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { +func (x *BinaryExpr) AssertCompatible(lt, rt Type) { // native type will be converted to gno in latter logic, // this check logic will be conduct again if lnt, ok := lt.(*NativeType); ok { @@ -544,7 +544,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } - OpStr := bx.Op.TokenString() + OpStr := x.Op.TokenString() xt, dt := lt, rt cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion @@ -552,31 +552,31 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { xt, dt = dt, xt } - if isComparison(bx.Op) { - switch bx.Op { + if isComparison(x.Op) { + switch x.Op { case EQL, NEQ: assertComparable(xt, dt) case LSS, LEQ, GTR, GEQ: - if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(xt, dt, checker, OpStr) + if checker, ok := binaryChecker[x.Op]; ok { + x.checkCompatibility(xt, dt, checker, OpStr) } else { - panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } default: panic("invalid comparison operator") } } else { - if checker, ok := binaryChecker[bx.Op]; ok { - bx.checkCompatibility(xt, dt, checker, OpStr) + if checker, ok := binaryChecker[x.Op]; ok { + x.checkCompatibility(xt, dt, checker, OpStr) } else { - panic(fmt.Sprintf("checker for %s does not exist", bx.Op)) + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } - switch bx.Op { + switch x.Op { case QUO, REM: // special case of zero divisor - if isQuoOrRem(bx.Op) { - if rcx, ok := bx.Right.(*ConstExpr); ok { + if isQuoOrRem(x.Op) { + if rcx, ok := x.Right.(*ConstExpr); ok { if rcx.TypedValue.isZero() { panic("invalid operation: division by zero") } @@ -588,7 +588,7 @@ func (bx *BinaryExpr) AssertCompatible(lt, rt Type) { } } -func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, OpStr string) { +func (x *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, OpStr string) { if !checker(dt) { panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, kindString(dt))) } @@ -602,48 +602,48 @@ func (bx *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, } } -func (ux *UnaryExpr) AssertCompatible(t Type) { +func (x *UnaryExpr) AssertCompatible(t Type) { if nt, ok := t.(*NativeType); ok { if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { return } } // check compatible - if checker, ok := unaryChecker[ux.Op]; ok { + if checker, ok := unaryChecker[x.Op]; ok { if !checker(t) { - panic(fmt.Sprintf("operator %s not defined on: %v", ux.Op.TokenString(), kindString(t))) + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(t))) } } else { - panic(fmt.Sprintf("checker for %s does not exist", ux.Op)) + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } } -func (idst *IncDecStmt) AssertCompatible(t Type) { +func (x *IncDecStmt) AssertCompatible(t Type) { if nt, ok := t.(*NativeType); ok { if _, ok := go2GnoBaseType(nt.Type).(PrimitiveType); ok { return } } // check compatible - if checker, ok := IncDecStmtChecker[idst.Op]; ok { + if checker, ok := IncDecStmtChecker[x.Op]; ok { if !checker(t) { - panic(fmt.Sprintf("operator %s not defined on: %v", idst.Op.TokenString(), kindString(t))) + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(t))) } } else { - panic(fmt.Sprintf("checker for %s does not exist", idst.Op)) + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } } -func (rs *RangeStmt) AssertCompatible(store Store, last BlockNode) { - if rs.Op == ASSIGN { - if isBlankIdentifier(rs.Key) && isBlankIdentifier(rs.Value) { +func (x *RangeStmt) AssertCompatible(store Store, last BlockNode) { + if x.Op == ASSIGN { + if isBlankIdentifier(x.Key) && isBlankIdentifier(x.Value) { // both "_" } else { - assertValidLeftValue(store, last, rs.Key) + assertValidLeftValue(store, last, x.Key) // if is valid left value - kt := evalStaticTypeOf(store, last, rs.Key) - vt := evalStaticTypeOf(store, last, rs.Value) - xt := evalStaticTypeOf(store, last, rs.X) + kt := evalStaticTypeOf(store, last, x.Key) + vt := evalStaticTypeOf(store, last, x.Value) + xt := evalStaticTypeOf(store, last, x.X) switch cxt := xt.(type) { case *MapType: assertAssignableTo(cxt.Key, kt, false) @@ -672,27 +672,27 @@ func (rs *RangeStmt) AssertCompatible(store Store, last BlockNode) { } } -func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { - Opstr := as.Op.TokenString() - if as.Op == ASSIGN || as.Op == DEFINE { - if len(as.Lhs) > len(as.Rhs) { - if len(as.Rhs) != 1 { +func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { + Opstr := x.Op.TokenString() + if x.Op == ASSIGN || x.Op == DEFINE { + if len(x.Lhs) > len(x.Rhs) { + if len(x.Rhs) != 1 { panic("should not happen") } - switch cx := as.Rhs[0].(type) { + switch cx := x.Rhs[0].(type) { case *CallExpr: // Call case: a, b = x(...) ift := evalStaticTypeOf(store, last, cx.Func) cft := getGnoFuncTypeOf(store, ift) - if len(as.Lhs) != len(cft.Results) { + if len(x.Lhs) != len(cft.Results) { panic(fmt.Sprintf( "assignment mismatch: "+ "%d variables but %s returns %d values", - len(as.Lhs), cx.Func.String(), len(cft.Results))) + len(x.Lhs), cx.Func.String(), len(cft.Results))) } - if as.Op == ASSIGN { + if x.Op == ASSIGN { // check assignable - for i, lx := range as.Lhs { + for i, lx := range x.Lhs { if !isBlankIdentifier(lx) { lxt := evalStaticTypeOf(store, last, lx) assertAssignableTo(cft.Results[i].Type, lxt, false) @@ -701,18 +701,18 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } case *TypeAssertExpr: // Type-assert case: a, ok := x.(type) - if len(as.Lhs) != 2 { + if len(x.Lhs) != 2 { panic("should not happen") } - if as.Op == ASSIGN { + if x.Op == ASSIGN { // check assignable to first value - if !isBlankIdentifier(as.Lhs[0]) { // see composite3.gno - dt := evalStaticTypeOf(store, last, as.Lhs[0]) + if !isBlankIdentifier(x.Lhs[0]) { // see composite3.gno + dt := evalStaticTypeOf(store, last, x.Lhs[0]) ift := evalStaticTypeOf(store, last, cx) assertAssignableTo(ift, dt, false) } - if !isBlankIdentifier(as.Lhs[1]) { // see composite3.gno - dt := evalStaticTypeOf(store, last, as.Lhs[1]) + if !isBlankIdentifier(x.Lhs[1]) { // see composite3.gno + dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt != nil && dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) } @@ -720,12 +720,12 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } cx.HasOK = true case *IndexExpr: // must be with map type when len(Lhs) > len(Rhs) - if len(as.Lhs) != 2 { + if len(x.Lhs) != 2 { panic("should not happen") } - if as.Op == ASSIGN { - if !isBlankIdentifier(as.Lhs[0]) { - lt := evalStaticTypeOf(store, last, as.Lhs[0]) + if x.Op == ASSIGN { + if !isBlankIdentifier(x.Lhs[0]) { + lt := evalStaticTypeOf(store, last, x.Lhs[0]) if _, ok := cx.X.(*NameExpr); ok { rt := evalStaticTypeOf(store, last, cx.X) if mt, ok := rt.(*MapType); ok { @@ -740,8 +740,8 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } - if !isBlankIdentifier(as.Lhs[1]) { - dt := evalStaticTypeOf(store, last, as.Lhs[1]) + if !isBlankIdentifier(x.Lhs[1]) { + dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt != nil && dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) } @@ -752,9 +752,9 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } } else { // len(Lhs) == len(Rhs) - if as.Op == ASSIGN { + if x.Op == ASSIGN { // assert valid left value - for _, lx := range as.Lhs { + for _, lx := range x.Lhs { assertValidLeftValue(store, last, lx) } } @@ -762,19 +762,19 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { } else { // Ops other than assign and define // If this is an assignment operation, ensure there's only 1 // expr on lhs/rhs. - if len(as.Lhs) != 1 || len(as.Rhs) != 1 { - panic("assignment operator " + as.Op.TokenString() + + if len(x.Lhs) != 1 || len(x.Rhs) != 1 { + panic("assignment operator " + x.Op.TokenString() + " requires only one expression on lhs and rhs") } - for i, lx := range as.Lhs { + for i, lx := range x.Lhs { lt := evalStaticTypeOf(store, last, lx) - rt := evalStaticTypeOf(store, last, as.Rhs[i]) + rt := evalStaticTypeOf(store, last, x.Rhs[i]) - if checker, ok := AssignStmtChecker[as.Op]; ok { + if checker, ok := AssignStmtChecker[x.Op]; ok { if !checker(lt) { panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, kindString(lt))) } - switch as.Op { + switch x.Op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: // check when both typed if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet @@ -788,7 +788,7 @@ func (as *AssignStmt) AssertCompatible(store Store, last BlockNode) { // do nothing } } else { - panic(fmt.Sprintf("checker for %s does not exist", as.Op)) + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } } } From ff437b4d5d7ec3ccdd700e13fb46f4a0d1277126 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 25 Apr 2024 22:28:19 +0800 Subject: [PATCH 156/193] fixup --- gnovm/pkg/gnolang/debug.go | 2 +- gnovm/tests/file.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/debug.go b/gnovm/pkg/gnolang/debug.go index 60b286da38a..c6e39dfaa5a 100644 --- a/gnovm/pkg/gnolang/debug.go +++ b/gnovm/pkg/gnolang/debug.go @@ -104,7 +104,7 @@ func (p *PreprocessError) Stack() string { // the actual error followed by its associated preprocessing stack. func (p *PreprocessError) Error() string { var err strings.Builder - fmt.Fprintf(&err, "%s\n", p.Unwrap()) + fmt.Fprintf(&err, "%s:\n", p.Unwrap()) fmt.Fprintln(&err, "--- preprocess stack ---") fmt.Fprint(&err, p.Stack()) fmt.Fprintf(&err, "------------------------") diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 53a88377a2f..606f0b90e2c 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -252,7 +252,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { errstr = strings.TrimSpace(fmt.Sprintf("%v", pnc)) } - parts := strings.SplitN(errstr, "\n--- preprocess stack ---", 2) + parts := strings.SplitN(errstr, ":\n--- preprocess stack ---", 2) if len(parts) == 2 { fmt.Println(parts[0]) errstr = parts[0] @@ -273,6 +273,11 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { } else { errstr = strings.TrimSpace(fmt.Sprintf("%v", pnc)) } + parts := strings.SplitN(errstr, ":\n--- preprocess stack ---", 2) + if len(parts) == 2 { + fmt.Println(parts[0]) + errstr = parts[0] + } // check tip line, write to file ctl := errstr + "\n*** CHECK THE ERR MESSAGES ABOVE, MAKE SURE IT'S WHAT YOU EXPECTED, " + From 500f98446e5e756994ac37ebd86228814e475c7a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 2 May 2024 22:51:55 +0800 Subject: [PATCH 157/193] resolve comments --- gnovm/pkg/gnolang/preprocess.go | 12 +- gnovm/pkg/gnolang/type_check.go | 152 ++++++++---------- gnovm/tests/files/types/assign_nil.gno | 11 ++ gnovm/tests/files/types/assign_nil2.gno | 11 ++ gnovm/tests/files/types/assign_range_d.gno | 2 +- .../files/types/assign_type_assertion_f.gno | 2 +- gnovm/tests/files/types/bigdec_6.gno | 8 + 7 files changed, 103 insertions(+), 95 deletions(-) create mode 100644 gnovm/tests/files/types/assign_nil.gno create mode 100644 gnovm/tests/files/types/assign_nil2.gno create mode 100644 gnovm/tests/files/types/bigdec_6.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index abce4b1240a..a1180f5d32e 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -790,12 +790,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. - cmp := cmpSpecificity(lcx.T, rcx.T) - if cmp < 0 { + if !shouldSwapOnSpecificity(lcx.T, rcx.T) { // convert n.Left to right type. checkOrConvertType(store, last, &n.Left, rcx.T, false) - } else if cmp == 0 { - checkOrConvertType(store, last, &n.Left, rcx.T, false) } else { // convert n.Right to left type. checkOrConvertType(store, last, &n.Right, lcx.T, false) @@ -989,13 +986,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else if riu { // left typed, right untyped checkOrConvertType(store, last, &n.Right, lt, false) } else { // both typed, refer to 0a1g.gno - cmp := cmpSpecificity(lt, rt) - if cmp == -1 { + if !shouldSwapOnSpecificity(lt, rt) { checkOrConvertType(store, last, &n.Left, rt, false) - } else if cmp == 1 { + } else { checkOrConvertType(store, last, &n.Right, lt, false) - } else { // cmp 0, both typed, assertAssignableTo - checkOrConvertType(store, last, &n.Left, rt, false) } } } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index e70de60848b..39aa3774f2a 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -91,10 +91,7 @@ func (pt PrimitiveType) category() category { func isOrdered(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.category()&IsOrdered != 0 { - return true - } - return false + return t.category()&IsOrdered != 0 default: return false } @@ -103,10 +100,7 @@ func isOrdered(t Type) bool { func isBoolean(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.category()&IsBoolean != 0 { - return true - } - return false + return t.category()&IsBoolean != 0 default: return false } @@ -116,10 +110,7 @@ func isBoolean(t Type) bool { func isNumeric(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.category()&IsNumeric != 0 { - return true - } - return false + return t.category()&IsNumeric != 0 default: return false } @@ -128,10 +119,7 @@ func isNumeric(t Type) bool { func isIntNum(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.category()&IsInteger != 0 || t.category()&IsBigInt != 0 { - return true - } - return false + return t.category()&IsInteger != 0 || t.category()&IsBigInt != 0 default: return false } @@ -140,10 +128,7 @@ func isIntNum(t Type) bool { func isNumericOrString(t Type) bool { switch t := baseOf(t).(type) { case PrimitiveType: - if t.category()&IsNumeric != 0 || t.category()&IsString != 0 { - return true - } - return false + return t.category()&IsNumeric != 0 || t.category()&IsString != 0 default: return false } @@ -393,7 +378,7 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { // XXX, this is a loose check, we don't have the context // to check if it is an exact integer, e.g. 1.2 or 1.0(1.0 can be converted to int). // this ensure expr like (a % 1.0) pass check, while - // expr like (a % 1.2) panic at ConvertUntypedTo, which is a delayed assertion when const evaluated. + // expr like (a % 1.2) panic at ConvertUntypedTo, which is a delayed assertion after const evaluated. // assignable does not guarantee convertible. case UntypedBigdecType: switch dt.Kind() { @@ -510,13 +495,9 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { // =========================================================== func (x *BinaryExpr) checkShiftLhs(dt Type) { - var destKind interface{} - if dt != nil { - destKind = dt.Kind() - } if checker, ok := binaryChecker[x.Op]; ok { if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), destKind)) + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(dt))) } } else { panic(fmt.Sprintf("checker for %s does not exist", x.Op)) @@ -544,11 +525,8 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { } } - OpStr := x.Op.TokenString() - xt, dt := lt, rt - cmp := cmpSpecificity(lt, rt) // check potential direction of type conversion - if cmp > 0 { + if shouldSwapOnSpecificity(lt, rt) { // check potential direction of type conversion xt, dt = dt, xt } @@ -558,7 +536,7 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { assertComparable(xt, dt) case LSS, LEQ, GTR, GEQ: if checker, ok := binaryChecker[x.Op]; ok { - x.checkCompatibility(xt, dt, checker, OpStr) + x.checkCompatibility(xt, dt, checker, x.Op.TokenString()) } else { panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } @@ -567,7 +545,7 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { } } else { if checker, ok := binaryChecker[x.Op]; ok { - x.checkCompatibility(xt, dt, checker, OpStr) + x.checkCompatibility(xt, dt, checker, x.Op.TokenString()) } else { panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } @@ -593,7 +571,9 @@ func (x *BinaryExpr) checkCompatibility(xt, dt Type, checker func(t Type) bool, panic(fmt.Sprintf("operator %s not defined on: %v", OpStr, kindString(dt))) } - // e.g. 1%1e9 + // e.g. int(1) % 1e9. 1e9 is untyped bigDec, that is not compatible with operator `%`, + // but it is assignable and convertible to int as it's an exact number, + // so this expression is compatible. if !checker(xt) { err := checkAssignableTo(xt, dt, false) // XXX, cache this? if err != nil { @@ -635,49 +615,50 @@ func (x *IncDecStmt) AssertCompatible(t Type) { } func (x *RangeStmt) AssertCompatible(store Store, last BlockNode) { - if x.Op == ASSIGN { - if isBlankIdentifier(x.Key) && isBlankIdentifier(x.Value) { - // both "_" - } else { - assertValidLeftValue(store, last, x.Key) - // if is valid left value - kt := evalStaticTypeOf(store, last, x.Key) - vt := evalStaticTypeOf(store, last, x.Value) - xt := evalStaticTypeOf(store, last, x.X) - switch cxt := xt.(type) { - case *MapType: - assertAssignableTo(cxt.Key, kt, false) - assertAssignableTo(cxt.Value, vt, false) - case *SliceType: - if kt.Kind() != IntKind { - panic(fmt.Sprintf("index type should be int, but got %v", kt)) - } - assertAssignableTo(cxt.Elt, vt, false) - case *ArrayType: - if kt.Kind() != IntKind { - panic(fmt.Sprintf("index type should be int, but got %v", kt)) - } - assertAssignableTo(cxt.Elt, vt, false) - case PrimitiveType: - if cxt.Kind() == StringKind { - if kt != nil && kt.Kind() != IntKind { - panic(fmt.Sprintf("index type should be int, but got %v", kt)) - } - if vt != nil && vt.Kind() != Int32Kind { // rune - panic(fmt.Sprintf("value type should be int32, but got %v", kt)) - } - } + if x.Op != ASSIGN { + return + } + if isBlankIdentifier(x.Key) && isBlankIdentifier(x.Value) { + // both "_" + return + } + assertValidLeftValue(store, last, x.Key) + assertValidLeftValue(store, last, x.Value) + // if is valid left value + kt := evalStaticTypeOf(store, last, x.Key) + vt := evalStaticTypeOf(store, last, x.Value) + xt := evalStaticTypeOf(store, last, x.X) + switch cxt := xt.(type) { + case *MapType: + assertAssignableTo(cxt.Key, kt, false) + assertAssignableTo(cxt.Value, vt, false) + case *SliceType: + if kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } + assertAssignableTo(cxt.Elt, vt, false) + case *ArrayType: + if kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } + assertAssignableTo(cxt.Elt, vt, false) + case PrimitiveType: + if cxt.Kind() == StringKind { + if kt != nil && kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } + if vt != nil && vt.Kind() != Int32Kind { // rune + panic(fmt.Sprintf("value type should be int32, but got %v", kt)) } } } } func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { - Opstr := x.Op.TokenString() if x.Op == ASSIGN || x.Op == DEFINE { if len(x.Lhs) > len(x.Rhs) { if len(x.Rhs) != 1 { - panic("should not happen") + panic("length of Rhs should be 1") } switch cx := x.Rhs[0].(type) { case *CallExpr: @@ -694,6 +675,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { // check assignable for i, lx := range x.Lhs { if !isBlankIdentifier(lx) { + assertValidLeftValue(store, last, lx) lxt := evalStaticTypeOf(store, last, lx) assertAssignableTo(cft.Results[i].Type, lxt, false) } @@ -707,13 +689,15 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { if x.Op == ASSIGN { // check assignable to first value if !isBlankIdentifier(x.Lhs[0]) { // see composite3.gno + assertValidLeftValue(store, last, x.Lhs[0]) dt := evalStaticTypeOf(store, last, x.Lhs[0]) ift := evalStaticTypeOf(store, last, cx) assertAssignableTo(ift, dt, false) } if !isBlankIdentifier(x.Lhs[1]) { // see composite3.gno + assertValidLeftValue(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) - if dt != nil && dt.Kind() != BoolKind { // typed, not bool + if dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) } } @@ -725,6 +709,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } if x.Op == ASSIGN { if !isBlankIdentifier(x.Lhs[0]) { + assertValidLeftValue(store, last, x.Lhs[0]) lt := evalStaticTypeOf(store, last, x.Lhs[0]) if _, ok := cx.X.(*NameExpr); ok { rt := evalStaticTypeOf(store, last, cx.X) @@ -741,6 +726,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } if !isBlankIdentifier(x.Lhs[1]) { + assertValidLeftValue(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt != nil && dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -749,7 +735,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } cx.HasOK = true default: - panic("should not happen") + panic(fmt.Sprintf("RHS should not be %v when len(Lhs) > len(Rhs)", cx)) } } else { // len(Lhs) == len(Rhs) if x.Op == ASSIGN { @@ -772,7 +758,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { if checker, ok := AssignStmtChecker[x.Op]; ok { if !checker(lt) { - panic(fmt.Sprintf("operator %s not defined on: %v", Opstr, kindString(lt))) + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(lt))) } switch x.Op { case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: @@ -835,31 +821,31 @@ func isComparison(op Word) bool { } } -func cmpSpecificity(t1, t2 Type) int { +func shouldSwapOnSpecificity(t1, t2 Type) bool { // check nil if t1 == nil { // see test file 0f46 - return -1 // also with both nil + return false // also with both nil } else if t2 == nil { - return 1 + return true } // check interface if it1, ok := baseOf(t1).(*InterfaceType); ok { if it1.IsEmptyInterface() { - return 1 // left empty interface + return true // left empty interface } else { if it2, ok := baseOf(t2).(*InterfaceType); ok { if it2.IsEmptyInterface() { // right empty interface - return -1 + return false } else { - return 0 // both non-empty interface + return false // both non-empty interface } } else { - return 1 // right not interface + return true // right not interface } } } else if _, ok := t2.(*InterfaceType); ok { - return -1 // left not interface, right is interface + return false // left not interface, right is interface } // primitive types @@ -872,19 +858,17 @@ func cmpSpecificity(t1, t2 Type) int { } if t1s < t2s { // NOTE: higher specificity has lower value, so backwards. - return 1 + return true } else if t1s == t2s { - return 0 + return false } else { - return -1 + return false } } func isBlankIdentifier(x Expr) bool { if nx, ok := x.(*NameExpr); ok { - if nx.Path.Depth == 0 && nx.Path.Index == 0 && nx.Name == "_" { - return true - } + return nx.Name == "_" } return false } diff --git a/gnovm/tests/files/types/assign_nil.gno b/gnovm/tests/files/types/assign_nil.gno new file mode 100644 index 00000000000..e4012745d4f --- /dev/null +++ b/gnovm/tests/files/types/assign_nil.gno @@ -0,0 +1,11 @@ +package main + +func main() { + var i interface{} + i = 4 + var j int + j, nil = i.(int) +} + +// Error: +// main/files/types/assign_nil.gno:7: cannot assign to (const (undefined)) diff --git a/gnovm/tests/files/types/assign_nil2.gno b/gnovm/tests/files/types/assign_nil2.gno new file mode 100644 index 00000000000..8af61a1e496 --- /dev/null +++ b/gnovm/tests/files/types/assign_nil2.gno @@ -0,0 +1,11 @@ +package main + +func main() { + var i interface{} + i = 4 + var ok bool + nil, nil = i.(int) +} + +// Error: +// main/files/types/assign_nil2.gno:7: cannot assign to (const (undefined)) diff --git a/gnovm/tests/files/types/assign_range_d.gno b/gnovm/tests/files/types/assign_range_d.gno index 4a84ff215ae..6903cb0b7bc 100644 --- a/gnovm/tests/files/types/assign_range_d.gno +++ b/gnovm/tests/files/types/assign_range_d.gno @@ -5,7 +5,7 @@ func main() { var index float32 var value rune - for index, rune = range s { + for index, value = range s { println(index) } } diff --git a/gnovm/tests/files/types/assign_type_assertion_f.gno b/gnovm/tests/files/types/assign_type_assertion_f.gno index 3b9a87fd5dc..bc2907eb8af 100644 --- a/gnovm/tests/files/types/assign_type_assertion_f.gno +++ b/gnovm/tests/files/types/assign_type_assertion_f.gno @@ -22,4 +22,4 @@ func main() { } // Error: -// main/files/types/assign_type_assertion_f.gno:19: cannot use main.Dog as bigint without explicit conversion +// main/files/types/assign_type_assertion_f.gno:19: cannot assign to (const (1 bigint)) diff --git a/gnovm/tests/files/types/bigdec_6.gno b/gnovm/tests/files/types/bigdec_6.gno new file mode 100644 index 00000000000..5ef078619b5 --- /dev/null +++ b/gnovm/tests/files/types/bigdec_6.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 % 1e9) +} + +// Error: +// main/files/types/bigdec_6.gno:4: operator % not defined on: BigdecKind From 1eabccea7f94042c9132ffda86e90f83f6c0c519 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Thu, 2 May 2024 23:06:50 +0800 Subject: [PATCH 158/193] simplify cmpSpecificity --- gnovm/pkg/gnolang/type_check.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 39aa3774f2a..baaf070f565 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -834,12 +834,8 @@ func shouldSwapOnSpecificity(t1, t2 Type) bool { if it1.IsEmptyInterface() { return true // left empty interface } else { - if it2, ok := baseOf(t2).(*InterfaceType); ok { - if it2.IsEmptyInterface() { // right empty interface - return false - } else { - return false // both non-empty interface - } + if _, ok := baseOf(t2).(*InterfaceType); ok { + return false } else { return true // right not interface } @@ -859,8 +855,6 @@ func shouldSwapOnSpecificity(t1, t2 Type) bool { if t1s < t2s { // NOTE: higher specificity has lower value, so backwards. return true - } else if t1s == t2s { - return false } else { return false } From 1e72c380084b55a9298aa46910edba638659d5c4 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 3 May 2024 01:27:25 +0800 Subject: [PATCH 159/193] fix range assign --- gnovm/pkg/gnolang/type_check.go | 36 ++++++++++++++------- gnovm/tests/files/types/assign_range_b2.gno | 28 ++++++++++++++++ 2 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 gnovm/tests/files/types/assign_range_b2.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index baaf070f565..1b6dbb3802a 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -614,6 +614,12 @@ func (x *IncDecStmt) AssertCompatible(t Type) { } } +func assertIndexTypeIsInt(kt Type) { + if kt.Kind() != IntKind { + panic(fmt.Sprintf("index type should be int, but got %v", kt)) + } +} + func (x *RangeStmt) AssertCompatible(store Store, last BlockNode) { if x.Op != ASSIGN { return @@ -623,32 +629,40 @@ func (x *RangeStmt) AssertCompatible(store Store, last BlockNode) { return } assertValidLeftValue(store, last, x.Key) - assertValidLeftValue(store, last, x.Value) // if is valid left value + kt := evalStaticTypeOf(store, last, x.Key) - vt := evalStaticTypeOf(store, last, x.Value) + var vt Type + if x.Value != nil { + vt = evalStaticTypeOf(store, last, x.Value) + } + xt := evalStaticTypeOf(store, last, x.X) switch cxt := xt.(type) { case *MapType: assertAssignableTo(cxt.Key, kt, false) - assertAssignableTo(cxt.Value, vt, false) + if vt != nil { + assertAssignableTo(cxt.Value, vt, false) + } case *SliceType: - if kt.Kind() != IntKind { - panic(fmt.Sprintf("index type should be int, but got %v", kt)) + assertIndexTypeIsInt(kt) + if vt != nil { + assertAssignableTo(cxt.Elt, vt, false) } - assertAssignableTo(cxt.Elt, vt, false) case *ArrayType: - if kt.Kind() != IntKind { - panic(fmt.Sprintf("index type should be int, but got %v", kt)) + assertIndexTypeIsInt(kt) + if vt != nil { + assertAssignableTo(cxt.Elt, vt, false) } - assertAssignableTo(cxt.Elt, vt, false) case PrimitiveType: if cxt.Kind() == StringKind { if kt != nil && kt.Kind() != IntKind { panic(fmt.Sprintf("index type should be int, but got %v", kt)) } - if vt != nil && vt.Kind() != Int32Kind { // rune - panic(fmt.Sprintf("value type should be int32, but got %v", kt)) + if vt != nil { + if vt.Kind() != Int32Kind { // rune + panic(fmt.Sprintf("value type should be int32, but got %v", kt)) + } } } } diff --git a/gnovm/tests/files/types/assign_range_b2.gno b/gnovm/tests/files/types/assign_range_b2.gno new file mode 100644 index 00000000000..a96c3f91ace --- /dev/null +++ b/gnovm/tests/files/types/assign_range_b2.gno @@ -0,0 +1,28 @@ +package main + +func main() { + rangeMap() + rangeSlice() +} + +func rangeMap() { + m := map[int]string{999: "asdf"} + var v int + for v = range m { + println(v) + } +} + +func rangeSlice() { + m := []int{9, 4, 6} + var v int + for v = range m { + println(v) + } +} + +// Output: +// 999 +// 0 +// 1 +// 2 From ff57c3678e37022621ad4b5b6b463f9ba2ac3a69 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 13 May 2024 22:44:05 +0800 Subject: [PATCH 160/193] revert --- gnovm/pkg/gnolang/values_conversions.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index 2389324a37a..dba5531d2c4 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -44,7 +44,6 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { tv.T = t return } else { - // both NativeType, use reflect to assert. // convert go-native to gno type (shallow). *tv = go2GnoValue2(alloc, store, tv.V.(*NativeValue).Value, false) ConvertTo(alloc, store, tv, t) From 9137217f8b55c21cdb928688bdcca8e0f876a6c0 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 24 May 2024 11:48:10 +0200 Subject: [PATCH 161/193] fixup --- gnovm/pkg/gnolang/type_check.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 1b6dbb3802a..61cab23390b 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -425,8 +425,8 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { assertAssignableTo(pt.Elt, cdt.Elt, false) + return nil } - return nil case *ArrayType: if at, ok := xt.(*ArrayType); ok { if at.Len != cdt.Len { @@ -449,19 +449,11 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { assertAssignableTo(mt.Value, cdt.Value, false) return nil } - case *FuncType: - if xt.TypeID() == cdt.TypeID() { - return nil // ok - } case *InterfaceType: return errors.New("should not happen") case *DeclaredType: panic("should not happen") - case *StructType, *PackageType, *ChanType: - if xt.TypeID() == cdt.TypeID() { - return nil // ok - } - case *TypeType: + case *FuncType, *StructType, *PackageType, *ChanType, *TypeType: if xt.TypeID() == cdt.TypeID() { return nil // ok } From 9a96287b0da7560841ceb29b2832be3e4f66d1dd Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 24 May 2024 12:47:23 +0200 Subject: [PATCH 162/193] fixup, revert recursive check --- gnovm/pkg/gnolang/preprocess.go | 17 +++++++++++++++++ gnovm/pkg/gnolang/values_conversions.go | 2 -- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0b35cc638c2..e1d6f99864f 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2422,6 +2422,23 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative if t != nil { assertAssignableTo(xt, t, autoNative) } + // Push type into expr if qualifying binary expr. + if bx, ok := (*x).(*BinaryExpr); ok { + switch bx.Op { + case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, + BAND_NOT, LAND, LOR: + // push t into bx.Left and bx.Right + checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Right, t, autoNative) + return + case SHL, SHR: + // push t into bx.Left + checkOrConvertType(store, last, &bx.Left, t, autoNative) + return + // case EQL, LSS, GTR, NEQ, LEQ, GEQ: + // default: + } + } } convertType(store, last, x, t, autoNative) } diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index dba5531d2c4..c5ddc232fcb 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -868,8 +868,6 @@ GNO_CASE: "cannot convert %s to %s", tv.T.String(), k.String())) } - case BigintKind: - ConvertUntypedBigintTo(tv, tv.V.(BigintValue), t) default: panic(fmt.Sprintf( "cannot convert %s to %s", From 1d65b4c1cb0168c92e59fcb11a5b5d34e7282b46 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 24 May 2024 13:33:02 +0200 Subject: [PATCH 163/193] fixup --- gnovm/pkg/gnolang/preprocess.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e1d6f99864f..69640471267 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2464,20 +2464,6 @@ func convertType(store Store, last BlockNode, x *Expr, t Type, autoNative bool) if debug { debug.Printf("default type of t: %v \n", t) } - // Push type into expr if qualifying binary expr. - if bx, ok := (*x).(*BinaryExpr); ok { - switch bx.Op { - case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, - BAND_NOT, LAND, LOR: - // push t into bx.Left and bx.Right, recursively - convertType(store, last, &bx.Left, t, autoNative) - convertType(store, last, &bx.Right, t, autoNative) - return - default: - // do nothing - } - } - // general case cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx From 26efc9490819242f92afe1fa5e5148df82f2898c Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Fri, 24 May 2024 14:33:55 +0200 Subject: [PATCH 164/193] optimize --- gnovm/pkg/gnolang/preprocess.go | 353 ++++++++++++++++---------------- 1 file changed, 177 insertions(+), 176 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 69640471267..c0f885d576b 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -782,118 +782,76 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return cx, TRANS_CONTINUE } return n, TRANS_CONTINUE - } else { - n.AssertCompatible(lt, rt) // check compatibility against binaryExpr other ths shift expr - // General case. - if lic { - if ric { - // Left const, Right const ---------------------- - // Replace with *ConstExpr if const operands. - // First, convert untyped as necessary. - if !shouldSwapOnSpecificity(lcx.T, rcx.T) { - // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rcx.T, false) - } else { - // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lcx.T, false) + } + + // general cases + n.AssertCompatible(lt, rt) // check compatibility against binaryExpr other ths shift expr + // General case. + if lic { + if ric { + // Left const, Right const ---------------------- + // Replace with *ConstExpr if const operands. + // First, convert untyped as necessary. + if !shouldSwapOnSpecificity(lcx.T, rcx.T) { + // convert n.Left to right type. + checkOrConvertType(store, last, &n.Left, rcx.T, false) + } else { + // convert n.Right to left type. + checkOrConvertType(store, last, &n.Right, lcx.T, false) + } + // Then, evaluate the expression. + cx := evalConst(store, last, n) + return cx, TRANS_CONTINUE + } else if isUntyped(lcx.T) { // left untyped const -> right not const + if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native), e.g. 1*time.Second + if isShift { // RHS of shift should not be native + panic("should not happen") } - // Then, evaluate the expression. - cx := evalConst(store, last, n) - return cx, TRANS_CONTINUE - } else if isUntyped(lcx.T) { // left untyped const -> right not const - if rnt, ok := rt.(*NativeType); ok { // untyped -> gno(native), e.g. 1*time.Second - if isShift { // RHS of shift should not be native - panic("should not happen") - } - // get concrete native base type. - pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) - if !ok { - panic(fmt.Sprintf( - "unexpected type pair: cannot use %s as %s", - lt.String(), - rnt.String())) - } - // convert n.Left to pt type, - checkOrConvertType(store, last, &n.Left, pt, false) - // if check pass, convert n.Right to (gno) pt type, - rn := Expr(Call(pt.String(), n.Right)) - // and convert result back. - tx := constType(n, rnt) - // reset/create n2 to preprocess right child. - n2 := &BinaryExpr{ - Left: n.Left, - Op: n.Op, - Right: rn, - } - resn := Node(Call(tx, n2)) // this make current node to gonative{xxx} - resn = Preprocess(store, last, resn) - return resn, TRANS_CONTINUE - // NOTE: binary operations are always computed in - // gno, never with reflect. - } else { - // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, false) + // get concrete native base type. + pt, ok := go2GnoBaseType(rnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + lt.String(), + rnt.String())) } - } else if lcx.T == nil { // LHS is nil. - // convert n.Left to typed-nil type. - checkOrConvertType(store, last, &n.Left, rt, false) - } else { // left is typed const, right not const - if isUntyped(rt) { // e.g. int(1) + 1< Date: Mon, 27 May 2024 10:07:06 +0200 Subject: [PATCH 165/193] improve readibility for recursive call --- gnovm/pkg/gnolang/type_check.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 61cab23390b..5bf798e14e5 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -424,8 +424,7 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { } case *PointerType: // case 4 from here on if pt, ok := xt.(*PointerType); ok { - assertAssignableTo(pt.Elt, cdt.Elt, false) - return nil + return checkAssignableTo(pt.Elt, cdt.Elt, false) } case *ArrayType: if at, ok := xt.(*ArrayType); ok { @@ -435,19 +434,20 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { at.String(), cdt.String()) } - assertAssignableTo(at.Elt, cdt.Elt, false) - return nil + return checkAssignableTo(at.Elt, cdt.Elt, false) } case *SliceType: if st, ok := xt.(*SliceType); ok { - assertAssignableTo(st.Elt, cdt.Elt, false) - return nil + return checkAssignableTo(st.Elt, cdt.Elt, false) } case *MapType: if mt, ok := xt.(*MapType); ok { - assertAssignableTo(mt.Key, cdt.Key, false) - assertAssignableTo(mt.Value, cdt.Value, false) - return nil + err := checkAssignableTo(mt.Key, cdt.Key, false) + if err != nil { + return err + } else { + return checkAssignableTo(mt.Value, cdt.Value, false) + } } case *InterfaceType: return errors.New("should not happen") From 07d52f91ea81406926adf51eac16bd88d5cff4c3 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 3 Jun 2024 06:54:16 +0800 Subject: [PATCH 166/193] fix lint --- gnovm/pkg/gnolang/preprocess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c0f885d576b..ef34943f256 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2482,7 +2482,7 @@ func convertIfConst(store Store, last BlockNode, x Expr) { func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) { if t != nil && t.Kind() == InterfaceKind { if cx.T != nil { - checkAssignableTo(cx.T, t, false) + assertAssignableTo(cx.T, t, false) } t = nil // signifies to convert to default type. } From 9af1aa7d4dee8a363c47e179905bfcc5b4d9b71f Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 3 Jun 2024 11:40:21 +0800 Subject: [PATCH 167/193] fixup --- gnovm/pkg/gnolang/type_check.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 5bf798e14e5..d4e15729184 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -620,7 +620,7 @@ func (x *RangeStmt) AssertCompatible(store Store, last BlockNode) { // both "_" return } - assertValidLeftValue(store, last, x.Key) + assertValidAssignLhs(store, last, x.Key) // if is valid left value kt := evalStaticTypeOf(store, last, x.Key) @@ -681,7 +681,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { // check assignable for i, lx := range x.Lhs { if !isBlankIdentifier(lx) { - assertValidLeftValue(store, last, lx) + assertValidAssignLhs(store, last, lx) lxt := evalStaticTypeOf(store, last, lx) assertAssignableTo(cft.Results[i].Type, lxt, false) } @@ -695,13 +695,13 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { if x.Op == ASSIGN { // check assignable to first value if !isBlankIdentifier(x.Lhs[0]) { // see composite3.gno - assertValidLeftValue(store, last, x.Lhs[0]) + assertValidAssignLhs(store, last, x.Lhs[0]) dt := evalStaticTypeOf(store, last, x.Lhs[0]) ift := evalStaticTypeOf(store, last, cx) assertAssignableTo(ift, dt, false) } if !isBlankIdentifier(x.Lhs[1]) { // see composite3.gno - assertValidLeftValue(store, last, x.Lhs[1]) + assertValidAssignLhs(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -715,7 +715,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } if x.Op == ASSIGN { if !isBlankIdentifier(x.Lhs[0]) { - assertValidLeftValue(store, last, x.Lhs[0]) + assertValidAssignLhs(store, last, x.Lhs[0]) lt := evalStaticTypeOf(store, last, x.Lhs[0]) if _, ok := cx.X.(*NameExpr); ok { rt := evalStaticTypeOf(store, last, cx.X) @@ -732,7 +732,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } if !isBlankIdentifier(x.Lhs[1]) { - assertValidLeftValue(store, last, x.Lhs[1]) + assertValidAssignLhs(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt != nil && dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -747,7 +747,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { if x.Op == ASSIGN { // assert valid left value for _, lx := range x.Lhs { - assertValidLeftValue(store, last, lx) + assertValidAssignLhs(store, last, lx) } } } @@ -787,7 +787,7 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } // misc -func assertValidLeftValue(store Store, last BlockNode, lx Expr) { +func assertValidAssignLhs(store Store, last BlockNode, lx Expr) { shouldPanic := true switch clx := lx.(type) { case *NameExpr, *StarExpr, *SelectorExpr: @@ -827,6 +827,11 @@ func isComparison(op Word) bool { } } +// shouldSwapOnSpecificity determines the potential direction for +// checkOrConvertType. it checks whether a swap is needed between two types +// based on their specificity. If t2 has a lower specificity than t1, it returns +// false, indicating no swap is needed. If t1 has a lower specificity than t2, +// it returns true, indicating a swap is needed. func shouldSwapOnSpecificity(t1, t2 Type) bool { // check nil if t1 == nil { // see test file 0f46 From bf202eb82357dad97fedbf0ac3e102c1908f3d48 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 3 Jun 2024 21:31:41 +0800 Subject: [PATCH 168/193] merger master --- .github/codecov.yml | 24 +- .github/dependabot.yml | 5 - .github/golangci.yml | 5 + .github/goreleaser-master.yaml | 502 ++++++ .github/goreleaser-nightly.yaml | 501 ++++++ .github/goreleaser.yaml | 501 ++++++ .github/workflows/autocounterd.yml | 6 +- .github/workflows/benchmark-check.yml | 6 +- .github/workflows/benchmark-publish.yml | 2 +- .../{benchmark.yml => benchmark_template.yml} | 4 + .github/workflows/build_template.yml | 31 + .github/workflows/codegen.yml | 36 - .github/workflows/contribs.yml | 84 +- .github/workflows/db-tests.yml | 54 - .github/workflows/deploy-docs.yml | 2 +- .github/workflows/docker.yml | 84 - .github/workflows/examples.yml | 9 +- .github/workflows/gnoland.yml | 135 +- .github/workflows/gnovm.yml | 161 +- .github/workflows/labeler.yml | 4 - .../{lint-pr.yml => lint-pr-title.yml} | 2 +- .github/workflows/lint.yml | 87 -- .github/workflows/lint_template.yml | 27 + .github/workflows/main_template.yml | 37 + .github/workflows/misc.yml | 121 +- .github/workflows/nightlies.yml | 45 + .github/workflows/releaser-master.yml | 46 + .github/workflows/releaser.yml | 45 + .github/workflows/test_template.yml | 49 + .github/workflows/tm2.yml | 116 +- .gitignore | 1 + .gitpod.yml | 2 +- Dockerfile | 66 - Dockerfile.release | 48 + LICENSE.md | 698 ++++++++- Makefile | 8 +- contribs/gnodev/cmd/gnodev/main.go | 6 +- contribs/gnodev/go.mod | 1 + contribs/gnodev/go.sum | 6 +- contribs/gnodev/pkg/dev/node.go | 3 +- contribs/gnokeykc/go.sum | 4 - .../gnoland-start-manual.gif | Bin 0 -> 759932 bytes .../gnoland-start.gif | Bin 2543753 -> 864779 bytes docs/concepts/stdlibs/gnopher-hole.md | 2 +- docs/concepts/testnets.md | 3 +- .../local-setup/setting-up-a-local-chain.md | 255 ++- docs/gno-tooling/cli/gnokey.md | 18 +- docs/gno-tooling/cli/gnoland.md | 80 +- docs/how-to-guides/creating-grc20.md | 3 +- docs/how-to-guides/interact-with-gnoland.md | 12 +- docs/overview.md | 2 +- docs/reference/network-config.md | 2 +- docs/reference/stdlibs/std/chain.md | 12 - docs/reference/stdlibs/std/coin.md | 148 +- docs/reference/stdlibs/std/coins.md | 19 +- docs/reference/stdlibs/std/testing.md | 11 - .../Provider/json-rpc-provider.md | 2 +- .../tm2-js-client/Provider/ws-provider.md | 10 +- examples/gno.land/p/demo/blog/blog.gno | 24 +- examples/gno.land/p/demo/blog/util.gno | 13 +- examples/gno.land/p/demo/tests/tests.gno | 2 +- examples/gno.land/p/demo/ui/ui.gno | 11 + examples/gno.land/r/demo/boards/README.md | 2 +- examples/gno.land/r/demo/boards/public.gno | 2 +- .../gno.land/r/demo/boards/z_4_filetest.gno | 8 +- examples/gno.land/r/demo/event/event.gno | 9 + examples/gno.land/r/demo/event/gno.mod | 1 + .../gno.land/r/demo/gasbanktest/README.md | 127 ++ .../gno.land/r/demo/gasbanktest/banktest.gno | 71 + examples/gno.land/r/demo/gasbanktest/gno.mod | 1 + .../r/demo/gasbanktest/z_0_filetest.gno | 47 + .../r/demo/gasbanktest/z_1_filetest.gno | 20 + .../r/demo/gasbanktest/z_2_filetest.gno | 45 + examples/gno.land/r/demo/grc20factory/gno.mod | 6 + .../r/demo/grc20factory/grc20factory.gno | 164 ++ .../r/demo/grc20factory/grc20factory_test.gno | 58 + .../r/demo/tests/realm_compositelit.gno | 22 + .../gno.land/r/demo/tests/realm_method38d.gno | 19 + .../r/demo/tests/subtests/subtests.gno | 8 + examples/gno.land/r/demo/tests/tests.gno | 14 +- examples/gno.land/r/demo/tests/tests_test.gno | 36 +- .../gno.land/r/demo/tests/z0_filetest.gno | 28 +- .../gno.land/r/demo/userbook/userbook.gno | 5 + examples/gno.land/r/demo/users/users.gno | 2 +- .../gno.land/r/demo/users/z_0_filetest.gno | 4 +- examples/gno.land/r/gnoland/blog/admin.gno | 6 + .../gno.land/r/gnoland/blog/gnoblog_test.gno | 40 +- .../page_events.gno => events/events.gno} | 71 +- .../r/gnoland/events/events_filetest.gno | 203 +++ examples/gno.land/r/gnoland/events/gno.mod | 3 + examples/gno.land/r/gnoland/faucet/admin.gno | 2 +- examples/gno.land/r/gnoland/faucet/faucet.gno | 4 +- examples/gno.land/r/gnoland/home/home.gno | 4 +- .../gno.land/r/gnoland/home/home_filetest.gno | 247 +-- .../gno.land/r/gnoland/pages/page_license.gno | 860 +++++++--- .../gno.land/r/gnoland/pages/pages_test.gno | 1 - .../upgrade_d/README.md | 9 + .../upgrade_d/v1/v1.gno | 34 + .../upgrade_d/v1/z_filetest.gno | 18 + .../upgrade_d/v2/v2.gno | 51 + .../upgrade_d/v2/z_filetest.gno | 22 + gno.land/LICENSE.md | 1385 ----------------- gno.land/cmd/gnoland/config.go | 16 +- gno.land/cmd/gnoland/config_get.go | 2 +- gno.land/cmd/gnoland/config_get_test.go | 2 +- gno.land/cmd/gnoland/config_init.go | 35 +- gno.land/cmd/gnoland/config_init_test.go | 69 + gno.land/cmd/gnoland/config_set.go | 2 +- gno.land/cmd/gnoland/config_set_test.go | 2 +- gno.land/cmd/gnoland/genesis_validator.go | 2 +- gno.land/cmd/gnoland/root.go | 2 +- gno.land/cmd/gnoland/secrets.go | 14 +- gno.land/cmd/gnoland/secrets_init.go | 57 +- gno.land/cmd/gnoland/start.go | 332 ++-- gno.land/cmd/gnoland/start_test.go | 152 +- .../gnoland/testdata/assertorigincall.txtar | 247 +++ .../gnoland/testdata/event_multi_msg.txtar | 43 + .../cmd/gnoland/testdata/issue_1786.txtar | 2 +- .../gnoland/testdata/maketx_call_pure.txtar | 32 + .../{map-delete.txtar => map_delete.txtar} | 0 gno.land/cmd/gnoland/testdata/prevrealm.txtar | 184 +++ .../realm_banker_issued_coin_denom.txtar | 88 ++ .../cmd/gnoland/testdata/time-simple.txtar | 18 + gno.land/genesis/genesis_txs.jsonl | 4 +- gno.land/pkg/gnoclient/integration_test.go | 8 +- gno.land/pkg/gnoland/app.go | 48 +- gno.land/pkg/gnoland/node_inmemory.go | 2 +- gno.land/pkg/gnoweb/gnoweb.go | 4 +- gno.land/pkg/gnoweb/static/css/app.css | 71 +- .../gnoweb/static/img/apple-touch-icon.png | Bin 0 -> 1502 bytes .../pkg/gnoweb/static/img/favicon-16x16.png | Bin 0 -> 172 bytes .../pkg/gnoweb/static/img/favicon-32x32.png | Bin 0 -> 317 bytes gno.land/pkg/gnoweb/static/img/favicon.ico | Bin 15406 -> 7406 bytes gno.land/pkg/gnoweb/static/img/logo.png | Bin 8538 -> 0 bytes gno.land/pkg/gnoweb/static/img/logo.svg | 6 - gno.land/pkg/gnoweb/static/img/og-gnoland.png | Bin 0 -> 4739 bytes .../gnoweb/static/img/safari-pinned-tab.svg | 29 + .../pkg/gnoweb/static/js/highlight.min.js | 647 ++++---- gno.land/pkg/gnoweb/static/js/realm_help.js | 6 +- gno.land/pkg/gnoweb/views/faucet.html | 2 +- gno.land/pkg/gnoweb/views/funcs.html | 33 +- gno.land/pkg/gnoweb/views/generic.html | 2 +- gno.land/pkg/gnoweb/views/package_dir.html | 2 +- gno.land/pkg/gnoweb/views/package_file.html | 2 +- gno.land/pkg/gnoweb/views/realm_help.html | 4 +- gno.land/pkg/gnoweb/views/realm_render.html | 2 +- .../integration/testdata/improved-coins.txtar | 86 + gno.land/pkg/integration/testing_node.go | 2 +- gno.land/pkg/sdk/vm/common_test.go | 2 +- gno.land/pkg/sdk/vm/handler.go | 66 +- gno.land/pkg/sdk/vm/keeper.go | 77 +- gno.land/pkg/sdk/vm/keeper_test.go | 6 +- gno.land/pkg/sdk/vm/msgs.go | 5 +- gnovm/1.gno | 17 + gnovm/LICENSE.md | 1385 ----------------- gnovm/Makefile | 9 +- gnovm/cmd/gno/bug.go | 13 +- gnovm/cmd/gno/lint.go | 82 +- gnovm/cmd/gno/lint_test.go | 20 +- gnovm/cmd/gno/main_test.go | 4 +- gnovm/cmd/gno/mod.go | 2 +- gnovm/cmd/gno/run.go | 48 +- gnovm/cmd/gno/run_test.go | 8 + gnovm/cmd/gno/test.go | 72 +- .../gno/testdata/gno_test/empty_gno1.txtar | 5 - .../gno/testdata/gno_test/empty_gno2.txtar | 5 - .../gno/testdata/gno_test/empty_gno3.txtar | 5 - .../testdata/gno_test/failing_filetest.txtar | 8 - .../gno/testdata/gno_test/failing_test.txtar | 7 - gnovm/cmd/gno/transpile.go | 9 +- gnovm/cmd/gno/util.go | 6 - gnovm/pkg/gnolang/debug.go | 15 +- gnovm/pkg/gnolang/debug_false.go | 5 + gnovm/pkg/gnolang/debug_true.go | 5 + gnovm/pkg/gnolang/debugger.go | 781 ++++++++++ gnovm/pkg/gnolang/debugger_test.go | 202 +++ gnovm/pkg/gnolang/eval_test.go | 62 + gnovm/pkg/gnolang/gno_test.go | 12 + gnovm/pkg/gnolang/helpers.go | 2 +- gnovm/pkg/gnolang/machine.go | 30 +- gnovm/pkg/gnolang/nodes.go | 12 +- gnovm/pkg/gnolang/op_eval.go | 4 +- gnovm/pkg/gnolang/op_expressions.go | 107 +- gnovm/pkg/gnolang/preprocess.go | 135 +- gnovm/pkg/gnolang/preprocess_test.go | 60 + gnovm/pkg/gnolang/realm.go | 7 +- gnovm/pkg/gnolang/store.go | 37 +- gnovm/pkg/gnolang/type_check.go | 4 +- gnovm/pkg/gnolang/types.go | 81 +- gnovm/pkg/gnolang/uverse_test.go | 4 +- gnovm/pkg/gnolang/values.go | 3 +- gnovm/pkg/gnolang/values_string.go | 2 +- gnovm/pkg/gnomod/file_test.go | 2 +- gnovm/pkg/transpiler/transpiler.go | 4 +- gnovm/stdlibs/native.go | 19 - gnovm/stdlibs/net/url/url.gno | 9 +- gnovm/stdlibs/std/banker.go | 34 +- gnovm/stdlibs/std/coins.gno | 137 +- gnovm/stdlibs/std/context.go | 26 + gnovm/stdlibs/std/emit_event.go | 4 +- gnovm/stdlibs/std/emit_event_test.go | 5 +- gnovm/stdlibs/std/native.gno | 17 +- gnovm/stdlibs/std/native.go | 39 +- gnovm/stdlibs/std/native_test.go | 194 +++ gnovm/stdlibs/stdlibs.go | 4 + gnovm/stdlibs/stdshim/coins.gno | 125 +- gnovm/stdlibs/stdshim/stdshim.gno | 9 +- gnovm/stdlibs/testing/fuzz.gno | 12 +- gnovm/stdlibs/testing/fuzz_test.gno | 6 +- gnovm/stdlibs/testing/match.gno | 1 - gnovm/stdlibs/testing/random.gno | 5 +- gnovm/stdlibs/testing/testing.gno | 1 - gnovm/stdlibs/time/format.gno | 3 + gnovm/stdlibs/time/time.go | 2 +- gnovm/tests/file.go | 22 +- gnovm/tests/file_test.go | 114 +- .../{access0.gno => access0_stdlibs.gno} | 0 .../{access1.gno => access1_stdlibs.gno} | 2 +- .../{access2.gno => access2_stdlibs.gno} | 0 .../{access3.gno => access3_stdlibs.gno} | 0 .../{access4.gno => access4_stdlibs.gno} | 2 +- .../{access5.gno => access5_stdlibs.gno} | 0 .../{access6.gno => access6_stdlibs.gno} | 2 +- .../{access7.gno => access7_stdlibs.gno} | 2 +- .../append/named_unnamed_type2_filetest.gno | 16 + .../append/named_unnamed_type3_filetest.gno | 15 + .../append/named_unnamed_type_filetest.gno | 35 + .../copy/name_unnamed_type_filetest.gno | 25 + .../method/declaredType0_filetest.gno | 19 + .../method/declaredType0b_filetest.gno | 22 + .../method/declaredType1_filetest.gno | 27 + .../method/declaredType1b_filetest.gno | 27 + .../method/declaredType2_filetest.gno | 27 + .../method/declaredType2b_filetest.gno | 26 + .../method/declaredType3_filetest.gno | 22 + .../method/declaredType3b_filetest.gno | 22 + .../method/declaredType3c_filetest.gno | 26 + .../method/declaredType3d_filetest.gno | 22 + .../method/declaredType4_filetest.gno | 23 + .../method/declaredType5_filetest.gno | 24 + .../method/declaredType6_filetest.gno | 20 + .../method/declaredType6b_filetest.gno | 20 + .../more/assgin_interface2_filetest.gno | 14 + .../more/assgin_interface_filetest.gno | 39 + .../more/assgin_two_filetest.gno | 18 + .../more/assignment_filetest.gno | 26 + .../more/convert_types1b_filetest.gno | 24 + .../more/convert_types_filetest.gno | 21 + ...ss_realm_compositelit_filetest_stdlibs.gno | 13 + .../more/declaredtype2_filetest.gno | 33 + .../more/default_value_filetest.gno | 31 + .../more/errors2_filetest.gno | 17 + .../more/method38d_filetest.gno | 21 + .../more/method38e_filetest.gno | 22 + .../more/method38e_filetest0.gno | 22 + .../more/method38g_filetest.gno | 34 + .../more/realm_compositelit_filetest.gno | 228 +++ .../more/recover6_filetest.gno | 30 + .../more/return2_filetest.gno | 16 + .../more/return_interface1_filetest.gno | 15 + .../more/return_interface_filetest.gno | 19 + .../more/return_select_filetest.gno | 25 + .../files/assign_unnamed_type/type40.gno | 20 + .../unnamedtype0_filetest.gno | 17 + .../unnamedtype0b_filetest.gno | 17 + .../unnamedtype1_filetest.gno | 24 + .../unnamedtype1a_filetest.gno | 23 + .../unnamedtype1b_filetest.gno | 27 + .../unnamedtype1c_filetest.gno | 25 + .../unnamedtype2_filetest.gno | 23 + .../unnamedtype2a_filetest.gno | 23 + .../unnamedtype2b_filetest.gno | 27 + .../unnamedtype2c_filetest.gno | 25 + .../unnamedtype3_filetest.gno | 25 + .../unnamedtype3a_filetest.gno | 25 + .../unnamedtype3b_filetest.gno | 29 + .../unnamedtype3c_filetest.gno | 27 + .../unnamedtype4_filetest.gno | 27 + .../unnamedtype4a_filetest.gno | 27 + .../unnamedtype4b_filetest.gno | 27 + .../unnamedtype4c_filetest.gno | 25 + .../unnamedtype5_filetest.gno | 41 + .../unnamedtype5a_filetest.gno | 32 + .../unnamedtype5b_filetest.gno | 30 + .../unnamedtype5c_filetest.gno | 25 + .../unnamedtype6_filetest.gno | 24 + .../unnamedtype6a_filetest.gno | 24 + .../unnamedtype6b_filetest.gno | 27 + .../unnamedtype6c_filetest.gno | 25 + .../unnamedtype7_filetest.gno | 15 + gnovm/tests/files/convert4.gno | 2 +- gnovm/tests/files/convert5.gno | 2 +- gnovm/tests/files/float5_stdlibs.gno | 6 +- gnovm/tests/files/print1.gno | 2 +- .../files/{std0.gno => std0_stdlibs.gno} | 0 .../files/{std10.gno => std10_stdlibs.gno} | 0 .../files/{std11.gno => std11_stdlibs.gno} | 0 .../files/{std2.gno => std2_stdlibs.gno} | 0 .../files/{std3.gno => std3_stdlibs.gno} | 0 .../files/{std4.gno => std4_stdlibs.gno} | 0 .../files/{std5.gno => std5_stdlibs.gno} | 0 .../files/{std6.gno => std6_stdlibs.gno} | 0 .../files/{std7.gno => std7_stdlibs.gno} | 0 .../files/{std8.gno => std8_stdlibs.gno} | 0 .../files/{std9.gno => std9_stdlibs.gno} | 0 gnovm/tests/files/switch8.gno | 2 +- gnovm/tests/files/switch8b.gno | 2 +- gnovm/tests/files/switch8c.gno | 2 +- gnovm/tests/files/switch9.gno | 2 +- gnovm/tests/files/time16_native.gno | 14 + gnovm/tests/files/typeassert1.gno | 13 + gnovm/tests/files/typeassert2.gno | 32 + gnovm/tests/files/typeassert2a.gno | 15 + gnovm/tests/files/typeassert3.gno | 15 + gnovm/tests/files/typeassert4.gno | 58 + gnovm/tests/files/typeassert4a.gno | 62 + gnovm/tests/files/typeassert5.gno | 30 + gnovm/tests/files/typeassert5a.gno | 29 + gnovm/tests/files/typeassert6.gno | 25 + gnovm/tests/files/typeassert6a.gno | 40 + gnovm/tests/files/typeassert7_native.gno | 44 + gnovm/tests/files/typeassert7a_native.gno | 43 + gnovm/tests/files/typeassert8.gno | 18 + gnovm/tests/files/typeassert8a.gno | 18 + gnovm/tests/files/typeassert9.gno | 20 + gnovm/tests/files/zrealm12.gno | 16 +- ...alm_const.gno => zrealm_const_stdlibs.gno} | 0 ...lm0.gno => zrealm_crossrealm0_stdlibs.gno} | 0 ...10.gno => zrealm_crossrealm10_stdlibs.gno} | 0 ...11.gno => zrealm_crossrealm11_stdlibs.gno} | 0 ...12.gno => zrealm_crossrealm12_stdlibs.gno} | 0 .../files/zrealm_crossrealm13_stdlibs.gno | 48 + .../files/zrealm_crossrealm13a_stdlibs.gno | 46 + ...lm1.gno => zrealm_crossrealm1_stdlibs.gno} | 0 ...lm2.gno => zrealm_crossrealm2_stdlibs.gno} | 0 ...lm3.gno => zrealm_crossrealm3_stdlibs.gno} | 0 ...lm4.gno => zrealm_crossrealm4_stdlibs.gno} | 0 ...lm5.gno => zrealm_crossrealm5_stdlibs.gno} | 0 ...lm6.gno => zrealm_crossrealm6_stdlibs.gno} | 0 ...lm7.gno => zrealm_crossrealm7_stdlibs.gno} | 0 ...lm8.gno => zrealm_crossrealm8_stdlibs.gno} | 0 ...lm9.gno => zrealm_crossrealm9_stdlibs.gno} | 0 ...initctx.gno => zrealm_initctx_stdlibs.gno} | 0 ...tbind0.gno => zrealm_natbind0_stdlibs.gno} | 14 +- ...realm_std0.gno => zrealm_std0_stdlibs.gno} | 0 ...realm_std1.gno => zrealm_std1_stdlibs.gno} | 0 ...realm_std2.gno => zrealm_std2_stdlibs.gno} | 0 ...realm_std3.gno => zrealm_std3_stdlibs.gno} | 4 +- ...realm_std4.gno => zrealm_std4_stdlibs.gno} | 0 ...realm_std5.gno => zrealm_std5_stdlibs.gno} | 0 ...realm_std6.gno => zrealm_std6_stdlibs.gno} | 0 ...m_tests0.gno => zrealm_tests0_stdlibs.gno} | 520 ++++++- ...ils0.gno => zrealm_testutils0_stdlibs.gno} | 0 gnovm/tests/imports.go | 21 +- gnovm/tests/integ/debugger/sample.gno | 46 + gnovm/tests/integ/debugger/sample2.gno | 8 + gnovm/tests/integ/several-lint-errors/gno.mod | 1 + .../tests/integ/several-lint-errors/main.gno | 6 + gnovm/tests/package_test.go | 13 +- gnovm/tests/stdlibs/native.go | 79 +- gnovm/tests/stdlibs/std/frame_testing.gno | 12 + gnovm/tests/stdlibs/std/std.gno | 12 +- gnovm/tests/stdlibs/std/std.go | 92 +- go.mod | 4 +- go.sum | 16 +- misc/autocounterd/README.md | 2 +- misc/autocounterd/cmd/cmd_start.go | 12 +- .../staging.gno.land/docker-compose.yml | 14 +- .../staging.gno.land/overlay/config.toml | 4 +- misc/deployments/test2.gno.land/Makefile | 4 +- .../test2.gno.land/docker-compose.yml | 14 +- .../test2.gno.land/overlay/config.toml | 4 +- misc/deployments/test3.gno.land/Makefile | 4 +- .../test3.gno.land/docker-compose.yml | 15 +- .../test3.gno.land/overlay/config.toml | 4 +- misc/logos/misc_test.go | 5 +- misc/logos/types_test.go | 1 + misc/loop/cmd/cmd_serve.go | 11 +- misc/loop/cmd/main.go | 7 - misc/loop/cmd/snapshotter.go | 15 +- misc/loop/docker-compose.production.yml | 6 +- misc/loop/docker-compose.yml | 4 +- misc/loop/scripts/start.sh | 39 +- misc/loop/tools.go | 2 + misc/loop/traefik/gno.yml | 2 +- misc/telemetry/Makefile | 11 + misc/telemetry/README.md | 56 + misc/telemetry/assets/grafana-1.jpeg | Bin 0 -> 483246 bytes misc/telemetry/assets/grafana-2.jpeg | Bin 0 -> 609302 bytes misc/telemetry/collector/collector.yaml | 22 + misc/telemetry/docker-compose.yml | 65 + misc/telemetry/gnoland/Dockerfile | 13 + misc/telemetry/gnoland/setup.sh | 19 + misc/telemetry/grafana/dashboards.yaml | 8 + misc/telemetry/grafana/datasources.yaml | 13 + misc/telemetry/grafana/gno-dashboards.json | 1360 ++++++++++++++++ misc/telemetry/prometheus/prometheus.yml | 7 + misc/telemetry/supernova.Dockerfile | 12 + tm2/{LICENSE.md => LICENSE} | 1 - tm2/Makefile | 4 +- tm2/pkg/amino/genproto/bindings.go | 48 +- tm2/pkg/bft/config/config.go | 66 +- tm2/pkg/bft/config/config_test.go | 3 + tm2/pkg/bft/config/toml.go | 4 +- tm2/pkg/bft/consensus/common_test.go | 46 + tm2/pkg/bft/consensus/state.go | 27 + tm2/pkg/bft/consensus/state_test.go | 75 +- tm2/pkg/bft/mempool/clist_mempool.go | 33 +- tm2/pkg/bft/rpc/config/config.go | 4 +- tm2/pkg/bft/rpc/lib/server/handlers.go | 55 +- tm2/pkg/bft/state/state_test.go | 4 +- tm2/pkg/bft/types/params.go | 2 +- tm2/pkg/commands/command.go | 10 +- tm2/pkg/commands/errors.go | 16 + tm2/pkg/crypto/internal/ledger/discover.go | 83 + .../keys/client/add_ledger_skipped_test.go | 10 - tm2/pkg/crypto/keys/client/add_ledger_test.go | 15 +- tm2/pkg/crypto/keys/client/query.go | 19 +- .../keys/keybase_ledger_skipped_test.go | 18 - tm2/pkg/crypto/keys/keybase_ledger_test.go | 10 +- tm2/pkg/crypto/ledger/discover.go | 19 - tm2/pkg/crypto/ledger/discover_mock.go | 69 - tm2/pkg/crypto/ledger/ledger_secp256k1.go | 29 +- tm2/pkg/db/_all/all.go | 5 - tm2/pkg/db/_all/all_cgo.go | 10 - tm2/pkg/db/_tags/cleveldb.go | 5 - tm2/pkg/db/_tags/fsdb.go | 5 - tm2/pkg/db/_tags/rocksdb.go | 5 - tm2/pkg/db/cleveldb/c_level_db.go | 326 ---- tm2/pkg/db/cleveldb/c_level_db_test.go | 112 -- tm2/pkg/db/cleveldb/no_cgo_test.go | 9 - tm2/pkg/db/db.go | 12 - tm2/pkg/db/fsdb/fsdb.go | 276 ---- tm2/pkg/db/rocksdb/grocks_db.go | 342 ---- tm2/pkg/db/rocksdb/grocks_db_test.go | 34 - tm2/pkg/db/rocksdb/no_cgo_test.go | 9 - tm2/pkg/iavl/benchmarks/bench_test.go | 14 +- tm2/pkg/iavl/with_gcc_test.go | 19 - tm2/pkg/p2p/config/config.go | 2 +- tm2/pkg/p2p/fuzz.go | 22 - tm2/pkg/p2p/switch.go | 24 + tm2/pkg/p2p/test_util.go | 18 - tm2/pkg/sdk/baseapp.go | 13 +- tm2/pkg/std/coin.go | 3 +- tm2/pkg/std/coin_test.go | 2 +- tm2/pkg/std/memfile.go | 7 + tm2/pkg/std/memfile_test.go | 288 ++-- tm2/pkg/telemetry/README.md | 23 +- tm2/pkg/telemetry/config/config.go | 24 +- tm2/pkg/telemetry/config/config_test.go | 29 + tm2/pkg/telemetry/exporter/error.go | 5 - tm2/pkg/telemetry/init.go | 35 +- tm2/pkg/telemetry/metrics/init.go | 69 - tm2/pkg/telemetry/metrics/metrics.go | 286 ++++ 454 files changed, 14938 insertions(+), 7122 deletions(-) create mode 100644 .github/goreleaser-master.yaml create mode 100644 .github/goreleaser-nightly.yaml create mode 100644 .github/goreleaser.yaml rename .github/workflows/{benchmark.yml => benchmark_template.yml} (97%) create mode 100644 .github/workflows/build_template.yml delete mode 100644 .github/workflows/codegen.yml delete mode 100644 .github/workflows/db-tests.yml delete mode 100644 .github/workflows/docker.yml rename .github/workflows/{lint-pr.yml => lint-pr-title.yml} (94%) delete mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/lint_template.yml create mode 100644 .github/workflows/main_template.yml create mode 100644 .github/workflows/nightlies.yml create mode 100644 .github/workflows/releaser-master.yml create mode 100644 .github/workflows/releaser.yml create mode 100644 .github/workflows/test_template.yml delete mode 100644 Dockerfile create mode 100644 Dockerfile.release create mode 100644 docs/assets/getting-started/local-setup/setting-up-a-local-chain/gnoland-start-manual.gif create mode 100644 examples/gno.land/r/demo/event/event.gno create mode 100644 examples/gno.land/r/demo/event/gno.mod create mode 100644 examples/gno.land/r/demo/gasbanktest/README.md create mode 100644 examples/gno.land/r/demo/gasbanktest/banktest.gno create mode 100644 examples/gno.land/r/demo/gasbanktest/gno.mod create mode 100644 examples/gno.land/r/demo/gasbanktest/z_0_filetest.gno create mode 100644 examples/gno.land/r/demo/gasbanktest/z_1_filetest.gno create mode 100644 examples/gno.land/r/demo/gasbanktest/z_2_filetest.gno create mode 100644 examples/gno.land/r/demo/grc20factory/gno.mod create mode 100644 examples/gno.land/r/demo/grc20factory/grc20factory.gno create mode 100644 examples/gno.land/r/demo/grc20factory/grc20factory_test.gno create mode 100644 examples/gno.land/r/demo/tests/realm_compositelit.gno create mode 100644 examples/gno.land/r/demo/tests/realm_method38d.gno rename examples/gno.land/r/gnoland/{pages/page_events.gno => events/events.gno} (64%) create mode 100644 examples/gno.land/r/gnoland/events/events_filetest.gno create mode 100644 examples/gno.land/r/gnoland/events/gno.mod create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/README.md create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/v1.gno create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v1/z_filetest.gno create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/v2.gno create mode 100644 examples/gno.land/r/x/manfred_upgrade_patterns/upgrade_d/v2/z_filetest.gno delete mode 100644 gno.land/LICENSE.md create mode 100644 gno.land/cmd/gnoland/testdata/assertorigincall.txtar create mode 100644 gno.land/cmd/gnoland/testdata/event_multi_msg.txtar create mode 100644 gno.land/cmd/gnoland/testdata/maketx_call_pure.txtar rename gno.land/cmd/gnoland/testdata/{map-delete.txtar => map_delete.txtar} (100%) create mode 100644 gno.land/cmd/gnoland/testdata/prevrealm.txtar create mode 100644 gno.land/cmd/gnoland/testdata/realm_banker_issued_coin_denom.txtar create mode 100644 gno.land/cmd/gnoland/testdata/time-simple.txtar create mode 100644 gno.land/pkg/gnoweb/static/img/apple-touch-icon.png create mode 100644 gno.land/pkg/gnoweb/static/img/favicon-16x16.png create mode 100644 gno.land/pkg/gnoweb/static/img/favicon-32x32.png delete mode 100644 gno.land/pkg/gnoweb/static/img/logo.png delete mode 100644 gno.land/pkg/gnoweb/static/img/logo.svg create mode 100644 gno.land/pkg/gnoweb/static/img/og-gnoland.png create mode 100644 gno.land/pkg/gnoweb/static/img/safari-pinned-tab.svg create mode 100644 gno.land/pkg/integration/testdata/improved-coins.txtar create mode 100644 gnovm/1.gno delete mode 100644 gnovm/LICENSE.md create mode 100644 gnovm/pkg/gnolang/debug_false.go create mode 100644 gnovm/pkg/gnolang/debug_true.go create mode 100644 gnovm/pkg/gnolang/debugger.go create mode 100644 gnovm/pkg/gnolang/debugger_test.go create mode 100644 gnovm/pkg/gnolang/eval_test.go create mode 100644 gnovm/pkg/gnolang/preprocess_test.go create mode 100644 gnovm/stdlibs/std/native_test.go rename gnovm/tests/files/{access0.gno => access0_stdlibs.gno} (100%) rename gnovm/tests/files/{access1.gno => access1_stdlibs.gno} (53%) rename gnovm/tests/files/{access2.gno => access2_stdlibs.gno} (100%) rename gnovm/tests/files/{access3.gno => access3_stdlibs.gno} (100%) rename gnovm/tests/files/{access4.gno => access4_stdlibs.gno} (57%) rename gnovm/tests/files/{access5.gno => access5_stdlibs.gno} (100%) rename gnovm/tests/files/{access6.gno => access6_stdlibs.gno} (67%) rename gnovm/tests/files/{access7.gno => access7_stdlibs.gno} (72%) create mode 100644 gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type3_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/append/named_unnamed_type_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/copy/name_unnamed_type_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType0_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType0b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType1_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType1b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType2b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType3_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType3b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType3c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType3d_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType4_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType5_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/assgin_interface2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/assgin_interface_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/assgin_two_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/assignment_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/convert_types1b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/convert_types_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/cross_realm_compositelit_filetest_stdlibs.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/declaredtype2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/default_value_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/errors2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/method38d_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/method38e_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/method38e_filetest0.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/method38g_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/recover6_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/return2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/return_interface1_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/return_interface_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/more/return_select_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/type40.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype0_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype1_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype1a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype1b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype1c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype2a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype2b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype2c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype3_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype3a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype3b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype3c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype4_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype4a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype4b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype4c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype5_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype5a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype5b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype5c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype6_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype6a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype6b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype6c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/unnamedtype7_filetest.gno rename gnovm/tests/files/{std0.gno => std0_stdlibs.gno} (100%) rename gnovm/tests/files/{std10.gno => std10_stdlibs.gno} (100%) rename gnovm/tests/files/{std11.gno => std11_stdlibs.gno} (100%) rename gnovm/tests/files/{std2.gno => std2_stdlibs.gno} (100%) rename gnovm/tests/files/{std3.gno => std3_stdlibs.gno} (100%) rename gnovm/tests/files/{std4.gno => std4_stdlibs.gno} (100%) rename gnovm/tests/files/{std5.gno => std5_stdlibs.gno} (100%) rename gnovm/tests/files/{std6.gno => std6_stdlibs.gno} (100%) rename gnovm/tests/files/{std7.gno => std7_stdlibs.gno} (100%) rename gnovm/tests/files/{std8.gno => std8_stdlibs.gno} (100%) rename gnovm/tests/files/{std9.gno => std9_stdlibs.gno} (100%) create mode 100644 gnovm/tests/files/time16_native.gno create mode 100644 gnovm/tests/files/typeassert1.gno create mode 100644 gnovm/tests/files/typeassert2.gno create mode 100644 gnovm/tests/files/typeassert2a.gno create mode 100644 gnovm/tests/files/typeassert3.gno create mode 100644 gnovm/tests/files/typeassert4.gno create mode 100644 gnovm/tests/files/typeassert4a.gno create mode 100644 gnovm/tests/files/typeassert5.gno create mode 100644 gnovm/tests/files/typeassert5a.gno create mode 100644 gnovm/tests/files/typeassert6.gno create mode 100644 gnovm/tests/files/typeassert6a.gno create mode 100644 gnovm/tests/files/typeassert7_native.gno create mode 100644 gnovm/tests/files/typeassert7a_native.gno create mode 100644 gnovm/tests/files/typeassert8.gno create mode 100644 gnovm/tests/files/typeassert8a.gno create mode 100644 gnovm/tests/files/typeassert9.gno rename gnovm/tests/files/{zrealm_const.gno => zrealm_const_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm0.gno => zrealm_crossrealm0_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm10.gno => zrealm_crossrealm10_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm11.gno => zrealm_crossrealm11_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm12.gno => zrealm_crossrealm12_stdlibs.gno} (100%) create mode 100644 gnovm/tests/files/zrealm_crossrealm13_stdlibs.gno create mode 100644 gnovm/tests/files/zrealm_crossrealm13a_stdlibs.gno rename gnovm/tests/files/{zrealm_crossrealm1.gno => zrealm_crossrealm1_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm2.gno => zrealm_crossrealm2_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm3.gno => zrealm_crossrealm3_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm4.gno => zrealm_crossrealm4_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm5.gno => zrealm_crossrealm5_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm6.gno => zrealm_crossrealm6_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm7.gno => zrealm_crossrealm7_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm8.gno => zrealm_crossrealm8_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_crossrealm9.gno => zrealm_crossrealm9_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_initctx.gno => zrealm_initctx_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_natbind0.gno => zrealm_natbind0_stdlibs.gno} (95%) rename gnovm/tests/files/{zrealm_std0.gno => zrealm_std0_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_std1.gno => zrealm_std1_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_std2.gno => zrealm_std2_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_std3.gno => zrealm_std3_stdlibs.gno} (65%) rename gnovm/tests/files/{zrealm_std4.gno => zrealm_std4_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_std5.gno => zrealm_std5_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_std6.gno => zrealm_std6_stdlibs.gno} (100%) rename gnovm/tests/files/{zrealm_tests0.gno => zrealm_tests0_stdlibs.gno} (69%) rename gnovm/tests/files/{zrealm_testutils0.gno => zrealm_testutils0_stdlibs.gno} (100%) create mode 100644 gnovm/tests/integ/debugger/sample.gno create mode 100644 gnovm/tests/integ/debugger/sample2.gno create mode 100644 gnovm/tests/integ/several-lint-errors/gno.mod create mode 100644 gnovm/tests/integ/several-lint-errors/main.gno create mode 100644 gnovm/tests/stdlibs/std/frame_testing.gno create mode 100644 misc/telemetry/Makefile create mode 100644 misc/telemetry/README.md create mode 100644 misc/telemetry/assets/grafana-1.jpeg create mode 100644 misc/telemetry/assets/grafana-2.jpeg create mode 100644 misc/telemetry/collector/collector.yaml create mode 100644 misc/telemetry/docker-compose.yml create mode 100644 misc/telemetry/gnoland/Dockerfile create mode 100644 misc/telemetry/gnoland/setup.sh create mode 100644 misc/telemetry/grafana/dashboards.yaml create mode 100644 misc/telemetry/grafana/datasources.yaml create mode 100644 misc/telemetry/grafana/gno-dashboards.json create mode 100644 misc/telemetry/prometheus/prometheus.yml create mode 100644 misc/telemetry/supernova.Dockerfile rename tm2/{LICENSE.md => LICENSE} (99%) create mode 100644 tm2/pkg/commands/errors.go create mode 100644 tm2/pkg/crypto/internal/ledger/discover.go delete mode 100644 tm2/pkg/crypto/keys/client/add_ledger_skipped_test.go delete mode 100644 tm2/pkg/crypto/keys/keybase_ledger_skipped_test.go delete mode 100644 tm2/pkg/crypto/ledger/discover.go delete mode 100644 tm2/pkg/crypto/ledger/discover_mock.go delete mode 100644 tm2/pkg/db/_all/all_cgo.go delete mode 100644 tm2/pkg/db/_tags/cleveldb.go delete mode 100644 tm2/pkg/db/_tags/fsdb.go delete mode 100644 tm2/pkg/db/_tags/rocksdb.go delete mode 100644 tm2/pkg/db/cleveldb/c_level_db.go delete mode 100644 tm2/pkg/db/cleveldb/c_level_db_test.go delete mode 100644 tm2/pkg/db/cleveldb/no_cgo_test.go delete mode 100644 tm2/pkg/db/fsdb/fsdb.go delete mode 100644 tm2/pkg/db/rocksdb/grocks_db.go delete mode 100644 tm2/pkg/db/rocksdb/grocks_db_test.go delete mode 100644 tm2/pkg/db/rocksdb/no_cgo_test.go delete mode 100644 tm2/pkg/iavl/with_gcc_test.go create mode 100644 tm2/pkg/telemetry/config/config_test.go delete mode 100644 tm2/pkg/telemetry/exporter/error.go delete mode 100644 tm2/pkg/telemetry/metrics/init.go create mode 100644 tm2/pkg/telemetry/metrics/metrics.go diff --git a/.github/codecov.yml b/.github/codecov.yml index ecd223f0e84..ea1c701d946 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,11 +1,8 @@ codecov: - require_ci_to_pass: false + require_ci_to_pass: true notify: wait_for_ci: true -ignore: - - misc - comment: require_changes: false @@ -25,7 +22,7 @@ coverage: patch: default: target: auto - threshold: 100 # Allows PRs without tests, overall stats count. + threshold: 10 # Let's decrease this later. base: auto if_no_uploads: error if_not_found: success @@ -40,18 +37,5 @@ flag_management: target: auto threshold: 10 # Let's decrease this later. - type: patch - target: auto # Allows PRs without tests, overall stats count. - threshold: 100 - individual_flags: - - name: tm2 - paths: - - tm2 - - name: gnovm - paths: - - gnovm - - name: gno.land - paths: - - gno.land - - name: misc - paths: - - misc + target: auto # Let's decrease this later. + threshold: 10 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f5f686570e2..6a2a2966370 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -28,11 +28,6 @@ updates: everything-else: patterns: - "*" - exclude-patterns: - # NOTE: grocksdb should be updated manually, to match the version - # available on Ubuntu's latest LTS release; and updated in conjunction - # with the ubuntu version on .github/workflows/db-tests.yml - - "github.com/linxGnu/grocksdb" open-pull-requests-limit: 10 pull-request-branch-name: separator: "-" diff --git a/.github/golangci.yml b/.github/golangci.yml index 8b38691ec75..e78d09a582e 100644 --- a/.github/golangci.yml +++ b/.github/golangci.yml @@ -38,6 +38,7 @@ linters: - gofumpt # Stricter gofmt - unused # Checks Go code for unused constants, variables, functions and types - gomodguard # Enforces an allow and block list for direct Go module dependencies + - forbidigo # Forbids some custom-set identifiers, like regexp.MatchString linters-settings: gofmt: @@ -60,6 +61,10 @@ linters-settings: - opinionated - performance - style + forbidigo: + forbid: + - p: '^regexp\.(Match|MatchString)$' + msg: it will re-compile the regexp for each execution; compile the regexp with regexp.Compile and store it as a singleton issues: whole-files: true diff --git a/.github/goreleaser-master.yaml b/.github/goreleaser-master.yaml new file mode 100644 index 00000000000..ffe122153da --- /dev/null +++ b/.github/goreleaser-master.yaml @@ -0,0 +1,502 @@ +project_name: gno + +before: + hooks: + - go mod tidy + +builds: + - id: gno + main: ./gnovm/cmd/gno + binary: gno + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnoland + main: ./gno.land/cmd/gnoland + binary: gnoland + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnokey + main: ./gno.land/cmd/gnokey + binary: gnokey + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnoweb + main: ./gno.land/cmd/gnoweb + binary: gnoweb + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 +gomod: + proxy: true + +archives: + # https://goreleaser.com/customization/archive/ + - files: + # Standard Release Files + - LICENSE.md + - README.md + +signs: + - cmd: cosign + env: + - COSIGN_EXPERIMENTAL=1 + certificate: "${artifact}.pem" + args: + - sign-blob + - "--output-certificate=${certificate}" + - "--output-signature=${signature}" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + artifacts: checksum + output: true + +dockers: + # https://goreleaser.com/customization/docker/ + + # gno + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}:master-amd64" + build_flag_templates: + - "--target=gno" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}:master-arm64v8" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}:master-armv6" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}:master-armv7" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + + # gnoland + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-amd64" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-arm64v8" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv6" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv7" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + # gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-amd64" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-arm64v8" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv6" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv7" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + + # gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-amd64" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-arm64v8" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv6" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv7" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + +docker_manifests: + # https://goreleaser.com/customization/docker_manifest/ + + # gno + - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}:master + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}:master-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}:master-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}:master-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}:master-armv7 + + # gnoland + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv7 + + # gnokey + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv7 + + # gnoweb + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv7 + +docker_signs: + - cmd: cosign + env: + - COSIGN_EXPERIMENTAL=1 + artifacts: images + output: true + args: + - "sign" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + +checksum: + name_template: "checksums.txt" + +changelog: + sort: asc + +source: + enabled: true + +sboms: + - artifacts: archive + - id: source # Two different sbom configurations need two different IDs + artifacts: source + +release: + draft: true + replace_existing_draft: true + prerelease: auto + make_latest: false + mode: append + footer: | + ### Container Images + + You can find all docker images at: + + https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} + +nightly: + tag_name: master + publish_release: true + keep_single_release: true diff --git a/.github/goreleaser-nightly.yaml b/.github/goreleaser-nightly.yaml new file mode 100644 index 00000000000..0cb2a50b633 --- /dev/null +++ b/.github/goreleaser-nightly.yaml @@ -0,0 +1,501 @@ +project_name: gno + +before: + hooks: + - go mod tidy + +builds: + - id: gno + main: ./gnovm/cmd/gno + binary: gno + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnoland + main: ./gno.land/cmd/gnoland + binary: gnoland + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnokey + main: ./gno.land/cmd/gnokey + binary: gnokey + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnoweb + main: ./gno.land/cmd/gnoweb + binary: gnoweb + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 +gomod: + proxy: true + +archives: + # https://goreleaser.com/customization/archive/ + - files: + # Standard Release Files + - LICENSE.md + - README.md + +signs: + - cmd: cosign + env: + - COSIGN_EXPERIMENTAL=1 + certificate: "${artifact}.pem" + args: + - sign-blob + - "--output-certificate=${certificate}" + - "--output-signature=${signature}" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + artifacts: checksum + output: true + +dockers: + # https://goreleaser.com/customization/docker/ + + # gno + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-amd64" + build_flag_templates: + - "--target=gno" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-arm64v8" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv6" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv7" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + + # gnoland + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-amd64" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-arm64v8" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv6" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv7" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + # gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-amd64" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-arm64v8" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv6" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv7" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + + # gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-amd64" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-arm64v8" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv6" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv7" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + +docker_manifests: + # https://goreleaser.com/customization/docker_manifest/ + + # gno + - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}:nightly + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}:nightly-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}:nightly-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv7 + + # gnoland + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv7 + + # gnokey + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv7 + + # gnoweb + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv7 + +docker_signs: + - cmd: cosign + env: + - COSIGN_EXPERIMENTAL=1 + artifacts: images + output: true + args: + - "sign" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + +checksum: + name_template: "checksums.txt" + +changelog: + sort: asc + +source: + enabled: true + +sboms: + - artifacts: archive + - id: source # Two different sbom configurations need two different IDs + artifacts: source + +release: + draft: true + replace_existing_draft: true + prerelease: auto + mode: append + footer: | + ### Container Images + + You can find all docker images at: + + https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} + +nightly: + tag_name: nightly + publish_release: true + keep_single_release: true diff --git a/.github/goreleaser.yaml b/.github/goreleaser.yaml new file mode 100644 index 00000000000..35fdfbea0e5 --- /dev/null +++ b/.github/goreleaser.yaml @@ -0,0 +1,501 @@ +project_name: gno + +before: + hooks: + - go mod tidy + +builds: + - id: gno + main: ./gnovm/cmd/gno + binary: gno + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnoland + main: ./gno.land/cmd/gnoland + binary: gnoland + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnokey + main: ./gno.land/cmd/gnokey + binary: gnokey + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 + - id: gnoweb + main: ./gno.land/cmd/gnoweb + binary: gnoweb + env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + - arm + goarm: + - 6 + - 7 +gomod: + proxy: true + +archives: + # https://goreleaser.com/customization/archive/ + - files: + # Standard Release Files + - LICENSE.md + - README.md + +signs: + - cmd: cosign + env: + - COSIGN_EXPERIMENTAL=1 + certificate: "${artifact}.pem" + args: + - sign-blob + - "--output-certificate=${certificate}" + - "--output-signature=${signature}" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + artifacts: checksum + output: true + +dockers: + # https://goreleaser.com/customization/docker/ + + # gno + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}:latest-amd64" + build_flag_templates: + - "--target=gno" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}:latest-arm64v8" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}:latest-armv6" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}:latest-armv7" + build_flag_templates: + - "--target=gno" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gno + extra_files: + - examples + - gnovm/stdlibs + - gnovm/tests/stdlibs + + # gnoland + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-amd64" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-arm64v8" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-armv6" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-armv7" + build_flag_templates: + - "--target=gnoland" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoland + extra_files: + - gno.land/genesis/genesis_balances.txt + - gno.land/genesis/genesis_txs.jsonl + - examples + - gnovm/stdlibs + # gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-amd64" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-arm64v8" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-armv6" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-armv7" + build_flag_templates: + - "--target=gnokey" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnokey + + # gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: amd64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-amd64" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/amd64" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm64 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-arm64v8" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm64/v8" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 6 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-armv6" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm/v6" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + - use: buildx + dockerfile: Dockerfile.release + goos: linux + goarch: arm + goarm: 7 + image_templates: + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" + - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-armv7" + build_flag_templates: + - "--target=gnoweb" + - "--platform=linux/arm/v7" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + ids: + - gnoweb + +docker_manifests: + # https://goreleaser.com/customization/docker_manifest/ + + # gno + - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}:latest + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}:latest-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}:latest-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}:latest-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}:latest-armv7 + + # gnoland + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:latest-armv7 + + # gnokey + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:latest-armv7 + + # gnoweb + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 + - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest + image_templates: + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-amd64 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-arm64v8 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-armv6 + - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:latest-armv7 + +docker_signs: + - cmd: cosign + env: + - COSIGN_EXPERIMENTAL=1 + artifacts: images + output: true + args: + - "sign" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + +checksum: + name_template: "checksums.txt" + +changelog: + sort: asc + +source: + enabled: true + +sboms: + - artifacts: archive + - id: source # Two different sbom configurations need two different IDs + artifacts: source + +release: + draft: true + replace_existing_draft: true + prerelease: auto + mode: append + footer: | + ### Container Images + + You can find all docker images at: + + https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} + +nightly: + tag_name: nightly + publish_release: true + keep_single_release: true diff --git a/.github/workflows/autocounterd.yml b/.github/workflows/autocounterd.yml index 3c1812a3ba1..c8251a05490 100644 --- a/.github/workflows/autocounterd.yml +++ b/.github/workflows/autocounterd.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Login to GitHub Container Registry uses: docker/login-action@v2 @@ -29,11 +29,11 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Docker metadata autcounterd + - name: Docker metadata autocounterd id: meta uses: docker/metadata-action@v5 with: - images: ghcr.io/${{ github.repository }}/autcounterd + images: ghcr.io/${{ github.repository }}/autocounterd tags: | type=raw,value=latest type=semver,pattern=v{{version}} diff --git a/.github/workflows/benchmark-check.yml b/.github/workflows/benchmark-check.yml index 3946f2145e4..9009f23f80e 100644 --- a/.github/workflows/benchmark-check.yml +++ b/.github/workflows/benchmark-check.yml @@ -3,13 +3,9 @@ name: run benchmarks on every PR on: pull_request: -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - jobs: check: - uses: ./.github/workflows/benchmark.yml + uses: ./.github/workflows/benchmark_template.yml secrets: inherit with: publish: false diff --git a/.github/workflows/benchmark-publish.yml b/.github/workflows/benchmark-publish.yml index 4fb0a717635..8baa4c7889b 100644 --- a/.github/workflows/benchmark-publish.yml +++ b/.github/workflows/benchmark-publish.yml @@ -6,7 +6,7 @@ on: - cron: '0 0 * * *' # run on default branch every day jobs: publish: - uses: ./.github/workflows/benchmark.yml + uses: ./.github/workflows/benchmark_template.yml secrets: inherit with: publish: true diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark_template.yml similarity index 97% rename from .github/workflows/benchmark.yml rename to .github/workflows/benchmark_template.yml index 74686be6a8f..bdd3d607ca3 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark_template.yml @@ -8,6 +8,10 @@ on: test-flags: required: true type: string + +env: + CGO_ENABLED: 0 + jobs: benchmarks: if: ${{ github.repository == 'gnolang/gno' }} diff --git a/.github/workflows/build_template.yml b/.github/workflows/build_template.yml new file mode 100644 index 00000000000..a984589caaa --- /dev/null +++ b/.github/workflows/build_template.yml @@ -0,0 +1,31 @@ +on: + workflow_call: + inputs: + modulepath: + required: true + type: string + go-version: + required: true + type: string + +jobs: + generated: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go-version }} + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check generated files are up to date + working-directory: ${{ inputs.modulepath }} + run: | + go generate -x ./... + if [ "$(git status -s)" != "" ]; then + echo "command 'go generate' creates file that differ from git tree, please run 'go generate' and commit:" + git status -s + exit 1 + fi diff --git a/.github/workflows/codegen.yml b/.github/workflows/codegen.yml deleted file mode 100644 index 206a7bda0cf..00000000000 --- a/.github/workflows/codegen.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: code generation - -on: - push: - branches: [ "master" ] - pull_request: - paths: - - 'gnovm/stdlibs/**' - - 'gnovm/tests/stdlibs/**' - - 'misc/genstd' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - generated: - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: 1.22.x - - - name: Checkout code - uses: actions/checkout@v4 - - - name: Check generated files are up to date - run: | - go generate -x ./... - if [ "$(git status -s)" != "" ]; then - echo "command 'go generate' creates file that differ from git tree, please run 'go generate' and commit:" - git status -s - exit 1 - fi - diff --git a/.github/workflows/contribs.yml b/.github/workflows/contribs.yml index 4e07a4e8afb..8fdcce9332c 100644 --- a/.github/workflows/contribs.yml +++ b/.github/workflows/contribs.yml @@ -2,74 +2,32 @@ name: contribs on: push: - branches: [ "master" ] - pull_request: + branches: + - master + workflow_dispatch: + pull_request: paths: - "contribs/**" - - ".github/workflows/contribs.yml" - - "gnovm/**.go" - - "gno.land/**.go" - - "tm2/**.go" - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + - ".github/**" jobs: - install: - strategy: - fail-fast: false - matrix: - goversion: - - "1.22.x" - program: - - "gnomd" - - "gnodev" - - "gnofaucet" - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - run: make install.${{ matrix.program }} - working-directory: contribs - - test: - strategy: - fail-fast: false - matrix: - goversion: # two latest versions - - "1.21.x" - - "1.22.x" - program: - - "gnodev" + setup: runs-on: ubuntu-latest - timeout-minutes: 5 + outputs: + programs: ${{ steps.set-matrix.outputs.programs }} steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version: ${{ matrix.goversion }} - - run: make test.${{ matrix.program }} - working-directory: contribs - - lint: + - id: set-matrix + run: echo "::set-output name=programs::$(ls -d contribs/*/ | cut -d/ -f2 | jq -R -s -c 'split("\n")[:-1]')" + main: + needs: setup strategy: - fail-fast: false - matrix: - goversion: - - "1.22.x" - program: - - "gnodev" - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version: ${{ matrix.goversion }} - - run: make lint.${{ matrix.program }} - working-directory: contribs - + fail-fast: false + matrix: + program: ${{ fromJson(needs.setup.outputs.programs) }} + name: Run Main + uses: ./.github/workflows/main_template.yml + with: + modulepath: contribs/${{ matrix.program }} + secrets: + codecov-token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/db-tests.yml b/.github/workflows/db-tests.yml deleted file mode 100644 index 362b9e16e6f..00000000000 --- a/.github/workflows/db-tests.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: db-tests - -on: - pull_request: - paths: - - "tm2/pkg/db/**.go" - - "go.sum" - - ".github/workflows/db-tests.yml" - push: - branches: [ "master" ] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - test: - # NOTE: this job uses a specific version of ubuntu as the version of grocksb - # we use is related to the version of RocksDB in ubuntu's repositories. - # If updating this to a later ubuntu release, update the grocksdb version - # accordingly: - # https://github.com/linxGnu/grocksdb/releases - # https://pkgs.org/search/?q=rocksdb-dev - runs-on: ubuntu-22.04 - timeout-minutes: 5 - strategy: - fail-fast: false - matrix: - goversion: - - "1.21.x" - - "1.22.x" - steps: - - uses: actions/checkout@v4 - - # golang - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - - name: install database dependencies - run: sudo apt-get install -y libleveldb-dev librocksdb-dev - - - name: Set environment variables for debug mode - if: env.ACTIONS_STEP_DEBUG == 'true' - run: | - export LOG_PATH_DIR=${{ runner.temp }}/logs - mkdir -p $LOG_PATH_DIR - - echo "LOG_LEVEL=debug" >> $GITHUB_ENV - echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - - # test ./pkgs/db - - name: test ./tm2/pkg/db - run: go test -v ./tm2/pkg/db/... diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 5dab03c1f7f..79680369822 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -14,7 +14,7 @@ jobs: with: github-token: ${{ secrets.DOCS_DEPLOY_PAT }} script: | - await github.rest.actions.createworkflowDispatch({ + await github.rest.actions.createWorkflowDispatch({ owner: 'gnolang', repo: 'docs.gno.land', workflow_id: 'netlify.yml', diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 9616f6c06dd..00000000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: docker -on: - pull_request: - paths: - - "**" - - "!misc/**" - - "!docs/**" - - "!**.md" - push: - branches: [ "master" ] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - build-main: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Get commit SHA - id: commit - run: echo "sha=${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - if: (github.event_name != 'pull_request') - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v3 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: | - ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest - ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ steps.commit.outputs.sha }} - - build-slim: - runs-on: ubuntu-latest - strategy: - matrix: - target: [ gnoland-slim, gnokey-slim, gno-slim, gnofaucet-slim, gnoweb-slim ] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Get commit SHA - id: commit - run: echo "sha=${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - if: (github.event_name != 'pull_request') - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v3 - with: - context: . - platforms: linux/amd64,linux/arm64 - target: ${{ matrix.target }} - push: ${{ github.event_name != 'pull_request' }} - tags: | - ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.target }}:latest - ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}/${{ matrix.target }}:${{ steps.commit.outputs.sha }} diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index be95eec7a50..a01f465f38b 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -4,10 +4,8 @@ on: pull_request: paths: - "go.sum" - - "gnovm/**.go" - - "gnovm/**.gno" - - "gnovm/**/go.sum" - - "examples/**.gno" + - "gnovm/**" + - "examples/**" - ".github/workflows/examples.yml" push: branches: [ "master" ] @@ -53,7 +51,6 @@ jobs: run: | export LOG_PATH_DIR=${{ runner.temp }}/logs mkdir -p $LOG_PATH_DIR - echo "LOG_LEVEL=debug" >> $GITHUB_ENV echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - run: go install -v ./gnovm/cmd/gno @@ -95,4 +92,4 @@ jobs: # Find all directories containing gno.mod file find ./examples -name "gno.mod" -execdir go run "$GNO_CMD" mod tidy \; # Check if there are changes after running gno mod tidy - git diff --exit-code || (echo "Some gno.mod files are not tidy, please run 'make tidy'." && exit 1) + git diff --exit-code || (echo "Some gno.mod files are not tidy, please run 'make tidy'." && exit 1) \ No newline at end of file diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml index 0481be8ebb6..97df3f13a2a 100644 --- a/.github/workflows/gnoland.yml +++ b/.github/workflows/gnoland.yml @@ -1,129 +1,20 @@ name: gno.land on: - pull_request: + push: + branches: + - master + workflow_dispatch: + pull_request: paths: - # XXX: for now keep the paths for gnovm, tm2, gnoland and misc the same, - # so that coverage information is uploaded for all of them together. - # This could be removed in the future. - - "gnovm/**" - - "tm2/**" - - "gno.land/**" - - "misc/**" - - "examples/**" - - ".github/workflows/**" - # XXX: end copied part, below is the "ideal" paths on which this workflow should run - - "go.sum" - - "gnovm/**.go" - - "gnovm/**.gno" - - "tm2/**.go" - "gno.land/**" - - ".github/workflows/gnoland.yml" - push: - branches: [ "master" ] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + - ".github/**" jobs: - build: - strategy: - fail-fast: false - matrix: - goversion: - - "1.21.x" - - "1.22.x" - goarch: [ "amd64" ] - goos: [ "linux" ] - program: - - gnoland - - gnokey - - gnoweb - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: go install - working-directory: gno.land - run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go install ./cmd/${{ matrix.program }} - - test: - strategy: - fail-fast: false - matrix: - goversion: - - "1.21.x" - - "1.22.x" - args: - - _test.gnoland - - _test.gnokey - - _test.pkgs - - _test.gnoweb - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: Set environment variables for debug mode - if: ${{ runner.debug == 1 }} - run: | - export LOG_PATH_DIR=${{ runner.temp }}/logs-go${{ matrix.goversion }}-${{ matrix.args }} - mkdir -p $LOG_PATH_DIR - - echo "LOG_LEVEL=debug" >> $GITHUB_ENV - echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - - name: test - working-directory: gno.land - run: | - export GOPATH=$HOME/go - export GOTEST_FLAGS="-v -p 1 -timeout=30m -coverprofile=coverage.out -covermode=atomic" - make ${{ matrix.args }} - - uses: actions/upload-artifact@v4 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} - with: - name: ${{runner.os}}-coverage-gnoland-${{ matrix.args}}-${{matrix.goversion}} - path: ./gno.land/coverage.out - - name: Upload Debug Logs - uses: actions/upload-artifact@v4 - if: ${{ always() && runner.debug == 1 }} - with: - name: logs-test-go${{ matrix.goversion }}-${{ matrix.args }} - path: ${{ env.LOG_PATH_DIR }}/**/* - - upload-coverage: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Download all previous coverage artifacts - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/coverage - - name: Upload combined coverage to Codecov - uses: codecov/codecov-action@v4 - with: - directory: ${{ runner.temp }}/coverage - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} - - docker-integration: - strategy: - fail-fast: false - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: 1.22.x - # TODO: setup docker caching - - run: make test.docker - - run: docker logs int_gnoland || true - - # TODO: docker-less integration test? + main: + name: Run Main + uses: ./.github/workflows/main_template.yml + with: + modulepath: "gno.land" + secrets: + codecov-token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/gnovm.yml b/.github/workflows/gnovm.yml index 172c177ce8f..2096f9460f6 100644 --- a/.github/workflows/gnovm.yml +++ b/.github/workflows/gnovm.yml @@ -1,155 +1,20 @@ name: gnovm on: - pull_request: + push: + branches: + - master + workflow_dispatch: + pull_request: paths: - # XXX: for now keep the paths for gnovm, tm2, gnoland and misc the same, - # so that coverage information is uploaded for all of them together. - # This could be removed in the future. - "gnovm/**" - - "tm2/**" - - "gno.land/**" - - "misc/**" - - "examples/**" - - ".github/workflows/**" - # XXX: end copied part, below is the "ideal" paths on which this workflow should run - - "go.sum" - - "gnovm/**.go" - - "gnovm/**.gno" - - "examples/**.gno" - - "gnovm/**/go.sum" - - "gnovm/Makefile" - - "tm2/**.go" - - ".github/workflows/gnovm.yml" - push: - branches: [ "master" ] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + - ".github/**" jobs: - build: - strategy: - fail-fast: false - matrix: - goversion: # two latest versions - - "1.21.x" - - "1.22.x" - goenv: # TODO: replace with pairs, so it's easier to read in the GH interface. - - "GOARCH=amd64 GOOS=linux" - - "GOARCH=wasm GOOS=js" - program: - - "gno" - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: go install - working-directory: gnovm - run: ${{ matrix.goenv }} go install ./cmd/${{ matrix.program }} - - test: - strategy: - fail-fast: false - matrix: - goversion: - - "1.21.x" - - "1.22.x" - args: - - _test.cmd - - _test.pkg - - _test.gnolang.native - - _test.gnolang.stdlibs - - _test.gnolang.types - - _test.gnolang.types.native - - _test.gnolang.realm - - _test.gnolang.pkg0 - - _test.gnolang.pkg1 - - _test.gnolang.pkg2 - - _test.gnolang.other - runs-on: ubuntu-latest - timeout-minutes: 15 - env: - COVERAGE_DIR: "/tmp/coverage" - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: Set environment variables for debug mode - if: ${{ runner.debug == 1 }} - run: | - export LOG_PATH_DIR=${{ runner.temp }}/logs-go${{ matrix.goversion }}-${{ matrix.args }} - mkdir -p $LOG_PATH_DIR - - echo "LOG_LEVEL=debug" >> $GITHUB_ENV - echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - - name: test - working-directory: gnovm - env: - TXTARCOVERDIR: ${{ env.COVERAGE_DIR }} - run: | - mkdir -p $COVERAGE_DIR - - # Setup testing environements variables - export GOPATH=$HOME/go - export GOTEST_FLAGS="-v -p 1 -timeout=30m -covermode=atomic -test.gocoverdir=$COVERAGE_DIR" - - # Run target test - make ${{ matrix.args }} - - uses: actions/upload-artifact@v4 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} - with: - name: ${{runner.os}}-coverage-gnovm-${{ matrix.args}}-${{matrix.goversion}} - path: ${{ env.COVERAGE_DIR }} - - name: Upload Debug Logs - uses: actions/upload-artifact@v4 - if: ${{ always() && runner.debug == 1 }} - with: - name: logs-test-go${{ matrix.goversion }}-${{ matrix.args }} - path: ${{ env.LOG_PATH_DIR }}/**/* - - upload-coverage: - needs: test - runs-on: ubuntu-latest - env: - COVERAGE_DATA: /tmp/coverage/coverage-raw - COVERAGE_OUTPUT: /tmp/coverage/coverage-out - COVERAGE_PROFILE: /tmp/coverage/coverage.txt - steps: - - run: mkdir -p $COVERAGE_DATA $COVERAGE_OUTPUT - - uses: actions/checkout@v4 - - name: Download all previous coverage data artifacts - uses: actions/download-artifact@v4 - with: - path: ${{ env.COVERAGE_DATA }} - - uses: actions/setup-go@v5 - with: - go-version: "1.22.x" - - name: Merge coverages - working-directory: ${{ env.COVERAGE_DATA }} - run: | - # Create coverage directory list separate by comma - export COVERAGE_DIRS="$(ls | tr '\n' ',' | sed s/,$//)" - - # Merge all coverage data directories from previous tests - go tool covdata merge -v 1 -i="$COVERAGE_DIRS" -o $COVERAGE_OUTPUT - - # Print coverage percent for debug purpose if needed - echo 'coverage results:' - go tool covdata percent -i=$COVERAGE_OUTPUT - - # Generate coverage profile - go tool covdata textfmt -v 1 -i=$COVERAGE_OUTPUT -o $COVERAGE_PROFILE - - - name: Upload combined coverage to Codecov - uses: codecov/codecov-action@v4 - with: - files: ${{ env.COVERAGE_PROFILE }} - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} - + main: + name: Run Main + uses: ./.github/workflows/main_template.yml + with: + modulepath: "gnovm" + secrets: + codecov-token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 84d181111ec..06b2daa1d3d 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -2,10 +2,6 @@ name: "Pull Request Labeler" on: - pull_request_target -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - jobs: triage: permissions: diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr-title.yml similarity index 94% rename from .github/workflows/lint-pr.yml rename to .github/workflows/lint-pr-title.yml index 75253d068f4..631f764c37f 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr-title.yml @@ -1,4 +1,4 @@ -name: "lint-pr" +name: "lint-pr-title" on: pull_request_target: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index db4e5c81026..00000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: lint - -on: - push: - branches: [ "master" ] - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: 1.22.x - - - name: Lint - uses: golangci/golangci-lint-action@v4 - env: - # Don't attempt to compile/resolve C packages (grocksdb, cleveldb). - CGO_ENABLED: 0 - with: - # sync with misc/devdeps/go.mod - version: v1.54 - args: - --config=./.github/golangci.yml - fmt: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: 1.22.x - - - name: Install make - run: sudo apt-get install -y make - - # prefill dependencies so that mod messages don't show up in make output - - name: Fetch dependencies - run: go mod download -modfile ./misc/devdeps/go.mod -x - - # inspired by: - # https://github.com/Jerome1337/gofmt-action/blob/d5eabd189843f1d568286a54578159978b7c0fb1/entrypoint.sh - - name: Check gofumpt / goimports - run: | - output="$(GOFMT_FLAGS=-l GOIMPORTS_FLAGS=-l make -s fmt)" - if [ ! -z "$output" ]; then - echo "The following files are not properly formatted; run 'make fmt imports' to format them." - echo "$output" - exit 1 - else - echo 'Succeeded.' - fi - mod_tidy_check: - runs-on: ubuntu-latest - if: ${{ github.actor != 'dependabot[bot]' }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: 1.22.x - - - name: Install make - run: sudo apt-get install -y make - - - name: Check go.mods - env: - VERIFY_MOD_SUMS: true - run: | - # Ensure Make is installed - make --version - - # Run the tidy target - make tidy diff --git a/.github/workflows/lint_template.yml b/.github/workflows/lint_template.yml new file mode 100644 index 00000000000..c1330d0a3d0 --- /dev/null +++ b/.github/workflows/lint_template.yml @@ -0,0 +1,27 @@ +on: + workflow_call: + inputs: + modulepath: + required: true + type: string + go-version: + required: true + type: string + + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go-version }} + - name: Checkout code + uses: actions/checkout@v4 + - name: Lint + uses: golangci/golangci-lint-action@v5 + with: + working-directory: ${{ inputs.modulepath }} + args: + --config=${{ github.workspace }}/.github/golangci.yml diff --git a/.github/workflows/main_template.yml b/.github/workflows/main_template.yml new file mode 100644 index 00000000000..8efb0277816 --- /dev/null +++ b/.github/workflows/main_template.yml @@ -0,0 +1,37 @@ +on: + workflow_call: + inputs: + modulepath: + required: true + type: string + secrets: + codecov-token: + required: true + +# TODO: environment variables cannot be sent to reusable workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations +# env: +# GO_VERSION: "1.22.x" + +jobs: + lint: + name: Go Linter + uses: ./.github/workflows/lint_template.yml + with: + modulepath: ${{ inputs.modulepath }} + go-version: "1.22.x" + build: + name: Go Build + uses: ./.github/workflows/build_template.yml + with: + modulepath: ${{ inputs.modulepath }} + go-version: "1.22.x" + test: + name: Go Test + uses: ./.github/workflows/test_template.yml + with: + modulepath: ${{ inputs.modulepath }} + tests-timeout: "30m" + go-version: "1.22.x" + secrets: + codecov-token: ${{ secrets.codecov-token }} + \ No newline at end of file diff --git a/.github/workflows/misc.yml b/.github/workflows/misc.yml index 5b0dc40d7a6..5fbdef73190 100644 --- a/.github/workflows/misc.yml +++ b/.github/workflows/misc.yml @@ -3,104 +3,33 @@ name: misc on: - pull_request: + push: + branches: + - master + workflow_dispatch: + pull_request: paths: - # XXX: for now keep the paths for gnovm, tm2, gnoland and misc the same, - # so that coverage information is uploaded for all of them together. - # This could be removed in the future. - - "gnovm/**" - - "tm2/**" - - "gno.land/**" - "misc/**" - - "examples/**" - - ".github/workflows/**" - # XXX: end copied part, below is the "ideal" paths on which this workflow should run - - "misc/genstd/**.go" - - "misc/Makefile" - - ".github/workflows/misc.yml" - push: - branches: [ "master" ] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + - ".github/**" jobs: - build: - strategy: - fail-fast: false - matrix: - goversion: - - "1.22.x" - program: - - "genstd" - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: Checkout code - uses: actions/checkout@v4 - - - name: go install - working-directory: misc - run: go install ./${{ matrix.program }} - - test: + main: strategy: - fail-fast: false - matrix: - goversion: - - "1.22.x" - args: - - _test.genstd - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - - name: Set environment variables for debug mode - if: env.ACTIONS_STEP_DEBUG == 'true' - run: | - export LOG_PATH_DIR=${{ runner.temp }}/logs - mkdir -p $LOG_PATH_DIR - - echo "LOG_LEVEL=debug" >> $GITHUB_ENV - echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - - - name: Test - working-directory: misc - run: | - export GOPATH=$HOME/go - export GOTEST_FLAGS="-v -p 1 -timeout=30m -coverprofile=coverage.out -covermode=atomic" - make ${{ matrix.args }} - - - uses: actions/upload-artifact@v4 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} - with: - name: ${{runner.os}}-coverage-misc-${{matrix.args}}-${{matrix.goversion}} - path: ./misc/coverage.out - - upload-coverage: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Download all previous coverage artifacts - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/coverage - - name: Upload combined coverage to Codecov - uses: codecov/codecov-action@v4 - with: - directory: ${{ runner.temp }}/coverage - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} + fail-fast: false + matrix: + # fixed list because we have some non go programs on that misc folder + program: + - autocounterd + # - devdeps + - docker-integration + - genproto + - genstd + - goscan + - logos + - loop + name: Run Main + uses: ./.github/workflows/main_template.yml + with: + modulepath: misc/${{ matrix.program }} + secrets: + codecov-token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/nightlies.yml b/.github/workflows/nightlies.yml new file mode 100644 index 00000000000..a7a74f5bfa6 --- /dev/null +++ b/.github/workflows/nightlies.yml @@ -0,0 +1,45 @@ +name: Trigger nightly build + +on: + schedule: + - cron: '0 0 * * 2-6' + workflow_dispatch: + +permissions: + contents: write # needed to write releases + id-token: write # needed for keyless signing + packages: write # needed for ghcr access + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: "1.22.x" + cache: true + + - uses: sigstore/cosign-installer@v3.5.0 + - uses: anchore/sbom-action/download-syft@v0.15.10 + + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser-pro + version: v1.26.2-pro + args: release --clean --nightly --config ./.github/goreleaser-nightly.yaml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/releaser-master.yml b/.github/workflows/releaser-master.yml new file mode 100644 index 00000000000..71cad8af8ee --- /dev/null +++ b/.github/workflows/releaser-master.yml @@ -0,0 +1,46 @@ +name: Trigger master build + +on: + push: + branches: + - "master" + workflow_dispatch: + +permissions: + contents: write # needed to write releases + id-token: write # needed for keyless signing + packages: write # needed for ghcr access + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: "1.22.x" + cache: true + + - uses: sigstore/cosign-installer@v3.5.0 + - uses: anchore/sbom-action/download-syft@v0.15.10 + + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser-pro + version: v1.26.2-pro + args: release --clean --nightly --config ./.github/goreleaser-master.yaml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml new file mode 100644 index 00000000000..bfb8f57c77b --- /dev/null +++ b/.github/workflows/releaser.yml @@ -0,0 +1,45 @@ +name: Go Releaser + +on: + push: + tags: + - "v*" + +permissions: + contents: write # needed to write releases + id-token: write # needed for keyless signing + packages: write # needed for ghcr access + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: "1.22.x" + cache: true + + - uses: sigstore/cosign-installer@v3.5.0 + - uses: anchore/sbom-action/download-syft@v0.15.10 + + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser-pro + version: v1.26.2-pro + args: release --clean --config ./.github/goreleaser.yaml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/test_template.yml b/.github/workflows/test_template.yml new file mode 100644 index 00000000000..c6b7207bc53 --- /dev/null +++ b/.github/workflows/test_template.yml @@ -0,0 +1,49 @@ +on: + workflow_call: + inputs: + modulepath: + required: true + type: string + tests-timeout: + required: true + type: string + go-version: + required: true + type: string + secrets: + codecov-token: + required: true + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go-version }} + - name: Checkout code + uses: actions/checkout@v4 + - name: Go test + run: go test -coverprofile coverage.out -covermode=atomic -timeout ${{ inputs.tests-timeout }} -v ./... + working-directory: ${{ inputs.modulepath }} + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.codecov-token }} + verbose: true + fail_ci_if_error: true + flags: ${{ inputs.modulepath }} + # TODO: We have to fix race conditions before running this job + # test-with-race: + # runs-on: ubuntu-latest + # steps: + # - name: Install Go + # uses: actions/setup-go@v5 + # with: + # go-version: ${{ inputs.go-version }} + # - name: Checkout code + # uses: actions/checkout@v4 + # - name: Go race test + # run: go test -race -timeout ${{ inputs.tests-timeout }} ./... + # working-directory: ${{ inputs.modulepath }} diff --git a/.github/workflows/tm2.yml b/.github/workflows/tm2.yml index 5c7c24e98e1..7471fd74cb7 100644 --- a/.github/workflows/tm2.yml +++ b/.github/workflows/tm2.yml @@ -1,112 +1,20 @@ name: tm2 on: + push: + branches: + - master + workflow_dispatch: pull_request: paths: - # XXX: for now keep the paths for gnovm, tm2, gnoland and misc the same, - # so that coverage information is uploaded for all of them together. - # This could be removed in the future. - - "gnovm/**" - "tm2/**" - - "gno.land/**" - - "misc/**" - - "examples/**" - - ".github/workflows/**" - # XXX: end copied part, below is the "ideal" paths on which this workflow should run - - "go.sum" - - "tm2/Makefile" - - "tm2/**.go" - - ".github/workflows/tm2.yml" - push: - branches: [ "master" ] - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + - ".github/**" jobs: - build: - strategy: - fail-fast: false - matrix: - goversion: - - "1.21.x" - - "1.22.x" - goarch: [ "amd64" ] - goos: [ "linux" ] - program: [ "./pkg/amino/cmd/aminoscan", "./pkg/amino/cmd/goscan", "./pkg/autofile/cmd", "./pkg/iavl/cmd/iaviewer" ] - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: go install - working-directory: tm2 - run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go install ${{ matrix.program }} - - - test: - strategy: - fail-fast: false - matrix: - goversion: - - "1.21.x" - - "1.22.x" - args: - - _test.flappy - - _test.pkg.amino - - _test.pkg.bft - - _test.pkg.others - # _test.pkg.db needs special dependencies -- see db-tests. - runs-on: ubuntu-latest - timeout-minutes: 21 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: ${{ matrix.goversion }} - - name: Set environment variables for debug mode - if: ${{ runner.debug == 1 }} - run: | - export LOG_PATH_DIR=${{ runner.temp }}/logs-go${{ matrix.goversion }}-${{ matrix.args }} - mkdir -p $LOG_PATH_DIR - - echo "LOG_LEVEL=debug" >> $GITHUB_ENV - echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - - name: test - working-directory: tm2 - run: | - export GOPATH=$HOME/go - export GOTEST_FLAGS="-v -p 1 -timeout=20m -coverprofile=coverage.out -covermode=atomic -tags='ledger_suite'" - make ${{ matrix.args }} - touch coverage.out - - uses: actions/upload-artifact@v4 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} - with: - name: ${{runner.os}}-coverage-tm2-${{ matrix.args}}-${{matrix.goversion}} - path: ./tm2/coverage.out - - name: Upload Debug Logs - uses: actions/upload-artifact@v4 - if: ${{ always() && runner.debug == 1 }} - with: - name: logs-test-go${{ matrix.goversion }}-${{ matrix.args }} - path: ${{ env.LOG_PATH_DIR }}/**/* - - upload-coverage: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Download all previous coverage artifacts - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/coverage - - name: Upload combined coverage to Codecov - uses: codecov/codecov-action@v4 - with: - directory: ${{ runner.temp }}/coverage - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} - + main: + name: Run Main + uses: ./.github/workflows/main_template.yml + with: + modulepath: "tm2" + secrets: + codecov-token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 0a06c2cf055..019c0be3c98 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ genesis.json # Build leftovers build +dist # Legacy .gitignore data/* diff --git a/.gitpod.yml b/.gitpod.yml index 794108f4613..49dec8ed15d 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -37,7 +37,7 @@ ports: - name: "gnoland RPC" description: "the RPC server, managed by tendermint2" - port: 36657 + port: 26657 onOpen: notify github: diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a18c7125a82..00000000000 --- a/Dockerfile +++ /dev/null @@ -1,66 +0,0 @@ -# build gno -FROM golang:1.22 AS build-gno -RUN mkdir -p /opt/gno/src /opt/build -WORKDIR /opt/build -ADD go.mod go.sum . -RUN go mod download -ADD . ./ -RUN go build -o ./build/gnoland ./gno.land/cmd/gnoland -RUN go build -o ./build/gnokey ./gno.land/cmd/gnokey -RUN go build -o ./build/gnoweb ./gno.land/cmd/gnoweb -RUN go build -o ./build/gno ./gnovm/cmd/gno -RUN ls -la ./build -ADD . /opt/gno/src/ -RUN rm -rf /opt/gno/src/.git - -# build faucet -FROM golang:1.22 AS build-faucet -RUN mkdir -p /opt/gno/src /opt/build -WORKDIR /opt/build -ADD contribs/gnofaucet/go.mod contribs/gnofaucet/go.sum . -RUN go mod download -ADD contribs/gnofaucet ./ -RUN go build -o ./build/gnofaucet . - - -# runtime-base + runtime-tls -FROM debian:stable-slim AS runtime-base -ENV PATH="${PATH}:/opt/gno/bin" \ - GNOROOT="/opt/gno/src" -WORKDIR /opt/gno/src -FROM runtime-base AS runtime-tls -RUN apt-get update && apt-get install -y expect ca-certificates && update-ca-certificates - -# slim images -FROM runtime-base AS gnoland-slim -WORKDIR /opt/gno/src/gno.land/ -COPY --from=build-gno /opt/build/build/gnoland /opt/gno/bin/ -ENTRYPOINT ["gnoland"] -EXPOSE 26657 36657 - -FROM runtime-base AS gnokey-slim -COPY --from=build-gno /opt/build/build/gnokey /opt/gno/bin/ -ENTRYPOINT ["gnokey"] - -FROM runtime-base AS gno-slim -COPY --from=build-gno /opt/build/build/gno /opt/gno/bin/ -ENTRYPOINT ["gno"] - -FROM runtime-tls AS gnofaucet-slim -COPY --from=build-faucet /opt/build/build/gnofaucet /opt/gno/bin/ -ENTRYPOINT ["gnofaucet"] -EXPOSE 5050 - -FROM runtime-tls AS gnoweb-slim -COPY --from=build-gno /opt/build/build/gnoweb /opt/gno/bin/ -COPY --from=build-gno /opt/gno/src/gno.land/cmd/gnoweb /opt/gno/src/gnoweb -ENTRYPOINT ["gnoweb"] -EXPOSE 8888 - -# all, contains everything. -FROM runtime-tls AS all -COPY --from=build-gno /opt/build/build/* /opt/gno/bin/ -COPY --from=build-faucet /opt/build/build/* /opt/gno/bin/ -COPY --from=build-gno /opt/gno/src /opt/gno/src -# gofmt is required by `gnokey maketx addpkg` -COPY --from=build-gno /usr/local/go/bin/gofmt /usr/bin diff --git a/Dockerfile.release b/Dockerfile.release new file mode 100644 index 00000000000..2e36453382e --- /dev/null +++ b/Dockerfile.release @@ -0,0 +1,48 @@ +FROM alpine AS base + +ENV GNOROOT="/gnoroot/" +WORKDIR /gnoroot/ +CMD [ "" ] + +# +## ghcr.io/gnolang/gno/gnoland +FROM base as gnoland + +COPY ./gnoland /usr/bin/gnoland +COPY ./examples /gnoroot/examples/ +COPY ./gnovm/stdlibs /gnoroot/gnovm/stdlibs/ +COPY ./gno.land/genesis/genesis_balances.txt /gnoroot/gno.land/genesis/genesis_balances.txt +COPY ./gno.land/genesis/genesis_txs.jsonl /gnoroot/gno.land/genesis/genesis_txs.jsonl + +EXPOSE 26656 26657 + +ENTRYPOINT [ "/usr/bin/gnoland" ] + + +# +## ghcr.io/gnolang/gno/gnokey +FROM base as gnokey + +COPY ./gnokey /usr/bin/gnokey +ENTRYPOINT [ "/usr/bin/gnokey" ] + + +# +## ghcr.io/gnolang/gno/gnoweb +FROM base as gnoweb + +COPY ./gnoweb /usr/bin/gnoweb +EXPOSE 8888 +ENTRYPOINT [ "/usr/bin/gnoweb" ] + + +# +## ghcr.io/gnolang/gno +FROM base as gno + +COPY ./gno /usr/bin/gno +COPY ./examples /gnoroot/examples/ +COPY ./gnovm/stdlibs /gnoroot/gnovm/stdlibs/ +COPY ./gnovm/tests/stdlibs /gnoroot/gnovm/tests/stdlibs/ + +ENTRYPOINT [ "/usr/bin/gno" ] diff --git a/LICENSE.md b/LICENSE.md index 5c705e516c8..b5d453a337e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,8 +1,694 @@ -Each project subdirectory has its own license terms. +The following copyright notice covers all of the files in this directory and any +subdirectory, except where otherwise specified, including the **tm2** +subdirectory, which uses a [different license](./tm2/LICENSE). -Gno Network Public License 3.0 (copyleft; derivative work, forked from AGPL 3.0) -- [Gno.land](gno.land/LICENSE.md) -- [GnoVM](gnovm/LICENSE.md) +--- -Apache 2.0 -- [TM2](tm2/LICENSE.md) +Copyright (C) 2024 NewTendermint, LLC + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNO Network General Public License as published by +NewTendermint, LLC, either version 4 of the License, or (at your option) any +later version published by NewTendermint, LLC. + +This program is distributed in the hope that it will be useful, but is provided +as-is and WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNO Network +General Public License for more details. + +You should have received a copy of the GNO Network General Public License along +with this program. If not, see . + +Attached below are the terms of the GNO Network General Public License, Version +4 (a fork of the GNU Afferro General Public License 3). + +## Additional Terms + +### Strong Attribution + +If any of your user interfaces, such as websites and mobile applications, serve +as the primary point of entry to a platform or blockchain that 1) offers users +the ability to upload their own smart contracts to the platform or blockchain, +and 2) leverages any Covered Work (including the GNO virtual machine) to run +those smart contracts on the platform or blockchain ("Applicable Work"), then +the Applicable Work must prominently link to (1) gno.land or (2) any other URL +designated by NewTendermint, LLC that has not been rejected by the governance of +the first chain known as gno.land, provided that the identity of the first chain +is not ambiguous. In the event the identity of the first chain is ambiguous, +then NewTendermint, LLC's designation shall control. Such link must appear +conspicuously in the header or footer of the Applicable Work, such that all +users may learn of gno.land or the URL designated by NewTendermint, LLC. + +This additional attribution requirement shall remain in effect for (1) 7 +years from the date of publication of the Applicable Work, or (2) 7 years from +the date of publication of the Covered Work (including republication of new +versions), whichever is later, but no later than 12 years after the application +of this strong attribution requirement to the publication of the Applicable +Work. For purposes of this Strong Attribution requirement, Covered Work shall +mean any work that is licensed under the GNO Network General Public License, +Version 4 or later, by NewTendermint, LLC. + + +# GNO NETWORK GENERAL PUBLIC LICENSE + +Version 4, 7 May 2024 + +Modified from the GNU AFFERO GENERAL PUBLIC LICENSE. +GNU is not affiliated with GNO or NewTendermint, LLC. +Copyright (C) 2022 NewTendermint, LLC. + +## Preamble + +The GNO Network General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNO Network General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions. + +"This License" refers to version 4 of the GNO Network General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code. + +The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +### 2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +- a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". +- c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +- a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. +- c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +- a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or +- e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors; or +- g) Requiring strong attribution such as notices on any user interfaces + that run or convey any covered work, such as a prominent link to a URL + on the header of a website, such that all users of the covered work may + become aware of the the notice, for a period no longer than 20 years. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +### 8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to simultaneously satisfy your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +### 13. Remote Network Interaction; Use with the GNU General Public License. + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License. + +NewTendermint LLC may publish revised and/or new versions of +the GNO Network General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNO Network General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Gno Software +Foundation. If the Program does not specify a version number of the +GNO Network General Public License, you may choose any version ever published +by NewTendermint LLC. + +If the Program specifies that a proxy can decide which future +versions of the GNO Network General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +## How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNO Network General Public License as published by + NewTendermint LLC, either version 4 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNO Network General Public License for more details. + + You should have received a copy of the GNO Network General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. diff --git a/Makefile b/Makefile index c2f5156e054..12f2e70886c 100644 --- a/Makefile +++ b/Makefile @@ -35,16 +35,16 @@ install: install.gnokey install.gno install.gnodev .PHONY: install.gnokey install.gnokey: $(MAKE) --no-print-directory -C ./gno.land install.gnokey - # \033[0;32m ... \033[0m is ansi for green text. - @echo "\033[0;32m[+] 'gnokey' has been installed. Read more in ./gno.land/\033[0m" + @# \033[0;32m ... \033[0m is ansi for green text. + @printf "\033[0;32m[+] 'gnokey' has been installed. Read more in ./gno.land/\033[0m\n" .PHONY: install.gno install.gno: $(MAKE) --no-print-directory -C ./gnovm install - @echo "\033[0;32m[+] 'gno' has been installed. Read more in ./gnovm/\033[0m" + @printf "\033[0;32m[+] 'gno' has been installed. Read more in ./gnovm/\033[0m\n" .PHONY: install.gnodev install.gnodev: $(MAKE) --no-print-directory -C ./contribs install.gnodev - @echo "\033[0;32m[+] 'gnodev' has been installed. Read more in ./contribs/gnodev/\033[0m" + @printf "\033[0;32m[+] 'gnodev' has been installed. Read more in ./contribs/gnodev/\033[0m\n" # old aliases .PHONY: install_gnokey diff --git a/contribs/gnodev/cmd/gnodev/main.go b/contribs/gnodev/cmd/gnodev/main.go index 9b769321c83..2038dc647e7 100644 --- a/contribs/gnodev/cmd/gnodev/main.go +++ b/contribs/gnodev/cmd/gnodev/main.go @@ -64,7 +64,7 @@ var defaultDevOptions = &devCfg{ chainId: "dev", maxGas: 10_000_000_000, webListenerAddr: "127.0.0.1:8888", - nodeRPCListenerAddr: "127.0.0.1:36657", + nodeRPCListenerAddr: "127.0.0.1:26657", deployKey: DefaultDeployerAddress.String(), home: gnoenv.HomeDir(), root: gnoenv.RootDir(), @@ -84,9 +84,7 @@ func main() { Name: "gnodev", ShortUsage: "gnodev [flags] [path ...]", ShortHelp: "runs an in-memory node and gno.land web server for development purposes.", - LongHelp: `The gnodev command starts an in-memory node and a gno.land web interface -primarily for realm package development. It automatically loads the 'examples' directory and any -additional specified paths.`, + LongHelp: `The gnodev command starts an in-memory node and a gno.land web interface primarily for realm package development. It automatically loads the 'examples' directory and any additional specified paths.`, }, cfg, func(_ context.Context, args []string) error { diff --git a/contribs/gnodev/go.mod b/contribs/gnodev/go.mod index df5236bc4a3..4741a5d7326 100644 --- a/contribs/gnodev/go.mod +++ b/contribs/gnodev/go.mod @@ -53,6 +53,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.3.9 // indirect go.opentelemetry.io/otel v1.25.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 // indirect go.opentelemetry.io/otel/metric v1.25.0 // indirect diff --git a/contribs/gnodev/go.sum b/contribs/gnodev/go.sum index dc5528a4be8..a2c9f154560 100644 --- a/contribs/gnodev/go.sum +++ b/contribs/gnodev/go.sum @@ -100,8 +100,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYp github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= -github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -112,8 +110,6 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/linxGnu/grocksdb v1.6.20 h1:C0SNv12/OBr/zOdGw6reXS+mKpIdQGb/AkZWjHYnO64= -github.com/linxGnu/grocksdb v1.6.20/go.mod h1:IbTMGpmWg/1pg2hcG9LlxkqyqiJymdCweaUrzsLRFmg= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= @@ -207,6 +203,8 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/contribs/gnodev/pkg/dev/node.go b/contribs/gnodev/pkg/dev/node.go index 7756a1c866d..30ad262b1b0 100644 --- a/contribs/gnodev/pkg/dev/node.go +++ b/contribs/gnodev/pkg/dev/node.go @@ -42,6 +42,7 @@ type NodeConfig struct { func DefaultNodeConfig(rootdir string) *NodeConfig { tmc := gnoland.NewDefaultTMConfig(rootdir) tmc.Consensus.SkipTimeoutCommit = false // avoid time drifting, see issue #1507 + tmc.Consensus.WALDisabled = true defaultDeployer := crypto.MustAddressFromString(integration.DefaultAccount_Address) balances := []gnoland.Balance{ @@ -541,6 +542,6 @@ func newNodeConfig(tmc *tmcfg.Config, chainid string, appstate gnoland.GnoGenesi PrivValidator: pv, TMConfig: tmc, Genesis: genesis, - GenesisMaxVMCycles: 10_000_000, + GenesisMaxVMCycles: 100_000_000, } } diff --git a/contribs/gnokeykc/go.sum b/contribs/gnokeykc/go.sum index d7bda688d4f..4027483eb1c 100644 --- a/contribs/gnokeykc/go.sum +++ b/contribs/gnokeykc/go.sum @@ -85,8 +85,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYp github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= -github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -95,8 +93,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/linxGnu/grocksdb v1.6.20 h1:C0SNv12/OBr/zOdGw6reXS+mKpIdQGb/AkZWjHYnO64= -github.com/linxGnu/grocksdb v1.6.20/go.mod h1:IbTMGpmWg/1pg2hcG9LlxkqyqiJymdCweaUrzsLRFmg= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= diff --git a/docs/assets/getting-started/local-setup/setting-up-a-local-chain/gnoland-start-manual.gif b/docs/assets/getting-started/local-setup/setting-up-a-local-chain/gnoland-start-manual.gif new file mode 100644 index 0000000000000000000000000000000000000000..40c79bd91f63ccbf631c727b1a6a146af84c2a07 GIT binary patch literal 759932 zcmZU)RZtvE)W3^wWKwpR%fwh^Un{h6wT_BErnf3?UIQ10xd&83hL?rOIic><} z6c_@{t?ixJzIwy?z$K|+<{ApitLvNHx&Dhw%`K&A?q-gjRNvnpcJmL9hDTbY+gO`?aby$1i!vvw(4ji$U-P2!2(rFP|*yrP%Odfl`4){ z-9E5j&1#)?o!4J1q1yGP4}B?;5TUxww&R)RP;BA)?XJP?r9Oyo!){;B)%{;=k;c6t zzc)fDs7TYnHys@QFdWh5qe)IGy?&@@%gHP{r}sY`vDUMmeB~S|nAqdWQuXJaFkErw z%k@^5t^Pg_p_`rF;6Kb2e>(2=M8ZW3Mh$1_%R?s$^j59jImdIJfPJ$_QF9l>xs zsou<+gXtXUL~6{JhpVlgFSpi`Z!Zs*TLX#G1ONWM{rLlj<6DL!;i*_gpizS?BeA$A zETizGFsz~pHC3!)NX$W2u@r6-R&mr}7}g;A1QqLe=6sMfn7w|&8p7R=VFTrxQ?Y>w z?SgC)#BL^R5~coO*e1#0soEwhQODb+0JtY@ziLWh+NJ7hs@kO)n#bFvo48HdWtfLy z+GkoPsM=@Q=f~S;JJ(Oz=eYG_I^=rIsXFBO?Z!Lg2i;6M6omc5bS#X-12`7NQiC0f z!Q4}hB?(ekPNgZD0H?BabFfo+w%e3bMSd8Tb7gS?z`3eCAM9LRT|ebqQ{Ru}QrkQS zaH(tG1-sOD-%PnQ^#8*GHV)&d0h`9CA;9J-IQKNLWljp)wRK5T&9!aS9OBx(={D`! zu^Wc%)_IVi=GJwR4{__hsGoN0x#`Dt@4cT>bMO1T3vus%y_t3&`1cRnV-N{n-D3!i z2I?`4#WUkEf+vmRIZCLd?)iRY|0~6ptcCt9W+99;SncsRfPWqW0V%l6Qsad{4NnR%E;~+ zuMR9GD!};03h)H$*A~BT0Da?xJ9|P*uZl?rFvfVno={uP67qS_m_W5B3sr0PpOT+H%2$_*tN{ch2@zx$pqyoCnxD z_lUDXbUuF0r`kL33Rofj19LuL$~*s|wnFkYem>;FyWs7rLK=>_5RT{xpEK+6eZowdJZYo(HeCR{PcgU28u7z*_5^@~!u&t1-I;uk~K| zHiTT)SirH?2eJGbqq%CW@FDA??0!v9*IFAI?2QS4Uvp|*tsM_!W5(I9CHK14K^l8= z0qoaW%2ns21=(Dw_G_zkt#h%!-ddmXYj3Tqb9IMoZD06x^j_Dwf5G0~!}9MO<*N5g zglr$N`*+R2UF*FIuy@V?{@p8e^}Y>|ohxVmp6%;;{{igXJFtK65m!UtJY@Hw+Q0A0 zwITQi_K)W&|Ne)%hR|EckGBi|fw$|1FL3NV1nhu86z;|deCQquN5Bw{TVoUr&OU}( zz%X%rV+;>;AIBwNgzBa-P8#Qc01`0D$lVmL1wA0H3HZk8)&#M@IV7777!#;(g1JKv zsV)P?C2pD$zu+9vVh2tra5pC>LXQ|Z0w>kon!gs{9J8tgPU+V-r!_#2Ib8y$O>der z25?SzA%Qct+$~x2&=Y~0z*(SMOU@6RQ<3SwIiLELyj$q0#AV=o$W2QD9Oq01J7^)A zyA@u94?9!f2wH@?wU*G}o~x(@Ev44Cmhr&O)m?&?b8lKJq;W5_Awesp+-+4_unYZ~ zpzpPAZ8a9Smqyb;tF85Ib?&fB)61Z>-kY|DFSu8h*um?g-0e+?uq#`R;Efr#_Lc(N zYe%)<&6WE0wg%WW&?R_l`=-5P0QbfN61;uH-O)7xeWgCcGEEc$Gr>34%tKD=^VmOxQpfp*~fA39HGJc2~rC=Aa3aV#*^?9>JoBD zb=x^Ejdz~}2{~fq>6+9^xKFJKIp%clnzq3El{p=9BGAw^>z?o{_cG*E;9AQ79 z?!AXJ_%9P`VfU#Gy~jL>FEcJ-zjAMTPo?o+7a(B|r96G-O*;RF(ok6uXc0JZ5O5I0 zkYo@L(BOmN9x9v^i4&z>lR&Y8g-Rbl9TvG!gzxlq(7;|}fI4^1{8?)d?(D)YW_yTc z!`AI{Z`gc6_kL(ZWK?uaY#b>5i-4ybR(w)&%GcDibUz4;8k&)pUqB~REJSZlUm`>o zfmEBs&ED9E;v>q<33kuL=}Oc`p%fMwZizw*z#g8Y_N5&DOfD>JhO~$cEGj8eW}s*I zTv1XTf+8r`5r2Fx2=n4Q?(~@G%GJgC6>e{=o%7(^(?wLeh^b_QJ>=xh$7mdmiqrm% zp%vJ&uQ7?C!#jtvCsVJzJ>$`+9aa~BXy#O&ck zz)@wKP-?vw0E=8AuGFHNsGpG`#2Kco$vUdzo*d4VNn~uO0Fzq+J1oE<+5+1ov`qE2 z)Ob$P9c9i+EQT)5iJb4jK?QaG!yIJ9nQgP3>^W>q*V(PI@TTcX}w$>AsB%9v^h^Xz%|h?CyKQPF_Iofq-Vb-lXo{9b`CN?@obK*yf$rbWeA2CwL6k?qCHQTg#Vd;# zj6lXpe5WTmc+85e!0j)D9BSZQ^8b)bI=l`6wXQ?$wV=PAZwp|q7Wxx?Po18pkic&!2P>&j{pTD z6FWjm*UIGGI*0&(v0Z71VqI5ufZ={oN@SjKF`=!1ZJ9li_AW{16N-wRCbL4$3DlSw z+X2wDJrG3Da}WvB`Q~@ zNUmbYG+$>e*Fd{llJE+|+H@~EC|s>fP6wPzWDVI`Rle^|Q!8p{V>fxPMfh&Sg496& zl)%WO%npHNa?IXFK00d{knC!l;4xnvh?0Run5F498~b?Dv0NTSCAzk156^Aa+jcVR z<{C9b?pe}>n4%xWUY-zeiaAC=@(W1m+~A~_nL8~{t; zYowW=KYUhD=)D{*`)h|{g-Fct-esz~Sw{4;=z(490#;Lsin+z-o$trdR0vs~B#Xd+ zm75L07P=kg_Eo!2`#163d5)&Oh`9!!jC54+r= zwrXFl+uVmNan$Px6cvtS^$u~hXrd)WEp}&ww+VyScYIqDf#p>#{cy2(`3c*k)AHZ` z-AXl-MGTFaq#rpIb>$Te(yJTE^Y<)PHT(m%UybF_w*ZN@Vj(3x4PEj{8hyVbZM44a zsMSVOJuff!$vtg%MBK$cJ1soF$)jxRQD(nOZ9c9dG&y@?sA9N_@)>f`xuPJIfaB8X z-D^*sf%aq!P_;49Lo65QD`g8Jro6{6iZCn;P?p|`luGy(;|Wz{ca74m_s_gba6{C=i6bC?pnq9S~{(855uB>tG# z7L6i7Z{q=#6Tm#HLG~fg!=T!m!4Vz0d--UPH==%O+9vmP=*CM?ieQxUnP2HrrxoF>p^}R7U0&l`J zWWeXFC!6(~v#~p>DC=b4Z~8^(?oyDBw#`Qf0k1XVR}A>{5q@1QuLj|Vy>gMhDh0IY z7-XO2oXuzlNpTf9JRz)H++YXM53Au$_YdXLt`55K0tUtAMHNP~>=rj0Jwb+q-m+;& zQhBYD@gPgye<2zem7@|=?5*)k$HfZsh6(s6zk-yt2Ti%M6`@mY>0+&#=xCP!0gZQN z#tf!Be=kN*v{M^2c-P5|yOrek9i-(!Y?K)aatIV2iE@Gjvh4a@y-K>Zj}L4Y3+Hph z%&-^@#R`MRDwS2u_bdriHAH7@1q}!Mm?I1>(nSZj9%RH=pRDwVKM_ifIb%0ZUGEcq zd{AHxo6o>zvhb09m12@%22&UuSUbe8Q{TAgJbS~VkCFn7GYv_w;4&(WCw`S> z@2MSe-%EtOX;mk9xl+ZkTNdv6^C0|Qq}Rem-6b6AkeOw1eyW(=#z8qmAO#P8d2 z2&3u!!8WLk0fd?8C-~RCOA1FB7u;?3W6L4-z^q?)rQbM73&-<_Z;F>hdUxuZKfG`B zIcgPFbjmJbrTb*Uq_fZ+eqT$8Zt~gjvn)1z!p4c2RTEh_?F#Tk;t0Xf6~~taj@-0P$PezxO*!+J+NlNZ(hLm5^W$@3yiKVq`J;n-k6NFSC#)vKHQa z85U+vf~|vX*Kbyh=I)1^u_AaGF}@iW*+;Xs`Hoq>@)B(vTl<#U_NbouWNfD&5c#X> zaN9@rXE+}6H61Q0?0IKh$SNr?sZZRXBJii(9dj)N?`zmZS zr#m-pM}>Og$f4-)SOpBRSdr#hB1}Zrlbm6#TqmOhsR&{GI`pnZ+HkoXjYpY4F=FR0 z;dJpu2QHJ66I!j|TheqV#O}XF?A>ENQ(F8Ufh%;iL_{AMAPQ1f5fv0zpdNa_1r^kKS{&x|AIB+mdA=%uZ6?S6fF<^ zT^7gL?f2CQ<-+kY(N@vXipufe@%HFnNSN_6BL*`fu%b1no+GSi5dwtJu(aLVlhMPN zxoB0wYgocL0#u%4{CPy8LI<(B9neu0z6f+iajqLnJV(ipMazjqD;Py91w^Z4Mguyd zZNgbK&urAmVsu4f^jT50o}&#iV@x_@3<6>_Ct@tgVy(%d%|Wa-0kMvmvB*ZTQN^)t z&#@jDm_UpePop@$fH-g7IFGovkoCBb%qX!;lpqX*Fe6Z`Q5;V=5*UOe^^6h~07@c@ zw^2cWfRK2!Q4?9?vpeJUMUd0Zf;E!jb49?V0nxnL@vsS$Vk2$R-)7dK-&ACAxr*XNT#9M0%R}%Izfhsr5)dV25QZOE|9_Ek|1C*5TYe? zDHFEoh`urb(hi4hktG}i5T%JA>mVc?W+q%rpbl4pT14V5$rA4!QFk0+a^VTTG811x zj58vr&z*?~! z+;#ph;!9}Fto?z9|G$V2hCpF)A=U~12k|p9v$At?|3iGsB%Z?3vhs?`s_L5By7~s= z;t~NA^!5&2%yuXiHnvM!N6*K8l-3bgH#%SYSmXS{;?nZU_fdPTaM(zyII}$XKRwg@uT~jWJh_O74tdg@^Euy`LKP zp&(J-vBiL4>V8)ebTE}_bLr&QY6N(tejtJBaNG-PSX5x;p0W^~-YC&v0<((0w@CIK zNSi}A|4Q<5{6aZX^=s!Q(V0X6BWTx=1;1va#c{dXOdOd#JVyk> z2!tRL6@x-R%Za_vn9*yAAKb*cpc^w&gc|+Amn>p#U5ALkgHS8aH-Z9+NrUwo-AU#{ zx9B+bjXyXN!YD6^g(w*9m%b^fxS=8Qovu_^<(wFG3nEz*NARq=ijzfdV7SdtYlbv0 zjL!l`8ap!T9xvBhTy9U>?~JkJW4)8>KX%2l}uof z`3h%kOMkU?vVPY38N6-XzUI1J%*Q_p^VVSoC5=9sa*W{V(Q|9|Kfyq!8Dy2qXWqSPd<}je;Z;6ewfts z={{*&#-;!H`wK2^UE}(CURm)EYm2`#j}qOJNE9$#1b41Y&Af0GKgy-V5;>LHvRw`~ zy3M94AI8@D7^TcV7g9~^y3KQA+n^>|*VfUY_w&@b|IZl!k|lo25x3cKs8mz`@Aax9 zadLuZ)AC+}d{nb_f1kC*__n(N^KMK$c=qMFq9rH|->7S`;B2b2^qWRSgr*7l*gtgg zN`txZrQx-g^3%Z?UpMqW%_`T!hOE+QbD^y2MOdH6&{t;%5swHXCOx91T^I18Vk0&X z9PGqV)CocZUM)wlDjMWrvqGjn3kK~8Ds!$HqeYiDE7_HJZaosCI$l4h*E`DLM4rU$ zVcWF%Obo;MvVTGyS0b?)3^LRWs!gAQO+^lTd2Sz*94jyjcTA5v_3EZrD%kRoD$uK% zHR_^9MfUG4g=FOo-35oRFyoMf6l>Cw5{Q1$VvsY-ss7WEnx`ZyT~e9S&Av~S3I74G zWGq3~N02}$EZVjg##+RfUWPCkI=?|Qh!CTH=8YUFus+u#q*U8bPvf_AC4Fe3G+!kX5~=)g+f%3+!!wnqStzwTI=^xOVioN#sGC^WSljYP8nO<5%k2} zTYA$-25^dPlN(R5%QkBa0!PUxN$2onTXJHqkmI$52eN;+R+=Tt{MARotwf=TeUGlG zH;tyg^t-)t*0tn9I07d;3W+@{TtQI*WS`{S-Ytpj_;q^wL`<0L5gQ*(if~J=lGp=2 zKU?qDF}*{45L4*eGW+|z4*<53+@XS75@bkz*A#5nb z8}o^IwHZp_X?F}@oTu>4MJ6krv7|aIYBUnkLn81K4mKBKUH*oi_VGND#eklFe_Xl| z2b3{$gu(1p5Eag{1U1Tu6S9t4Sa#7!##TMpbWSFH(_KeEkA^S2_2+ z)+$mfobw_=l_DcflZ$vNqL*s#SWTAfx2#ws$WQ5;PLQUaDu=Ji#G-AO0kK z-%Dt$X~J-kdO1p-J`pPKn!)tJ=Ldys1IpLTGA%3rRIkq+4BSW_YfBr?;_3eG{59o9 zVJcorBHsBhJbU-ZT`{ZoEkBiDCCfH;dCP`tOU&S}?V%Ku-=Y-r!(+6r`-snBCF0y@ zQ>zNYzR~f3%=fT4fvgjwG`Zobz~ux6?`Xrgd^#t`ZyF`%<(P3fxmTVxaAKky$z6Nn zGBajx`!MmF4e?VkIE*Lzxd$uM6nZA~duB8B7YMg6vZW1bL9pQ-D3Es*ZR785n(x&x z@L?Z!UOWh&#WUSd(Bb0QwD_IAlS=SwP>#7JbK=FX_>15>vB+DGk}4fZxn1$w?^A|5 zOoPU`2Fy9ai^Cm&+eRZb;zEg;XOeoR>8~%5Z0}=AhS(%C=*1Gk@!qa&P9(;EQE#{~ z3p2(1_~WmYzkt2gbD#64;`HO+jB%6@y+9!rGd7ns9+xp%8*4XFjxZ+yN@5iL5tomm zkJRjs>=~>yXUM;KJT2rF>aj)tI*#={VjX|}I}kP@1S=>KTn*6C4~5S~IFsmTjhuSl zJ_Rq>BTU{i{bW(~wPyKa7^>!FNQ$mGK;pDqL49Qv7Gyw0ixJe;;w7xCLIScO%5;g< z{W$#;+1PspxTKS!63*Y_6prMLztB+1fp5c@9 zf@Sw)*p9ldR-eIbvKVK=ShmcGE73dtQFv!Y#maVuafW_A!p5vhZwEnHwp=SK4z7e+ zUr0Sp(LK8|h>)WEh93mvjCih7e8$H){*(lwR|N0|fb0}(gvvo5T0^6ceA?4^)QIJR z1I&}pY%$lrq?Y2Fbt*QZ2ea_-&yZ(-r!E`Fc1Gy@A!zc+nRrA&dsJ1s91_P8f*=sdo#}3U1O#Qm z*i#9nnS*&q!$yVuuo*-1nFZwKy*9=pubRPtG=8ro(w7QdB~pO3wPfA{#o4-~r>_Cf zC=o;7m--=L5gBr)64~n|ICWwVQFi(>s+hF~-64fa>I*N)ayf_qBmG0dP^NdHe~;-HVR1lyyi;_rjiZ6IpRw2(;dg0Y@0^bhBcE;%$ zt%I35lzrL-K4-~umM2vkLBd2$cS)#xYy+j6eM1NxQqe-LqXknzsZggluSsaSeg;F9 zYU&tK+i5&ZG*=JPmNU>MA}h~MKi8QRB7>RrPsuO9FnYm8v3);bfH7HgFap4qt))sq zpr0+Jo4!|-{hd7Ne3JjvgSRQr%jzY$3|$XyY?Hhr6jPG<)v_~vXCu=@UT&hQa5XB+ z;~8R9=8n6}Ytog$?v$rkkw&KNu`LB zz2MJYs!&wGBwHMdYKr71MIs8nS*ILJw!(p@Sn=0B0rs}%=FPBvDYG7uo4W#uVq*tD)8C)B}x%1L}tC@6IS6(d0-N%iDX=0 zPgZJ(vsa>R$s23MhoOiE<+LwG@lu`YweepOr<^_^=fbPXTrVog4XT*q(z#!ANjK7c zCJJ{^itsQ~6Eh1HC;%7x0<*dj5MvU!7fE%dQF&uGYygvWATZ(dNP89ZRa-gt_#sw7 zRx@Kt#2ei|<%GSboWY4tgPxhCP${l`HNSYhLW0gN{32D9gi05=R+U}B*E=*&ERr%y zMxLy8imasN!f>rKd}ai99*}l@6p9v9!^-S;Lkv7}svSqwS&Obe29!Q`F#bWEK~et5xYTgH4M%;uP5IxkQ?hcp-*k>F86AA*6w!6m^OA z*`EZPgUDSHOezlmvT9k`=gpPnOO>W3A)fInBb|Y?#mxpJ>U?(4Q~ze!oNQ6bDjd5I zN&_7^@nV`S9S?)n%D7hH?_c5g!EJP3J(uD?IWZ9j1O`iRq|Y&G#j7f$#a2f->&5z4 z)9{(!kT;Kmno&P{g)WDI9=~E|SND^q!VK#(FscJq!z_=|u7k6hgNr z#|~nyrPMeL0&+Fsfy;_EY>ve^&9GcMvyCJ}h|kGFt6@aHb#Mmi(_|9qw6Wn>wy7OO z%(s!5snI|FZ+^;Y+q!C9UBhgSV4n&8#ZYNWWSxEzv><8av9A$!LH zcr|uMheN8brBi_U3QuV z>IoO=&3r$`EHdhIwR2?w{zcZzTZ=nqiNc&I8U#l7wW4yZ!9wJ|NYX@^#p!Ca2@bB0 zs}q2^KKQ|wHY6sxYtc8~LJVe6}8{Ooj46i z&m}GD>ua*v>C5XY&M?4vh%l>8_R^1}+W89;`b6RqLa8Uo6vQQtssa+o*gejxe)dol zZXJc+=Vj(Fa3XN$4_Zxs#__zo`?8o3U$Q#rPPk6U?_3PnL6KVPK-@G>^W`~RKo9(} z2HeB%_a^zY|8@$x%d6+?rWkkLHTtw?Qeos?;fI{yJzUh~ul%Fv{zqw5k@ETh2{n-4 zO(MT&pC6q{+$l1_$B**~_EiVlqGQi&Y}aFa2aEq`7|0ml=s==bMWyL4lK(@MFQ<4_=V zh0vkSClRTz#-#nd)Uj_il>DoyIo%!0`A1Oo`rs=CA8yGl!uKi;HwV3B-ahfT88`I{;|ASVEv$k%^-mXDL6?bCt?hG{LgLLzCBZGcaRx8?N`IQ0 zVpR(yqf_I9ss3fRnty!NGwG^#Oov=PsRdQn?M!^zo>NbxN6POFE9wz;=1_E~6>e3p znY-UUZ8Q}c?XN%QT*xBxo56+6*Xj&&PmYt`?o)TvY=;3Lw|Y}OkAcA`?x{(DYJ;g7 zJEsTxyK1j^Z)plE~A(e1xdH6*k~@l zVrm?IuNu3%=PkJ3`DbVlJoe{wiHs)IzBYF($Wyev@NLcWM=wi4*!6#$hqvl;e7OB90QF&deQT$>dHV2-#K7h`yi(ecPtlFj!z+DvX=X-<6PN9v7o z<}-KPky>f?yn6SGr93U??X$*=OxGK2y!;pJ?q>p#DutmaMDeFhdBd>zJdQ6gA(cW$ zt%v~K*LRAu%hGZl;$)a=FZ(D3^1HuE|8h%|mML@1BEJYaPt`3`MN?wJ;lI(5B0#+A zeC$jNQ02*lGfGH2)>m)Z?YcR5P^*cPhR4 zmHl=BB}NpeY2##d?rV%s>~k7$qt8UzYv%-uNCRrnQOAqUhBP@LjwK~8UX$N{3_O3& zEop9?<*6x~@=CRisIze=*jJQRg@R|^Z%;4#-PvoYiM{zGY>9hUXkQ3qKYUEl$z4&s zk=IW*Yi>+|cvz^hPn;eb*#szT~F1X^$YcV93B2?{? z1;pkCvMYZmnMf#2jjCw>;05w3FDzzDD+P$ju<4~R``^TqudE1`YG`E_8nu;;B`bx7 zGPJ(0(O17H#NtHrTHZ9sl{?@F(n^{)6ROa#E`3yMOl%RT2K-^P?`r*Z#uw?NL{CEN zuo094Ce=hj9Zdb3I=N0!JIeP9PYC#e`N4q4qbOT_gM?X(o7Q)`V|vwU4sb$|g>O9kN;c1SQ>a5f)LA;ORkh^1 zJO>({O>6$Ln{EDMG!7@BPbIeaa|wo9r&R2Cd}XTm^yym_I{Z5zyUU--{~k4CE3hVw zpE&etM=-&V(C}2BT)e3ng>XQWX(jqMIg^Te&%?3;q{vB`Ryu4{WgjA6rnk?~gc6Yz zh;JrP;vC8ucMzm}Ah-htp32O_DB#IzMkAJd=a#AgF&hS+=^KB|qSxVfs zV#4ECw@fWaIv>K^O!#AEycCfCcbST{qS9L{LLi-VAFS7GaoSc(p&rV^xT zZU&YWJ5SK%(?#2fO`3bx z^~Y7Phh}doRe82f+PiqYDpiu~lx$|^cE(9LTbD3v_OxV+A*KU2GZ7EsOxLu3y=tP*WrFJ@8;3c7W7vHrt6 zFx861``%Vp(X;QwI?kPGdG+-ewt3QdU?d@Tg`d_~9K!g`!;bR1h?m(~-JpCs)bsr> z*C+Mye;3ux+UT+$qb4@YOg)nlz%xb=NqLhp!9_nKffcDgXZc^{zibLr^AZ`_fa>w; zn8>RM>$I0^`D|_dFyTR56}=?0=ZT=eDGq0xw$IHbeLFb#R6Y--lTF3yO=t zEs^|BO4lotG$v8?f zyYRneRW>bwGzjp*_L*ERQ-$EdwSYB26tIdOX6hDAXE`swC_a(#hWSjkLL-4Ww=2b4 zuBDQ2VMi9PbN#(#(3zm@geQ&*|6AHsp$!e1p-Wi9tClcMfVA!r5ABkw*&U}n!kwtj z`!w)Bjy7+__s) z(OW+D0>t&2N-e|}UZtsSRtz>gHWM>s9r0~+vbQxdW?(q z6>%jr9Fz?*lT24Nj-(rGTV`WS2+0gLWliCnx^14L^GQu%hykh1-$Vxuy|4MT7r^Vudx<~teaz$_lN>-&@gUPJ1wlt-iq=Sm`h4QI zUu|3XoLamI<+BCaW|>?MI?ei09KV|`3v?(_z;PZv8*H&@IRuQ*My|LIWZA{nlPY*H zEoiHieN|t4;GL1Vc6w$kSFc(fkE0(4(6p*~r}ED@+T*#)_M!8bWoxvFEqg^^v#@?t zp6xon2qD?QG8w4KH%B@{RTQk&M-?DjF4cB7uiHz1?w%b{ifQ82c*kzcph@|WgvF$m zmC0RE+7;opGURoEk|ld$$SWx!Xz7gi?Wk)LO)&8Z14lRW*CO%z`}QwAgl4MgbQy#l z%B_*1S6)ojud$?8+<}Q*!c%cMD?8<;1FX1@fV1 z?N^(I{-?*xl=^C7b;YV`L)hG+q~c;{hH1@JrF)-6F-XhGzH2;`>XJDY8wB;I4TzP! z_YI^purCx6?|nTlPg=9QruS_nec-6+cga9-nQfBgi=Uyz5qZ+q>?Mh5@QPaP%0kl} z9N}{E!So;h>cusF%$FXrnA3DaFVgV4hml$B$%;)A(KiitWL7vM2Te$AzkL^ukRQ^* zjUQ8FY0o~Tl8(aN^5luz#$YkZ&*2@A)o>Gm_MNBQ&j3C ziAvLN1S?j@CIk6J3;pfxSY)%hX1A~JV$9DE@R)L& zHaSC`|MAJ|)tU_z1LDQ{N0HK9N!&jk3zyXA)G1A-2@52ooUp1{%zZCgpxNI( zp}~BGgmm*ry5qoo7TCo4u6N`BttGw6w=Z?@B%e}Y)3eFEpm}9=J+Fx58Nrg=P>Tn$ zmQ&1&;$L@9fUYtklRkdxFH}rO*+;hmZ^bOa@0wl=eY+Di&IwWWPq8FcsvumqE7|yU zb=6Tw$oXxi79rg@p~6FPS!Gw=PewXwp#W4|(jh0U0$oblHA$V3JdV zzF_|sYI{eUJ{cb4zmvH$5BdH?r}~1Q{0i!y<*}uf9WwThD5UAv-2O%j4;#B_TnuDS zFVpxF+5fI-SUJ{{s4(F!ss0r5cKLGj4VoxWSls?+|_PQvJ>@Yd17#{2MAg?DC_UkkKYhM6~3kq9nQ z$o$>>u=nE)F%!dNN04p(B$RODn#;HTH-wlQV*ZDGmKOA5db?Zs~`vCUGA}~ts++U;4 zw|!j{Dv1S>L&oB>h^5KY$r4<8TEb%5`l$AwMgDagw9dtdhQ%ys+tpUZA9Sqea*O{v zgxwr&&DveO4Nav}nxU`9$9dbn?4=jn(`0Vf;eIWaNh_vDJNyu8?S{kPv3S7Ie8BTN zot@8SmdQqk^N`Y>zcO6jRwX{4jHMGG0iqo6#H)D02;#o@RygTT8Zd0hrc zxg&+313BFzMe9;N6I&%OTjd~Irlt*QDNOPDM3t~o4%d=i0(>78TiIQ`={i}qI!2jP z3jaJ?)|A}3_lz?;NAm2%TECBYPL5&`>|$o(6b4Jr`wo>z>?Fl(wdI%?m5vqDx0N*E z#|CIe+7$GLUUr}G==IV~60D2?K`BN-$299ljChv4h_-6?<}6;cre3?oLe|Ll4C{+! zf`t2~Cw3~sdHuG9iKBLsZbugVhkC#5l)CM#Zy3z^PHYIv&E!sOb<5GKk6-d^(-+Hl z)JZ(jzyVJ7HefSqa6+}|7=_`9$ooPyfR*#os(E|43&jsJ%W@L+RR`)r4wCXeX$;m= zCuZ44?yGh{EC)|&dUpy3uiYazw=yrWQ*Sv3AHb=Pu7j`1sjszzpYy4omxF)MsehzH z0QfW@#UU{JG_cqqsQNUh*&(?5G0z$su&}H1xnB?BX=+-r>vZ=@%rpV>s4X zIH6+%#aRTsVI9_TGuhg1RNU$vp;KqjB}dri87!>KD&de}NwYSSDFMkT3F|zG&?#Bd5uR*o zqH-9YN?}ZK{#DK?6>y%a%jQ3q=srxH_>JVVp;JcCc}ApDCYVj%FjFGI)*<#Jv-&){ z*(s-+E!s_MUw{lTREKyJ--wk7D?Cx@Tr~qx<&BeK!iKxQcDw5!1cj%>T-x4ILv+(xmnYPR9iYX{HxCNhK@zvxhN&S z>XDp%bKlH?`)WKAH~|I*zs}vJ)?RI2rq6DoCe*-S+W!U}YY(VDw{uY3FHCLbe@(cW zy9ds{at0}p@wHv`8y;!a(FU`T1MM=p$4U+UT`kMGt^lsR`)AUM8-c9qz-%R#gb%Kr z01kPhYZal(l@!;F?CT9a`|tgkpDkUd|5ZMA5u^nwo*$`?$zge}a&BH+@7}xq(6wFY z2lmU+@UdbH3vwyNjPDbgw8du9{?;Ij^niPrtFb~|ytIY~b%T_qb*0lH)r zvV~E5qfjGOGxsG;Z|>7sc->qMyIoD)j2bxiHFJI78~affC1SYi%tw?SiAjL;{d$M4 zAm+yvz56};?Y*H5Q~9CMe`8wDqhDUuGkmv?*6zQnoiP4a@FGGWN8l9xPw;9)r2T&c zugP4;>~!E||NmF;N~&Nlj{Sc#9I3Vfn*X=p(Zj&4S2|08&bgyc=F|DO!U z?d>~sbQCWDHg;5W1Q;D7Ea6K8O5*=yI5IMWF(XWTShEVhBC%jatCZlB#j_(7B~^)I zmDRVlWnr@jW0gwfv$PMAS5}wHj+CQJc2*4y_ll0pE-jN!izrL>@qVC?Sp0fxafrubk6~*JTVQ((eZJ_1>V15K5=B)+w@zj`cuf zB#VH3Q&XD;*D{gXGs^azlQhx)^hcef#|E17VP=l1W%|{Soe8fgaA%~L9bK-HvK?e* ziu3=SiA>#_7QDwBdoWVBTw&TA_N7IXm&f+eO4*{saGy-Vk@=N}CF)a3tUpA+gXbs; zJQ}1li~Q%sXI1j%1&=i=adWhGwmW`*)5%s@Qx{(q9O5H<=b>N3Pg;cJGPJUl$muut zVZe>B*{TqLe7UTlg;36o&vzyYCqP0Yl5v`FeaOGTLr@Pm}d$ z3CLq|f{{K-SaRZjntbPh2lINK9$Ts1@&XerR;3CJn1#->b7m`R2zzp=&kAdOt2CW%qX{zWB_ zn6$W)eEDJcZOMeaXNoUJ%A~3%F z>O%POV|7fmtk5!x&x8OA$*)P#(aw7eE_7!qXH`i#XHouJO1tl=d8Ri*K;bT-1-{D# zo8_9RZpWow$zM(5{7bVJD+a5u8-|0F732+tsc+5oMkJ)|44;qdwi+Qq?1Fo)yQii7 zldx#NB6nx%C-{iV*L;T64Ck!)$qatn&!WJ&vxjuxFM=1VD2SQ;`OZ*#TLDxn-yrg7 zcy#?p09*Kde^9#5YxBXvN@q)>$^S*zJHBQ5w|(13byP>TZQGn|+ml_>G+C2v+qT_g zyUDhv$u(hmnjg;Vxv%?Nmiu4WU#$Cv&$fPHKg#pU{8SIrgTbG^!G?3_+(?0o&!-sw zSd^tW7t#7+fEpg-Ew;~>PBhxS^^<9gcB{R$Q>7wD+Ss{zZ0Fo&9yi<)`LT0adkj|9 zSfd}Fj0@JILU7KwUmO#}M}|(J(+_3@@I-;C0E6>i5t@W}8E)FXgLc6)4f?jKo&`#W z`l9rOFbTGyxY@l-lN3i2W{E2aJ@|}W=!}?*pByEf;Yb3sKigtG3_(a(pj5sx_WN;( zZ{IS`l?izZ5D6ykN~B~@MKeag0Y3xJ2@XUe)|NpN8USbU7mb!dE?|H%947IdWzBXg zApTNc?TLLI8yX2Y0+0?7LlyUlkSipol9mqNzLNXqU}{b~I;!AN9}y*H`b_$3R3%*{ zewDk3R&#Vrw75R0HnNC*`f^Nr^*XurT=*XrBLL6<^b+qZ&ifCG$=_LA{$E&JL|gnn zES`}{`X_9QS|(oe*FBw*1NNV=t-}?KU+EHzjm2(lC=&*pw-1<`S1_xuKbsdYKrWKS zGhF2h1-QFB996VbI(#%NZ31I9dkQ=(FF0&eCPPUXa}g&s0zY*;X^Es_L$%O1A7Fn{ zTn1Y$Z*O<|Ak%p06pu|uQ`hi>V1Hfp9OGK?CdW+oX#MieG536G%<0M{->$$R_kQ(V z;m_GpW(;&}QcK?+20#Y}DWE7xM$fJiBw1{tPhTOUs1mWEgCv4w~8LIVrldoxzn7G43Oa0av2JS z3S4Gnr}&Rhlcg3oKwtP^tkHn5ft0!zyOh~{Htl^6JNq>&dQ!Z=iH^Sw_>O||=MR%V zhSh4|(m<;m9ekue`ZBC#2E6!}84sMqCDb9-wd}W>$mm0zw*j_VofcJQ^t{d_HnBWZ zu2GXVpXb0^4Zl;`t`)H_eagD`>X@z<4dVZG(x~xBas?jZ-r(iq%=L3Ys-&LvTUO~^ zS@Y30kN_fC=`?HbBcoGCGeS-B04+F3$Uk&`I9Q$YY~uTH?g@;9?AHkj7jT0>kYEw+);Ru*Fp;68uK-c+$=Q>(P!dmTXvK)P}_**)F_?s=gAJB zh$U13B{=;aG@KVlG?yX?7Tu=Y*4?~n-cK2EQx(=Si}MxM61pbccSsm5i)NG8`6ZwC z$sALaPANR?KqMk~81{o^{Qj_kc1 zwRvUZd$!#wk{eMCTtw5%pdM8v_xwlgTI<3=VdXCdJd7Q{Pc+#Qfqu5p-6UH|xj?sM zWWUZ%R9Uod_2%m=>Y?Da@M+6pkt-!My4N}#W&3)JaeN`^)svGnT|`5|75tVd<2|eF z^RK)O!dmx!`zARPLCPGHYriAPnxOr#^^e4<1*7g)LpAt+4)PueG$$A1dN&XWb5m%sNeUcMFcozh_ckpvRg({5Z)2&s{@NTQWKHX@!=)iN`mi-=~`B7U) zqK}^Q)Pc+bSCv;#h1-HaErs3JlQpix#@CW*1Uab(1)nV{nJQe@-{;FUqdq4tK?VW8 z1~@+b44AqhxInEhsXH%~n*Ne>m4DD;N)xQ%rEO?;4c#QvcBF?Y2WGwM*vdvj$D87w zd?A?H>;7^oJo}U}f{m7quA}73jT>h*a1BuVH7LQr-xHV0#U_O#gDEVW2BB#zKz|n# ziYgX{(2yjWI~c3*&3gI~ITjNbh8$G-I0bf@mxe;ub=ej3ap~r-&xD<~2emq8GW>5WbSyC57;(}~SMiq!1Bf)zeXDPSe zu;~E0626X4ohY0Eh4o0c?*z%t7E((}%M82MBPh=s(Y&)*t{x@0>Yc?FX~CM95y`C+ zMT~rCzfeAvcc zXU<6<7u^3~Sz6vyP_uTfVsl5x;qianKm>cnLW5Z0;DGEfo(_s>aEV^hfcyd&S2rqw z_eweX{RX18u0B!>oTVJzg$=Hh7q&fvr4zoTf)jR#nHnv>h_YmWzqPVqVR31B5xCah z%=|sIi+j75xqq;YOM(q!vbdzIV&&%c?%sdoq_2Btc5n1RFY_6ymWUbq2Y{OlY%-_D zAB>E0^oU`k=j#)Ba_h0b9)e!HDY+guIAk{pF!+tdGB8(&930uERga>_Y!D^Oc(oEo zI#(v1{5lPNyPT3(_AS=F5Q=J7bkgh6vnxoN(Bcl*S& zRc_?!0l)LOFoIca*^K?ZD{JIixZ$8f_(bABeJ6!Cz$##dq~XqVj>YiJ6(y8^G-Ryr zq(%^uX*XO7W(sx7G|m+WCLo784&8B=1SH~{@zj?>B-hd0M!W6b1(C(x!wi^9(7=Q1 zIvL~>Tlj5|T*|oXA(BMfQwKkoX5gd;8ziA#JQg?vA;JXaI_yFoW`GqhQ$~R_JPJrn z!(j-DNa62S5<_^%tWCYz7sKsu4*=9hBFj$47= z%#BXv8OKA5gYaj=5dEQSl`?d%=?VElwbvmK#gI3jU_NHv#jSBT*p;D$(B8wf)bDc? zTsG4-c!_w@JB7&M?o_R#J!rEbu_=!f)ruT!G_g{K@Qy*^nIfx5?3o4WW_R836Qu;K zuwt5XZDkxCr0Go2_P@@O_q=)foH8(dVBq7KmoJD3QWF%;hzpe!q{JX^n{gXVbqsVFlF`#1B8UmDw*4% zdXSM>_ajiv-QWnI1_Qf{@pcqGi&}swlS#?tqsDBLWeAJHG1mbv1X~Aab*{qGu6ELf zQi5K)kRlA>3$SHFpvkGTC8SK`3UHS|B5t);Q4W!Nn7E|FysKBy(z#@W4`wuuXG28y~Lp*niHF&&(Gvj#S%z?Ob2ku#4 zEcY3W_5A{j!^y)_-$487fgg%h16Q+_j?;}eS%{pA(&gCliS6T2cC z0?TYi#V4ezT|;9S=qLaH7N##*y?==JPY~qSr?B#3hG{{}S4x6iw&Rb&U}La{VaL$l zg@OTKB88#Gq+DL)K=@tg+Py*4gXK3fAU73pV<4;_LOJ*MJ&-T~f|8go9R+-9FgI>~ z@{A!X-YRB%u27BDclck;G;A(qBcoPoQp}{_tbmGeYR=6@So#VL1=Vi11YS-(^+rao zV&P-)`8D*cv zEv>t!eT2fTuT59=t46<~G(+F~H{7W*{E#(TWZg?t=B7jXJVK=LSwhFSEWrSSFz-utFKvO>p?^`};?>GLB!+ElFN6{+?`dLrC-H3hNRodehP1!;GNxrmzRjD;) zFk-oA4wxD;Jzp>Co@KEkAsk-Y>2D_!R&}V|ALeUNT)13S*kxLM2ve!$(O^sNdVR~C z)-^rDa+$J2{>CyDbdtizI50in0O7>9`|nkSpZr0V{lo#0KLhhU!qum_1Mg5dvV6{o zhM>pCt2+qL1enql=)85}9#23lQnV1Yz4AA$@D2E^OA$h|tc4Y3UiSx?C$+`brp(o6 zxlxJuV^FP(S+0sQ%bvfz2Az0lcQI{7gw~>HwoVDG`uX1f!%|BIaI)Fm13h?$N%M6J zI8Eddp7V#`frPbhg5qFg?IL+GA!8@p-CZ9QNQ<`ZEhiZg+ud3sMtK)72NgKaRb#Al zDySbA^*zz_FIs-KPW`~#50g;fA!k)YOu4Z(a})SBXRX-MTt3Bn*0JFwo}7lF0A`?{ ziOTY9AC~jMEiVHRj<#wAZK_EXi`>`mHVPasEO3!GSbIQgBy6$NTv6S1(CNv8B22lP3PMkO+4xV>#x~+o|+>8thKGoT3z7!Bcj}9XL zjZmmRF}AH z;(}46F$EGu1;D1FROZt1uxy@&I)?6&46ZL_RVvZNJp#=WF~h!jS>uCU6J&ji?dD4& zqcsc5dpQI3o1CkAr}XQKv%P3&uo&n7Y;;I+n*64njSL}-9&u7(nhzAPKo!gAAYpWv z-{j|LGkJXxOu543+|;q+-YbZt>x;EOzX({KH%xxFxitbG+N<}J&F9@AL%03ffvfAo zVKs(97B#hasB#D<+Vu#B8XDhpu<+`}&$p;y<$?@;9WpExizGq!c`y>>^cxfmDyfw8*O2Z;|2v%S!U@Y`1Rk zjbGfv;_VqC@~qFNMjxYSBq18x&XO&gDqCrOpk_@d@YjfUk)IA%U4uYqaIN8mUU0PdE55_R=PI;aMJ60kjzZ#hF zm3eo5jCk?Xkby6!iO!^1CI`3^JVJ!&-H8y|)5p6k3ycdn z{ zQ9MjL-$=RMH&q*x9tR_s#us=1e<{zSWk_7ywxjRvXO#e_dTcmB8uVKu*~4N^(;_NG zFx<-Er0kbo38RnmULwzNDOEiAEsRitFE5v6_(@rKrf<`J`k6_%U|2tWr28#+G#wUi5R1Te!#fJLM1;b;ntJ{uS~nGRu`d zUFv{X7F*b)E*#gB;@%6$qgta$b67jy&1IURB1q3L%<(jmiT+VIxXw>s1%Om_Aavd9 zy3}^&7zDm;8OC5f^Ht@0mv?|88T2U*|hZwqgvdjS_elNB|h|42%w0t zqlT{`V`effEUB81DcJq)!sKtnW$AtP!1&@M9?ba;zeG}4S~&ZJZ1_~y{4}QIys#Yhj8e|1 zn7H_&ij)RmOH&zqV- z=<&&p^<(CKp-rwI>p$rSkCH};F>wL7nDF~`PWa%k_)3F?Wou+Z$37yh`SV@;Zb&b3qA+>#^vz_uaADG$j9VH z!w=+Pn(oBEfgO$5F17mZ_dQsllC=)01e%VwGlG8ZTIXctG zQ09$F#S*sya;pbE8U$=5k|m8lS(=G?wovJ^UyxPuT*nXh__X(hQRyo zJ6OoTt;$i`a$e&b09Tqs_u0WRKEN~UFm~0vF~4Q-^N^m->G|pxqX0;+HoN+S2~;ed z?bLMg@6^^JhxrDUi^}LL}=TRJvz0u zk-_a<{K%=VvDwf+2THfCYHF;|AZLH#eZYz~xNwbRF^;F%`(kzIG+xwlJVGe|G73M* ze<+Jp*HjILP0mA)V<&N(Cx@Aj_sMq~E&oy7|zM8Y((_gmv#WyteCxK@aHNOriWEG4wPEY`=pIS2=tZ-XE?Im{1z zP0LydzCnb*o(?+_5|?z@B3M~A+eYD5XTGL~)VjpC*`6iOzS^+5e2-$jVUGXh%d83z z@|6_4aTGQd6NrIx1UR{m5r6;XOx7chp#Q4Lsd-dF2c2pZ< zF{!=goXl=;hI_vzXfes@Yz#Lco1y@Th*3oFzI6MpV1Z|u?}Qq>u++giwKyHN8&qp1 z+KRu%>l6mdbC?f~%Uhr6ai6Q77A6qugkEHqt=d4Z)EU4;%Z1J002NA{f;s1KNthP zF^@>oba0=Ib-Wo;|1qjqmRG+o+>0nJ9R4<{yiEz^{AE;;LUl;~OPa`Dn<)Qh;r?7^ z---v@08$KY23LAmm zJuxaK3Kf_Y<4+t2A54}`Tbw~yN|;|r@u?s=B{nL%%q!kGBBYU~q6NL%sEsm}wxO%1 z40eFIuO@V?ceZk}Gm;u75(t+)zizpK0cpFx=oRBYV7!{!yMIY^jtz4$17l>1wtZXO zUw5`0*C6TlvE}0pEDC-?bYAOc1Oy*hZ~H0rWcla(D8t^t5gBthDWw&O(w^G^+)tZ5ou zg0k=4h{H=wYeqOKMwDypaR&i))Nwq7(m+K~GymVVQN$Cu%gCuvVaZ=)7NRUv&f40y zc_s>L4m0t$)68=shcP1s^1s__wtDtQVO}#%*}4KCCRSZs_ZE3AItbHOXV2F+$|&&| zes(x+V(5JCvEStUw6#`rff+{TSwFV@i?STn*kkVI$Q@(l?bAgO`geoqpa(@IKa}BQ z?_d1pT0VK}oH#ns?k=l(Sk}W^bf^Z4Mob{@V*(Fny@!t)Qu5;BA(%mpXvB(TbJ-Cz zhNxRg%Gy|?rjH05m@;trhh(k{Qj+8bi-p2@8dCzAk>S~O*qT&YE|7ah+Acgf!Q!kS zbJh4*tZku}R1N(gA%B+}rTTe%vO23n2NFmF znc7kZ7t)Z=u^Ryw_lOLOq@qijaD?2ppJeDGD!gOSyHAq>8rp+V9k>K^N&{!YOagUhYLQ|Z_rF$XFW)tUarc}V_vQ&@KC`1q6z{4In~8_VUr*2f*qQL9m{WK^!B=K_E=l-;yYryWNIB%g!-sLs zRcQ(J2l6i;Swe>q(rZ77+}Sw-}yaAYmQ zi-vIyJp-Yc!hzR22>w^MJe+u@`G zd4_oa0SuGsO|hL|3iX_9Iud)sfjnoMlN~KTw|WBLkT{Kd1K&4HV!4;Oy`hn%1bxw6 zxoR73peYplc71wY$8D@!AH9u4w*j<* zV2`B5tZ=D1t?f|CaIWK zJjjL-GheoTc4RXxU@k-%{KI>5R}d>fdr~ME<}2)oC3WcwF;azPZrq9i{V|xrc67^_ zlb@W#eYNN)1yt6&x~&c^vtn#oEL3<}TGQ^3UfLk9HWp4@N|~P&Rvkc*3*9`1t2Tw{ zG8P_r8glsN3(-ewnGdAYwW-B%sjyS&L0w+1_Ro(nuBodYv&)t%KDx-KbP+r0dOWQ7 z`R(Q2MhQHX_W@rtVg;7Y-Uy7=zMPyM#OUpxMvNy{CXKO|F{|HF^`1kgV+0?8+D->G zowRA?8MClg5BMGghkI=ncd|A(LzS}j5p6-82VYppRVQO7L>^ZOPe(R%OHozb&dG6A z>4t)pD5Yoa6B4s~n;P4(Pkqj3u0t}+j$8n%NR*?CBBSzXXqNr`z_xT?-}reTL6vVr?c@I%3jMtDgsmGiW+2J?2&xp=IQcmC5_11Hc{;Itx+)%LRS{og;GD5Vn>b=D^$Jy9^}zqJ zGs%&erL+2x2pbv(eThfTksAK?%RabCRv3e?gpIUWf!}0JgD8ZWYjfc+SobC$Z4byV zPB4_7$DZnv@N8;Twxo=LwU+O&i&> z$MUG%Rhe7#dhhE{!!R`_Ljs_%kYZ1~6B7J$P*UN>OMF=mAM0gEgY4q<)I%EuVVq%O zC#JT{=%l^JO~y9*kcnKN%;Ne_O&}2chk-kXcJ&S9$AI43fgyfm_1fUZdX?qKwuy?# zOL++ytj=N(o(cHaZs zN=Sb&K7%$X&%M$dc-I=AbIq)1;!e9*zbc-P7g)4vmCMA{rUKEZ=GMAes2_fCoP(wO`sHo-a(^G3toO#5FxrY- z%PUhYTvDa}-QjZCFO~F2@5=FYnbo;>JJT;%WxQT4uwTR)MxV~UYe-;HPn!$;vZt8~K!!#1FOq6Rfe(N8WiZ(A%r9Z-&+8 zUv?&q2#cql&`kfmUN>q{|G(@^*u-#9=fqHI3l}1f{q{Y^I!toAs2Ps~6C<^TV4tVb z{2vD`Mo_~o_f~#fHf3;~i;z`k+uB|88fZ8w31woWxwyH1`NJU=b+r#8fpXcW-08(oYw8Eu7-pe*fv9%9t>N1$` zWd}K?b%09YDqQzv7kj#Oh->O9+Vf?P7^!VUQsFv2<7J;(v29Fq>N>gO<$yV+ZNfs~ zCVlPYkbAmq%5~}{`}yTa2&sK0MBz3c@AX(pv3>3(W$Lz=@AX6}rhUFd;jUcw^;B!R zeX(WguG;hU%n+$#d064TKI8S=Qn6!oY3jbY!bAJo>xJ8N$L7P-!?)+x zpT0<)+t7-SeR#hwLlrxBv8Eq~_)1gYbNH~ZHeORsqWj;^7Oa+mg(0E&$s7or0&OI#oyN%Z!gD+-A_x?zwbNV zUN2+1Uyc;tp4Q%eKTdc5ewcpy{r(J&!9Q&#!k?(hA6=&+xWT_^?thz02l@y(yRFB{ z|E23>-^p$%emC;}9aSk3>Ha&aGJSk|0jK_VL8#b}6a8-F|M|alozXG>82M9D5gA>1 zoU?Os^H|gV=sLfWN30;3e)OA_N)AigtTn9jJ(+uf&JshT4_vQZ45D(DKj-doXwOh@lARn?h+2n9hz+{ zlP0`C-U)|X$`@IwWJ>!MG(u}NqdSI&9tRWUW@y=o1&%(KDZ?=}SuwwCN0)~>JPv?W z!i1FEtq3hO^{yn>X{yp?)!MtCJFQ00sspo474W-1fd^;Vf+e&SuQpP3YJ(JK-ljJw z^Ma^}lWVO%APr%&keT4HGc6F;yoCf`zB%|_>S|>mAI1jry&iQ!tUcysa@ z@@y+kuOu^Sp5?f+Sw50dzOCiv2+UX3l{^z_Hc6O>im47CWO}^qu1Hi9x&hQ>IQ> z?7RmjF=`3P`Iy$}ElMt^GeUgzRKFaFb3_P-#(+W0&^}v|`)2sS!3}~z4J1dErkQb> z_oO2i3KfTQc}xxx$Ac&912wqWxuY2QDJcI69@Y-dR)NH z0aYdqw}D>*sRR8|S|}kh=eEaZ1nOCgR}=Ye8m0J69 z*Z?VJsytn`XB)#``%^mVY_da{>ptl ziAnc?U~*m|g}qA(dU)swxFuIZ+)ka@5o0_rQ65=FdYHqz^(6IhQcy3E1Jcq9q)p^8 z@KZex9+6+2@4z{-u~h4B^qxB~PV;*?BUu4`{X&+TT{2(pML>U!P2 zER#ZKu{rktmZ9o-PZ4S`tE^NiMMw{O#||Kz-P>;}4(e$P!aNCFe-$E1{32pLC|ET~m$uw>$+*mHM zV(LM8*cn>eN?>V<^xXPuf_+RCQ=$7s2Az4;kxD0onc)|_$PLY6Jfzh=7^1BoKlRU= zyviH!MmwgLX@P0?2Pp=*$2dzAvdHCvo!|JbJzac`ZYifP?t}h?nhxU3*4xU|gviHclDm)8OAs~r&O&HFKMt&NDC#%~!Z2&xFvpQU0=w`_ z>f!)dbgVyxlOek5GNeKk(EbsRc&>6-^vz2EMYC^}R4e&dG~xJ%8?YV$KQF(!u!-rb zIz1fT#-p&q3WKz0qcPM~i~siLI{1eULR_m7L6PRq0qYR^qfb&2g24rjtq~@Wsuofp zkvUD6F_edF)8q{+`viXMZ4ymqWP77%Z_Ud65yO*#nmgo}_((tM4E4MZjAWsPb&!}Q zshOK(ExA-fv7S*U4kgEr*L8L{GVaj~s^HZ=8WJMk<5e)CP zLEI+o58CpI`hjpIulvVo5lIamsBuwXyG2~i7nPZ0wF1{&Viya{-=JcbR~TX=h1~_p*dt!r$jYVY~fGL z6bT;8`N=w?b>FnQb2q9#3uJA{Vd2il9ZChiq2jIeiBAy_jug`+(a2=1&gQYohBKQ=d-#67pRoPm|uC1>A(REhYyN<7IKHazUAXGbq$gYb?kDrgeP;wyf8!7%cTU2rr#0k)+A^E%EIbRQId$xi=&5$^&uyi5P;J6L z6?VJgHn_IO?85H^cX?P2>ZS$zwypldt3vzZbGlI%lMpi+lw9z=BUlf!A@c)lr4Ynd zYi%p~a@&0idQYp?8XH|r!%}gE16tXVs;)Am81c%_adw_QFGs7%9n**n5qj7zTM*N9 z#><9GgmS&B;$Llzj_T1Pi8iRmqSJ*^)ticvl}SqWlXmH7_Vj+|@$Tg1Em9(HndRy2_ak_-m_x;#ry62;Q zhRbiiPgPdFb8@mL2%OIfaH`T!etM(ioT^J~`Snh)d&~M<-)d z_kMy4gGLZ$GjHQlqkKnt#DoRQN^}Yoj%<#kqD4cc&w^L0B}Z@{0o`+gFP(YYnSf#y zjvb$B5Ifl~g5E~C7hepbHYgLE@0FBZQH-`m6S}RRue%=Rn;VZNRoTB77wHLJayED+ ztvW=1QQ0Q?nl|gz(3YkEgH_W96vDUch{f!=2$;#pt7 zzT72|WZhN#=&~El@h*CRdT5T5zaNazU-Gfy3xz;J^G5SwatB(s2xD%0Ao6w~OWvG; z)trvQT)QdC^7gT4KTm%3HbF0T{t2BX+irCiS5N7Ua-6I)fdHv1=oEhQN^^TB+&!PS zX|t=lh2M3rovD3`Bg#X)*Q?xpLRNG4p#}-!>}cY(y}A7f&f)hgUCt~~SO5CWrvs)B znPJk0ZUIB?+5H-3w?G#qB?;PsuW3u>uS?)LccLVcPNtaV1}^Sill&VJ!~@W`y_c+#fcMSF--h}BEO_xt*=e`j1Q(kw-slMtq+Vdu2gxs5 zRd_$j;YsHSp<|SkvwEbPC#WzljnAOMef*qg3kBQ95G)=5CPoYU5x;15hGQ=<;B;|+?W2ggV!0~Ttq zIYd~IX4cq$V?~b9k@pvE=@+j{q5Oh77dvbuFkUYMobY#wi(AM7Ep@M3?2@6yVj|(- zU=1ayWJ)df9<6L#ojfP+kN#@Tl_f3{3-r194d$uBnBgypBBho~shBD9WpbwKc@Ll` z4ux=*M%y5xIb@60E#$s#ri{ZWsIXlaNKRtL9SacuHUNsy_W!`xx@`*DQ-jYFGoklz zagtNP_V%cDmqDjd57wv|aw=Efp08#Q`TL{l0|@@^16;uj|NW@{(+B*&wEeb?{r|_y zT>lP+sn{SN+yCtYELfrOa5$0PSLOl#^Z^E}=n4#)1a}qK#*cPqCqucm2`!*ONw|VP!^Ofx&I;0#Mj? z_Lojh&nn4w(J^PY`cYA_Bku0-*axA{-?jZvj>9KCAjnWD^zq)FjGho=vSyMI%fUW; zTug@8k-7p&Msz$a{vfh|<``<#x8G#%$_@qs6!!A>!7!FACe{~faKpUf>6|K%NRKq@ zumAw)ORLW-O+A~!OS^3%(?m;LLZ<>YL$+NCs4(mw>n(rZ{6fPcqWA0=mM^zB%*M*k zI^##nr|q6@Je$3T)iT-lXWGMSc3M@@*Lf$n>60u0FC5tuiQ&FL7=Go=m+z2A)44EB zAo=!23WieE3WLe^rn9A5lksf%j^-b0tzZ6UFifP-*?P4%l0f%y$}5N!cBFp$%j8Jajf;C=?w-a0ujqz}`R#{Mtxx45^WiAvo411Tb*6-y@mH z!67ExC<{xCfatYaf!e64m-sxG0Hb zSs2?QwF=1;e}G8hrc&5}fDSH>Ts-bRD2i6{kqc3c)RH0^f;_dzh%1femNLuvTUcV; z?w`=553OOKCc!2Sb$GaAyalHZ;^1*cOnA>Ecl_`AQkXy$-hPFRT!$0BfN#>map(jK za-RFxpL@aw(IK%Fkw(�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

-aX%Ac-9WgK&1)Kwe_480Q>v72foS7F* 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

XAJfuQYzLBvR2Ww-PO-gfP{qE?dEDqT$Li5+S33 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

aBY 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ʹR>k!ve^hTy}~G{$(mTPG!U@JCKpK1#Hg$T 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%0Am;%^H?EE%{b7KN8G*qJ8RV1! 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

qa2|{mqdrDM*3aGQ156J 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
B(YXyc5Ab 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ͤ{>Pn>$ORXdeD>zICI+3LRL>`WW#RecrSo=F!lZMO; zNm=xZY3dipVJj8NvS`7H28o#RxsOQ;i#jmIYhxul{ED=gnV=jNM`(mjxHd|N8dPZs zXt0W1@XZL}z^X*fI6#_>PLSh6|HHv3&2V5q_mkNOLplt%8UyA>`v$7 zrt^5fd1|I;gcK}L8Vg($aC**9IF4=<&j#g$2VEY^)W`Z1dajKLq9#c}dXz!Q~BYmzZg39DjH^5g|j&^KaeEgHp8j5!8E#LwfjA0iRK zYtuKatWE+V4>Q$(T~!TLQqo@q)?n?h#q7uP(If`~6k&nWW$iW|GS*CZ%u^JdFTI_^ z+|qN9CAYdLxv?Vyd`k!1Q~yg2yQDXkl8LAPM9a`xMo*DXBH}<|QHVm72Wt%kY>frg zc~+o^R(i#NCa_oK;ZRDwK{<*+JpoPbV?1&p0GQ(#6=ha!D1@^*gs2JETYWg4)SAsf zRw6J%TS)S!tB>AJsG?@yyL~$&Iplydg>`y3QK%6C%18GGNgj#Cb!%19^NKLi+ zeA+t@G7gZrXZZ~tBh;8c+L3KWi;-DsI9ga0mw?Shge}-H*wg^X+vJIdi)Es7QwWI- z*NUCbPqi1#v5AsZ1|5x6X@Js@C0qml+F0VNP1vwp<7?T>)!fb9uR*1^vUpRry&q~N zOi)$2&{ZLG^%7{q%GL1IuS0|N+!oJ`T2B&Pd=%HL)!K8CGPIqcaB~R=Wj)%2O@exY zhJ+cU5lfm4pVKAE%V>?ORoF?b+kyQPfgOWeyv*lWMH?;02HM0`wIB64RjE?d%o(A= z9ZQd;h6jb*to_$UfT(}HP|mgA`^De;Y7RG@G&&SFG}Qz*6W~<3fR%&=t56^Ry~~7s zxcm4~L$FB&PSd8nmHjOR2iR3SbAkbOGczT(;mn5&_SMm0oODH>L=#%ASzGng-QR7k z<4xgrNe&Qp*K+XR5UHUD23YF1!-!BH^F!nB>Q!>dUK#f?rVIaX!7>_d^ifX_%RQy8# zXbq6@9B*wTh-;Y=hRukahHluZG_GMiCgVp)qnsq0=EXM+Os9tv3&0c@7`|6I-i$zI zV|QrAzC{$~q1(Enl!1Vw>K%g-g%ezSJ0%o13#s9kj1I;bK2oe6r2){z)1zEEpqK7vs*h3 zfjX0%#HoV{3Q!FdfsQNx#A9CA&y=K*%XsF~gG6KCw9a^DA<0X6Gm;4bKqV>2M+7!r zo`@Cs!zqCcE6Hak)DoJJMp!7H<^rdBI;Sc|);)pht|4k=!CB;@bfHOto z?$}DzW#*$s>ZCp_*IAWn0|ROL+uWrkqtT;#IMKI~x3fIwL<<|HZdh;r<6*Qt`~2Lo zshmVsLl3 ziYsl~vnIvMS()_z^_}$eOOyzm3)-|uBN^23Hl^n5&h~8GvRwhuU}xOysFv#B`$e@5 zH8kQuOJiYOTWe~JBD}U1M|3tti`9)N>$zz*14iMv&OpJ`A~5Zu-tHmRW;=o@s#7B< zQ4?Ns(d$?1YaZrkzgZ|pE43`+BLFQ^$wnZ@IVY+0w?e{&LptIvT_oJi;{o{H6E+=b zG#kROq=s3;&$jRT#&5d9GIH7Pr%5t++9&pzC(ODh29}95i?V*2wgLxm79=#I)-kyX zMNU>wA{#QhawdfigOkE2bAl=aKTszl$NVPo5;yS^M{&+t;~0f)yojo;P4O6)@foM_ z8n3C&N}tdFDv`D#EgSdo9|!Uv7xG%c@nCClyI8g|9`Yq;@+NokC(q`D9j?C6Ln=UJ zD97?F*YYjr@`;=9E(h~47xOVE^D;N{Ge`3@SMxPz^EP+$H;3~$m-9KN^E$WlJIC`p z*YiE+^FH_UKL_+cPwM8nLO~z%wJ0+~SM)`%FprU5Mu&3fzzor(^h&q%OULv~*Yr*2 z^iKEmPY3l-7xhsm^-?$WQ%ChwSM^nA^;UQFSBLdjm-Shv^-$+hCfm^eE+!ZoaeJZw z3fMu#GD}rB3@`~IAnYwSdvseF!XZ?0K`A8w?7_TXz>7*lDpamwmv&^oi)v4aBfP*h z(~Bnm96~`x0B?sBaK8&}KX!AkvRt1s3cn5mXRcol_PJnpEadiXtG`;IazqSEX9*U0(n9n3QSoyp7iC=D8!_AA?=9rszAl$2qk+02@r!&yQxng^%kH>6^dwBQ^`7H{%Z((?9`J7LjW>D{k5d3iA`&mY)zb7f3cX4X} z>3PKmdb&7#qW9F**%r0mL$hp1OyC(^b8( z5Ug6P_IfQy$p_F@hl=-&7VgdXNI0E_s2)$5J-o`+E0(Xn&)@I=4=|v>fdmU0Jcux% z!i5YQ9z@g44TA|25@DjKW?}?83^GzwP$3)zi)2DhxX_8>M>3~6wo>^@CB};wB4~i1 zfX&1S0uET%7{P&nG#WV~vj?ash6ye`^7IK*=uVPoEX>>lA#2tHFT(|Gibg3@d1P75 zVndIZF_thjFvwuZ?I8$pDfmM6vzP^96~bnX<@e4SQtoupHJTfa3 zB84Wtie>>tu6}`zCHgTW;*u0m>QzZKfaZ^4AS(sWSNbL-x{{9v+3u(}Cduv`_I z+IX)ZSKFgCD{==Y-NG%#dDzFiH;1-?c2rs9!CIp~QoJoq#5PmcShe8MGg#>rMK2{u z0Hz(8!D;!4PcbHanl^D7eo7s1SgDuYT7QVO9$UFRup4`+VT0LD-F4;LXP^<7m~e}| zBZosCeh6ZSB92I6i6)+iVu~uR$RZOEU7{0qWGJwh1+UyFOi7*GXa*7C@c2p|*vPm> zE!#0lwjQUzSDUN-eFb207T4OP+}%t(&@WWw_a$RA)WE ziu>j%#FEzzv`wN}tu}`uib{+6?#pk#{{9Pazyc3UaKTR8nnA(}XAr5apXw4QDi2)A zBw=Pauq$>MNI+R99CIA%1Mjvm8OQB>EWrlzVyq;f52tkhm`fQ;O!2K1`7yHv6LUN7 zX&ZIqFkyH3myhHNH}{IH*9 zxLkId7duUA##V1QW1^A-`?NF~a6HRe8Q;ccsWkKa@=`g6#W4g)gN$r3A8!=t#vLpE zai{@w4LRAj&S&%mcqX0qYY)Fo^)HW!nqc95C%$#ojm|7MYZLhTI?04(fExtC#D*L@W8zs+-a`Tj;!koi_&-Sz5!vo&V&2Hq(wx;k|7(6PRkp(iY{IABoDFQ0v5E&GeU}j_i z0|G9AQLAAa47VvC&s zV|GjpG zVA-1+PG?w)BF$Qu;Hz2z_fa(wb6h&SBs7k;A#(iCpPCJn+4#uBc?}k_P$Ym_?0em8@jG4`#^}?vy$2v8#ehBIAEc>gYWz18#VC(>h z6baJ;Mjn(TYguolEA+v3wX${V>~2c3xl&eA<9J#C@_JUa1(&d(3G8--3&-DLw^Y(| z6jX`mT(oj`sgAH%F~ADo01J4)1TL_F`!!#jHHtMuDZ;3P6xx5*wv5Qg05@40O|?~$ zpaX2fww`p43gpQmAMR#{Z@A$9@9y@l6y{W?h#R#BJdVGMz-)5oNhD$jW0@W8rv;UG zSKYe!NaBNWZE?jeV{}$j4=&Y)C2U`E1$M%XEGJX#=uBQ28Ke}nF>-~Gu_u2C!+j+4 zmVG5jDOZZYZ)|ef>f`t&7G_C7acRSvr z&T~?%hiVRs%GP1_upFi>>`2P`;QKCfxHXaQ6+^qe3P+!h??2W{zFeLEOFT#is|Tf6uqZ@XOSZNyf+5( z(}+1pWSza<@+B(C1x^Ql_WO-Q=X%TYi3US^JLZp=xywcV(?N`U=iu)7Knagp`h9%z zl&`$yFOPYDguD&^dqZzxzo&PuM;s7IwUjuQyho_3jpDd~#^)8x$Bd$v)Q-AWs?lCU z)?9o{MQ3)DObN$RG~M6yWwGe`8pz=msMqLxecthGdSx%d)Prt3s(f!==x!by7wGwka-KpfDPz?4`_MYhctD@J}yH5B(ZgqGG>MWNocfJ&{u)$B!5R{fh4gP z>+oy#Qi7^SfD}l8P=x@jaT`rRL=mupxTg+hAy4D?WtLPyWncqlFaYJ`;E+D20b4c!w-eWL0E`NmzChh=pCJ za2X*8HF$%Npnwo)iI<3pnW%}qWHTRwF&HxhZN^`86al%F032XAgO-746BE8;9pnH3 zxpe?1bX2AI7F4kt3otXOQE+!wiim)UVB#B|wgAtuLZoPl!B~Cq##5vl?;c#gLvF$qbB5>Sp0xrlVw zk8Jb+0O<&3m~hTOR?IMsdLWK|a{<>#iU(MaDN|%~6o<#qG@tm1ai&JAWRJ=?h%|eF>Lb7dWppD$tagvjr;i278NEP~#)!dkpympp=(It5*XDH(xjRerfX#QByh1qi~)mZ2$_iMc7(*`1NVbZ1GP+QRqlHiJA?t0o}(lAkiwQAXNk)0a`N`CbpNp*ouDfC~oLU62pQm=v>0t zECJb`2vDFF(wM)1LlW?PBDV{KFeV%Ec!zl^J?AmisVZY5Rr5KW-U*?NFj)gA53ItR z0&*r&^`I4FkaR$wv!Vdp6caW#pLwz#9Qu()CpCc?6d#$LB}!ek$#xeSnU~c6d7?=& zhryeFz)h?NlSn#C`Q@NGWg)!=PN=D${5d20DJA(SrW>LF+j2V*rkSHbXUs{US}Hz3 z>U9m8o9)?@&=sT6Wf}~So_*@4e+sC9N(GJJk7O7R7g(sD&=c2a3y8{^GcuB1m#Am9 zs5s}Sh8m&AV41!qIz4Glj5=ph*9e!IshPn53qYi!I;krfsfy~UlyHiu3JkhAbp^*p zk6Nl}LaOqBsIMAbtqQBFdI-S!slG~Fl`2kRN0=ZdcBs;=wGuKa=kh>EG>DzEcOubF25lo9%^^{TJ? z%CD-L00hvk0V}WrORxoNum?Mq39u1!2XtYEun!Bd5i7A1OR*Jeu@|dLgaNP^%ds8n zu^$VvAuF;YOR^F)On(OS3g=vp0*gIjgff%d047pMRg z3btiywr7jBX{)wt%eHOnwr>l!aVxiT3kpBNmUN4^d8@Z{Tdq{Ow||SaS1Y)KYqR%J zj0}^X0-(5Ls|alLYM)>dWU)1mx3zAGbyq~jiy3=I4< z4(x)PdLzF(vw;;vH(8o&H zeoLA1;G;?pfjy^SyO*vhmY{#R#2&rWkdaS-)m&sxHnDslxW~IN@m&UoQuWiiB zz5K970%79QYu98e!2H6{Wx=*kZjivm;3~)&VZS!O3j@3t_AXA56xCjLW*r&*SRL{|wLp z8zq#R&zROE1Pyz(iyzYLpcBwM=P|voQ5rDwx{OgFU~!cJf`aq<%mpnh5@K}mA*Yv7 z6Xc6cyAgg?aT{BqcxTreiUTO;T*)TUkBkO7hmsZZ*dU2KMAH!!F^$dMaLE$F(x8zQ zA4}4+8WSvP1n7o8Xd}4#zIe<=6KaPx(jHd!}-*2h|lc|7A&Brj z&&A1&Tv1FYPv4BrzE#VV;$wVM+aHLfaS3OWnL&BUoYCOFGgS;;48QsuMpzox%k7PI z?cC3Oo_w8CZ{jc$ddw3A6y?=6>O(<}gG0X&IqY*cN<#?0<2AGiu5{FrLH#g6fg>Q) zG%bUXcP!b--O_wH-ko#Y(cFv$*k7fsRK+k?d)RYU7C0<}9iuJO0G>WcU5hxHk^ycP z+(h84oxltZT!GyP?2Uh^by~BqVTrxpv^-JdaIL;UINYsL&vP;#Q(qU>$0!j*6<`G2 zW6N$G&&;jkKnLAD?&D$^kQOY1i4){_>_`$s|63oJaMb+PZ}d~GWHTu^uSO!O+RYW} zO)0>&Vc{@PVwk0Q%}Uxw&Iyi)M*Nb$;DUk}o#?ZRdsO9Tc1}=-A$xL9FlXD#R*b{sK^bhned$U9EyTlV9Zj_D0pIPiqk zmSW&awdqDWed8N4$HAFO%9cz%Q6BCGn?gi>T&f|FC(5mLvy(BgKp3xKYClCysYi!k zINA3N%|0c={{2$^RCnKfR6pf>xEJRqck2)1IRIb;(je@PfCPIExk+Qa#;)Z@1>W7h z*&ZsGl7r%(qGUVw?9HfVuzuGsCv$ui|96#6@9dW8_m1x!S0>tx0g&Xvqbgpr6X!u# zQj30QiQejOl1JhS;mJzkP#Eo8`Y>_Y2XJ?Oz;55Ld1Qmd8p}AU(v^HT9iNGGdl}!D z>s~4lZ|mQ+A=;+#lwiCEY}k11M_attawVOiVq6$?3ebe|IAw5qJn{7R-=bdcM{nu* zuJlVEY2D+{o&GXZX(~@2tY8Nx+i)d40Y<9s?f7@?m`&>uI*ab&@nT#@xi0O1mti=Z zXEM??luWqh}gDoFW#K2#8kLScSHK)DuXYco)uJ-jU_`dl@W#9U@ z8xg%gC!U~vKTmuT2%kcKAGFH(;jbp3PyXc(X=ub-q#xV3?kzS_J}OG|223Wajh(?x zuUH=M%CG-Jv0Ok95DFszKqHVaT82bp69b?$3(MxvdR0oVUGEnh7LSES&2?f_P>q0x zS7Kza0Zj58pYK-P*UB^C?!ULjZ0Pk}OKm5F*WC zvUBg$ivm!U^-Hh-vG8&0|IG6iH&=I;x7YU<82ECSxY+m@Iazs`x!L&{I$C;~y4w00 zJ6n63yW9I4JY0O7yxja8JzagBy?Ft&0<10AY49DOXyU-^uqzSC%RLESY61MxC<#J( z3%_JYrAH6~LW3kxd`Q5I5CIv7V00D5mJo+^yl`ZMPa-b|8d!2*XrRp|EUxbL;bc?f z!#ocz^rZAs$d-6bB2JW8QD#giu4YEarGO>Nmlc14fnbKfE1kVG%vuF1!Pi+@whsCC zY?tkn{w@~ z3k*OKTQyjlpR4;d_I)#g>y|1vR159_$3M}Qd@s0ac-*I?2pLndL9I)9Y=5-t)KI&VEQ;sntp0NK04 zL=T|^g+A+ajM=dqy(QCTQNoR*XmJccTFlHOs#!M$ly*o_irkY|M{HekyL8_o z4>K0uY?cmbpBqg&8mg+mX5{=C`zpkXSg= zqyk?W330Ob_8ZRubYWQ&Si{}T&xSeFq0Ca)Lm&PSh(Q$M5Q$hs4Z*~Ljv${(Fc5(WQZR`-lwvT9SVb#d z5sO*W;ug8sMK6Bw8VHDjyF4KX`b}{uWJKc{eE~){z7dXbl;a%fSVueF5s!J);~x3g zM?d}%kbxBBAPHGWLmm>5iB#kw8QDljJ`$3Vl;k8SSxHM?5|f$Kb+rskKp#N?Xu)0rm2K)FDiKhqJTV1OH-!bD3mFB* z0s+u)(ZWUy?Lsx|H%xspFq|P3=|}~601uq>q>Q=(N?FR%x3x5-^jpA5--FWqz;pqN z0UK)$fT9S(a3Qfn7(M~C0gWCgJJ9T@w?4{{{Os*o*6|Ho$|t3m zPIq8)-N}f$(Q5R`MP+U30!i9dx4u=5CWWa7o;X*Rio~vTtqe_9dQ#Km|J4AB*=cCp z^3xdYYjvm~tb&sI%&)BVC685q_mI) zDO_3GTGtv;t~O$+-B2p1QsI@Z&6BHNgTmJ)*mMZ94W?fOiw6NzpaQ+@l3|rA(I2Ji zpQS61u8y1BXi8SK!Pw1Brs`RSTozr2&4W~@R8?SpwMG)tRMx&~+H1%yyQ_WeeCbkB5_ZEIgU zXE^SNj)lzzm%%k;|7E?La z1`70uUwocO$KIo-t$fZc(h6_Du9+W|eMegVzJgF22A^!Xd*CFy-4a}+z>H(&sKx{Z zcgqVJe&ML!>PrCWQW2n*!O-PhdicvJ>s|5)`^2JUc-}&8o%;lw8t@_Lw0nnbqaPjV z8PYbn!<}1UK3z6GPJl2M;Nu?;xER1yKuRCPxr6jWG9c1Pb>;J+52ZHB$ej-BtR(i& z=nE2@qW7#nBq_5~24WX*`({X%mLtYy2`Wuck)G|N1KZ#?5^E#4wD85NrXp;Lj>FCqLq^ z*TMrb{3eF>4FK&;0o~$i+H2U_&|cz?0SzVUP9YD0@PSs)R7y`g(ojFvkPJq!9yTix z@Ci*6>(`cvoj}2fJOO+%(I)EfTSi0nzGVkxr3b}J5Dd`>vB%@g10g<9u|x|Gg^&V4 zO^u%LYpBo`ZxI(yYuv&w`~<)ke-Y*Q$`^MF|90^TzmWWP%L6#TFwUY5Z3hj}LUUZ? zj7-Iy(&Bc4X#kM~-lQuo)W_=#!MwhLZ*qgFVC-WI4?Nya=vD>!*dhS)CZXuh&Z45d zsBsbN0~~b%7B#}(eCqYc3g>Jh3r=Al|7{{IHY*$_qL+SeWhM(B<`KofhI#UB7tE0k z+;8weqf4rh0tt~8cPAG|k|awK8LY6syv+-IEWy-o8GDQTcrgLEt^81m84IH#Xv7Mp z1N&5v4Z-R$9B)5(FxPzHPZWm^8clsr&U}q^6!n>?VIV{qbGEXcv2oDUBAV~tus4NTc5#mCzAxDwkI__R%W{Ez=`MR>i z)F(gY?hYKz0xG}>Ly~4pk}(@I7g3VPz-=WZvjMd3q_U2;2!JL7>?R3AAfn|AuA>hN z>+6ID9!0Szfnhh0107WmYOE58|6WtGo^o7X($;hI2SQ5?A`t zH785;aMQzP^AU!PEftf89FsolGYY|P>t2!<{fjbzs|yS4$5he)){ij6C~$nPEJiad z(=EY<5;f717XU>nOH(d!LNHGU#kOD;M>99GKtsjz!K5)YHxLiq6Dac$D`T@lv5JN? zg302Iney)u+!8w-;~>hRvOT3U3}jS3YsNmC)JcyH z{G^WQ`18k@?mwrrw)(0w{|Te<5{MHgR7B6|0Z;QTg>ofY!WWo>j9SwV?J!3GE(*K@Jq*Z4BX}*)x4q$0zU=4b`(`o;+(a63ixK8Ee0B2fc#15^hft>$nlov$jv>L(m7 zMCUMCT~q}z?*8nhKSX7+d=*&%Q^Z{8JuG7q7ZofYV<>2p=9X2$I;>=d?LO4>18+xP zkB?S@RlVL77ob%-{~9g_Lv=Y6HTmq#RCh&H9~NTaDzF_KMOU|eamywNATbURb#N`Q zCT^@sjN<;WW__1fBhg&Can)X-Y9{hvB+f6{1_qbya7-nFvojt2z(v~0MXFXrNrvCj z#z!l7b|kp=P`E5rcy6kf*PJOWA}t2Nw+K3wa6~v!^9E7?a}uC&B|A=QX-XIk-hKKWOS$N1ughkC$mA=r0)9m>~9e!hjTg0$Ep%ubG>>*_*!^ zoWoh1y_ttYj4mcvgT`5%@4}39p`6zlp5s}b=b4`C*`8~edG1-C_nDvj*`NOzpaWW< z{|B0&3)-L$8le+fp%Z7E83zj8ly8>qc@tPJKCc^8l*#7q(_>h zOWLGQ8l_WOrB|AzTiT^x8m41frqP&tXWFK%YU*xUr+1pCd)lXWA%PV3r-ynx1c!`| z8mT2|;>u~4m^vWR2@iq=FS?AefKk*Ex_PTA*Z{<$>LO{XQw-oqq4Xw(rtCw0I87Z& zpr%ZU<}o_RVG+%`t3CKRe?hDjYUph3p$2N7)Ed|d1{fifg|@n)ez-9vA*mBvu@fl( zK)|sd8?x5`vg`M;aRjn28w5VUG(O<6J0K4hW2tzBP*cO;Bt?SDCXAd91DVTo-bdx66=P>Qx!927USN_V*!cjnx}*XSX)!K1WK@3g&IwGqp7vwHj9UOP;uVn?pyxD)px13cl%m$5K+AfNlc z>%qD+T*L1u2|B>Tx!c2wo5m^z@u$pF3G*De?UxzzhaS}%GL z1im#nNkWyrZ`-M4oIUH>w=LYbAzYVW!N6<#$DzA2YJ4sj9La}p%6*sf|8P8)Ka63Q z2f-(6!@nHN-N-Z?d%VFrvc21}Ej!J_K)Z)v#m##RVth|s@S4_l%jaUpGr7m9_qSnN z$kp~eyZjd#T)=He$+O`W`Wvh+JT;`e<{VrX2t87Z@XoD@!oN(=-6G64ozt;s%rpB6 zFdNN5K+Q=V3|t)4JL1KMz(M|+()gN%n`q9~70%==+025`oUNVkqsi1rGA00Nw5++< zNx8jjyiiO+TSv>FO4&c{)^T{zuBOY#Ov;qY@9sTaeXCHtt&dXBjg<<|Cn7gChgG5U2Jik z%`hP`(d^I~4c!AJQW7BOxV+vGq1XLk%=kT>9qrg`-J={m-w6-Us-wyuSP%bw-X+-f zOq;*Y6d!nP+RdQaSuM@bg3&f@b~622I-TcxK8QZO%uSrkS=`J`UFeP83s4=-8(`Ii zpw-#Mc}+tv=?{MKAvgk#&leZh=8aw?{MbcnB%lWBH(m(N_qGR_S;EEaiBABg{-uP;l=OVm!|EEN&^lf;B*WWfy3Z`E5 zEFZ|hih+Gz_jiAUfIie&oXm^9)C++4i(kbZyBJoSRvu&nKd*_;F5v{Py_jz!83xm~ zXSHgrG*zf!mppnjs*O(UKC|m|#WZLKA^t6cpE!k`$HRW5SQ=DQc?f z9&2mB8$jG#odhSGSYa*z;!qMs6d}OG9vN4ku+ZOy|K5VHYwNK?@}!W%p=YsT+8Ur8 zNkwl%Zum#dGtn9Vk`mU;g0tXT-Xz(DygbEijZ0PVI z#E23nQmkn4BF2mwH*)Og@gvBPB1e)eY4RjWh+jZ}_#lQQhz1{6z6$^oK@*rdZwi?S zf`AyGK)IxJC`Q~KP5lsvqgO2nx>v!X8tC*CnZI#O9$~1NfSR(Q1@Jr*BahB2t_%X= z^afyq6|_y{Rp6opLfcmshFY1YN9nF6P0d;rl7Vm8#EKU)ZtPf0v!#qlIl1;P(bB$(NNrI=D_^{^5q&9n$y$Ku{TR_tXg6ELhR|C<&Em+}%smno5sHkZtwSeOHE9(Cwp z>*S@|d`1RapWj|fr|K#8IC2r?dHF0=`@1&kxXiC|c8fRDUdYkwd>S@QD{lW0V~O)FW*mnPLD+wx|_so&{o>Y@*>}+Hi5a$K_&?7#U@A(!5~- zC7g-U7cy4fk|l2}?jrGp?r7Sb zYqnA*JVUxt#B^Ph0IoSv#3oQ65tg*^EE3LKKdMmEE>bmQH4N`bvOdZlxVX#7M zC;+m_0?VO?Wq~M|h_p!7MYP9cP$+4J$^qYZjY@~=KXLp+m2^0krK3G>3aJ6R?HWoz zEf=^;+8<_qy56DJHizk0*3dDP0wh=sPCAU!kc;oY>ksrhC{L(Js5% zE=B;y0|Xo$$N+XuygxdZtq$J7ulJlvbQvvTA0E zt}p85GVd~(#5-?_^_E2{rA%`1|MF}MdkZwH0P(st*Ij%4HP~T`JvP~8pXBRzGv<;@=#z4n48+OmE)v6fG;ah zm$o;whJRZ#=bbTZ5n2z>5+RyJrF16>5>Fj!Nkt56?!e3Hw zx$j3thdS#*3o&@@P~O~}og%xwIp01fubkqHi`r%6)KI-CoySwYhvnG*&V`Q;ccb09 zY7k&H`|Z2`KK${^KR^BTuae1xX)`BO+XM7phfh>7w^r1xaCf6w;f8Vy%muH3f_jm+ zkVhMSXpRHlbH!OQH@*Or|4#!M_#g;DD7y<(U;`O2U5ZSns(V!p8wk__Vh%RF872=f z3@lj6N_UHKrA|2I>t5y}7CqS2p@ShjA`KUFJ8DV8h({D*mUw5nIQZ=vve}@gXmdjt z&J1u#R1LS5cm~ldP<+z+B4aXW9z1#Qi60zc2~S7{6+Z2PR|L|;ek3q2*sqU%{39R( zDab(*vXG`g8yDK9fC=^Qe`4qWOFE#x4+)5M+<9TOB;zn3u8doD6P#o|A+8=>5E_zE z1TQw}ibvQ>m4~Zi3m;g#LwOO6wp8A<6hk_kOc8ob2u2%R`O9cg3yZLsm;;A+%f^V& zIeLVgXQZgI^Jy`e{~UxFCN<|h1THg2VVunpd8W+f#IBo{lnX3U`AlfG5;&yotgpdlQ zmTPJk94TWIfU$t7ahoEgCVSw6LW!a@qNCAVRnNqx9oWBx?}(q4Tnp? z@E58uQ%>w@1+$ceDQ+24zO5!^m%X!WNeefhW3(=TnM0;=dx*FjwuvkNYo=(lu-w)9 zwwF~|PX{wsp3~CydbY*WUhPSxnt`xXnJyIR_)3Kp)VTx_kW z-B1Cpo{SMkVFN7S0TZ~u20rjX0?>g47j(fLsKWntati-36o4>!a6yenz`Ci00S71m z>pZvs;(~aaM)>d&e0p8f6kvM`>(T;Z+=vgy*r_xVW#+aKj94aaTK1701ZeyKLhz!) z4A?Q3|BxgM8sEW-Q25{h)FciOlbEEry>eN0Tc4-)u5eU_3N+=@VrOU&#pAuoFFqIt zhb>tF2N*Ip6SJCl!s)!-4YHfzjEL$^lf^E^lgJ8iWEr91!&R;WU`Y5z$LI)%|4KlN z7ck>U6ACA`OBovIr-TiH$VxUqq55=p?cr$R?g*W;^BBV%w`b5A zE=)TjEh|F(CE{?U+QZ>qX?EmAYA@wdzHszyu`F-!y>pdZwywL!o3+OQdPm3wOcLZ$ z|89HC=fBSVmz|}vscqY|%hz_Hx-BN{aN9%0wey(&W6UA~IY6p&&IT$QF!r;V8;?Qgy$KnrLPX1|}g0eQJR6J`%j7w0Ya zzZ9CO_U2bFsir2T7wtu$5c&2_TuK5!V8;a)`@|pPrlZ>E44ff^QBo{Iz3V4o;d zFMvat@cuKfkN(G~pZjxve_66-aYeO%RN^OJl%Yg^^TYpX9_D}g`2lm4!TSA0_SMX~ z^xwg3U;jPY|0P8MvO@hS$M((Fqa|JgW}pUcAP07!2Yw(3hM)+JAPJVB37#Ma$`C8q zTEH}d`=KBVZeZEfUJTYC{jngHZO;H=nF`vV4<-kj$=nYPArTg#5gs8DCZQ58Arm&C z6IO{Q=~eBJ$OL4-0x*C$%+?cbVWvzV7d{~lUfDlj(cJam7Z%|Go}n79{~;T;p&Py- z9LAv>&SB@6ArX0wlEEAu?jaw7p%BX56GXrc@?aG9p&=e3A||3DE+Qi~q9Z;c3QEu! zbxr~d4CO&0CT8NiA)h853IKK@D2Adajv^_RqA8vtDjuS;q#`S}qAR{4EXJZN&LS<= zqAlJcF6N>x?jkStqA&g;Fb1PA4kIxZqcI*MGA5%kE+aEGqcc7uG)AK|P9rr|qcvV5 zHfEzXZX-8#qc?sdIEJG*jw3miqdA@xb zD1h+gqd)#5KnA2h228oV*gzg6LSk7YV4Czbq(eR=L`Eclyh70Q|Kqkq07eR8&18VQ zykKK+h9YJOoI7 z;xyPKa>2<@I>{hJ9+VIs1+2wJBnkxZQ+Z43Q4xcS0dq7zNFMm%*w%mM9w8$)}>wEWkZxt#l;iL0gNP$4#@FUA-V!A z_<~n;lL_HuAGQaF$b)EPSM9(CxUHZbZdpV@rjtCxUxJch*34!y(;s@8$Z$lW+{uhl zoHn7Qw5h~U`GKM6rD5`AWjn_ zhprrQ{V3MRCypix12}180EP*%=$XwBjE-D|&fnp5|EQX-DVw&bApOvxpecz;1eTW8 zg5FY2X^P$L>G)0P9?Gb924`gYDJ#@zpav+KK8AW8=p_D&p;Bf^c1~6%rD+Oj=Y&B- zNa>jZpS}E8+#OYd0w$xQlm7HB7*%SpXrV0k(aK#i7!X2rIA#Ya<*% z=qcqH9D%?|ofaIyTOO;nhTc;?fRSdQ$JrpDmIjTgShG$+8ySKJK}Nd%g|xN`c0DCx zY~|(!CKg73DQxRi%qzb(>(Tk>A@pmme&Rae|EjJg1yMl)svwWA>f{$(thiRI5-b43 zBBfzKthZhb7B*{;RhCp5D?^m#I56p4sI0R#t0~;;iCKYELTq{v1DZ61B|PQ*_1LC@ zm&Mp>j#8{hf-A<3hpN405eaJ=5bGfrYZ)XfSuQKh`UA9z?6e|fsjf)21_Q#T#gr(k z#ZK9_25q^%+A z4NPGSoG*~eYBZh1c~Z*3!?ki721Xl!0w2po?#Y>)AZVBpd>-iyq0GoD-kMkTV4lKl zuH-pRc}NhBapqKhLgoS}W=dSc0_}rN|D_%!Zt6i)Um~vJa_($aZrX)z%kh}wLd8PB z?0u5lj(E%JVjjCauFu9!L(G|ZDy-2$Q|WHgR2Hs$6cOrynFIY9dY~J6^=09F?#HDj z@>;7HmADma99kB5Es`$FnFnf3tP-K5YGwK zLOiHXsF0kMap93@@{{jYwBn_*B8OO)ssPLM|up+?Q0Yt$PAkGK7@bfC^ zsn7!BP_HEDLXo|jm|~oDZ12HAVbPitc_#81gK;Rp2b+~KqJ)9z#F7Sc@DzA3AUoD*QUEKp5hwZqvFc!eDH-K^pPcj=5#|@8RJNU^a^l&Mg^5q#ZkQgij|1vNK zvoH_DfX*K6A{zRhMyn zUE~GfaY&gGaCaFG_PPO0+Ta+bs58X|HdRb;tl8PgPV91(PlC8-igEbazflvdA$Z3$cBv^nnTCgAu|N` z0!%T3oIfXXLKhB~oHLMKa%@HO)a-L;S#zUcGX&k$M8jR!BA$xP9%e4uL@Bfz^empJ zt2=$uQn;Bs6X!5bHC0!&tgf^X@ZVn&3L7zm!jNr~e8Ob1(kw~fGnE&$bQ@654popf z>nJ7oAo^y zGizOvz2uE-JL_jN|BPlw6u_aLSeDgW=XR(>XgUM7X*qIoTrx&lfK@*?bVoOG{t!Q2 zVYjw6XBwm;c=hzw0T&f2KX+{5F-bSHpGRcrIta*1ZfMQ9gt=>P<=0W^BW$y!cN&$$qqt% z=cdEpad^XDX!EydVAG35267Q;QY^Sihpd}%$-qfBlt;OgOJCsf#@GEN@njBuD1_tY*Xdpo z0~L7SWv)h@|Mr)N24GmvZLhArVDP5Y1Rc#a-Jwa9|L}dsAn2^d&{{a_xsFmm^Iwya zT}81rp@J8YZ;caTaudvtWVu^_--LGg%!J;9|F|3MTRV65G3PiSepB;^c)X#v6uw`b z+pqY>RW?C-YNvMq3-qRAU6}b>c~||>JTc9 zJb${M`+A^P(0UNM@ff;|i%hozWp7FbD${zrCD*uLl09(9zc*@Vd@g@av|~4{Q+t@6HRX~C8GyyM+q)Y91uTcWZm`7^B%j+-#pF}R-H3BVdqQz$|aZkMHV(nyh=OaG&XIyC|ZL?$)As>R+DUx zv0azXW9MzE)^{wS_z7b&i|#pe>>Cl}T8c?7U0Z5O@AGrV-P6UHq)$=kh( zJ$-6gCg=TpUFxK`Bx&*v0(2L_nB&^z}$uIJvnzMzcwvaDC@zw(PUL5=xcr^ts=sHB|*Rx8XFZAivK;cv7wvL8{tW!By*< zyb$BKBH)PdL+a}|xT$l#-dm>xc9j}?PTz+UzVLjLZ&^_VOzQiv#&7>O1A7=8Lr?($ z1OUhcj7MZ;SU_5a0;3S1NDd*$<`WyRA_?8V7ohQCmPW~Nv&~McfU7YvB(t%Lp~P-> zADu)jFuOrJJOGKGM8!qMM#o3UNXbdcO3O>kOwCQsPR~!!P|;D+Qqxn^RMl11R@Yb9 zSlQWE2Ej1JA}m|DEkg__G)^VJ0N%cU2fARng(G4nKdk_%H6wwD+qQ(ih zEK_l4NQcMm}u4Z-eRlKZD7D#?iuBi;BQ~C0Sr~3)!FlB z(4j?-CSBU}Y1FAzuV&ra^&(yxB+Q2D?r<1)7dB*2lvKlk1>~k=f+o%I|4up?5(LK} zx1G{I!A?F%zyMxk#0wU51+Lxg&xB&?KrU80!iMD>gj|3K2e<=w$Rt|ne$Vn>_rRHX z%u~R6y?!ziaKHh(66+xZ6XNd>|GIKcs{FdDC@2Ou;KM82l2b0F^U_<-sgVfu=cEhX z`=|{JB*-9xU?%&GIilusuR8ng%Ii2IWVE0@WWZ}^0C#pQ0KS|+(oUHfy-S9u=t^P= zLlM2uZab}}oF_p&6sjsW6LA~|tQBtqXfmUs?1&E9YKy8p-8Q`OMd6Urk;nTG5QM_8 zjOeOE<{m80IO))=?mC&4(~dhU-zush@#xvdJoIQ3YPvy#Jd-|2|LbgTNBz#~??3Dm z6_G#AUNiMnR8v)TRaRSd^;KA7l{J=Q;wzF3;Re&}!uTu*fHpF^t2Fs`!| zyJc-XKvakr)zvt-l5JL~C9j3O|DQ>pfKW`NC9}1x~ zSKBk%)zaH#w_@W-t-g9FV2iYU7T11;iQ70Xl8_5zWE!7#-sKc ze&h4^XM`25_)D9^wRPM8OPX(kS+mx9Yp%QY`fISm7JKYb{}#-Rf(kayF{^16U>htW zfK_UamIQ$KH=c>y?`^{v3i@fkAfxLyf9DUXcTw$%bLH@M(BlP&gAaF#P? zSqcf%Cd7=eKzBGxk}uEk!t++P7A(E(kUTf269+Lq&9g=FRyzoQfbzu*W+MY-u|ra) zgEa;Iab^OKR$#_kx*h0jsQ}b!*lQ=2VbK+$H-K!iBxi99Ue0}Y+y_$A8kWtb18vV= zZ=3HFT@N1e<=c2LjJqoz-mle{QC=aTjSO=c@>f|7S2{R=D*=2f(f=IRtH@2x9hEB` z1rB(bQL&8yWaD55J@`QohERkfBw+~`5fA}P$ra65|G)*E)T!FN5Qe@04nR^kLlEIG zhC57O)L5nf9ipR#gaG2W#FCC6@=!oU9MBD=N5n)eF^V~Sq7wZ9FY#GXEaad96Seq7 z0y&XmQ#@i41>!|8`U8noloIjONJbeNpmq=wfC=q*M?B_Hk9*`}AN}}8u%%Iu1j-e` z26;$CCQ^}$%nTo@#mEt@36hhfWF;+WNj3cjkelRWCq4N|P=->Jqa@oUD~Uuono^ak zWMwPWSiV(q(Ur5LWi4%)JMWNEm%HR;FMat-UAbf5y<3bH@&$9Vh})^<0NM}|IK+$bf#0C>tts;-T6*<##5g2q-Q3uS0S9r{p+MpU8`rD#PhdQpsKRHGZ^ zXh%KzQILjIq$4G1NlkiEl%`arD`ja*UHVefd{d?~rRfisQ&XJgRHr-TX-{LA4h4A5 zr$Z%bQH^?3q$X9VOJ!#v@k;}q2$%#e@JN9awyt|62m~g;{}Bm%)`%ILfG!g7*}dkKbb|nFU=M39)e=at z=c)h&mTA7vrZTh>7_DqSYg*I}f~{^vS8MA!*bMwu4#C}AZqXoGbo6yyX9_H5&ox^j zN;ig@rK@$5TiWG*)@ii!YI*H=0uiKFz3M%I5lpb&^oD>0hk>sMPEdlgvY`a)J;4aD zP~ZFJH;uHzk6&?x9wi=NH**2bpwwFu_u75Q2~z_uKt1BPu# z!%RU`hBnsLd~Oe_cLeKZ_qyLK0urp-1n5mKGvX`n{ic@$NFc$z3Gm+Z_U7IrFhRcI z4Mr+&1dNX{_mPHhhi- zF_)>Aoko?xz7dUnflCTsaU_G?go(-FEd-uTx_d&=V2_w+=oa>AP zdIy92@Mc8d0e}7@r2mVDzrN+8a#{xky0#Nwn_WN4Tc>z{tVje6*pYnrzaaU)y}~~; zKpV*zyUA#)T@Wn`$c6&E4F>Qm4XiZH5Ur1+0I6fEG1w8$;=sgG9aAek+q(nuX^uea zh!&I$7rKS-qM6HUgVka{7o4l^BC*g*Bxv|Ric^5vf(N}a9_UgS=hBE41TT^BzzCGO z0l>H(^a2F50tKY83}lH5{GBFzzKDxJ2gry6fI|8Ziv{4n^^vgs>%ad4KqlOi33$OM zn8Pqk4*dD7{{&<%7~~7$62StTxz1X`1Dr!I=(-Wih&EiG|C7RFT0Kq3K+j?b-Ep8P zyoV|TrwH6N6{H3T2(%JpgQ~g1L^L4f!<7x>Ju`bcE8s*2bRAIB!B_m1OVB+SB*Ywv z!Ol4fA%wcT5)?MD01fo4V4TA=w7}I$zG_>(o?FE&ki=BH#Xo?6N^FkD@T}d~#6c)N z?L&uQJfh#Lm#C->I;zY;LNK108Hd$$p2zk__gf{ed~v?4334RBdF3t1Km%Cdne3HZ4akf}dtiyAu?i-spzOt4NTvLg;}OnWVWy=)`QH8JYC9-tnO~KsnB% zgDA5X-)R||DH@Z6J)DU$rokPZnMonL78e_@$GL;x8G|}ONmvSqo=i!pDH)lu$lI_2 z_+gKz^vSRUk9i>owsE7K980CC6Qcx5Zlb6Bf~ng=!zNqvHEpVM#*R2wnSwu9I1|__*)(My=4K*i#I> z3yLtTp^z{N2?jh}xLrNHeuxR<%*O~=PH24`WPz;dZipH~_bk)=35d>!SmiyS3FH5x8ksiA7NdCBrgJIA? zShNY+gL{0C1=)}C!AV=(&_}?$8&O!>XawS!jMQYu4V#94?FhFb5(krl|16Tt;_(!Z z6jF}W6{fh@C;PniycK=zgOxSeqe%&CI0=6}K3Th*XMqHCj5rr!is=H&Ffb&So!Mq} zx&!(Jg3TR1cnm{$By_b|SS?d;`h^6bQ$Q$JDJWSaBOSI0*}oJZ;w;;VeT>Nn(&<{; za4}S&v)5&%y2w~q$?Sqim6t5SNt`W=lU)(90@-x&R6%f8R^r#Y;M$wZxO;_~6J^_j z>CAIUnv(p}V7!QhTadhUFldO`-Fru*84RRF0F13!dd=17b6kWaf@ob`Rhic59J~{t zxAHST`;y)2th>YT*7vJj{xYz0u`&b*Pjf{wO)1w)aoaJOy}*TB|1@ob%0bq@TwL4H zxsy~KwsDK^@zBiD7P>H9c-6z&)28_i$lg^V+uo&rN*S2En^I2>6b2C#zOcmO{@z`xa4G>lc2 zk=z}IzVBt<@IAffkjdLZ61@UdWIJGN3F4G^KBk04Mr2(%ZVkS>-~Rv@JouVB>x8fN zGRW)9I}tb_IP2qaExpNjmRT#DiVQS%4Tu9}0MBt*MLx}Bn~Vb@2ZBLP>NPuJpdcwQ z))*0EJJ^VzT7ct;HZO+BlLg`Cwa2}Dgr^~wRbJ#V#*bD#2+mxV>my0A#9vRozuht} zX1TfS4Hx5*kmuXRto!6z4jK;Lwyg7CV;1I=p^#%X!sqzq-lN_zK(Ik*WJ#oE4Zh-M zuG~6pt&|bjHyGdTQ`M9`XTU0)M!qFAsk}pVgDKX6PPSzN;%C6@GPKBzYer=hB7i|V zyH(D#A6DhyWV>2i$?rYrq0r{K2`;aA;Uc2fA-xe|9t$s#r zVB@ncim;~SByJDbfn`UsLt0dXxlRbO4qyx+X}hM%UJW3Wbt7bH%Fk?Oc)$vf2|Hz0 z>l=Z~0(M|%HVg4!1ffwMUB=>`X}y&clhk`kqP>~rU0$K7>~hmceYV_=tlAW&B?U9j z0-~{bpkf#1uma|f)aq00AR5Z8TJBY)!ue~)b(FqN&i{v&O8cwpY(ea%5Y7O}XobKm z;4a)#Ej`>ul3*C?5EE=cB3a1OX}R77x{f5ft^c(9WlZzx4~`LUxO{ylQz)v3a&32xZ}v0PCui7Lo1)v&L!IUT7v( z?UrF@^DdKOj%&zB?&ki7d4c5$o^bYd;Ft95_T)Mkk8!Rmg5Z#G8z-?_)|i9Qjf=Yl zP1aZ?xuQCYc6i_7o4#>W0QrfKK+8rr;9CTt{$jN9gcuZtqK1rN%)P33hhm zm;xeMX*$o0bDxH0M}o#4ughL(Q%?#_lV(KcA6(8r2;UW}1v!Nl@zXYEO)L1-PIawp z8*L+YV=`Xb_UPPBvU;bRGld5{xAsjhjQ`U$rQ-hX5EJ%Nu>@I82UyDV9RKXNlo`y> zaofA@Rg!c{r+5Ph`M?%nNK*M$Hu!$#_-acfIM#y*6f02|H@B+yo7eU-h4g}9b*K*w zR|jN07V7@?;{y^%FK|Cyk9F_lA>hTxkOp5vg7|@;HkdCkM=0SQCT7*C$c^r3$7Eu_ z4dLwt@h2mJ}`Xp0P_H( zK?c?fS4Q2rPkXVLkJ>JbxPNO7i#6)D>D653wqD+_^=E%Dds|ZWGp~8>wrQ-sF{2S$ z`!kvtMu=7R^eEX;z*^~m0Xe15Y5&(xiu$euNIj8vFLz{__UCwcmfv`v_sYw9EFPkH zIq&{TZ+pl+dM9bE&@ZkvNj$wD#}QUu)ntlg6aQ;ZMt3IrmL?GHi+cR0g{c?3I0J%! zPQvfIM2aZ3bcA9!j40mIQmV=!_ zgoXif0CYkRl4A=@tg?5d!ao3cvvIDt3u?oW01#iR&#Bba)|;K5p%AFG5x+y3YSXH_ zyw{w!Oxi-rW{}`RpS{;i>Hip^4V4+~=5Ym-x`i{4E8Dwk3c8E}@Tg8aWDM=CX+=)V zylDRR02Bqz7OiUwC-xE8jvz%m^-`)_sgPu~bZ1}&&;^R)!I|K`y()N9L!wF!zW7wv zrP9ZeDhU;0No`T1h+d>YE85Lgf?-&*mO_v-9!(ATYSF_ zP-B59LXtA`9&{>1TEmtVRl2)r7tByT4dz0nS~lR)Ly5kIB``MKfxc=gyJRvrpR={c zAUAfLkg2;0T2rfD&APSg*RW&Do=v;9?c2C>>)y?~x9{J;gA0cp#f0(W#v26KGNQ|t z5=pppDI#ULk`W`Q82=H5;K_6&hzqB(b;hxvkP-?o7>bhOvkV6ggr(-kf&2rC+e&2k zfIgZ_xv;*=az84g|dJ@CzCWPy2>hf*f6!GK<{ z8DBnn<~LegT}IH~fATo80h(%hbH{^E9%T)OYpuDc0tdMHqn`2=sVPg+Y@m`}Hqx|> zBU?t6nStXVx&I)3bbXPZ1SbO7=9@|JwJCuCrm-1Zh7M^{t^>*zBLxI9VxEf_w0C5o zZ7Inlq?}DSRD2W)@fM(|Z22h#X4b>LRiJ znqHGIBETZD$|mwj1fkGmY#3TD;G=~&;t2@78O%p#A;U#1@x&BYZ1KeyXRPtY97i0* z#~)9^oEK3b;hh#r2onOxMl^Rt7AQ;CE*R|Y=kGY<;L?SUYMfh5B{+BJo|vizt+OIQ z`@=KNmz0<^Im=$CUjeBJor*M1t2?y0%o+_?&@g(HS&e##=(VI^hq3fuGcy%+lzcuN zn1TR%LI1#$I9qAW+j9Qmbn_tj0K!FN4EDjJTq0L~p2W|+?gbgS~zMMD#vgrYYB2)m-dWQy}0dIqZ z!%{vHu*ESUB6gy&-Ms#0x+{utYZw@q-B_r(y}dzsH(VcGOt%0OI)Dv2WY!VIpnw@J zDhzj0qV7Nxi!+Xgj>3~18&hW}F6zM@b;E=oMc9Bust=4CJVgY?Vn=**@05GkVjP76 zI}vpOh@|Qr0h0JhQEZZTLG;}-oQSP1))9vx9D?y2sj4aF&4huJ+8E0yj@T*hY{Z0& zyi%gbnbG8Fc%X@LbO=Q6?Q(fy@Z@5wAr8lFN|hM6fP@H1%T8eN3j*LJshCH*KmP#H zQ}a`$9Ca7WFwC-=>DF`LW zghUjS0Sg@{!@*HP?kSWdh3AAu%F^+qlqr;vPex}((M*BVrvBX1Orzo-PHrlq2^b_f zaSFzmTC@&CWl1`wd83}T^r>RNn+tDM)1&fqr&lEslNR7ps9NKt}*x~k64twoZjDdEc3zWVjAfDNo*2TRz(8uqX(?dAJG${4F6 z_OXzStYjxkS;1PRvMnW}S~1Jn&U&^;u#{_I75mxJO4e*VGOcP?%i7ku_W!l8jcrRw z>kP-XD-9EX558o}+ur*2x3J9sB=ZGamDsho$W3lbsVG^}D)+hK!6P_qy2i zENw-~EnTrMyWkD4c&D4c1&#N-=uK}I0x` z0z$p7fCo%qP08WEwk@!N7tG+3H2A>~j`qNqF!0!4Y!vytLh9lKtkm{j<2)NqS3D!dfN}Wnnw+jNco{0=8 z-QZd0w$^Igl&?)K!(i9p(op19t6!bT_2yavyUxSKC{wTcej3z<^`Bnd>}R_e`rF_R zx46em?%06f+~`hsLeh5exDJ}`z4#JdBJZ4x*YA|%1OlCOxv8B^u!Cr7Lk zu9dp8g+KAfL@UO2eo3_@X-2%2JRCFQG_XjfMd6FvWU55+c>l!lH}S%JS2S$kxELyC zsd4mEzL^u#KG7;9i~f(I`{;Jt%FXkh`~2rXC!oC5J%DuMn+fk8!qCzEfnhBD=!J#l z$=hH~xc)oS(A%tf3qFpSKa~(52K&OuF>){#pyWKA^?vgp@<>v3<6N6?+cTcmwz~ax zxh#@@)c&K(Qhg_3m>2>+F}eAcH*efN-D#K*K>q1`WHBl`XSQbO;QtPIFigxx7TCKVI6&Y0@g9=z zW$EID3BZNW{_%yey!_`+|N4_V4(Fyf(uuD0bHm&JUmy(V#s{Vcb%F&%k&+9J27BU_ z4q!0`3Wr{bVL|~na8Sj795#GoSA2BWHpusW%J+NOVs{-FUED{0lBF9XWqsVjf^hXV zC=ApyzLKhd;$e7sY0517KB~TP0bpUOMpic9l0CuQ{zc))e@@uuwg?I3Uo8Shnc5n(ILpXPc ziHBSoC`la1Hgf0(Jdy!Eky@M)h+db6YS<~^fNO~1YmNqkst|~fNP-~8inz8C(6@zS z-~g?dY+*=?WXOgKV2J!diK5Vn4DpF*K#jL}hIU8+c-V63w1>wC0neC?JL5(6$Sl8j zYt~4Ia(HmFF?fW?cN7qT(zuN?_=d%n27Kwj`PTmyhe(87#8?(k%u&k zuAqiT^N|fT4Ei`iBiWB>m2t^%i;w7trT<8Xj5dudA_0ITLzTdY#dc|IGS;?Lx?$>F1RVZsYj1dkayW7yq22jQxCHd8vfLpCGwV* zGnNV1M?<7DY$+1vF`J(m7SKr`jQ^oEgg2XwNq6x?m$#WTKC_t}cn7L<0Y>Q#V3?HN z_LTBDpY&Ouwz&uS_khvnEX($?Mq76zbPV+;5nWbhT}wwKSY$)`70X0p>!~mjPwQ#x}Z_=E;8mpe(L9g>~IDVje-c<0ikABPF4f|>`BbM?d@6>t&jW1-eL zqbn*sKI#Bj3Vyx!Nrj`Qf&Xz$N7^8ff~E?RsD~PmEeNUiC?bX+oHEy^9ffyoL8oK;oMUANr!I`lyXDC#foiYoUYg5jld&rjkO4 zKRP#NlZkYM62iri7x18wBc>7xm$DO!4Z@zn@}}@vB=&i&*qW{N7nS-=h5+8Vh4*j?S%E&vS#44B5kP@HvlJfdDjMyI7xmLg zIQU%5r4p>Lr7dYJ0RQ_dC}IwSK?{t!AH}(aWhZS_Dz%&vr=JQNF#?*JO0-PXwA4zq=OCnx zflp|Qv>m&)i=|A=QnlPkYHpXXPm!-fi5U5VJ|UqsyayOT2@WAKA9+bBwXwAkSgk3c zt&khJl6!yn>4f_yh5Tu`R=ITlIe-RwZU`ECt67(h0S3AfDVS6ui`os=NgiuduR4+> z0zt6X@CiXk8c*w|QwyUw>Czbgn! zPzr`axl`;~!_x;znVm5{#;dACn7757`Z{i`-_q_!lN zIMhiJz)LVU)2~Mvy|t>p&Z<;mqE3!WB$K+T-NyiNSjkzk$3)0M z`>{``To~Gu!s6k=&iu^KyfH8wh02k+^hU#CK(51Ju7^bcd}lo)8zmCez;oM@?eP$J zx?UYR!kfyxXh*-!J2%Z+#SW&IIJukVNzV`wY+QHGu9+|K(9gUKt$7&|iPJfwDL-XX zb?GdFAEdwFHLH6Z2B=Wc+$+z)Fbp0^$n5Me(m0m-Ls$w81`Yjp-c*>+ zH~)Kh+DpE0vpF&SSf8x5=nN&&$a?E5&gh$){3{xVX_!M)&T|6O@;JaVEz}{IM&=m1 z(~}_2139{z3dQ`ZfMIO&YjJc@0gcPd)ey~MJ=SCmm6a=%;3@=EiOpf4!$ZK$`IgLo zN7AuS34qiIr-0Hqy?jb+)N|_2Ae`0ljM5mVMrPcO>|+$Vwb%`lqW~?>N-+^VRL_WA zaZ+PKJF>Toz1U|gB%(OPsSwVB{L|%pUW!53*I?1peD%E^JQ{ZG*Pxl)_5b4+ zw(To7`-;YG$V=Ts-whdmfi-5k-E81P{XvX#fE5^E)w}W#3!&9=ye`LBwFu^pg;h|l15Y8BkR$K6eyiM`P zt9{WQjtU}TQ6LV~S4;^o9`ns2VFs$1gmT&h0ZpY{R7vXKuiH^t;l$$m z&NEKYW}ujUO63TwI5ot_u#QM~*WwWz>r1>JinG;xzUMb?4ALtQo?hDLMd~S`+Bs@F zt}xI$5u_MA%WHnjK>U1Nta!fu>BfBGwQjm@H|yc_<=rXM$S%U*NDV|uLU{aB%x$Tl zS?;@jQP-Y5*&gcK-rZghec2u-ryf-n%Z>1!?{Qb`eh2OuoPg2|ikH+o%?`e=&c1<- z=z+)R6kqXU?dVx}>Fh?$Vt~VuE_#K9A7v=lCEX9T3=Y?dwJ%ISC0D;l&g&sHzkNB{GJ0k$(E^$JlQgV7A&5cEecv1o7I`5;1^ zO7>WD_dCU@QC#Q{j~dP0AuV6nrlI!j;tCc>#+`BXFWvV);S!p0=d}R&fT#DZYx!_e z>|~)gK3@kLAxbv0!3;4O64lzQ)FFQN@Fp1X5+8sTAN#Vu!kj1RoHq$q355U-2DYyN zlD>L@g@82|tGqraU{WyeN;hOOPF+_n-B(f5vQlh5Cp)Pj@&A(Or7)7U&0c78FAAgc z`@AMW5}ixIKIF#dKT4E#(gtn$3Y z4Mrad8jmu{W^FA?MZLo1hVv{R;Berjg^QO0!j2pqi2rPrHU-We)k1XuAOLB@6b>;4 zfT1#G55F;_2B1Q@ZVf*|>^4gS7y;KVHMHdm7!fZ?3Vb7WD1s$x6Uf~3$&gPqK;WRn z+6Sd*ouyBqMwL31YE`RI*JahZm1|e8U%`eIJC{L#I zL6Tbzl>EfzX}K)G>?68>i+-)YPS!UFHU!j&?7IlfEo94-Lj2~ zZ#smC0WF)#Bmg6e_0$_}A5WCpE;-c1YA3T`%y?xAd`7YFzRCphtvM(>Tj)T^5+so` zEU@%gw!kDDbZ`3@MvYM9KOiaFlseTTDAVoQvv|4Loep$tR(V@+rEg ztkTLWvCLA-ExGK{%P*-ctT4R?m9CFh!Zl}VkB_Fm~JaC zLOcL`;G`ZKQ=q&EEQsfUa0GyGl0{V#)fTD{+qG8Tx{fmtbbks*HD!xv9| zU)(lie?{$9x>?~Z72F9WC{Y$irzmb>bZvH4QkMCXN`Y&09#-g~i7wg=Fp*AL>7|)& z+UcjEjyf)Mq~3}EUxM9doGaM-;-RdOe2;4nqtQ8FP`(CRma&)mIst8sYsP@K$$@*1 z1ME(uZlA5-Iqn7KR%7dT#UaP&!~dZ=#WMTSM&s)=9_O2F#0B4*9>bq6RPvzGLtFZ8Y=tpFzv`lW_&Hx8D2j!CziOaKkU({PGn89D41~Z{Pj*xvv%e z`RT9U{`>LIU;q92zn+-vZ`B{l9dmUm_#Km5&wgrV&W5_7)2>gk&0Ec;uYH<00JBji(T~M7r_`tF^-Xp zWi;a%(U?Xxu91yxbmJT07)LqIk&bn=;~nvsM?LP5kA3vx9|0LiK@O6Tg*4OL~j~HeIaRFM%0MVGfg+#WdzIk(o?oE|Zzfbmr3HHWc{9=SC2i zK$0YIP0y5v z0mwwa6086^96m&v&Htn4w$Pa$l7R7<4Rz>4AsSJMPL!e*wdh4Lno+v!Ayx?6LnWj_ z5%MvvR)va)OhV+O@_=GsbK2cW50O%Q})U)-A;bKk<{wcTSkDl=)Pu zPYS9y{!zg-^mJA~y$Vf5bR(Qb6#z1&3SDW`*E76zI|PVp9*UW<9o-OBDKu+T(8?&j z`t?8z73*a&n_10nmb0Dp>}NsSm61^39Taf{*dqIs)H+P9fJG^k2n!0i3U0FVjD=10 zszle?wJN)9YyTM-P=WN=hp5BsDHRIQh1}NiQOP|m8CLtC`bbu%zkRG1Lz`XgZkM~= z_3n4U8(y%)!=p|8&RU`?z}D8*thLwkLVyn6rXwz} zv8ULSNiNwh6RZg;5j*i_7zif>)TS^DP(YpTwEzS}W&mq8RjvX!u@+RkvcUSc0`NRr z8|sT&GpLg%#sWhTbrED|mK+9R&(|bzhmF(ZIFos1wl)~9 zb8TjmR(HP8h42+MoNQ$;o7v5F_Omm)kzQhqGg=r6eHI&vauH-H18cEy_B)}YCIVfH zb5Uh_mYZpZtqh87PjvnqzlDY)$_<;@h=jB=0&P11>L~Z0+&vxb{AOZhWw(EN+1Qh= zwXW9v>wal<>}pR}LjpHLqs_9Q2T&;=)JcQFZ%Xh;Dd*fuZH;wq1#)6U=rtpEY%ykw zZU5VN%iIBwxqP%uA!)=renF%nw1FOUp%0ztMK`*ZTKes&#_Sp~b9w+OY!#0u!2XKohH|er_S;^H^)ZUx|vYq-q2tdQ6{M)uUr!k7(3&G)bf+3*ztpa_erHeYo9?}BY(d})+fOn z3j9<1pjvX zLCOO1+d!XfqQNs;SMXY8n1yCti!^=`e#+Ku0N6*`K?tD7{aAGFt0ukbdG}vq-+BR;@c!}1O+MtVMPhk;aSjc`_AAVTx7WJ zPX{AJ1HB;yxrm9#?+d{&48?E^$xx!~OW%x*6u@9COe81<#il&!<3`V=SPC1mgHXsS zR5}j(BIExgPly1>c+MjZ*T7HWZl=^q5L#p)iUS8_q-6T+;@(gx7Op8g5dRIB@Di=( z1XHII=WXsH#R_LIpFqJ7yJI5`Q4tH|w<>W|>aO5!grV!;KiD<1-Iw&d|1rvepk(c|=l2(p48rGpaQCF}yy+y>GW zdjTPF@go-5G03#g7aS;y$5{hEluEh`4E`WmLLYOBVcWDG;L1thM63s6KU8O6t zOPj6H4_pL2lF*ylM0n59&KbW^^z*fvQWa#rEqIFV^baf zkfTUWIstA$T+*QK(kb%NY#OsIO~`pz&v6)Y5W{o$-mE(L5C1xS!a8ro5UP_c8*|#= z^W{+U*n%+$?I8mO#-q~fIoVV5BB(sE%QOx2KoK-S71W~6;2Qjv`o$POqu2kPSmW>qDAqsDpu4&GgJ*bCLY{OFjMA6>H#xuWIR(e z5KHhuw$Z;RG)y<6F*bro$kITtwAhRjGST1^stU!-bN>n-)jPWB0_qa7wi6FhgvLN| zBmeX%#*P~al`3EYNg=T;Jq1c#Q&h1u@@7j?`Lt5+^C`<0f&&Zx=P1ikHv`KGrS+Q(l{V+pHeZB3K86yh@)cB(Wv(RvWibt@ z6-Cm zT#2O*>_fnU1sB{^N223igR>7^A|ojFRjcwq__bp9zykUe1Dv&5f6!XAXCtbW|LRq` zKvWr%^<`l;W@Xki$!il-B7g*}3a()NdV~tBApaxu69Sr{B1muzSPUGq6%S>i6<+Z8 z;6YqIm!CaY*> zZTEI@H+RKQ<+R{fdTL?HVy$jT+-eRKEKyGB^ftTU=Ke%Lpw{L@&czfn-|W*3)U`X9 zcQRIG;mj6c5d;=NL~{R7EdlmCGLw9>^Z#Gd*D5CN5&#!eSH$(Ew-mV+d$&zxwpTef z*GEitE%(>ppf@w#*5G(I0({pxH1cVmgUI+!UmCSU`zr0P%*2S!^(qTCMgU}6hZwjdEP1z<$DJ%WqT898W)&OUQ|!fMQUk`gKx=*ZJ30o3W`DV zf(`kQ5jl}Ri+6?x)6{|~X$LB(iT`n6Cv?#Dc3LNrrKfS|q><-}bR0*M=fic{4R2;g z2{yG19HnSk=MEzWemL2Zp+a*`8I{(6mZ#8^Lm8C=a|y~uc&e3Aen*i1QHFm`k&!u> zm3f(g(pCsrm#oM3qGvCmxq9@I7^jGtwRxMlxtqstaH`pTMk1J#hnmBAdJ4go3)!35 zxt-nlo#7dGZKX(+$DBtfp7A-K^?9H9xu5-6tHP0m{&}DYx}XjEpbe=C3>PMx}q)mqA@z7HF~2tx}!b%qd_{PMS7%3x};6|q)|GhReGgax}{zErC~az zWqPJ*x~6UVrg8ciPpJ!Yy8owr`lo?9sD0W`q_z!&`lylmr4c}jn7XN(I$`kXe4Ki! zwFs)|xe!wL!H{Vou;jLcv`F7`mIGef8+B*ign{vZl^lEfGfS*W8J|2P@D#G}O9y(f$vuJyg`>C0fc! zC5~uK0Q?yR9MA|{#g*Z}xh>dG?1t^7!EtPjTdmjFX~OfM#4H@BFg#K>yv=xqK#Ks_ zh;YN(Si>j4N;eG>>TR|6n+;BU%BdWYQ(QW-lQVPf-6Cd4)6&wcd!*uWxD2X%8LvFz&Rfgv{Kd%)M814Jab@PNtb!DHzGwK3@xYtbyyVXgcd^7}6x>!K_yV8U5y~}{r!4gpBFa_<()349&9*@Bq(9hpP>Xz^6 zdi>X6Z~I_gVo-Bt00jrG&KRwp;L8F9S&U+{Z87Ta+=`J!K%}-Q!&y@-K0hUEO|_ zJkz^1BVz&i{S*AXF^etWdt@>Q-n#=8P?~Bm3_j&mel!uDu7T4NeN+&4QM)5#4<{at z-89fIe*dpA5=lwRi?=kef_N#9X63!FH|LR_=Z*Q$ z`ypV0em6(1};3Q)_Z0;Xa2ykLsrrDeWHLX;SZ16^xw~AmP!v0)Hx!gXm3s z@IgQHzpwBI)<+9g572i&qP6E5&?_L{4DKEc_Bz-D@sArMd7zaU=9~82P>lmCesljK&F1N={N%T3%viYHo6NdVYdJDm6XLO;v3HR3M45mL@nsxv2p#fT0F-QHDbuD- z9gP&$W~UOAU(TsR5VK87bV*i=a zzJC7#4lH;u;lhR^CQ&=pq*tp*!q81@fC&~Nv>^1ed%+GtyIK@$p_;~thM`{;MJWByBMKn>;reC5S z3m3ua-C?g|j}3kH$lrQ%qff7XJ^S|V-@}g|%DdE23-0@?bw9gf;KpMep#Q)D56B~j zaA5^V%W}?!Ttg_28+yAVy&kph*W&qi` zTo(_x@|!$YG4X3y4xsTBWL`uuDS{EMBY`}m&8kJLjAr*zL0rHSTw8ZK@UD<$5(}-r z|2`$HyVat0ZMMR3yNy(O$I%>QD2rzGhkSRQcxWQ>F?K zn-*mCCIzs|FT)(O%rnz0QOY+bP+_=I2*4vSQr;YNK0^w<4A4T;REnw6|b66bKA?JCunoN^jw%KQ+ownL*v)#7aZ+k-wf)2r5x7~N+owwe5 z^WC@Ke_y1v)GY&ExZ#H*p19(RGv2u4k3$~0#xHeyX>>mUc2qLa&fs1`z-dfGFe11g0g80-EW45GY`AB!Iw$faiX%@tXcBI6(?JEf5(9AOKBe zK{wn_g7~Z81}`wc*@*Ci|}z(N_8i-Qcq;nZkovY;uzhde~# z4UtyD0D90A@#7y89p?&K4e??IL=(Q0A;l=lsEKGp8vm-MX2k$($byGjP#Al&prYUj zi&Od3{a=qNNlrOF}Cv11%@)W_L$QH|8O;vY|iF&q}aSWi>rQN*Ob zF9qv;Z{z|Lr}GXiV)AfLETk6?82|=QDON_I;uJY4g-n{wh-4r}0y*}@GCuN^ZUNy| z(6}g55{qQmYU3Z4K?W)f5iDZaV;u2=Tz1J!H&iGCtc>FzVdTs{`Z5E+ zSpfn`bqO3Pmqv{pPd z1ufjiNtQmO5n~(*D7`7v8agegbC~Kuo4QnY@Uev+MS@qK2~`W46o?ni$6Co#))t=C zmB-waPwNV;m`*^Nx}YabERY|Dk&`In(trin0EmL1fojx1ta6enu&?sauDN*t1GON{ z2@FL66`;VnE>KvmjEAdWoMmhl2!UcE)Tp41jAK!hmI-v00)hP`1lE;TDKLP650VGN zz(XJu5w?{d{YL?dYg_}GHVjAF;JFCVQ2&`GptgJE*>8mqT(Dk+9jx-1cGKXC4#u#r znBDESOjFU06%e&#O%nn9`mN}mR=k?M2L*bSLkxiTsBEDLeOJjU=S<)M3vjOnoVpI_ za%r}+(Q3LlOPbF*46~aBP`Ua$R?(KFzZ+PfGXgwd-WoW%`H`&~9Gcs|2ACWG7BGRG z+FpMUwyNPoD1j{?z|#JBbgPfV55vN={*aJKieb1uIdt1JhJ%e_<{zg#UMsaI|J15pV~YPBMvL8CAw8&Cqw2i&0^Y>JP@u zQWWisHz+cSKz1nrPh&vO%?uZ=&@dO zxHc+q#$mn<(-l?AL^yz@ETHz>Ph70bl5KS|K0>aANW)0a5wBJI0$wCx@mtY)R?xSk z3lB6Ge8O*zcN75b^NP*m%Kz5h(50VCt4Vt{rwK!|5Olt5V~Qn6>bSU)_&u(x(VSs6 zf4CfMZNigp6Ec7mCCn3yqJb;g0S>tOpsQ@{e*Xf@4g?g^)lROI30ub;w~L>?CGb{3 z0Pg!;l-pw=_(fTr?$)-uBB^b7mxprkayy~e=YIFQR9@HMe*E8q4Df=q9N;JXH{@ly zuANbxS`8t6=dS>7bc>wd73)%1d|sf6<9$=~*SeUhvs#H7W`J-AQnHNg7KMSzUh_7NTxxkjMO+CVTw z`4ynCbj6z)U>&gqw6UL(um(se1cO;0l)>BpRp5b`hupZI27-xPc;G3di2i|8Itjq< z&Ckl614;B>YlMrV%$O00?ZKgd3nfjTP|buB`qA^v)E63t!>P*~k`^KHOVG#- zpy`joy;-5H8L;7+`{YLq1;rG~;2B1NpY>4WWre7z!u@H76j^}{VI?XAW7W!al-k2x6ETiTTn!-TLRB4{K$r|12H#`JA=1QS zVeG`Z$N|Zm5XIEiJsuK+5fK5%n+iFiAeP?+I1(9##S2*q%Q#lDIeKRGOZiz_ zssMs=seuMu+(7VRkJ!ad6=W7ACSXhweuRT^*;|)wRAIuIKc414v1HYG0eGMqvIz^z zd>ojmmzr(NYDVB#{DxJiq&hNT4XLJ3*`{S3jCdc4s$LXhZdeRtj6sl!4U92G1y342t3$>|buiQ)5V}1N`Q3D$07wi;1=;9YN9>JOeRg zMM2~yi6$wGgpC%M+%bTMQCg>GG^d!V=}1IU93IGbf<<@&6PCJ_dqRnh^5_BrU@8ur znqADCz9@TE=$#%aomMCZiYRlLWqk4miB4m>1l*-!YQUikrM{rvL23for8g$ni2p)I zYb448)ToEb;HZA8Sh_));v_JP8wMnRjM}PSEM^_C0fzY{P5|9y6WgC>~XZ&h--2-jbCSUQUz5Ga(9uim@ zO9Ff=1P&TmOwzM9V^@0IYJLHI6`A<0o2Dq-1Ok~1n%BJYL%6mJqOPQ(W?Xg7Sk6Qf zRQ~J3d0ADuDJo!PoqlM+YG~tTIlj%f%dO! zI_WmeulL@hogD~HEt3WBF9&L{scax|3fCcaZu+6_<7Nf=3hrIlFvfUX@x7>uNV04b3b%>`crpm@B*|%{0@88L+%W=6 z@T7!D-?4=*Td0uqa>$y>{sFTcJCxFKG8StwHH*q=9e|~jY%GJbIDd11bTgjVn1fsg zH%BKlU(DW$u8?GLbc!S=XX2~IfryaEZV<8|BeEL{^hE5Nxs~0J%32%y!MZq8GrZNu zw%Zr6@v#haM~qR}GPJnZ3i#3-BRhonw$MOEvq2N#fwJtS{OvJ3%I`v_vqfp#UIqSU zvZ|04y%F$%thDk@vN0rLxz$^}0&Y^uf=I{npF}VTm-J8Pv&sLu^f^cc!n)>7bKv0h z97%iIPiHPp?^^fX?wKAemDn_eLgp+vbEBm$Nhq9);;^kupvF`+u^se+a&>KDv`Z3< z=gKBg7xho?-+@;2Uvq=ec}yU#il3a2;K{Nv1j0RB;Bu&}F4D9~Pc%gXwno5kBNL}} z{0LVJRxVwh1+DI9c#HceKv++JZ~^GP0JTiQwIolnOB>8NXv-uP-HUZxSznuAk(&wP z1zH1B5ar2i8TM*1utT?1X%AV!xkP9JHE@3$%PQ1;C0_J?wKw5*MNab^9I~}(bYyP! z!y)3pf*DolwRBSeq^8CcL3R3-@BAQ`5SKN;*~NG7XLbKVN%zrbtV~E=#P@JZcOLfl zK$N$^k_;9Wc469f*7oshc+A{nskv2lgaGqX-giJ6ZiI z1dtPph*G^BN& zOnM7l_3N#A(8M~Gn)LbvNLQ#|4B+$l%39E^xo`;s)KCHVjSEs?j_iYqT$B$!vCblPz$)Hr{^oOj=X?I= zgMP1P6L}6e*Zk5URema7{@0{_^5X277yT-QmY@|C;|uXzBsvz6?v@(xFx#xj68`Fw zZ0Hkz@f-i~BY*NM|KdmbJmC;K-e}+pP3s5#4N~#2&%W)4Z7ga3YI9OV4O&u;2V-NG z<-b0WFMs;0|N66k`@6r*#}%(KzsUauKiEfq;r9`P(f-$n77%Cv08YRds0JVZ=X zTx4u?e1wdYoTRL@yu{4Z+~mY0n3yPn0^KmP5JH=HXo$*sO9GHE`V5UCHARh3WrcEe z8jCga4FoO=I7@3{fM8}mPzJTYz<~Iiwm>*y-pBx>&WM6tYT^PQFhUh&qGi4-KMzP} z5RU9$g&u3T9~je)hZ{;1lF2G#>j#L2LuF2pwP&MD#Nseu_Y0i8aACgegqj( zDH_Uwqk`M&dED;L)0DN3BX+!c=C?G+8V)Myst!>Q2eT(iL|Z8 z5cryA_dv%9O1$Z1a#)N;p$jF}gdAD&WXhE-U&fqS^JdPSJ%0wha$kh7W+7&g@IXRf zY(b5>dGMGn=_j!TqgKtj=~Kp11+5NN)pt$@#XC+MqHF1}rTMxnsEu(Q+p>25^;|my z=mpbndlnaXA@RTm6n>mX|Kl%i2m9s%H~N6D_0gvl;$?6oIg;bE5tj~bu;H#7Ff;=X zL@+@G7i6$O2OoqmLJ9vT^b7*&#xo}X0V=r1KDAtPsttku3&6q*f5C{u>9hm!q=pIIX2J% z?)>Q2Jq@7pA>03e!bvem^$>snbA9ZtNlRyu0D=pQJ!lJ`Hi*=S`QWYAF1!lhZbpEH z3k)b!wFCsNKYK+uVTBiFxM7DMhB#u*rqN$>oy|H+UJ3NLewc41n^qdzdz=)paL%?hB|7g zr>44UtFOko*BRF{YvvihA(A^*ZS?pHYqt)J2(P z(+x?00oDKcjuC02w$>0?D96qlDZ!n9#dQl{Co5)@3GJ_C;aT*mK!0(!_V0AeDlHl8i4fHA6h^R(!(-Y+5^~c6tmXH zzy0LkCxd-!>&HWR-bD~Z(9LDTJCW=JqPf=PK>_$em$LGNDHD(BXAxIz}T(1kCAVGO4-Df!tYZ3GG7p617_CwOltUbvy7bO<*d z;^8X8LS69gw!{Q>1Y~%^794s+DYl^J0_!u;1_clS{54=p0x}vHfwF~WQI8Eh(aQx_ zq@@27?m;Jpl3^U>I7d3x(T;bFSo)qIHbiw!WBn)qso-`M2@q+FeA(b0sbiwOSr3qc zZcCy+r6 zhHwQ)zy?s^m)XfObr!lEe8%C84|(Hhpu&hZm{FW|6{kq3Od%enIZbL-)0)@BreySp zJl}{?a}~f}IM-K{o)oDlN&-+aym_;ejU{c%ivuHh`5WzN0fC+bS6yz$&FRe{m4irv zIMcJmo~_G$id%=tlybW~VSpFFNki|9#0FyG%no@mt)3KUc}i8*lS-_>8(#7WitjKGcYNGu96m_W zp2p&x>w^d%(eR>JDIk4W800(SgO*_k$b*f^lclbzlzB=~Y|jj7TGhH%wzk!+9!(v` zH+XkA-YxB@08_e99!E zWF1JN2*a;wfTxoMZD>V1TGEzwSC{PTNlb*&kZksae@#G#OgmfJ*4DPS#ck-MA(xW4 zHn+b8Zg7P=T;dkDR@X3Ya+SMW<~G;4&xLMur8`~fR@b`M#cp=ByIt;f*Sr7U1#fu8 zJ6`gZ*SzONZ+g|cUiP-vz3+u@eC0b|`qtOJ_r-61^}ApG_Se7v1@K(|YSaLm372Cm zaDo-QU%O z#HefthWGH|v8))yle~h9L(C&0Wfm=}V?bha(qjV8;jm@Af{mvzV#B8RK?E4VjzMx^ zzrjQT?>b*T%9dO$Qz8R!0yBjx@jzA@f&)rlZ5Yz74( zn$g#GO`ytdpfWG$VCRzMc@TRxLZAPPh!&Fs(MSNrqPxdr0)eH%7RLWva?rXeO+%wE zQofmw$PBS_f4Z6;ESzfRq>e*&(eOdYm|c2(-QJZJ)phCg8TVLqLKMhg$?EC_$8; zPy%kBU<6GtH@ej=iDvV@Z`>lknRO`eu;79drPE_W|ILz#gkDQGjSJjSRA- z$`cR4a2Um5*_7;!(E!mqx6Jj|p2c{8d}{}e!;=vS&qA^@QSwm+V%j~lO;Rt-l7@1n z2^G~fUB04ma->bvasJ9@&wOfTTXYMy?vfd`S0$-FYDhiHC>{UE*+^vWeAsn{x~XM7 zSA{0sQ8rI#(2M@*s>fy6IEQD=`{@yLhx^-Y*Y>-Q0QYkXT0x~ z1%2_4zYfH7|EuLifd{D0ITymehNuAjqXX*`B?2P8{FDEU=KC53GC=I>gl!vv38cUY zd^-^!feAE$Y}2+e5;qNGH*F&UCLnfIFV+7AD1XPG5W01Hcs<=4-oH-ah&LfxF%RQ_^Kj#ZQ z6xlqU^Mlumgu@{rlj*@r07H6`qy|(Zr`x@iNB{|tErEC%Idqg~a+;d@7^PS~ok|z4 z6AqPwzv18uqfsV#2^5{!GGHk`CwRj+v^_W|zYDp;Jwc~8XhivWnxO+kIVc)QySa4f zL@CMuQG=FK$spK^IVPaP*h!aCG$Sw6gl&@o6qNtFyAweb?7JgCK@kwNZ5yK!#6Vmm zL0NnRq$vmj3&NDJLCMfTk!Z#-c}4|E#+fieH~T?8P(m(b!fJG&YwVOQEV9|zMk?&a zWO_tjbHpoLj4pIND}=q1I}Q`6#FcZ$L0H9dz_r)tMI&dB{TD@ga zIEK`i`4OUsG#Z3ll{@pfk03@UphYGafm<{Jaccq&1d5#u#x3y4o~%120Ln)IhJ4(D zXz+<>C@bfHlWKqlKO00OLV#`1LJCN>4e|d5SlKaMq8Ke?wt5%{>Qgh+*f3hKKEE>v ztg1>jBS-|p$mECyKP$@#xR|S?%de!$XZuT2SeLp?g=j#sk8B34ED==zh|#dDTBDd~ zBZRj+%i2JyelST;5F1@E%&OeWxnvi8;D<=rhQ>sL$6SbjuuB5^Na6d29oVa>$Y zh4M%_#C*y&qol-C%%}5dsO6pv({>LWbXdqNtW zP0dr$!Ri8|`log53QdgBJD3w1pAiP>C>6>k*i8vPo^5#kkYS zqC@~OH3Ga70eHyCy-UF{J<206Qz%6Q1C@fbFuS7@J9Z*966u-8TmYmiHKp4MgWL+H zSch0Eo74k9qf0b>`VZXmLpkWjtuUviTOPnMmFlRAV=9LsbpqMT2|x8jNwK<5Bs-GS z9{j8bG{aO?wH~cP9Kd70uOt7fnp%n-%Yvp84?10_I@r|A!&4lEM6LRt@OrHz9M4!i(4mx9HL6_Fi1S*pX39*xK{C`b%q zwIbypCs|fINI9gUv;GXHoAn7H>lfGfSf%*U7lj#!<(VC=ACMhdOpw3|oIs#R(+ku) zqs&DWJktx5tv97wcw7I|*h9PxNe$LWjnvS*_~4^4!W{6hi01ejV+)Mp`@b-n7pXGH z=zG7Fg#aG>S*~Ia83aiA@WZsdTViP!)EHZJ1rWQ8%_3o%;Y1coB_6{m+|xYVy--_; zr5~S|+&U=-xXp#&!~;YeTiv*srg4sIi>cIDt+9o}Cdf2q*oPufCeRZme zUFjevSRo|i%uU}I-6~*RJ7}gE6-dI#4VM(s+=ZLQ=w0Jjz|}lmQu5s4OODNDSwEmS zSi}*SOkP?NO{$CD->tehA(d@aS$*WDtRe%zO_%QlmT~1&UWLy^wW-Z2qT)e~w!IYa zh1dJdKJ6Ra%=Q16dX1&@nGwOsR}979_z1t`4O^jDsNDe==PlUk$VY^&1EX!aNZQ1P z?Kc1#7`zY~Uk$sK%f^>AReh-fRoPf@oh!gN%^TSm`VB~ZMcHszSWI2o6%M_70e&At& z95YbQj*$Okl;qn=lrcQ^&|31yScM1(o5nnVJRdTHa7@`l#!P^Xq=ekpQ=SVst-6d6 zqlnyIgX6}$>0bLF2xj&Wpm=5vQQyPFj729~KF&*k3&a3s zdX)&VI35!@6xRI8IvnS4HRYDmWmE=c1mI9%Ce>&bJ<~AZbdC{16=9b6AfECUn%ZBz zVJ)L&;Q`RG5;G%*pqK_IqBB!oQqk0m)@E1GAS-D~uwz8mLSCdeSO{z&i(N<7f@a2Y zX`!QBk@lzNIN?9x*NQVyz3r;limlNg>I68C_&MpFSrwFu=#J(gr8WzcW;?o@+Fd*W z4&?tyqdYgQZqoqJ+F`s}Htp(m>or7(#GYM4CZxaFkjM+bh%29O<;w$dTy0~SUk z!va?PeawfQ-X~P$IDn`kYwKACXUz+-!3I(J86%R>7zCs0L(uDy+-ZX@Y^8dP`Rj;) z2HyX;Yn@wWc!FuO!Q4Ces9Gy#cp42`fG4p=^ieaz%Ijw&fvM`gp;fe&5`GjWf9;|6ec1Z?Ij55t`5YQZMi9J z=oYE*euJl$iix&kyS&(j?u0jy4Sy*}v5~8HUL%Gb;7qmH`R3h1tsf;eJ1mJGs($|< zpCCgV*3r`zNHIeIbAi$v+GrlWDF+{{c=-qaCdcF+kX0O#%f;nkIJP3GR)-Ss`(Wzq zBN6!y1Nsh}0Y7o3?Z8I6Ky#}_t`0YEL&~l#Q#Eco9G3(F_&;54>^6b0XvN=SGTGwc zImN&$ISY>*)nNsXsba~OM$IX&TE|y`7q8PGw-#*Mmhh!DTI)&dA&*E+Chm|~k(n}Z zd{ON>qjL3I7C-;SmE_6UJ(e`eI;E;$wQdCsmau90sUQa6Jc9dHpXr)S0I#BUOVsUrkQuj8AV`HsiI3pC! zK59Fm%3eBfkoMqE=+y@BT|FljpP=e6C>%}lPM30MFLwJ;*^3?`2SNp!reEfrch>Rl zO2eT+p7x~+9C5$MoD;`=e~55rBGk-;n|uNkECCY$#;+!8hBwop-0`t?Qy#~_4QxS6 zIIOSPGDMeYf}s-Dk(?aC3BFhYkPYyi5gV!NI$dsQZbEZpZFb-gd7NNui&V#f0r^s2 z>}R#XTlWxs3WQ^mH8;-fJFxR}yw=TD76j%rtO&7^4+ANF(Rp$$kGKB=8`K%?JL@pF zI98+jsPGG;2T-jOdhQX9GSmaw1$a4_c1%I8uon(vSoWwGZZpTYP>f%DLll>CJQV?pt)(``v@6E1ZWNFTwW$!J_wBQN-Y?R*-d^<=O>$UYArDy&R@L4@<=nxRQU;t6CLiqwZoWy5f08N2zE#$>WAOejXSA~M}goM6zMi0fHvq&4X2|R>n?A zn=B2$D*_>6SB=r^r6~hebQ}tPnjncLNTUD+M2$K%z%OV44QV)ftYHEMe9aMOJ|Ap?g1307jxbzUWBkp@X*@Zfj)*@ypJfmj^ZolwhB_K!OAu#=I4^Pt!W zH0a&8oXa%5yy zO?G04U5-g+nP#4eW|}(LVG9JgVDE zQYMDwqK(P}8C1koMW3y)s!7Oeoqa}IYD3gEglHn@F~Vjfq=785LMWS?n$!WX9)(I& zg(sM;df6?Bg>3}ksae8DSbw56*9@DOd1C+N99;Yd8Mp6r8_;-I*gH+StN8XSlX<;& z(KYE3^1z<$IWypIJ?aK>$asYn$F%?-Z0frciOExQ0lA1Lj31ATnFDkg{nWoQZyTb#J1Ib_$3V@2FTc`7 zQ0-)R`3w-BIr0?Ijw2t%PLVan@?=L*^89TaIK%PshjCL(>ZbpELTIhk0n2yae*X=4 z;GJlK^;%EajO&4yK3p?2h<``!$QWek?@al8Q6N#icK&I){FPaB7Tzd4#VyzuB;uf zE%EA+yQa~cjBQLn?=V|&pwT|_5RY_Jikl{A=Ma@aZX7N|)&Ep?D_m&Y_^DNmV7LW-|`MEu??;1oYQXdo2{lP2k` zc@RJ9u8pkNfGfkZ$!3;Ml%#Y;InT++*O*|Q^qglhnzy~`nZ|k6lU`{?Fai?1<|xr? z!1Kn$t5Y5TeIC4IU+!~~1?x0%q#5imr4emFR~j7sns-M0BDAfEpZ30A@L(wTlhs4Zd zzH6f=Wt;uR+7mdAZDbY=EgkO&B?->zWU$1kRTVH&{6xsGa!u?Yjf*gLl93pXEU$Ub zi{3@bXTi2OIK*iUJE)Sf}e_1f=!-k9@D*t#pQPCNR>rvITMp>)*B5^bNBo*~izfbryZ`~(X{8gDmoPRe zO?2-jzGnaAmSN?}{k>bEgOX~=SX#p`O!5Foh}<$tL`hO6upOm)$5p0*)u-4nhfB7y z1uJ^dqBV!9gF43wr+3=auC}#z;!0YB+9W3q@+L0)CdfW^aG%Pm0G>TBfao>MnOL*H zSm$dJH&j9Cj>8R+Y+yx$w0FjiGgi=DDbgxo-AxFT6fQmRJ4fKe`@ORVz1`?(KEgT< zS8?E!g=6cXCTplMK?4dpW7s5%#UW^oj1KSgvYpz!?Jzqgs%=%?ecw znsh`KGX!)P%8e>FKUhZO!MBkuZ%^P|Hkb9jJO$~03|$$=PJ)#;inOoMHR^swxX|8; zFP{Iio6-z-29$A0QC6!}zfy-f$-J~|6qftzc{UksyQKh0hqPomS22_+khOAcRXH&4 zVJ9FinY=4~+*G-<=CZM$tp2@P6;S&s1?z9qskO^6VG}Y-`w?~!4>(l|GT;-wQMz0m zbXo7h)|JfCp6>S5Q`^GL``z;wPN44r;bm`=RGp-rl}I`WB|CWxWP zN_a?$rwBQJh>AYaiB_l+Mx~0Y*oHDFi?wKrw}^|msEfO(NUi8rpXiIcNL~L6Cya;Z zh{cGE$tVYmvmvGkSin(B$|#M~NR8EKjn{~c*_d2=BWR=;5n`x~*hqKbNRGGojW{um z<*1J9$d2vkj_(MM@hFe;NRRbskN1d=`KXWk$dCQ#kN*ge0V$9JNst9;kOzs738|0^ z$&d}{kPiuw5h;-qNs$$4kr#=P8L5#Q$&nrDksk??At{n0Ns=XLk|&9hDXEex$&xMU zk}nC9F)5QXNs~2clM;!5vviX?$&)?llRpWRK`E4$xL$`ilt+n_E(vZ+$&^j$lurqj zQ7M&ENtIP;l~;+CS*ev<$(3E{m0t;#VJVhlNtR`4mh+Vc0#JsrahCsW>6TAos8L?N|2q}8J!BCm+7gV>&c$&*_EynRL;e3?n$3v2?F_ogCZ;%=Ei4GohylIRdE>JEKl zqsfzP$LM|FHKb&cqeRi5)hBI>bxJ;wq&u;s0j6ZrR;8J9r8*I63+km`3Z`Mol~(r^ zv_o*DC8lZmlme=s2#}u$iUj}ZpKN-c9}p*W3a68xrhEDWP1+@~mwR%^Y171_Fgg?& znudhH7o)_C^irsX_lhL)I3o%SAKDWnieixZiea!4m};p!;i)z>2+$ET0-VG{TBoKwH&04$4_tvO0Z<>X&5XHw3_`M*1|yMO*)++C5R=s$F8Wbo$O@_u+h)`1vD~+_b*8J>hOPR_v`y=@T8U|+(>@XOwAnfh zb(#bLDn{%&09=a%aDt!yAg_5U302#zz+y;9QLX=MNU(%jq8KW)bOsO^3lt$5Z6F2^ zdC9C($gvvRd3{?SSVFfyF}M^X7&t?ts46mPa6?SMss^IsP=m@hp zfwM@W62vrYS3wiB8>Uw~ zpjoS~a|!|gdY^G%uLBw=UK1dAGZoTbOJe`ysohCBP8@ z6Ix`nkevGVbGbp7k@It>bP$TEoj(g%4OMgcn}nHg5QUiqg;Y`xvI2HztK0KCCK z1i~0F!S^A*mkPM2iMP1`!3A746R@_O+QL?+z;k=UW&`Tr;t-dpvQ;eC7FqtrNy&jYx(5t>P5i_aA~I}320fTa zhRF_Pe8dls#O?cwa?zPQye-7AbgASW>pR9KQMv!7zu|>P{QEsW*A=tC!PJYwIynH; zTfQ)H6Eb|ep~J@(0KSz=$Qt5hgKWvzYseei!PWb8C@jRw7*rkH#3DSxiR{65+{TRh zq;Zf~u$%^!m&z}Z4ZC*=Q(VgwaLfOKj3>GL!d_6As2swK*Sd12R73p0h;+iGJcf{Y zGBMoAlMKbltTj>`jp>UOwtUQnO9jj;&f~1DNF$jKv%BP6pT0|=aayPID!jxyyl`;5 z9gw`m+X?C{mPGV6eYIu@;CR$Wxj`3ezG1s-Hg&vKYtHu*YEiInTNwrxIX*Tdy_RVW zBt{C2(E%5zg$ot290ztgshAc*GiL;0xou-LyTT8x%&tpmfhu;$wFWciF%*r?doy4c&1Iw}X1My&?dEPwT__iZF&nKv zx)B>peR?IM)W3LFrmQ%C`fdM+qI3?{YIgk5P+dS#QM)FM0q#2~6a;1!oo5hdcLB{d zi)+yvrDiNGa|k!UrZQ)P?R1dkWafa@W@KO=MPf1YYz_PudT`SL#t4;th}bL;rHObi zLD$aMqd0xkdcD!Wyj&F&Op(3G382rhE!*uWDY)AO4n5oI$qZeC7UPDYGmPi!EdJxlhh~cv}@7vDHR|~ zH#)Jai@=|?AHLiN_;mr(4H?yqb~XZh%beN{_5|9%bUw{<3w#e}ge%)*-t5pWxfI@+ zJ5l@XP3tA!-r-75P~iV2lhDx-;SVt3Mdsgyc*Eek$(wQ(x3u7QXx0$@(LinDmkkT0 zYBd+0;mSqTGS8%r@DUOkmyb~q0i^ALKHm6E?qq5U zpSrg{Jrq-5cdCqE=|M$bIq+R{?dvTa^+vC7SMDd2L?ipTXxz=Yk*eL^mqLKA0S3RG zxmPf1H4u-NKR^nCqP`E}bl8RMJJjt&yE?B9Sxdnt0aoPNaqzlg4=Xe@?iYJ~79ZVvO&kzU?^J)= zdXX;MUiJSZa`iV~6lvJFQJ`NmYiXWy^%~Sp#z6N6kzS`475`Hfx z*v#`n6!88a@>rp=Fl{7B%=PeV_-S@8jX?NpzqHe?`I`@w5iu{q{uf`%`6!JIza7uM z{ks9cwR9TXVVeZep0A@Hl@?>|)Eyj0BeX;mIX(V)X=QO(BuM!V(;<|!0qEWwT8ate zBKPha>Rkx)RpIzv)lnR6<2in`=dj+6VkYwmvE!8y5q8(&IpDuJkfoT>e-wsb*M3tK zDRFh7$Gzf)@i&Y8LLvV8&f?IZ{%%tpK)?V1AOWLs2-qB%fy7YLlpZs~;*?n(Dvp(H zK=S|f0vgh%5^EeMq}r=-0X?3h>89p;6j%vKfJ9+P!YCroXkv(=DQOAIY7F4O4llB4 zZwO&7Dd4BGlS~th&@ce8vdK*8B<%xVhhq>Ajj!vQl(3i>Hz`bLzAZ<%6xcAAi)3B zc3RV^%X+nmRS+8OFg1IYsT5OXn2b?$1fx2P3G)eih=iQBBy_j+ezPMm}Eb=J6L*3H{@z0k9{ z;|*t0_J+?L5i>bcdW-?hz#ecslNn{{d?k;#){}m{d+h0t2qB0lP@>2v>+YlT99gUp zEV3JLoHs@xW2IZ_flR@GFk?@@Qb>u2mD>oD#zX=gEKWNrntQG=4Yh&nG6w%aEI_Rh zn@Nzf{Tj?Kz;z^m-~t%mNKr&k&af~rX%>6ZuqA(VZ^$BPqcF*Asx)#6kKA)bi;ylM zsGKdYWHO&1X=zb4EdLTNyoc^f&ag4Fc=5`NSW}bE333FbkV+gdga9)GMN_i`&{~wy zMjd?=(nx)xz>pfFJ4(__HHFD3sHA$T3<92tN~BWQvCs!OL|9!*YDZx3YFURPmxG0hz);WU~pB!+bJ{Z$2~5r8h)j8}nwKK^MEYOO9mGAPfyi zB$23UHKszk@)TN3C@i8mITUPBM#>WkV6s_2q1RlnC2dQrmmHH1n}@g-1#Xute5%Ek zSeyatvt_Drowdg#fzEc%{GcQ=QQ+ECx=DxImE-NHBYu+Yp(SiL@1<`x7+HS>0C?%O zft&=f`o7-T4+`>4%&5SBA$%gN(@x{(J@tC#<>2rJ^3~8qAD#5lc>)K5)G-1H0uC;n z$Mo3E>NKiOsWL(=Q9(6zcT~Y*V%1$_A3mm7|H6^h3!Tn&m(2g=;cJy3Expi_ckMkE z-Ln%``ESRf#fw_$>P9;lvf(`*#0oN4pZ)cDO*mo2Bb;LTY|V;B{r1`C)p}A0@HYv0 z>mSwr_ppP(Z&_>cRR#uQirqY5ea`!cpAc9q!4$y`tfDx3Wg^*t>+uMQ~HngLy#D_(^&;gEC z!~x0$8(m|On;d8X2xdTnT7!iYH>5BSEzf+{s~;DO)r9xJYy%98#}mN@E)+Ejj&W?3 zL#}1FaeyR$ibE3#(F27%YUhNsTA)GB_(wOrOF%ay+5G=Z0>BpGLV>kuU;wWe$hHkp zk>h}%Y!q~bLZ(rVpd;QWNm)u$?gSisdmR%_*-Dwv?o+pO!l+I)fLcnS15fF|N^Y43 zSB}znBtu@=rl$qwL2@-JgI;@9@fN*ZvTO#>nJEeeKRQh3dw~fb5$R+XYB~{WR4e22 zELhH^b&NI6RGwMtce!Y8@LAAIQk)VXfk5fWoa7nVQlbTouizGuCLpTeDc9IJ=kzL~7=sfs&OTm=i!Rz6lKvqnHvqnG28* zpiLo4(m^X^NAO8>CDP=kF~0;7pn#KGf&mu!sKEaKqsCC63j^pkZ(6>9dM#IR;AZlm z8b+a}i=!WPMo*6v&K^ofq=|XxGq)PFVE#pEV;x5(_hSVjtVJ_vZP7cNrJnb! zCIXCl)O5PlpK@aiInjqgnRXHpDw|n8k;-)f%IYe}FM{(*5t9d%JTMPQud!oqZuH;dY z*Ph5bzyhw1{-W9IC}1}EyrxI}QmqIaF(=Bv#TuH1xXt9&jd7~0aUNi$g;r3ig_uB0 zyP?*~BF3V`f$nGsT7dZSc9Gt7=6!dDs5JkC30>oA13gw#lEnF#A8$=f^ zc05Tey!0jt2=d1CGyNxTO~wsEIL041ckC;RMJj!Cig9nq1nd z(%3g+D@tnbRukJAw()?r<~M}mXS#2G=^cM;tc}MNV^bbNgsx@}W79b}#KCz!qC9gw z9Lmo-7Hq%yt015I${*qWIh!7-^dO#h8trg)Ak7SQ^Q6?{A%{c_n?6*MVFD5ka(d<5 zbgf699qnoF1pTma013Q332*SH@#fycyKgtOU zP&`5u-xy;z361x}GEUgHYN0^ErxaaCxcScS`S}w$V9ll*u{m_oh*Qym$po$J@*WR|2V0)X3-V*hXY`-JlE%Z z_6e1K1-QKspbf)RBeM!1_+qcPCczW>s;~G*;Ox!P8c&ZJZ?ASQvwE)>oX_(#p#Tr? z#xjVrR)T_dP1alw_O$;4;ocmet-p@QN;0NRB#)M|}MyU2?%DW=3_N)(Io)0lBFpcJA41Vtf*T}01Cj&~)53r*) zz;Ge5@But9h5X2`@<9vl$wGw1xll&Jp2ZB&&`qom1M2|7hkon+*|HLT>L1Yd` z&j<@({ni5y^Cjf?kRZ+|IL>ej?=U^S@bE4X6HAHh^uv+-zyUImbo|cmxZsuw;Lx@L z@S4CAL{XO<0~8l!ZYtsN%uI-gLpKPfwgPT3`Xr|O85yTG zio^KK2@Ve;TpovAyivoRL;w$ny}(fqTaXYf#$)L1s=}pvc#b=)(WE+U9h1cB+-RZN z@kACf!ye>sL=So5v0}mn;&5sPlVlwk3?9Oz<)}(Lc2Q)Sa0+%0BGr)}lhA9Rq~MCK zB$aU%4G6<-kuqw|aFXmO24*pe!zZOt8^!U%o@D6=@`CK(97XLJO;T;R10yqX9qaKL zJ8oo_lGfURC6Tcip;E?r*9;q@Tj^ZlQ1QOT@y1v-q5jAc6-qNZ?a?qfh%cJcuudkB)R6+5E#W8Gy7p%Ca)Y0^FWQIDH}2i%o7gk@dCz5 zFggF!0JJl8hOv1(k;-JKaonp+?ny>ObgXhL=2ne3L-a+b1wWnfKL6{U@F6+wN z1vx}#Ak;B807QTEi(Y6BXp~1uQ#SknNkF#0(n_y%c8mi{{Zaw8l(Nh*IK_(d%BAtL zVNB_BaI|MNrPG}LPfgw9Oa&rN%Vq!8ji3^yOiiNk8pRUobXkILPR$@t7Y0zdO{|>p zPUU1!6V;rwOHmh~@X~Zq&4>XY^-uG(C=-fN@pMwD15@)0VcgVC!8E~eA#$E;P#NYS z#4}8t>{HvcQ%z%1RWln}OIBm`QAc$;6i-)m4cY|tP33D+Rkd71^*S7NRbN#P3e_Ji zDEJKj^&yb8SjW^$tJPYs6E8~@*;FVr?!Cq7Hhu}wX(8(lV=w98mU!4qK1J+>Ubztu`Uk}!tc4b>17Gfh- zVkh=mt6;qrU<((HVO6i)?zB3Bbz?(TWJi`{F`^(z7G+Zs_)@kw(zI7uR$u-PT18f7 zb)_FTZ|e}qWmBUMNl0U1)`E6cgnBkyf!1j6LTKr=W{);hfsbOJ7HXqbYNr;mkdGgk zmOrspYqyqbfi^ZG0A#yXY{!;t%N8if(_F2VE6w&!)fW1w7H;EKZs(S6>(*{3HUYH% zvp_QwW~Y>G{}ylqS8xZHa0}OPm2zM*t6lTS9`aYd%M?rzZZPN zSA55pe9PB-&li2uSAEx)ecRW4-xq%4SAOT0e(TqM?-zgbS9%SQZ}r!I{}+G*SbztZ zfD71w4_G0~5rG$&fg9L?9~gooSb{fIb&#z}_#}ZQ;7BxBO)7u_epWd7L4+0mI0H1e zB=S~+EvSUo3l20`fy?3kEVX1)SPeKB%I0-~b6AIWn1_4Vhky8d4Q`2;v->E)b$IOC z5N1572o^HNf>Z`uoVX2wln5}mU4{7B%s_F15s16ki@z9*!&r>RcyzJYh>184&KQY* zGhtwAeOd&HO|F9Cm`=v*G>bM}%{WY#i;Vl&kN+5u16hy<*<7)B0nr$r)EHwb07DZ7 zj+;Rl%2LUmGym>u9{j0z7nPbE12*a84za+8WR zUYW>L=U4B7j$65o>47;WV4|S8Gdvgr_yGd^Ep=jOh1(%@(#U7WWtchHm*ZKU=b4`C z*`9g#orSrUgSjasEfyUFC*_4cr&*4trc`$!o6Ex#W|?FH`Ym+QNNID_yi>4vMUe~k zo-0u?w}40>n8FLOKCI+Nh5jsgqi%mzrh$Gul#57s6~tcrGDwQ>O5^S>=$S%VlAk zF`9{R_uO+sNirc}j=Un7snc4m*P5-{+N}|$MQ_SZ6vQr8!9t|}mEFk2fwuaTk3#O= zE}ZX+8v0S9D;lAuLnlQeY~Px(8{4rT8?rY#t{b2jA)}dStiOsCbc1#w^dg)*6iMQy zu+0Ob)XEX8^80LX)UXN^@Y5fYD%S5$S!3MZE-aC8G%T| z!=_uF77VwPYxH_cMOQS5_1nTP9K$nQ!`pOirxB`|JHVm;pa+A~TgMS4-?his+bVMd z)LMM>7D}5Pa78Jjb`3%e&mmkK40V7hz&i5`sLSAyUWDJTYd7ugm4kc`bV4 z&ndgHC6RJE`1s57T+jEM&y8C2xOiUx6FQ7yGwq@fEL#vB=9=}uLFpTbWqMx}a~B(v zU7^b!hcZIh4Mnrs$rQZLKONLVUDS8^{8%>5m-cU!Raj#c)iXP3P2UDjuv)@z-I zxeR9GoO!W2BzfJ|e;wF^UD)4OFBUssb$xk#Jq=XzpPuPXYMeZYV7)?IGj*;n89^VUviZ^c)A?8l-Cj2Zi%deK!B=RmM5lfJh zNM#dB3Wf<&5A%6u?Gpp^UBvU{tDzd_pg!{_jY9ymQ(0!8(eZIQOrJ?gYSK4<$T22J zJ2qhB5-jYJ2}aBL@p2vZ5(FA8W%V8)RU|pf3ExPU^gFJRMJSDcHzGd!oR1+ zf4kI!Wr-S*(LbTNiGF(ktW@fbL9~+4GH#jSJN74880C+mc$EdnDIXBxvX=8N&Lqw zQiXT|-Qd%wOw2z30ozy_=+MsrfJOvx5|WEUk%IgBg-N(jp2UY~C@LXfkqV!P3XM2W z;sDqZLkG+3d%{qONHr}1yu6o%U`Q*Uep#U>W@yf&N|!Qi>hvkps8Xj=t=dKt&kYAM z{OHPWNCiP!_hC54NJE8!f_k$59JDM=SSki_X3P5E?p>Q`l0nEP7OdC>bIabt`@ljL z!w*C;*c8j9)(pi=vLX9*8d|k3c|qRV^~YtOb`9%2V+ljr0~I2GX?sgZT-1V3moCHC zZ_u-;C9EY9du+uaw>SK)TA%~+Z^+@LD{XFw^5x4}3Hk6%0f7$BsghixRdq}waXI!8 zP@zHrt4YU;F^}F&L-q0-uY?l(q80XG+^27|AgEQ{QHI|h^bv*1W}?{>fF;zC!N7TM z#3$cQJ<+!yH1!Du;1LsUsG)oziZ~*PC7O65iYcn-MgkI0Hq9v~#n@eIX%&G*cp0st z20dWVSl2T^<%n30mat|2OK3y<$I}rP(g%PMExssYkQu%ffQ`QWbcU47^avyzOEU4` zjxZh>Tt*qZrQ?uWVu_KKIR@}07q5My1%h%`MSwT#v=a^y+o9u)7}pJ99SHDD71x3U zR0&v;D@v;09v(`XlYtZ6htd(0>apZv@(D;~N*o4IAxsN47>}h@p{k&e2NnUU7_H7~ z>ZQ5rx+|}}`uZ!dQt?)wn2<6V2AW8easdQ0ap~r;Jbeb*j5p1g%w+_Udh4;XQh-S^ zWeh8Uco3M2%|y#K8>yyrF=MW|;s%A)qm|&A?h@;+IVY#v$|Q|U*IsF#yT!uR+qOuu zD;1yXl+zq^ghmYiLKxaP{3pd!C4+7lp5Ay!1R6l#AQ1~pKu^e_62Snx=SDff1PWAO z$+zV~wn4mVupG((7O2~axmwX&FA@%%HbHA@c$`VgedYIx$m9_KGg(x_918^WAnk3; zGiT9XMp;AFB+Om>tX`%BXWQ?M&W7DG$4Z`@1qCW&39}awSPgb7Vq>s%$z^-}H{VQa zoix)t`Z=z9OtKXgG`+jVt{CORl)?3G7{vwl>GQLGp5C{AQuu_U zy;Bil3*FfU@}@V42nY}WKr5hn8s?{oA<9955|j}vrYIp`@F@l(!_v6$3J4mjOhed7 zapFV|w-5n^jab9DE>R~_kc&++grVD7h=`9^0~AV9g`S9n2)1A;3pYHWHuM**fe8y& zj)RkUa)?9{s?da|nS~C02&okgOo)RZ;=vRm!|!RUhah4Dj$~E2<*kZ+h^UQ>hWJBO zFffa9+~N_p_eFxuZGo{%)e+v;JkI5ANnkYJ0Igt1;xV$3j(j8}BPmHTC3vkf&!Rx-)20iN>=U!LjY`79Z`9^J3$JQZ=7K?cPOepJq!dAoY*<8Q-E=j z^HAQvTm`4{2@8Buin-*8(UO&n3rOHFr65n=;(5j*t|eORgb6&ah(kx1s}x`u1Tn9q zJhW7RNccoU2;JuZeey7jf4fU6ATWx0MvJ5Mw4((Mlfu|slrJC^DcjzeFR=*|D*LDx z8B+?Whsuqj%%i70Lz97et_!F2bdWz$IwO)!)TG7=sSqEvM7^uWLiJSg%dnU6OU17Yi;#WQs08eXD{WI_ACXA*1|oV^!ge_>dDCe{hI z@U3@v*OYH!tO4l^zy;kQu>d^RoZeiNa%alCH5o~-rIFk#E6Ps{P$waK?e6vl3QPJq z^{f00pBLQAh0meUop#;lx`=|E4wcra*sz>M%j+g2{dal(JO_J?!$hUocaGx!HSc%N z;o!yE30lE{@GEs{V1%_If0RriNE$o_td6*}`DF%88Ps0_*JZD<5pa%J9M=Y702>O( z>+WE&h4-a+6bpuwF_BeQ!4kR1Mm{o2AYNM5wMy zvl~X5uJgXtz%Us+5=B^gK@c$AT8Hu2 z{7TZW_Ntzlt?-Zo?Xj?39cx@E`*O|hAp$uBWs6FYjlD016dis8F0WKQ{s1j?pA=u%4x&s*hp!0xbF6A0H{4L@l z_W=s=@Q%L{Ttj3TguB7-kQQ%uE})fi-*?W9cYHCxp!h64FbklEyuQbf^8uKf!&7B< z;fp=qzz;s&t_k?#IW_tzmLB(rXIrn|5QUis?CJ*B_0We*QfWK9`Oben^rQa=##(xc z>#Ct;pUyF?^3R3N$mR8s4Rh^@To>46_9tp+BuI#cU5gaM%Ljf}Vv}dJ76q>vsLy%k zIkx}(m+`l$SZH|C`T-P2C>>557y6kB@B!2%yHT8tH`+7S&vc zs0IoZUFC_`8BUR1?3{NzfQJcDNWq)*#i1O|Asx;k&6L~nZA1J4)T4Aq%gmG0EP!GRA{&lZ zj_hGASrQ={#xo$A41UiafzKEqVh<4^ZHZ1n(G3*wp@f`az!=&j%F@aCA-n)0MnGaN z)zDUG#wryAxIoY&%2vJPp%A>BBc@(XFqhVGV8djL*!kiSY~ThuMXSjRyGWMDF-;@% zSPjMr--O``+8#tTSl-1TF2a@(HY3R05ewE*TI2)&IOYRofMFB@L^y`ylnl$;O$7k< zT{ha%6-f~j2Fy2}V}g;RVtGM5o?|*1;Xt$_8ju)W$=-Zn%hlzeKH8%=@*wZY$UdUu zuC<&V0HoUBANa8zGWcU1ZX`!`q(}PIJ~&eY3Jmk1(wre6-+jnTBmwgEkVU$jBTUgT zz#2@*7t4hrK_Wm%)*cy@-)yxX+L=Zc@MM&6OaizfOupF)`lKAuq-fYAZxsQyRNrvP z;_+buOYYTF%47vj&@bAA0`y4+Zh;1M)BaVVCpzP-A&%WK1IxHx=grzPQeEBk7dGnB z3kH$iUE{yK;|D5<1gy|8<)HnkWkVX>U9RK*RJ;_h`K5TdWz~q5=NTbBmY!lFrc*HH z>t&%`7L8!mQtYi`W#-9cmLMKzCY(7_7QvfSexz%@CTzxL@AQ<1y$_`&(0%>o1?(no zLXGACULh#wL5|k;9H+BnC!BT5avCR$T;@{f;#XSNSXzO_cx706T~ut0 zG0MtvVpAAU6Q1qUXx>_eT^o4XUTYTNU&5W6m68??TgSLf7}8l{ng~+7fedy;b|Gk7 z&YG;8U=MO=UlQjT#M3Il!H24WK-yXVXSyV4%G-$=rtXAMj@}kjt^qM{=YbXy@62e4 z$|jN~sgf=!g>Yd~euTCtPfCtw8nhOSv_{;Zkd@q9HC%~4idJ(H0VNX2m<;5EMqO@B zX@BWEUrxlnQ z2X0VQSe%lasMF=9Fbs=)VU9|urZzIKemt9Bh`w%V%ykH*1kZNal9=wnJFxiTrbrmMQHD;?dw%2Zp$R;pO=YXh~8%UZ>9 zAWEVjhZA5B#N_7|=xhflfX)&nQ)J#ZB8D>|iRP&ZjI5F%zD7i7-Z*VQE)Y=^EI`yY zn${+pu`1S+AXT2-9bOVb0W@Hh$im3JrG2Vl)7n_q;>gH!?McvH$|{x$Jpew;rP~o~ zj?n5mX@%cfBCeLmxUvEN(|$*yX|3FLt$jCg>1PE^C{_WRVZen1r=6-9KjO~Z?=n>LrPQpaF zvMccxukjx5@%>~x=9?;DTfUlUXgSqSp23r3)|zr7bH-j0k<|3+pu_@UEdtR)g=-0E zk;1SQ9EoT0{ustxul3%@!m8x^Djn$9)-H8#R7e-sVNd~pLpTBGL`avTG7J~RWb(e6 zLAstanUEoB5$CExs4`DIOe+bpF9@M;#%Ylh8ealS8vzsp20vkn9@+%!=!irkh=wrt zV(8r{=!MnSwOn2+8ckuO-&EFdNyrsY^`W{z=9V z87&BX@*Zc_;B;~%1f~Jo5#?@cr=npn<8X*%<*OpE+29)uMmb%bG+8B{vgz&OadeWsUC0F{t?5Fae*pz zgcrCV7WcD1|Fe>olT!$EAZtU6GHV(h+dY$UVrX?0v9G)`;sQ>Qdk`!%sXT1S9% zB#3nXULQ7MC$?fQHe<_X0poQWKz3tKHf2|~WnVUCXSQZLY5xR3uhkO#St4>^$+xse}vkgxU-AUTsaxsyLRlt;Og zPdSxWxq2%(mbZZySt1==5d>H{n1{KTx41!z!kE8z&xPG$sd-0Kt{U)U4Ud_e&v~p~ zS(f|8Zd&&q1ZMR)Ysmb$n$}9$zy{3lwX?zu$5KtY)()YQ@*U^{;6TsShyOE25Tb0{) zB+VcGj5);4+x)tx~PHe{;LGZl~96l0o zm%QZtJ$7F-==S~2O~7t1{vABNdi-`82zN%V4Y|Vs_j5z}lYiuMe2K_@6H|U3Tz(&9 ze#yAV(FKW^yxl%bDZK!!!2>}+I3yO0M`TjDWHyTcz{NRTR-g%LR(qU4w_oJ~`T&=c zR=~l$W@mqIcw9cG*X?(FUccw}{eQqf!9l`8LIo%(qKhj-$4AKjNXbb`KnExWq6esn zp-lj?Ap$4>10f8|HHfPs#!@2+)}*eqBhn&^v8@NjHw_D{A_0lmC~ zfLn+;sVpHFHNdqy}0X7(U|Kw(5Bc4b}vx=D8_=D@?rs{G0A5dD?j_fcFH9 z&#z{VA!tJmJM{2F5JL>4HeTJkIdyFMWfEHV00<-4%j8=@G&V8L;S zTQqTP3Rg%OGJpk!GBSc55#XfAm|!eX6xpvtR*#9L_^Kl$}tm73h``j$WgG&vJ>*+OeBtxWI>DrE=VDcioML@ zl87g-R75s4nY;!SF`Hy!13VRw!%8FR@(vU+Ga0Ho+Qdpy%n0N-MN3P+QgpYmS}hT# zNp-!_R3TBl(z8mJ)YVj8HE1+XEh0^}6+HQrv{RALDV2y7-A?>1YmUtDeWysU2-!ZU|)LYMbgMJ038z4a>)`C zSSkeAGuTkIFi=fGPxVydZ%?Jx#D^VLQwu-;A%GKBa>VTzAvS${h2vC>z!Xy>w;}L1 z%(UW-(<{k=d02`+o|R`(OvcvGC=y_CX{MWY`sqPx%vjeAptkyItRry|xGs}ipzZdt~c)o`Rg{87cWc=6%&;&;b7!&1C zQ9Vvn;3^pdpXqSpx7v-)CXy=+NGR7b-cV3_lEWYYr3XFa6-9KU(VWZnx2|_7AzmOm zArlZI!2l$%NEE;zfl6Zx)bYh{!V?Ktj)O2T+zw)SGoahArX5zR2>kh0KpOBO?u*+;9@Mu!OejyhBjiN?1Cmg zx7`e87tmP~Jovl=UQUKwyc6>{MYcH(5=TVrUDh1=NJvKV5WX2o1tfV%OgeIF<+#&N zWF(4a+)r*K^po0#$F{ZELUU>VljAJDhCl`u!*XpplPES)8rB2=G1m!{5uXLR?c{L4Z}Y>28?H7(!w>8&~-2GuBJd&1j*9blJ*?%#2&x{)DAK zL2OXVx@Iu}=E4-FPnE&kh%?nVPCx-83mzoXQ2^FU*8FmC3o8lO{x>#3wsV%qE6_0C zDNiQ=bauTe9KZwy%v%1&p*dt>yV7?yj@D}t`RopfGFl&PS`%Qhl;%KnS0j(^lXyA0 zTRHUEMVFHDp&fPQOxM{{cb>*BziXJcYBkZ2oneJxGUXJ6xI2#KQlfn6XM#wvOyaF@ z3MS3v2DBNhCQWslE#znaRR4L^iB>h6=8WEyYLn2F&I_jUS!!9(nxj#M5s?>-BQ&)N zPjuc?tmHf*o66c!s=>8wRm)^!9sAg)acY)ya{y#5d)W@riD+2*#2a}Q3WUTIQl&KI zHwy;FHc_xhRdtUNfvFW<)wFLxO6 zD%G949Vlz%)w16!6;pJGc8o{xA4^Xo>#yC zz~HBZd%O{o@~cX?8M$hj-5g_azOvvVcRk#iuuW8(5I)je-*%~YI7CYPxULY8T;HAE zZv&s(0)~^&<%4l4z#~0pdq_0p@NxpPbEb2h4MEw($l1<&<})8OYb4^(EvdsZ@e;?7 z07N4?nhrzdDd$<#4vVIb>eWD{E$tf)FIUWhjDn>R1IA28+5rs6aNEwCIJjX7O;XDe zaobkVF?kv=3mzZqUP0Z>A*0BxR%3s=JGFGGlEjpjHIO4ZunQ@8XdDgJs{8j>qT;Ea z;M;(wtW@m(-5giRaIPw`J&oxSD!UEW{&u!29BPXpTil#%&ZVbBB6YfqV7rs`te4GZ zR$18$`ZhAWdc`CDJsAN5o3}{RtwP)x{NNrT^F48U&uye}bFLnEwT%5``7Hd#-o?_G zs=ZTkyBoDtz!j&2T?SVaTxMC^^}WS;fsZ>l5#_GMZO0cqii53N-gfu@(%ddum|`g4 zWJSvpd8(KeGTatU_&`yO0jGluAh^-_J?nj_K4)F)d`5to#;|p;Z@nddvsMi)6_{Y< zb-buexxAGCa0BP98)e=s1#)RpX?xG-4%^0}bxB$@89QQi&!yCt1;ZTO15=0xTgKSO z3cP3kiof!*H3AToYe(aI@@xhju)#~>$ir&gZ4mt8dsw1RA|cw6H>wo1;&mBEUG-;S znA}2tR9=sMEU-8C$n~!KTrmt|x%KyxZ*MGHJzS82;WrqXPke+cKb30_b9w(7F*ZUx z?YffwY?*!friND8IBq=^%{i{tvOUV)Bk>uRe%>Y_1o3}w&!1h-WDO0E z`+C03SpfB-3r6TC`Ma-Xldqcjg49ET1k}6%G`!sLKOK^`u**OVyrlJzo)g(X5WK8S z8Y}60z@@mp^qar7W3r97)&^1Iy}n% zdz=BX3*RuUWZ^-y*}S%?Jk0w9WWXf_j4)ICsa`uda?t=Lv_aqtqNbZb(s?)&l!yR2 zLo^JaRa2So$fho271Qe}EPy*n;leJoz%N__H)KLM%pyF@!!r0InA?C1_=IUXxA&u} zF8qlkJi-H$sRJv+D`P?G)4d;Tf>1KBcZx7=OT4$sBJ&wPj#H-tU_%T@nK5|74pYG_ zx4g>OR!_~ zL^0HrsT)N_?7|SdMr>RfIm||Gl%x^-9oCRU3do{c$&y?-YQ)HJNyLUkIEtgkpJM|7 zl$4CTNRa8V4y!(hQb}UcfDAJ^iL5;Z?5V=5LvedZ?9wV|;K=DS1B<+ur2|TaYyzWO zNLsX|>gdQC6BK;O0vsF2CAdjW=z@Bgjj43G`$45O%fu|;m7Lr(32ZqK3Nq3$mD}n@ zzU)g8nZ2;_OTm1ac|-%o5l3L+p;bJ}oovB*`maUFJtjawRU=C1t4E0cicE(IGovJ( zs_MkfGyorhM!`!y@Pk4$a0rDAO1o@wkwU|EyF zOi>ke1Y)9#6@5_=nMZJ>OZn0itANfQiBGR|JMjbqf4*F@KOhquCWYlH(&+8*qkg-uEtEv0+y9LFrhoY0I zKsTmBxi$n8J*BE7T~a0()0}!6_Kd}(q0|$^9bYXjY{}I++*PVHBAS8FywuWU4Mz4{ zo-l&NG+QrZ-B2aV3tlPEPQ3Hb@@vy%g;93@ZC6A=A_l0Pl5kggrG$B$ zI2r{^6+3_o$c33?0_@b$s3gK3eN!nq0AZq&Cn_3*Jph_0ydV6uk)ws-M6{de6|3}- zQA^m-tgi=P0EA6dgtez5a)zLIAV(2gxDRIb=a{*o(E7_ z$uckt$lFqbM{VF&<_cS=rKP}KS)BqZ5c4l!{X~QRA;!+h+)?A(1pwM%joGRl+yx`V ziJ)ASDpDImFq7@dx|rIkMGT0+T8rIUE!YRW^+U65)(FVkO=!Pf8bsEx-JR_X*R@(K zk=?XqP)wNF7aY)FbGV}YTVN_&#YL)y5X7I|S>W79U5S9h_1bi3*jTv5oZVTwTtB?j z)NJkBhpkulP0`r`n)jVwL%3IoLd>IKy%c239i>G2)I&VUE2V2dB2~uk^DF(WKr`^V zj9fj|VybKL(wLzo+&dznk=QG#S=C%W2o73E9hvSNKDq)L3nt;(rCjTi)BF>eo`FP2 z)04d8)>ovh0lq7?C8g(V0|XX586Hp^F0?ZL_?ba#Jx3hk8Wsyb*}H3XEny|#^D`22 ziQ#}7RTTa(MJ1-7I^u;vKb+CuUJ{e;lQ7h6UK|wRX%QM2PT-v}WA@v(&C;sn;gSyi zv5EmDDgIzFfmZchVkeehv6xZ%`>Hv{ovuyPW)0Rqh2jwY6&Xg?mMr0#pU7M4g^nd@muxAZePIYD=p{96Jp_Sesl;GW zRy};2Nd?%FKpO+1f!K7gmL_fG$zT;?9tairgymRG^zG$UF4bW!A>oUH`2=MfMiN}6 zkF#}KHn8Pw3+7@imGA8bYvBZIBRoU@J}nP3=6{d_a9-eS9t%3KKLnAk0JwvA{$X*m z&>h<6Gme*w*`bqJ68bpH2nLVjj6DZjXeG)3LqQ~j_Fw`9*>v`)5F^OWJypsTv>~>M zI8jv=%BPM2+kcf(Y<0kYCaZG}Uum9@i1Ow2+|(PI!84noGKpr3`<06(=#f4Mm_&kj zeqQX_=6Ne!hF;TwO=A?sXZRaOa0OovhGsxpXA)&wqOL{7A%INoY7J}(kaY;J9_v3? z$A(==v^J*dEz7XhJtYlUanqNz*2vD~$q5uDyY3%B<Ig247kKdS3;erv)1F0ZF0z<#D^WuxrER_r`%>?U~ZFgWWXP3(1QioH&2 z(Y`^{?(Be*P+QgP|5|O0My1QfY|qB7!>;WFnC!Xs(YpRZyk^GG4(=kAY{&j>zIN?? zHf;r??c9cLO5N?azHH*oZS2l&?cQ$g?r!h?ZtxCo@g8sT2EI-9Ke8t4^Db}prkK=j zZ}`sc+)eBGhCt*iFO_N1_}*{+?r;D8ZvYQ)0UvMzFK`1ta0E|q1xM@k9+dPR>jqzN zw5}ituWav>jb@^4ObzvWNVlQ@MKXzolbwaFc3M{Wsq(Akv3fN9|YOi){zjkcTc5R3Ao7~Lj_M!W{ z%55KaaxZstKX-KhPj?gV_M=ds%?5WS9zu1WcY3dPd%t&l&-c+|cj1QjkCb$*k`s7RWs5@-xC)6-cNqzUw-Cqegp3;tx!^G z4Sp#tdUGAo($4~bcYf~ge((Q&@Yim41ejE#6l z3Ky0C4^t0JP7YCI0vkgYk+ik8x45~wyS%-=zrex5!^FkL$H>Xb%glWW2MYvt0t?V} z3a8E5+uYsW-{9fm+J1c2}MWl^Yr!h_xSnx`~3a>{{RCD+*VBif`JGV zDqP60p~Hs|BTAe|v7*I`7&B_z$g!ixk03*e97(dI$&)Bks$9vkrOTHvW6GRKv!>0P zICJXU$+M@=pFo2O9ZIyQ(W6L{DqYI7sne%Wqe`86jDb}tRI_T`%C)Q4uVBNL$v~rQ z0SK4bvUg51D8 z^x2RbO@#S$1b^uz_H8$kGM@J?Nk!4;-er;&?E|DC3M;>E}-6)u6(JkEGxuA3+ZJS2b8hLk4h6UZWrw#63v} zmVJmxMl~ELmq7+3QlTjtWM)Cab(4vpCWVu&ngyF@Ea2uHai+0Do_acQE3S6_>Fck+ z1{;!%HKb6Bq3j_FUn8&ukehI2OnJwbU`RU%rUV)Z$*58xvBMe@Y%s!9RJ_8)i5^M+0R|Ch070m+ zO)!B172J#g1x<|6?6dbFhosUsOdP-h{?Twlb51}FoYYVv!2xntGtILTa&16`08x9O zfCpwL;lT|IoDH1V3YVQV71+kz_1poh-FDP)Pr*QeQ*-MD+Jr+}HFCCH{Wa8uQyrMn zvoURW8QwbaoCuPIFrBzlq*<6L(q#1fW-aYCk=@b$U=s&OpFiUikS``d=zgcB9L;E zDbo~U5W@;xD0@lp+?qf~2BC$b6JYxx1qe02AF>buwTi{8%-}oYO`(ZZ@Exvn@U`Vx z@rqc?q8578FJhSodg^IdkdhUcFapea+^a(KoVI{4rhtpfLW1<(sGi*f>O5!sBKi(B zg*M``1^g-&_}nlp(ShTs4P&~HNcW26K?A&)ThFN9rq#-~>JDHi%gNl~L3 z2XC+e2B^?*oI+A3L6wC7Ve)SEk>Cech$K4_kZ)P2Th*}tRLWC2A%e9e#cY%W!O)4w zfm$P=FRLb^0v*u+o#bRENfkpXq$&V5L{qCi2crK;KmwGo#5cc5A_5SBJFQqE5*BF$ zM-qWhaZ&{k&j3X&)N=}S@<9)H;G!yO@t*(O#L*KLthmYS*d9Q89IT67RsiX$hE`&Zf;7QQ&{8#Kz4w428IY!o2e5_ zBu@Y!RSfrxqV58tq8(64YmXJEWG74684-(REX^oNB}R&bu2Ey=>3|yf*x5J+z@+Wt ztU+1!S&oXf3?l79kaiQ%)q3=#32-T;7+JL>@-_*ii!A@7nuU)1plyc z0#4n+0gkJLv=;ZNS8ZW*mFk27G4QEB-GXzI;6VD=ue`|Yje6JX!S1d#Y`8yJM;*6`qqB>SQ597t(^c%78A{4OYSTTVjx> zFyv2ULk$vkf`kc>Pab?1!x!IOwCD8_;ZO?-acMC55VX*^EFp%QwzYrn9)Ojb-_op>mz$Gi3tp z1VD2Wz=lpR1^o6~VNZeB3$Da0AidZpHaq}xqEio;yXlHs{Nh^a^oBvb>x06&kEVv` ziA$|n6t}wL8U1+GLSAbeb94m&+mXf*`cNKcbk?7k3bx%05PU|CFF=Sgo z&`5gHv9dI)Oc%;WwKCMP>p}B!8-w0n_q;Jl?q}C`m`>NWF0(FFc4yb=XivMe?`*<& z+q=qDurC?#%_K51E_y|5@c-if^t;Xm_KN4OTKDgcVUu- zWwg%+A9MgDn+pMIb{NJi?_9e5KT&7Uo8b)Qr^|Be>ZZDu>3ehm1{L}hTyq2M4F-5y zAJ6HgH{01j_s*T^I{X&Hpzj*su>t*|q z1jrM_0%Jh}MzP0n9|c-90AsVKV|U_eHYX&hwSZ~VS{n6$IhROVfGjX3ay2&q8rWl^ z)_NvpfxFdy2^IlFW^Ak=bj}uiXfS4SaadXhZB#aHUx$1(l~z)9b>U|?$mAcFW>ngz zgF*;YM95{!*M0AGeC@UWZDGQFbEjv2b|w&F2J1Hlg(hG!xJY24M2FXchc<9ZV1H<^ zcu2s8l15<#7>9B=hb!@Eu6IWYIC>n#GIumF3$;Zpb#fTEho$9mnPq!3W`d=q0#1M| zIHrg;mw}|^i1*=F#RdT{2z1DHACa>LV`f$DMH;8&K+VF0%Ex`6s9jrzbu@Tg*i}W^ zrixl-AK2G~_Mt*!1%9z1g&V|!BIJYjhJ{J6ci41(!iWSTKmsI?e%8c8=Yn7dr%nO@ z3V?ww7ywDoSSzHnSM zDFN>U5c>x(A$`S21;7BSV+2kBkqaP^Kvyf+;CEl}E@r9X2tr_Ir)UMKptt?3kG6 z!CYg+h+S}xq}Gt>c#x497?qhvuRuS3Cr_c0P5|0UIa!0m*>?FcHM59xQ`eI@iINY~ zbYHcb0-#(cgaZ^87$XUru_PC}!J^8gKxM|76l4$qa+J(TLE)7+KpBj2l|3U60;m!K z{AD>lT4H*h|Cc8|pnCGTrfk}# z;eZw8<9R`u06276WNu%}-@4c0&hr8q54xj~L{22UtmB|4~! z>Lrny21OYT`W79m!i-`7E_O8s&!DEKm8i5}C4uUurh2NV+6+#EYkz76*3+t|g?BiI z5{K#w0n#_a_oy^+sadG0VW4lFnySJ&ti;L`)guD}*#QDd9(3vjr%^Bq;E4M(61D0J z9ci25HZ}8cHA^8^#rmz_8m?iXkn1szeo&Yxl@is;3|94yRt0XvM&3wFdMTnJF_%fvo?FPIGeLNyR$so zvp)N?KpV6|JG4Ywv_>1U4jZvYyR=N(v`(uCFMtA4ivm;lv{rkySevzYKmb#V0xzJo zU>mk#JGN#p16}J+WSh2XyS7&g16^CSY#X<7JGVZ|wNv}Gbep$&ySFtPwNs0>d>goe zJGdR|wo{9DgqygEySNFf09}i>j2pRX`0E4#LPySU34r7N|No4daIyTA(>tqTK)8@$GQ zyvX|&w41!l+q};E6}#)T&pW-;TfI!-x!7vG+Pl5n+r8fVz2Fbt(|+rIAmzVI8r@;kruTfdq6LqBA{`n$jUs|ffT3jG_v0zANa@V}KnzzCec3akbO zTm%dJzz`h4TF}5mAi)-V!3#{mSb)JC+`;>+!2saFB0R$I3&JFP!YF*cCY-`7+``?v z!Y&-cGTgi{Ji|78!?|0-IK0C=oVq&P!$2Iwl>5U%T*O8!xI}!!O1#8uo5W1~e#B6m zwN4zxR9wYIJH=L<#ahg>SiHqv{KYcc#b7+fWQ?+6T*hde#vXgdYTU+dOtEbI#&SHz z^BTu=e8+g4s&<^meB8(IxyODS$bw9VfIP^Ce8`bk$cVhijErH5+{lm|$pH1pl3dA_ Yj69Tl$(p>$zmmzE{K=pkBS8QFJJFw^U;qFB literal 0 HcmV?d00001 diff --git a/docs/assets/getting-started/local-setup/setting-up-a-local-chain/gnoland-start.gif b/docs/assets/getting-started/local-setup/setting-up-a-local-chain/gnoland-start.gif index 4da21bc863b3aa60f2420489800be2dc0798efa6..4882aabdfde819e3bcc92dbf1d759d466c7d1f26 100644 GIT binary patch delta 859306 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

(Fku^Y8QKGe)l~^L#VvKS0xTI1oU00)xj0{ME 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

(ox~ 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�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�E@(jaeyBGps1SVZJ_w5-|*$0T&W_#k9Q>Ia#^3_XakWJ1R&ZQwq2u2_+$&)Qv4F&QD z(|;MCu%$!}hRU`mP5m_yd&y1xd`Yp)18-n~1W1n{4x%8ALj>jFG4UQDE+PdmP1tNj zI3R*Hl$im>&5-n=Bu2ywb>I|a;vYC-A~xG3>cJnn9@t#sC{l?Kz(dBcA=e-Wawr5W zB1gqQQJ?MM7Zx2T5uYuZ6#}XonxInvsDD%TZ9(@9*u3c=IkY0c0gVK_lKdeFi!hYG z37)+C83@A47#f^39NN1m&;M6#V?UtM0ezJ@o+I03$27vqwqcp1DWeVw-{};>1EL%n z9t-l_Nd=M%3-)89og+ZPBQwU{1bUs^=^8m67C@q-1(F%Jc#2HY&N{!sh5*+WW_OD*JAorsRb!4d(X)wJDr5mSUPVZaR*p73Bn_Dn*m zVP{OiVhn*_G)s4F<4VGsDOl0N7-2K!Rlj7Tu?(fn6ja@`p^%ACmU!Sho(3_YSO0iq z_ytNXHbS-SRZnhP6C$Blz7mEhWq0F z-q@vuG)vf=+bso}LUG~$L2Z}AjAfG4pJKuzFmg_s&_bD1CS?+XGWf!qV2&`tW2beY zGwR#5i|%NQYRJUd%Z~EsU&v^ZD8j@w z&5;hNfMQrEHXhqNX_7t+gP6hm#R_53&;}LY^Q7qO@r$4k;B!u43J~D=2Aw>H?mD*1y@Is%gMXHs60v z>7gcxT|_2e)>gn!#TlSi|1VP3apkFM0?_;kYgkQ|4ILh)YN~{CqFcG4Rrbq`4(p#x zX|Ku)61@n#B;gLdloz4bS*|5YY|;jOjS>Ei-b80y`sT1r>H5Wwn#q65h%RYNI;?}P zDoZ&m7$xhZ$rIB&N!=LPhp-pG=G~~(#FdQfo1!UZK7cv#1e<0-=WriqD&uX`kW@-+ z$O4^syaEG2#Saw=Y`_(UVWWi_i)St7m-P$Lva4v3f=P*_ORd2%cxz=@*`FK)q(-Xu zbp^8GLU9tOe$@^~$x465=n}fxVLVN3NsO4u_F0XAWqhVB0Da2QLWLDcE!_6b8$zx4 zI2ziP78g95J6Q-)hN}OMM37N~Q2@i|I)(d)3~#f~rcc9#31Z`xRFca?7v*>Al@r~b~40>Cfa^r3e+2v&hC zXR!n7z{aC!uk?QcZ|Z>GyH0^mL9X|K00xWG24FAqZta0V#u z3)e8@K2S+|JAi*K?G}$APcggVRtx*3+x4df^03o*$6w0vWgS)klQNX;ax1d(;7x=9zi|xX zOD+@gz5?&pLa6`r6fq$?A%v!}BspftDiL_~ttSU^^AcWJo^l(oa9@@(K-J;H+*>U& z6UUy9&)iJM%v~fVrI1C;H zaK-jB_QGX7V>I+~G&~mA%ziKi3*?S5D5O83VEI>Lw6!E1=Lc$57;2{4KD4??7#o?#G1G{@L8I@1b;4vh`kvoy?LY^6%E&_+_zLZ<}uP&ccx zRy3G|YZ#W`|6HT>{mrzv%9BC&piyqMFhhcWE{sl><;!F&T^BX-5cbaMjH8vcOJ1{{ z3UV)JAkKWVT7$N}j`dKVbG)+JQx`OZaI}BQ(6fRzHf95BN8_{3rZO5MBp7N1t+c2^ zX2GCJv|m50Ty66=pEX34|{a zR7*mdnGgR`bW8hbgG%0QPw2^mYxRRH=kY#($mv5^o_N3bI96W<8CPqn1n!2^x2Jq3 zP|&yTNda^Fs)2Whj++*dQwv_brF(yn=zHk6C<6~fshwd0UV<3PFw?q<~u&BGYr{i^=E90qGdP|^(tB-%{1K^$H z!MfYdi79ojCXYHl^yRAG6{yds18jP#7yH1P^{T-7uiLt?n=ttfdy8-2tP}h9QM)_Y z@~^J~|FpBjv|~W6{_w7E`$|v=9*@+iJ3H6jX}JG-x0`yf+uXZ5c2rOMx5s-^hl#SA zj=F0yQ<~bR$GW_O7;M(Hy|aJHxf?seC%nQhJi|AthyTez!WcG>0XS~LL z+yZXAm)$GFZ>-0M3UMnV$T!=>tBS}Ug>#O)%fCF#$GptX{76B3ahs17%tircCC&G| zzE8W)2fff&EQb$$sC&+>b2?H{e8!^(s!Kc4<3i4x<3%KU)Z5+xh_i358$H)|z1M#| z*n^zSt5`do5_pF_+NZtRgT15t@!G#V+;h6wFW*ST_u9oh-sipE?>)`Wq4Abafi48P z^F9CJ7rx;iKH?|-%Ljf148G}fPVvNm%sU+fAM>3CZj+5x4-+pzlK{KsroIA5gpT~O4Wf${(B#j z06{=FBo>XwVuG<;K9I*j^f{$gt=FTH$#7n!Sg=sb>=qk_20^GmW5VEbdfk2=CWiMr zvSloe5wr*)3^czyD?kIm07A4R2!;Pc$*M1Zq{^YFOCn99IJE#a12;^7($a&;RMl11 zR@Yb9SlL^mRfr^ z48Ao~mFG7_uW`#vYje{nNDF*oe7dTo6R~BVnB{t7;IXKW;^v(2z~x(Y`A(FZ6js~- z3KK9SZfq`*kQazRcqRd(#v)+l3D!MCG-dGN#g8Xn-u!v=>D5=UjI)5@V77UGfu2Mk z4*XQwZOK4MAs`E2}x>3~DGscnp~BLJTw1FqPa`W9uid zgcA+BiWKbayY*63aYYtebn!(PV^rx33M8nYummE>?#6X0PzbmpPSbId3S!H#k#CY~ z!wzyXID*L~8X$290td09upa+^t8!pT(I#**$S#>Wi_mZcqzTf5 zW3I}C>^$=d46Nsq^ zF3|AU*$AK@(E^U#h>iFB6rzES2C(4TY5xk~f>WO3Zps2nWe^`3%Qg30bkkLLU3MEo z$08yyz!DuGx!UfSdBeHvw0y~8wmM5W6Ahh@_;u&QcSj53sduMKcpC{4o@?N6#trwc zyYfPa;%6+rv`zyW#d$W@|$pA`7-Wdj@4BEtJt z=ju@Esxt)J^xgx_kx7w87KGZ4IPYR%i;mgc!?WyR#A0(} zU;`caKnO-qg2Fgi002lj3p9y+^-^9DGRU<-m||andB9s#V;y`92|AqV3HKg1LX5p7 zQJ1lX!hTnp8j37|!#RM}^0LDhCQVQl)E2_z(L#iA@MF7w^PS(Cc&B?^FkZ>K&Jh48 zj{zLOcB=8vaAY={C;F#^5CY;=q(?=Q*ry;hDaRNqMYvHQpmvx#A2yywiwb%zPW4Nc z6p!(aZq!jU(pecQ=4B{|=!Fr_SsN?#2(t-BQj(LTWF;->Km0QC$D%p>L!j=4S~t`blkB!csdq)PuC(3g)xV@cH5oQ7oPeWOI5 zGT+cLXyS1zpd$buWkW=1Y9N!zK?p|{pcP4;WJ4YLP>4oU zqKlb}K=G*&=5er@Roop6cX-9&Ac&sY>=^<=F$M>n=A+fB%SeOvuCVozIX3)M10aCX zCW_4xCsl%fHX5&FjI50iF{w>)dd4XzQYr%4-S~hA28l#MsId&$miW}uA};d@O3fyg zn(>r>G8FZuSk0;bR$+2Z9i?-VTNxf5eTD$I+JcesuxD%@=Tt~`Zwy#v$9ohZ5U%~i zrQP^QBTuE!d`?uci)CzM9sAfkRJ0+9g5-~uicQLjtTX`9-9?jdtV=QPU47#$U1hTu zoer%aA4Kghg&&RUs&f$cw#`ULDruan8FTav)wJl%efbP1Ih ziC7ujm_5@EuWD*+e|uJ;1x~Go@ESukS;vckHzm&@Y+Y#sPz~NrVqp_Zj@CgTHIkL|z)Mf>_wc zi&q?$8k(*riF(ZvKgbSH+C;R=X^4zV>>pO51g&(@ZgaX@qT6EGC3B@;U9I%uM3N&d zV@6^iC(_GI4UIMRO~q5P3}86NS2Wf(BwT)gc|BM@5(@jS=>W4qA7;>hv*p1W z3#@ast$l6(Y-f8VceZk%_l8f4nXz;j9%xuH8Ytm%bU2Cjc333az5}YVd(bvCrP~Km zQnJ&w6ZxQDJ&Dm=@A=a5j)=EtN0wO%T$6?QtMNXa(+qVK#ooFQ=m-G-4B>m-=}yJ6 zZaQ3BOgR9)#_?vf&HkLrX!&M{r)8Ae@RN6l8roJY`VgD1+PGgjRx1)XTgMS0V z#wj63Xa9!eUSq&L^-k|ez*DZJQI2`f+eHM=Fd}vxF*HNcZA{DX=RS9I(Ov&~*vFpe zM<>j%ETB-}5OxZQ+TXmQUT&C$$wsf{3Iw$A4Sv?1oR1j?hqJPKa zV_^9^9*!}2(%|fGe=WLy2X4&+6Mp7nio{8JW*3vpZ|xT)8q`^U1s-65?Y&>&-02Dc zWj?G70GtUEGbEb2t%8>nYbxbSzg8kZ$_MsQ9aKB4?m)|ohczTA%TQ-qEyV^1<=fj7F@j8jYgstH|s(J?Y z8as*c9WII{aH1Y8v@Y6ui*5ipD@vI8o0@_XA?aB|vyi@nA*uT!yaUPyy92{BY@I)p zHZe51p=pK;Oe@rXdzTTP>8zQiZ7n6}gFgZj<_!kIZG%d_UXPXH7xPlroMzfHY z;%db~@x@v~Ir#rG9WrP>ciw*vvFmjAW zGW;jZi?B>fGC4>_Hw1$$nz>c%NRRwTkYtzpn-T-Df?S~{Nw60CLnv(VnG1Bufy|DU zWJw7a!7;Rd$wNSknw$htLKzBV6qQ^^p_C1kj5ep>yGhVVoU8|EREaAaNy$)2OdQG+ zC`zLwfC*eRlX#{G3`wv2O0W#e^`NoTXtb+jEV3j9mr9Sdj0w?#u#^}ykSx6_6id6j zOT5g>#jqAMQVT_(z%G$9zI4K1fXekS%$We7H(LpRxtzWOv#+g#ZbX;I7`a^ z)HWW0%eY*}%=}Ey3{BA-O;xzK`@$8{OifpaGSzHN*L+Rb6w6wQP1>wY+q_NO%uU_g zP2TKH-~3JB3{K%3PU0+1<2+8}OitxoPUdV*=X_4+j85sCPU@^q>%30v%uemxPVVeZ z@BB`G@C;A!gp4R?u7%yyR4lqAOvSjr0^F+f#0d%LiJhbb zPI#yNgo0ZN(6hLN0xi&_G|)H51YK~@k$_N4NKghf$^E3tg+zb>MHd7Rf%SYyhscJR zl#KFO%%Zac@nTLCC5AoNg4Qwzl`}qDfW@YNNQ6abgcq%a7?sZ~-~-I$6i8u&LjRxz zPnZKykOcf($uV&h93|3C359Z^1qE%1A_WCHn9&V=LZn0tlj@gQ!3Z%6fD6G$cQUj| zEI$s^zstmifjKw_AybmkMQ`*&&J2UMsEde1g0Z4V!5g>uQs?-oDff4Y~BNzclEddcI0!`&qPZb754JK_! zjAI0kEV_Unh0)^^!b)6`SB+Km5K&iXRbDu~uKb1esD(h%FQ)lG9o^C?=tD$=5RS|b zacNLwlb>Zpy0dszVDQy6Rf)6-!dCEqzj1t)W|axcBvij4*HI)x!UU)~byIWy<)?)C z(7Z62{(wW(`ioTMr59UQbs&p-wJ+l9*FykU;%W-6ghb1+E<{C^asAa{(9}wuREKrc zQ5}Ma-BcGE08rIb6Ci?$9RU#4h2DCGysK4~;MK_}q?kb2qclYpQQ31D!Zss+SzJJi zo?zHs2v#D+k7C^goW%mII8)4ER<-ljut*gT)VWO3S`U-jZw!ajh+5y^ux>D>4pRdft<_}I zS6Y3wyJcCW<=ZYS)W8ket?)2^4g=I=&n)rku1t5VMh@M6*q* zHKjQS$X`DlU_LWo!CeOh?%z%ORKJkf{PYm3Y)CINgaAf{fi*A+S^; zINcE7o=1fl(hUI-CIAwD9s(0)+kOy^aRFZJqFu=F-IdT`x8dOzv0=vlAYPtD)>c5? z2f+mkTB7QQyDtuM^jW|HeRJTh)Jw}n-sR%Q_ri6sINcwrZ|SR&xuTp4B2#RO6& zWe`SPUx-IqWD|jKlNW`O1dtLBY6Bi|mg%4rVi}h#>cJ5t6TcD@J&+X5`B*^64PRc9 zXbDo0v8iF%Wl`vVWz?h+G~hiqInrb{0BgZ!NWx`Zp5}6nltkNRa{uUN^CSRHOJr54 z5o{KKXCY=63nD3rew(TcPJ&?vrA1AsPv0 zm7(Tl(PtVN<}kezS~kWZm9|xRJccHRh(=PxnUo-8DqHb?D}CmiW=Uvh?vWAfQj{iQ zRxo0OLE=?m;1>PTW3cFwCdiupB>X#PC7C-T1L`t@UPP|a1`Xd@5$Egm4qy(GBj&T{ z#bVSLXk2b*P8+TPID#*f{fh`+U8hTcI5!b z?OzBa0bZ|7(8Pi{ny`|XQmeplc)E0S+muU~m)Q}2Qe46ZcIWCAA2KWhtA*`_v9(TY zL+{=~2V2BInbShl(rkr=DcoO8j9~qJwj?5$a~<#WuCD7=Zuf;-EHjy*BJQV#?)|=Q zFj&}~NzrY2m+3B7{w~M$hDatfL7iplzI#{vevWyJaPr=8Ekqb_+&FhN))LHvFSf!5 zpTod^d8r-SS%lQ;<6Z}4<;OZ2u;-5OEgk~L(J}60?(N1c|Np*lZ7Ffg9+M_RS9P0= zpE?cFk=Jir%(l90D^T)trMVtIhkJ{M$hI*A@22*7@)m%B9>~+3m}JH38Z1?G%3H5YR8+E@hA9?LmLq@!pZo z;oi~laPnams-wbaJ)aPlZG9H?@1hlBLrNNx4npU%1~(=nWF5T8g- zB+pSy(UIaj(C#y+LBVb%$6@(xAFt0Riz`3zN*NqcojI>cooIU@?uCkF;miGC6aHX-QbvG` zJ@ns(W!&!V+va=U-UakpXf!1*h7ye-furt;qdcM+`u_rY975ck+M+}5H{9^oRYe1U(z|sB<64tq= zGQ22wi;{hJ4GZv3|0v{e_dlV~Utlzcniv8UqVFE$-*RI(yeSbdigcLS#Xr>I6$m<2?eorFXR2MeumsJN+j zwxz9KOrUjWjl7Cks&GrIqHR#3pMrnIdJ=C1dd_U4(pQqi-Ob0_ei6YB80Z*>5b5Z^ z022X=f@A;{C;0jL`~3ZX`|_0jjwQ)nLiI19M=#190R`$$>lb#C&rSkj_9j{|M1( z%w8K#09eX{d9#g7Ek&o!yi?BU5t+ZVW>Cg-D6>YZH0;u8L7WDEpTfLmjRXxOva?yQ zHkwyN(o%v(;Er)iX{#T>L5&=WN;cY(H`@NFng82ZZQQU$mli1bP03ouY2d7q!)CO>mAa6%REq9j07- z3HpJ+ivsi#VKV zZG0`@0A~k(>Gj8?o-_b~sLgrm)`#$1fPqjDVs?pL!4xv&ig!%5Tw0$&pewHh9f}|% zDbCl|5yGmL>Z&p-Dr$}kQcK@*g)wT9IJdDEtT^2|=dFLgHnpo!0E+6ELAsdP=xHi? zN9S?&9^}j*Byt4Pcj0N3hYne4KZy=d1#7*|u0v%UHulV{&>*Vwy3N>ZoGA`%P9 z(JklO^P_(k)FF|y`M5G(|G`We;Sl<5)}{tw z?yjGh2CV7Qox)Q%f{MdT;Nu`}Xv-S`X7(+10P7*_!rdWGFp1VEP}1S>?#ds&Jv(A- zYskXeJFAc&%(;r1zk@jAcfxLoS&Iw))9e|4Q=kAJ*B3;yxlRrL6&fGQ$y(@aeqK3| zmFDe@=ZuqVPKtpLEq_7mw>zKTyK@Hr9t3DG3i$#871+^sEQdYS6%TOB+aGgi7C2DN zVq+4tml`M*3PwmSC6&Te14fu01j<1I-b=8Z^Aqi#E02`KOheWg?455{TA$p;RNyA}Lf(Sb&$|8RA08AYOA`oA2Q6Tey zjB~n1#(t=Wdl_^D+5TXqEM+7iBQOF!;CKWPOsOMrgWE^K6h|Z2F^_2^M|CpgzTVh{ zekS@+@URzwMmo}w^%I;y`c}gTq;HUaf}~t~vhc`99x@q;gw$Nd1GpV&FBHIOpC})Z zJe>g$4fRMsCm%^5N;WcmOla5}wEy@gG@{Z)usgs7B7m@3=?hT`s*wKn#h6f@4^h!7 zmeNep$~y3YYR&WITB7GnIXx?vuNy`zX9>wuKJz)XjAkUpHy`kH^HI1w)cTTt5eQcG zPcfV%Ck6xQ2t-C}gUkZn(D)gN{?#*grwhdZ%hL(xHDWu$)F&g!S-bx^BAF`Dp9EbP z78uHGdITNNDiUB%YuG_E^`YF&i1f`z+^$5ykmkHH%2_GyVrV>~zRqNSfrvmEr`#eIAc?pabPFn8}j=ch-lO=8Occbh8SgL4{d&MN7!w`b@mKswkwy28|YD z8HDYqnwuk?6fK%LMT%{&11*ID7E{4VXfv_IA)cjPNz?%VYL^de+PQ{*B_F_92eK&X zTQ7+UJsgcrvz(QRT^G47bPlL6ITN2K*jY7Sg{^4E9ggU*lS)If)n9T&)JRz+Q0G3k zP4v`>FNjCL?lx4L>C(e)lh)cloK~G;d+AAIdI_vvmzrMKr<~*>EWag(J;j=peiz69 zWqISi>xy0*Y$0E7_~-(E`_(V(I2g$&<~PCC@UKnu6u$(|D#DS`*<|gPrw8vB!w!bv zhW(TV3xoJFkBE(c`4G7%Q2&*TEIxwD-m8Z-`k}099n;!$tVg^2kp!+;>sr5BV1oV? zUVx3oF{cHqYUPAoj16jO3O8bc#`og4QrrMyKn(ju$@IJGpPL) zX4y0=ODr5ny{T=t+KJJa?9h812EPwfi(bW3jyBf#^W6KF@p+Pli~`0c^Qsmkwmb@CrsTE%ij2Q zLW{A)JnEe-n}`cxBz4V>789x39V+BoNF`r5vYm=bZpAG^s?-(sT&^HFd%w| zbK4ZJegTDph$i2j7YNayg;!(-aG*cu9z;^R)U-4b`w~D?sp$2 z2i0&HLgDQ0hwtoncMdXq8{~I}iC{7Q2|c@X3`u50v zT&Ah+F@PUE;gh$|&M*FWhwM&8-lTx5mMev6K}lQt_X+54fD72)_GZ;K0w{oLfnydI zRtX1I5jO%NAOaD0Ry%fac=T}lQ(wCBeYOB~z9$gPwLunuLN8}M5-?p)wgwq+J8@!d zANYNLhhPUNc!H28T=wvRHU(u~5CQ059)7cL34{R-&;>*@QWuzfK(cb|FoNv0OE_o& z&bAkM=7Au13&{8XQmmqcA6OFYKy4DRg?XTKa-o9fAZIg0Ay6j?N|*sP=vM`xD(7HR zO(=U6u!NkEbuK3hJ}7)%_YTj}7Rr(V7|?uw+0i>N2nULz02%Ou(UNvr!2mV%fvvKI z5}<`#I23*Ohfr~CE_H^8s8Q(FNElIwhgdS3#D*BCmpi3%&iQ|=1iBch$C^hJ2ZpvejDaCS91CSBKJ0k{>s8veL(L4&^ zbBY&Xc%Xk=lM);Wk2@wNabtiZ2@(r`$8c#i03LBAUPW;d=nyHHUN;3YppYB^S%>;~ zb``=wE@UAx=0NjfHTr{-At{k2Wj`QNgbY-WdFF)FXp|M%8?ED%Gi8sI^>sQ~A?Y`j z#|JZN2qI?omDW%xbf}a|ARKc}QM9G$F0$){Wlk*~fZ+S_T zIk}ZUIbRjhipR2f-w=4RC>MSSANy9Ajj@;50Xt~5(h%qfFXIjjVKHU_g(3 z2bE$8OtfWZUv``pnJ8Y?oN?)Yl@0WdG*W|sDUl*}og8;nl;HrJwT5}%kyHhqxA|2h zi4RsHUslo(GihT4(2`^Fk{ZySfFwT%uvrFqYxl`nzM^Wb=^Wv7J%=N2-EWCc~HW-@w-rersGMy4@(!UAlw`7%mq6KEwhGu^7J5)gmSdaU;H zm}9vAI`JxA+ls93>NxXSo}_fIS64pNsvkI-Rg-9+11qofniu0rW1=cv+9|6To3R?Z zu^ij69{aHXc$RN}2C|unm?TSMw_~m+8?B1CvMx)ouj5`XyRjncI4x_2H#@UBOCaGw zTRZ!+KpV6|JG4amvo-spMGIZPnY8i)4cW@HB2!&ZJGI~H4pghEM;moMD^yQ;wO-qF z4g0lXJGNw7wq~2OSu3??Tc~RrC1+rHZMz(58@F^@w;7v8wR)Aab#@5zXSaU)w}2bC zf;+f>>kPD7HD!3VhD*4N8&Z_oxR4vUgKDx&l(>?6xtN=|n!CB2+qs_mxu6@mqC2{z zTmP58oh3$>=*$`tf4^%A%>};XTfXLdzUZ62>bt!zB(v-LzVI8rcI&G2Tfg>uzxbQK z`n$jUt0bimu2D-R-YOLRTfhd)zb-PsdZWPSaJaS?h6#I{XwtWVHU zVE`VyKdL5S`Pg6mg|CpX!K8r!9(<6B_Q6l!!2v6|C_J1le@q}V+`%<$!zA2a*LK4y zoWs}Q!z;YNyuv)Ekg=vPGOrOk(zL@S-2X2}e8ftjz#M}>?FzskjK%ykr6kP4W)i~g zo5V)8!?SU~W_-qIoW^Qwz?0Kir8pOFEK@ZaTh+0~c6`VC5C9v%0esxYeasSm43|gH z$3o%9hRgvSf8ZK>?8hL0s+sSg`dWY#1Wfvt16HTm)J!VqNv20~8WFKLMwOyMr+~b=PWFpEbBbGZw zR`p+}oI&{`!K|4#p*)+-%umXM$JTt!*qqJ#`x$}rf5>@yQ9HU}2P&Q3%pKZ%&i$*$ zhy2F`z{qVt$b-Dje4NN&u*ino$j%J^Ig%Vml)OLIDV;-GduC_L@)OO5=`)SgS0{nX z%X|{4{L7Kc(4Pu)u-woN?MSq2$`ie*8tuxcc4i;FsurCW+`~l*EkUDZK7lnLdOOh7 zI?@ESe>aWP(yd|8N($3aV$v>#&OF`IK7Gy$xg#0;&84RjLNY_mHPq(((@ZVN7ytrL z-N#T30*PSA76Z>lAk|Yn)wIz8>B$={JFuY2pDWQGy>=D7*H0s0e}H|<9c?4Zw^|2HaJ3A@!Zg0STG!oB zX%5BG$(*;8+q8E5Tr^D?HvOB8o&Pt#(bT4W+Nhnsq$$*gO4L4+4=K?Sf!)fn9RR6) z+y1)+^Zd?!tUqBL)_TCsM&Q*PfX@I}UtB=|XHB(TXA`lfvvNJqxg5ZqJ=vu^*t3nw ze}duHe~`v%fxoeuMu+XTi9IqIjopZi-cX5O9}-->465y|#U;D6$0!cb{Y#krv|l!s zAr;@M`q^;oOa8sqzl_@ke&DIibz#abBWMTVR%c8ML!6M^4IWeoj^K)n$h;lM@yr2* ztl@tE)*xQbBW`=4b_f4PEnUFF8VAD_f3ObspbrEvLc`>N@wP)yS1R|pL6W_sI`qRZ z+6V*p2s)0646w;6UH~i}TbFGAP4n1)Ts#5p>v#CD-*jyT9vmC8#KqyG!X?8wJ|2f8 zH$oV+!GLv7)^s2~H{QiULJqy%gXQB#J_!9gf{W2#_cv8IyyLiNJN%VEPG06cf25^E zq(5vfQsw;`9DL*2P$~zMZs)DnuB_;Te%+ETdmPc;A^ik@evjYd3rG$K{Wkz&sN@x8 z=Kzv!>%rtJ-0F5vDw-Up8{_4<{ya2J>NcL0 zgfPUh#uaJ+<&{1K{fFuaz~3GGf8`9?Q(+F|v@WDHS^!Mk3@fhd;6_`HP6UgN<|eg`6M+*!@XR6NPilHw1_rvT6ouG5)RW{f|Xf1#cUq9gp= zsj-<%5YEXknmaMa_To|H9Y#WFs6~47*J<;07^M{XO^3dbZ{F7-qpy{~zb~aGROR!e zEOM+V^aMcj*>Uu*mFVj9LsFS}k$&Y3xzIar<-_*gSl?P+I`#h(&Oq|?p&3T|M3IOJ zGtXh2hKc4g4BCBBudfQ-$#0_FjjAnFLh-j7iq8BvSv$h4&Q_%6%)3 zqgX%X#MX2~lBM((q$z*@v26vZL_%tnuTh!r??O@`QWf#8|N8s;L&j&D$Slq-3h}Vt z)Dyqq2!PcX&jIa_4o5)T{IJOKU4h(p1TRL03$Q>#7k$lr^S!JsSE*;z)}cUEGz+jnw+XAkc!drssFli6^9Ohi6jkJ1AH;j5~MV;u9S^sS0Pk+UtOy#@T>tSATf;% zo2j-J#DzB(F}Bp47TgLRm#D2DbcYbiPaC`f>=G z>uC}R&_ya~y3E5f%epNV862{huTNF0SFvW*x|M5JuV2B2(Rmw z$Spa0LGO3dLo#T@wgC3)ZxcFHJ5Ryj&|;9c117@^F@%g;5SJk=oRG2$XhJ4G-J;Vk z!~ot~A`T6w;xDK01X2Q*QnbxITqrwZjgAyWST!eCh|E|=6L!k&9@hr9I$)-T*sH?Kf2Ct*eD4y{9r8mzO z?6AcM+ro&IGymJX@W&O|lmfdE?Gv&W7Rj=cOaIClLqKobi&WA{DXrAf`a(Rbvn}$> zu+u7-k;;rD^)&I)Q&H_oFTVV$;;_B?T7ofIe-~41!VL(^Lb42bt;KojlrZ5jNbc@VkJ{fAlCca_t&svhvkQ)WMYXU|uiOp}jMTJ~8+g|mW04CTJbj4ki zYC}s$WFLJ~-XO_ss>8CDwT#JT(e06`D%^WfldTqsHh_{)>@uhT9b_=efGGy|Ndy>R zf1p}YI5}%FjHXoZ-vTP;gx@TD`4&WY!+dg+fqxZhHi6^YWLPjQj)^;R7di5hYgc0w zmnHLq&setqX!Kxnoll9&oxxfc|rjSY7t$oNj-Y4g%(tRZzj5C z%M{hbufU>T50AYtaZDL|3KS?=@sXhjKy44)j z9qfL;1bUOK<3yB8y!8!xP46Ck#P+irSk9+r%cU2A`_}^Ev7h>O&7uuZ!f5<1F z`pQICv*J(`CKxYfF}Xl!trqFM<#}*(K>cwYNofK7QCBh_8BA%~SV;NKCxEumCVc_a zLd-(en*Z!=4;%&fpPDdJJ_N=G2|hcN6y!%L=zUKU)3aaCxb%gGU~oi0ieCMs_QCiG zEejB&5Ckz13KxAydo8q*2lX^Fe@)nM7BT}^ZT{x8Qgx3c074CoD99!Iy-kWSY!}XS zb3pSA=tD}p9}}AxJu0ruUQ@IU3@7)n5^4kj8*G5(;21|a&e09HW6-A3(zqjX;xtyI z;~(GG3s(JQbI2H^=RBu{(?zCq4h$FqBCrtyY())tT-X`A6sHRLVoQ&re_?9E*F0&} zM0i&d5{+bMiU#p5U*O|p7Aje>0Td&FlnIgbnAJ(~e1er^WM0HVdAqkjV`7d}&_j^t zzPnWauqgAOUzhrKN-0?Fm#$>mG>xgpExBU=Iur=&-qJ6SWwT@@u_Uu5IHGIjuqMOg zArE2s7H-uIo+#Tzk%oa7e-y4z3j&myBK*&JaH_K!k@x#E2|71r3OX z@to`v=Ciu!ijL@VW$kmQKuKB6dzv<3vWHb@I#KpBfTGH;s%zL72F_Z1t4qAe~6+qwdZ+_CU_V{(?TORF-w4CfjcAGYGbqKldZ|@w9jVovxssX z7x&DX#c)2bo>FQW5m;l`T?&^I!^CG1C)!cHj`M@HYv{flhS-;iG@50V=}DbsLD)v% zxU~scM|er2u2IxkGbNN0f$83%QB8D>$ewn86KBe}+oiht$qq#fma1)?CHf zU=8O*keQ>ZY97EUtZsl4Am9rK25Ilmi zpI@#em3@p|f1aLzWbo_PU%88B1x@A0OB_ZrpH1fA+ECNR~D(dtDGvQH4pQ6=?IZ zZH_~BgQc3{1a)=9B_3plNi63D@#~q#=*YMFNWrX0_@X}hHQDmUi9Rs7u8mFJcmK~l z4Eud;V4-%PzpF=BfnN`m5V6t3Y*fbR-uZ5i)Sxkq2E>2Bct!(5I=GU!HD7Bt$fy%p?IV@5!NE7kmt+|=|3gcLvyeE z=DVh6cs4SPg10);4jHu3X??`vt?0hlSVgy>nO=Cetfs)!ZNA$X^ciJuXek#pvp#Wf zx;^TsTi@}!g^urfUUt0Dy7t}ieky0NRl;LQf1`oGlVhajox#}#cY;D}s}FMmFpzN! zip6bV_7st1TKU&NS>dgD95)$w^DVE%x@yq&sd#e5@OSGiWxruwIS!4S^Mv^Sc}JGz zib)?6Et{<3qDPJW7D7rEu%jP|6NS}g<^EDQ?DKe5&U*8WXclD)>jr^>~ zf9U)~YZav7$rfaMWA2#0CEZl@uT*h3lp{%*W;jaD?p(e@W5(5Vglw%5KJ)7 zY%mpYPzHS}06<^~9b*HQ5Cpy;k+_Wm=pd042{53r2@5Lnltg~E0VlR%D*t{<0tDfE zgwO&cKpc+d!6+aDzC?L2Kmz2jEYMI63ysS*?+#W+h%75J0`THEZ79aD3}xs5e?Bm*3vEJ9`%8ek5EsPqo;Bv=T9AZr1=Fp}10EyT}}!m0x5 z&?4BtJ)*$bG5`ZEz!II0$HL%(zL5Hgq7#|o7V8lEIIJ?TFE;`RCiG!UHpLLo5c@a{ z`*3hKmg5uyhy!!R5b5hfeDMKtf3eG^Clj?1J-j$)W-Xq`OHR~8d>Rog!NnVp3>yOp! z(uEB3LU=3e=+Yd+2ycvMlH@>W43MMV5Mol3+T4li0#9K!VmKv8e=mWvGKY<^07F2$ zzedI=DNh4sh($v4FZnTA!YVh>2|LviJ<~ESi4it)VE}M*D4DW8?ehfMfvzBoC?V`K z6QanNkv{LUa-8xhA0sMNtSVK^3b&vM8%ZmNN6!GknJkYo3m}=O1z2R02&!{z;^izw zuR9(<4U6C-6_dBBq`=ZeJAYTSC~TxI4WL7@6J5??o&s)T1n#@Wa{_WFaujN6Fa{7_ zR1@}b$WF@u8u3JhEr6~O5F}+pkF*t~&Hjdz306~Md?rX;bU^m-3b0f`|C~fNOUBA_ z2|kN(=XOi$l(fyJ@%OkOKq0`Ax-=s^NCK{OX`Jc=-m^vjlQ_d@n158{A)JAqz699% zGbGl9PkjhVdCNb*ZWHM2y;dVw;=m5}wB{JZI3AUc(xXYG6H||pNBy*)NHmJ5G-)hU zVCztEye50eiO^*1qqGUL=z2eepw5<+_<4$%-X zjI~+8LIZ|xMv=8Y>VHsLWulvwRgJW<$O;Hst(9WFq%VK79*X>$YMqD{|V%KLK zGh|!0U}dqTWy23lpcbs0Ab$c3He9GS%kvydmE zETp(jY=f2GRH8%v5V!0m|IhS>LmwCB`8(DfF*<*tlIfi*TAPKTIc~iCanC)gQ zlz&-dk@=HBkdhUIltBSOOxc*y5zb_2l`$EWy}8wbwKjpamSH)f*tD0`d7at0oi+HE zXSSHBi&c$zb^~UU6OL~2S)N^)wyar{J9CQZ}VR_=5 z!^oW}x}q)mq6rwDEkvWqgP%XnqtBxcqJK_juZ?4Tn$prj0ZQS-BrCX`lo?9sD&DFhpG)LfE2zMC zB1Q?h9G*HVW?3Nz8E_*hr{!a-sTznTZ2i2pZW^F0&fsIxa2FT=2+f*E*;uW``hNjd z2d>F?wmv!$5I~LHrmV+$s=Hc&q&X1)nqpMCW*&`>GqHxS+EV}edi8^l{KKKXK5o1$P)2vA&_SPJi8qD_^JQ*+RcWd5%Y4WaXYtld$)`B zP^IY#PMHkma}#@$3I>xkJ+drSDSui@t9iOJJ5HdWvcgJo$F+BAQmyl7!xof|yQd8s zaJ{-rY32!@`{fQhlvkQ9Te>iPXgtx=w{0x>u3q%pw`5FgX}n2#4Vh!g95#A*+OpNwrc1l+PjVb zAwL#8fi#<@wQjTOTW<%v?2slS7y^E(!5Kew)Lxay|5*W{y_@_JJj}&>%*lKv%p^oe z55n;ed;zi-Af%9!gh^(3mVfYMNrg^rIFrxl9L~2Os=j6)N<alDL z(#-L&#`ZkCEOe13uBiNz* zQkB-&aTa5~lw)dy#*cVoCq0GUKp#-3mfx_8t=)*nJ%9ZEZVq-EUSl`8VYeNHnm~nY!$@DKc(eGSOV(CL>xXcw)JCM# zIhh5G8JtKP-+8|0eIAGPUA@ROKmpaD{ObW%GnI9{W|Q8y(o4*W=Lrz1SCN+rt|H;t zO_jWpHlY3>rrtj-IeN=hu)cfJx~b+>YUf5CUrW9n@9+y=iGRl8+h@N7z+;}NHmYo+ z#pcgy?dK5j?;fA9%Eg>4?L&|DG}fAJOn9uS{pUMseOM9x7^z97pD7)8jN>kR|K z6(YY$Y3M4f@9%PMFj1Y9IDa+`?6DFIXEF^P|ND!zTq_bJpVR!FaogMNc`oknNR5Ox zrt)6wXN(2;-hXw)TfKk0@Rfi0ncstLp2&Vq7<(;QYHjjAvies^O*zyFf*}$~+R5^? z4=xPDzBS8Y9u(AZwv6H6LL^}hYtd=uE*GKhoq)`+U*)o$}Ezu~N}Ce0ee8BE`K`O>hBV7y}~*@ZK^{ zomv0w!Rn;~su8OmTe~4E<2D2bP?WZ5Pf=G%92;1)3!D3T-7+8!K;%ORS<<#X6(K+_ z;6MOEh>Tk%P)a#nhZZD=SPjy$iD7?g-Lh518$Tu20=PkgB-;Xj4o9vjWX#~GmM&ky zj45*_&6+lE;>@XYC(oWfe_kndv1EX36Otf2>BlHiZ?mMCgw_<}lm}4faKW&Rj}F{Mjzc8Ck@8M$fIS2mawB_JoYG|)rJR+TOC*(J7YKiNb12qc zRIO72H!*Y(Z6tqqS&|jl@E{ioNgP~FV{Xt&rH?LTojOMKw3JAaIt~EYEFP~6Izsp; z|7a!9-oAeW4=#K-@#4mhBTue;lu$f=C0Gb-I?wayozK;>kYN>CE)^nZ@914Scd3gP z?(*J@%TZHe$RCTnwSWTf9V>shwi1|u{c@|A zpUeD%kDQ~qH)y5kQDGZOSpvGId^tL5qKJ}o3Qvru(m3fpRZv-|A3jp@fOKmrkkJ)( zd76uyQ%=fNAqtrptgwH>5?idX$0D1ovcb852@u+yEHJN1z71>m4|2a*$l4ljab0AEY+o3GRHvKY!wKk+pR2EfTox^=29lF zx`W(Emm>{LIz~ep$XGE#2H=V$6$P@_W1W%=@NSjSP{?Xx4mW>X<)3Suye=UF+z7$4 zGt*qN%{Swmv(7t%`G5o39^y05RYf@T%SD^qu8Bw&l9XFn2#vrxD?VLWcujLr|8>($ zTjHV1H(mS|T*x7Cb#xHeyX?hc0F04fQ~J2+v-94&@4o{dyzs*lKeNA;pIf~0%QN4+^Up&cz4X&lU%mC$ zW1qeD+jHN&_uqpbzWC#lU%vV0qo2O|>$Bg!`|raazx)XE(_g>+_v4?JaqJ)%f1q*7 zmb&aYaC#9$is!H}Ahl8O0T^T;2RrD&4}$Oy|NC+k_D1Ni;+c>!9)Z_7;Bl{!g)oLv z@L7qjfI2Iv2s{$lAW{av!#v!O3O*bn5iv2uJrOa9N0f{Y6|qE1JW+E>R9o3<7_{E4Y;~fE(N1)6jk&0X-BOB?+M`~b?pTQU`lHo@r{?G{rh$EOHKuKX>>_ETb z7lI0)wa`f`7Hi6+3=N0?1x$#A>BvSBbcet&o_|FlRMqm>8ojt}Ikd&^@jy z7Y;cSrC_b9P&ITSeleAoZ!%I@>4H=gDfN~!sV6(#xz2q$L7qvVf9pE$`I>yv6R$Rr zKrDxv2Jq~GbCR$OvK)ZeglR#bfZ)yD|K{?y962;F6Di7LMVAYT4uTy9wZukCYuXcF zBb6*I%9U19(iO%OOI*##YDIbo%U&THKGjcEp|x9`c90|jihy(+3YHz&1wCg;zyTaf zB~c;>tA5Z6a>L5ne_Bu=yV{Ly77FIng5n{i+Rf90wEH9PGO9Ha)ulwyYh9I$YE$18 zgnP;QE%RnzK0ovBj{-5c2sEs}%WbX&o~y~uc=Emf4e(7c0D=eK^}#}*=SlU7ga|)4 z!`kXVI}rc^3y;nlLMkxIAe*8C93a2TO5VRvtYY}iwr&Oce{Hz%rP-t@c26$8tzVE#vWx|q znul)IBsm_0BSqWanE=@rjF|B(sZwOxpgIz)zDaGJ%uOiw7`8S{wv{>P6}X93BnA#j z5p+ESU_gK`hqj=ip?cj|hxU+uPMS>>bURSGY}`V`f3~(W)khcMklp$c_mmCU$9Nl| z-IGi=oh?Z37}G}3X_1+cMVFg%|HHb*!47M*qw=4XRMM-3t8_dmd}$7BdIMMZus!j~ z>6tt_531IrG7BfAJGm;*Ja4JKQlRalZM{$Lbc~kX3<5 zNZi5Qf9WQSNG*Rk$p=?~*w~vrp@eQx0v2?dDqZIELiyIey7LOKJFTAJHJojXBU!Jb zRpXA-6`Sq}$mK^V9I!cG^>((Bb02Sy(Bj+G@ zlS4g}QV%8D>kjk0PhjsX?|X#|KmnMQyidh;f0(^1K(J)n8Vkd2)M%T%z=0KnC=8PH zr55###IHpTvsYo7wTuXL!#V%vxf3nIpP}9n9vW6S)^}m1EZQlr0{Ld>_aA^C@F=QP zV|mJ{pAgQseA&6i3%QZ(*MuFPTMBFx&$K<&sVxwLcnTaBwFcr3lZGQ*bdq}0W>bb| zfAD_{yA+mSl*fFz0?YJNrTCLvoJ{zMT*4G!l@Y*LdE4_%itQZ=qYdDvjTZrLS zkYM*UA7dnn(l7CvKSgRUF3A1WEkC$mPoye-NFx zI2{EL-Ov=+0_;JR#mNFpTb+5HHtpb{1dJUdg^t*TQ85T}9YCJUS{9h1yue~AK}-c? z*Ao220AR~=MdNQtV+U5lEY>1eFrzhMV7~1lPN+lK@xx5vSlT6{o~&Xkeg?KYNi=3z zB4HOd#vm-qFvc3(@OjeEf^u; zMb>nXn)qF15_~}*K42+eNTvLRSFn{(JY69iV_sGnU;NhPbi=>o(y#4h?VTBazR+(L%6kette@K1}Wxm>Cz~gCNNj73gKL+KV0ij2}7Wl=MW5R)At)7=* zCRjwqdGKaSJwpL}|BcUt7E-bv5O$_vZct~Iq$}l;I)p?dLEyo-h8<2(60ML0T!hSU zp&CFyG$uwhWT$qLOdlcy8oXga$su-}noj{G09GPdz~@o|=6bvre=WIB`f)LTDdTv|Y?_ov z0%UJxDX?Mbi{AgmnwlWc1YqIiCpnBMPeM!^S?Hcf2js1wo<8T53DYoHK)Z2>;#B6q z5vsRLN*^Sap#}rcgiKgTmBX;%OyVaTW?wK>la9tG0l1;>e<|vI8YPXIXI>IqQ7&SC zR+aDZ*FC-qQB1z zC}fPZmSVW3e^OEeNHLZs1`blUsOwg=>$ygRL~W}Rxgk82>95k}AM8PFJr}v&i@Ek| zy6OhIM%Bcg|6rXS&B6AX!p2ERD%?kU3&;kl0PP1>9t7 za!O4vs>-UyA*!+`r}kk%lImmy!>9HnjV^4^o+qmsf9(^n>=3fatgfh$l46)KUCKH{ zSGp@fOznk|r2y#FhNk5ej3^R}Elj{E70wB!YUwaxlNDgVA{B&D<%tk{s|iA>8j{Wm zIR;jOYn0w=0}7pxzEI4@Ex?*!uS~>(?!+q&jw0~rwARZSoRUB}t);No+#W9BvWpsW z0^=H6e-;33ng-%o!4QyAB{9Lm<%WY)O~mIeg6Gm+R52sCg-&>W-iXX@$s*87r0U2n z1RHwSW+nec%dKKFnAh=Y7mT14671oF&H?fsFSuFXDwy26N!{lhBDDeB@LKN~G{8vS zs2Fr_zDX}rCMWTFZ}~25Q?4(fHJuSOq^~&EfBc5T{5n<;`V`;FSFC;P@7_fMc41Bg z>&1!DS%$3@lx;qVT_$X;F``9G^6DhXAY;}b&0+4X7Tn!(E6P&rKLWzziYrpQAf@c) zLp2wGp>PeUuGz6d3a7A^?GETTXZ{r<@iA;~ zfAy0G3a$!eo%)WvZ8^?un!1S{Hlq7lUyai}4tfaT%NO8KZF; ztMM9d|I{9|MGanqj_z-A_R5o5LCUy{9G@;;R-d>OpqxBS_VVWzOO+jmFEKr7^LA0C zCbIL*?-etz`3f=;sj88ApSP)Poz3Slf8;TxV)Bp1!~k=s7(GCx9dH%QUntV+C#a|c zr!9`u>}!0}PU__or;5hJG7WFA?L`I#_pRo^nFMM9EaB+d_F4`5u-*n{4bwzGE|a|) zl!{16i*^Gt+cLfoEu%3rCphy_;hwU&EipfEZ)J1go@pgdpT<-|HPBm<%Fk3PQuq$t~ zOr#ki@E~aB!B9iBPou2`zbRY}u^~is0)X$GJvHdM^i)T+={D_cOoLcXpK=v=8riB7{l!G08gDs` z|HkuWNXfV&35BpZgENQpR|jhFA@|p>eWhvibaz?daf>QBdbXfE4aXw4ZMM{Q@7-DJ z1ljGGItTMEFd$t#OOoU#e|KB;T)feqgttq(bG%vsdCOL9!Zjs3Z+5e{5rB7Gf-`&v zIBTdGa{hN;Gg}FVwO|WS!%P4zO85d?BZ4KDKTbFxDS);0cTxlKg&)a|aEyI}Qv9+4 zw(v1!|9A1dqBPcr5qE59cX)}rIMa1xePdONdk2bl<2s1vx4d}1f2f>uiI`hpmji54 zF+&HlNyAKpnmk>E7(-ScvYQv@inPd! zY#D|740lwGgHV8De~~qv8+wCW^Kd^1<|J6}cK70vc%tvfqHEE61kpR>D}fkD^XWNv zvaNt*da7DA_;vcM`?r#1Hhqn{X=gYsBKC@CRuK6Kr1KoUXkevl$9%~8rwh1u!+Eod z1E^Cmw{`ZWDEMeGcn&-G0F{cjIX3^zVXw?uIjh&26lbq!f3fJ&U}d{|$0Fe|qq`q5}f76|I;2 zYutRU^F-aEf3?cPybFcAlCw+t*?i8j%cXb3(QiD@8-nuf+04HRB1hCyW^UV-9a1v= zo8UYFM(WNRI3nEmM1kRG<+5*eySG#Q9hPn+lRJ#Fmn`YLoV0a~*6}XCdpFVw+%r49 z>pj+|1yd5^-}5^F+DqiN?T9b0kPa21ms2-kN(18Xe>jmQJR_jgt*in zTb}EmGs|OFQTqf;akcKVzV501tQqur34euqJ+i~>@oTdp*hSs@f%1Fv-Mc-)!@lp= z6!0g~fAl~5Dm)GPhrMhbK4&w)ww=DnB1O#D5O$}13}Mkr>^~3$ghK+x;*cPSOJ>vg zghr)PYSnthX0=U((efZbCCKoW*u`kf!^}5|R9&|4&z6XK#;k zaD-fJd~~{wn3kR^(M3QY}&PL-^QI=_io<3eg6g?T=;O}#f=|Fo?Q8I=FR_|KZhP&`gH2m ztzXBUUHf+K-MxPYA71=;^5xB+mvvAeK!3x;p1B5`0Y)T|L@tg{NeKQxbSRE0@My7! z2ZFMv#1L6DQ3@|?x?)5woUt)TA&0ys$i8MWYXT1=tfBz}s8Zlb9`%Ue$+QB%;K>ET zsnUQevwSj?F2B_B$Z-CMAc7Q^Ao9i@+lVn0IQ8(Xh&0!H#sM{HWMoJ-+gy@7CVws{ z1y3O?n4lCn5LJ|kvlwDCQAkzPFMtg=z%dkF?-|Su27l&j?m!M8dgt%WMr=q}xNm)o1`^e}5U~+;av{0Hq6Bbsd=}^cT#>O zEr7EDc9(FY%DSVVrJ3Vvn#n;xW_um=RcmPfjK&vM1LAxl0=MCI!eU1@dmv)~ zsy%5{BIH*1AfcNEZwYzV)HWJ^VQnH83Lb|%17#u_#N7Zu#sCD(Gu0e~LPX6OWg$54 zyz@Xh7#Rf7*Xi~G3e2|2W`8eTN9F(`P$FrJcD1I$XN;RM7jg>ptw4AOgdaX0Gz(RYjV56`ujY>w|XP7!#BuA^-Bh*wS-T}@4^>b0O>W2~qTz~I7Ll9s}{uU9G z@Cz1+Yh3x9aKD5lU`0bf0H#=$GEMPlb*pQ_$p3_ZIu5{09oIS<0*E&Ro3W1o)nEV* zO+h0BR7(oJo1C-^SFk4-ATSq8pb^Cpnw*6~X%}G{YBZ1_brgnfi}*|Slqj`JkdJpw zXiSs5Cqiqj@r)Qb-+!V2D2`k#Kz?JZ#S&~5#JJ6`3V>6@L&PTqK$d}FZzLoKt%sSf zF_6O-`f=iK!!pUnyOPQI^WXlx$=tM6jJwdnmDh95y*E?IrP%%6Q@@1=q_fB!ABo6?i1OB&A6=X~0Po zkY+?+VF1Y)?nxiIW;SDmz$!R1R?tM@lYpiF&M@gQQ6p*961tS7OtM88vzw+A#Ys(r zt))tfw4@iqNr8NFlA9H%XEn<vQtDro5(yk<`&Tf`7s?VhAGl*K!h8_f;%Im2D3PC7lMgfXw(_qiir$Z8| zk$XC8>qA9J%AtOgG1a)&Lf8l|mcC<?f6I)t)j$&?S z*jYp%_K02a!-2as;bA;!fZh)B7`IKJuYL!WWyx<C^sF^j0oSB6Is`-v0UvuHWTRbeHKXDMA5YGYc=QY$9PZkk!B=Eanna`HKE&4|;E{ z0!o~5;tEr8woUjNKoO&_FgO;2Yjp_VBEXj^;D5CV1r#iHd-Js|v6itfUc+LC@F)h< zwrX!n;sq)jiB@8k11an*XRmAoE}stnQ?qbcHOoQTW!m$!zLeH)g&B`DwOPd{Wg<0X z3rXotVUNXoUL^1P%md`&jnSAu1rVZ$Xi=hX6hMq8g(c{{M&ZtnLkLyar2ywrn$mfd z?0=$ryD)}07s`899{OcZlZq0rjv|fCU6B{S;7m z`gQ!P*{hMNkUOHbn7J;s_y7%SP&;E+Mx}%Nyaib{`Wn3vNVKA{+Fb+}cni`lA)O%| zR}AQ4*SB8h0n8G~Xw}-(99y)g4@GGpT7O!sSBL<;O<`|Pl$*~C+i<)K)#1MKwb6ns zYxej^ZD1=rVGS=al102~#VD`06aVP7y`V>uoB^&_&_;7LfqVs4?}h-m@MxUTs#s+n znZfYpBg_vlWh}37bhD&kAG9p8GUR*-K4%>h*)?z>oH-KHEV?7=+*6^sR^=xJ%zr3b z?(r5=V~&GJ;-`N&NoMdAOII2u$^q=^I6t83Kfd}gulNk2Z=IRWjR{*1D=c1qnqgX( z)V+3PJA?zEBen~%-MY22622~6rVe~52^0gCkRLq>zBSyIHnc!9 zNWX^*7{&0neRC$QkrzvAIRClPHCsEq{PH%Ei^1Aho60jX^lLdfY{Wh(EflkvM<6MU zQ4A$95Bsw@0zes`(=s7}B|ZVV8}b#3n#AoxxCEpES-_^6$eS>1Eq@D(x_UW3N7EPw za1#X3g#_S5Ui=<1yd7mKHV+gGEHr~k!^H`dI9{q2x*A5ygE>f20$ntPUi8InS(^)# zI=?$aS=d4+c*d%kwl{<~p(#fQxPW6qFKa{w1PaFt<2!nYIciJpV>Lxr-js9uypa)10m#XCoPv>JJoM(H!dD)>S!RIesLC0HycDC`?5Y$7Neg1^8x zmY73`93qf3NT|UD?T4 zh|4F~OJ9OAqoYWonJ|qBk)n)-=6X7Z+yxKQzF;vnxpW7~?7DtDICdy6R15&dM64zF zi+X`KG&DblRDVU0yh78YFR;u4%?KDL*S@ zO|o;S+=R1-+=9Z4jsIx*DCp57DXPPuTt-Q%HmOnovcfi`w5&}Oot%5hC!irPo62+` zGq=N;Sx`ka3&E%RN@J462NcR4L9g1YngnRG|4hBrgnvUwAhM2}DObC_Vc5?%BtiRh z(8LtbJzGwQn1rkW(Ek+27~;l}kjzqd^|3ALLmUMu`TS*t-i&6B>~p z*lNw5EFl*SP!Pq37Ijes0L=t#2bMelW$C`sghGEjln=7e2=&R=d(DR`IN97xNUB9U zJH5oII)8A}O`{~yE11kJg+3Xh4Cc&2EImkNJiqa(1L=f~>Knk*G|=oiGABK_6{{ri zY)bNE$~!$z&%zY{&=M_kXwPWzIw*a;n|#8bQ6dMu%VRRqEx-Wp>Vs^gByB{ip+hk^ zMbJEW)Pq5n24%+OiUSD6lKJ@_3YE|S)lfAZE`P)n(KYhTE%<|VS|%AyL0a`N;N;6m z^@l}#OTx(1eo(?(g+^tJ5lMvthE!DCL!T?umRCL1WG%zoW4PDUmnrpvRoJ}pnJf|0 z6Kr)kG~CuR=+-G^#NxaRB@0R0EYpo_Kq3uIIZ)HrI5`NQ*LvMW8eFVwD_8O=$wH&K zDu06|7jc^TBU)SO4jtJfx7gLiyW z;R4wv>BZ7BgJBv{nq}9j<5`teG)job#eca%rUkJ?)c_jX0(EuBhlD)u+fIN91h;%l z?;G2vlNTw-&b;YG#;DJe9adw!S_Zt*qYbjdV1Rh#4AYxZx(dC0Ws_f+LRFNM1vsJc zbR`!-*jL&=D3GC$siAyqRVHfKnC!O_W!H#(&WXiMi>(5>{XxD%Nn_jCuJt2KEq~fx z5QevHO)%8R8dT0}c(!t6AIRG~7TLz@D}|T+)tnllA3Pd;p{R%bO`9y#8v#gnrBy2& zuiF(dVMyKo9^=n^_+6b)jNYA3j?CV?a!EZC-p9g&Jqi&XbKcPfwc7n2YV=VoP~V?S zxE%UJp2b-M%fpE@J<$c*G*l+CdViy|HMrO1-{;KFZLEapLkzOI!2BXxo6QzskQvvF zlaaFmy>$(~eJnpzI!d#EM2jCvgFpq~DOH&$J#j7upqJTEwPsk6&Y__VFddS~Q~dif z5=&UA?9&Hm;VK-5_KeA!eF9QD0$eer%%#mGUDU?h&Mer61^9yaX{-8e;(z3+%c4Dt z#sjeEoj@iY1eu|QjHCc0sH*MpPYHm#$b*0&2AArifD9&4>Z z(%wksC?hzS3-mZ>I%FR4vwuB#l}}^jI0iLoU}N|TMg=+o9fpEiJc3%_<9L}n$ZX>* zI5&=>v@-Z)I}+v!A~7w@UnHI#C-h%2OlFo^<_q@V3!IWu%L|1%f|nTmT`J zVA)ef=wt#4?$FI`u=Gld1)UV^YddZG%oS0Y|AQe6U|bm9fHxS}l7Ddr9(FvqT|8JB z;vA>Bn}9)oL=_oIyCbeMP}%e3l_b_UXHcC zb4FADzX}`_(i=q1*=(i3h0f@PUb9RdhLpbK9;JhCo(K7o6`T}Tm1#<2IJ1FPOv0aXGxB+IzC_uTP~s=YMz+| zVA5o9Mon^F4Yowv=t^e}8{}W{p|a(#|63 z4C&DB7{LZi`GbXrBA7=|N4n(L;}dByJ8g60leJ*EL^cHM^Ab$P>?i;h%&mih7|Do^ zfdAZbvZI4A5o5B+CT$0Er-LD0N2AwvwrG30Zb|;!1$5_^OGV_Sn7Y}S=vL|i#_p;X z;98;PJ7f&Xf`5hiif=s|7z~48^xkA5VC!;D2TrgB7$bu)Ws>AY3Suw{Ux1q~YwJ32 za5>0{qAr-4XiP|uga=0ggxv4|pKVr^77RaDOK?;Z|IJ{)hAz8>DO}DLSMdhtgFPtl zJV}C|P%4(#@O44)XRYy#fCE0?QrQ)@_!{~@+Nn3j)>7?jRz1PjVOQe z@*>wK?}n)u2rk$1F9-857xOVE^R2M*AASTX7mYJ-@@jbTGS>z#_XjzL^E$WlJIC|? zJlAt^VDk*$bC>AzB^Tl>|8ohKX|g%=LRa)fXY@vQbS3YboV?>l$B0O$^h=-R<2DE2 z#`I42^eRsW^-ve}Q783MH}z9T^;B2&RcG~9clB3?^;nnnS*P_{xAj}c^<3BWm$v64 zD1S%wAh-5x*Y<7a_HOs~TnCmj{`PSv_i{J)YG)vNb=Ec5NAMbOdOhl)m;hbt3!S=! zk1`}F+3MFl_kQ>He+PJ6=V_{z1M@zI4ES$R2p-+;hD2X*bvdGg_5=K4se;(j*j;HyWxA~i2^5MjW zz8UgvAbI@thL!(@ls5{YhZl7VNQ#enCdK)tclxJ?dbzL}*bW7rPt(XKgP#`%qi^_( zMTN;|c|+j(ZFu?Zk)pAW`m|U3wP*VyO0}lSZc1j$X`1XTFsxWHu#XC=Cjt5ZLVqfb zQar1NvA>@vaJ)El%C@p`p9*MJEVw2zt|w0^YPt^*osuec%7BGxF}?>dl+vw9?-KU5 zgRQDZjIuRjc`PYOVT}75)t{!s=A@XaE3P^k%f~8xzo+U%%y&Zl);9nISp6_AdqQOT zZBX;$NB-nj{^ie&|Jx%<Yh>NuQ4Ufl9^t%0y&+GU6zW)yxC^$%1Xp>q29)Egg zP=&z8Ra8N7U;xm7Is}lQa9~zTCFhpvwXncib#RLnd#ixPn+D59jCJbPb<_(`2Q0km z{2CiDsPr3Lbg=AZG@;N;E%uA+wHs0Fg{<%p@WlW}aVD6=|AY<;0=o%G_MItLtzCs7 zVFD~u>&B} zn1eSD-XZ*nu$0iDM2i|diZrRxrA(VTeF`?{AP?d56i(hmLei{xfI(@b02 z{9)W>@7<_RiPtduB#0F3o_{>wPv*HbpLwsLmqcT{aRd?q3^2eOKHpfDmpR8M$J}bh z!6C$LuO*<3c(xJHnux}bNZfE`xTc{@awu4iZ)tRhU}GSbSjCCWb@m`e&Hd2)(F@MqLT7Pm}UhrRQ1uQV- zA(7$NWq=52`5J1mS&8M9bk>;=Y8?tBMJyBUSsoLMG3SWC7s;*21?BNjPTX>(ZaLn{A>(B3LP2f3g;B}YO9zmL>QA*U%y7dFKMZli z5>HIAa7_64VFVg)yfIL#F-x1GT^cKxulkfZkZv9#@DVG7P(VwYoaLw(9&HJ5jI+w? zLg5=NPP|7hViq!Cr(pTULF&8f2wZQmliBMS&KuJar@q$m8!FEz+g1nDS+fjKE@!;!1;K| zE7!%i)tYSz-Y#C_(9Q`_)M((}K ziyQ_f3l4qs(oau)_10gHefHXK&wcmae-D0t_~M(1c>oa{{zfj3KF<~{R6ayrXKgs+}V23E7XO7KNqYV#<$V4h~ zk&JAlBOeLLNJ>(0k%52(EC7qcVS!D555S~(B8b3FQs4`-GhNgikPD$%@K|1m00tzm z4^`%>78h`(9oUcoJ)QtDo3ubD#bJ$asHXuEus|+6IH%D)ixs}Kz$h)p%uBi`CWWB} z8R1|?4Ha)09SS8XP2+`2MrkgDBxE%&@X82mMIf2;<`RNOAp}Yj6~&Z*`s#^)BC*^I z|CU7nlR4Q!ph*gJpadY?YlT}PFm z2d_w!Ce8_j`M7mO1}alTrecCc$B8KistHAvK_ed>NV1Dow4D=$IYIUnqMN_o!;0_}|s3pxh<}ad{ET2ix zsXrP(WTI6+i4fI+n~7prt;CxNIcpw<1mH>;W7b+M0IeFh00b2GsNv;`S;BnXx0qp5 zUUZWcN*w9V3<4){L<(h^g{-dHqBu4{)v$<7>P{16S=43rYbMkQS6>T%+t|u>wzQkA zt!;0MC|~|6op5rf10+CLu+39$odoViFUbdS&C?L5_$}RdTME1>H=}ydZQNpK-8f9Q zi)-6%+uq7r+=_R+4q6~9<fy@lz3VcdAQCLvtQ9H9upzi42Kz)D;;^C>V+i^jTY}L_v|z)CMA(&4%z<=| zASn3qaazc077}WBWX@$ZQ2HhfsmE+!75_i1rnC$|O`#&5_tZS_b^u9#18)y;Nu5fy zs@1ECTv60iGC?GMQl4sJ04vIZNYCN{NFe2hTela$D&;D~>n14!Ab49VH^2Z4dhfD1 ztBRf^OELQ%K?R^`5yEK?yQzS-cT>Q1(^i5mUqNKZB5dKzn(IHZUDPrF##weMk^KDo8umI4jnIW zZwcl_X&$NTSDc+Mqs@$Zit$v*uW&z4WkB2qlh>P;%>29X-~1WzS772{W#EAbCaB_hoKuO2BltM z`)S5edU?dS8IEe0XyZ@8O-DptyzvuTh)DRy%XX`66{2tm5T*$Qtx#A*1hN?*BLOKA zHy(u1<#vXHQed})jsk)y1(rqPrRFD`u}GAQCqBWZH(GvKUR@;W!DESZ{&gc0?ojAy$hl(*FT>){q@{L)6wkMQ^ZA{ANhfE;AS2ia(CsLtk_~^7z7$;mXp{KY18A9+I|!N_B79EI0le|$8sDOYa!<(SLi3kCM2sME3&GLS$6R`29X z-{QRW!{!oHP+J1nUg`O}GuPbzC+NOZxZ96PavJo15flVgz~~C0^9ypn)Fe^^$BiR< zHLkB!K~%PrdQ$FANJshNNH_j_0Bk^$zb^(*(E97K52;HgDuHAC#Q}wuJn}x#6Akt) ze&5t74bZ(fWU@CKhtT+0?}hY)J}37l^Df%no6GX}%}0ghZE%pT()lDN%v z?iED9Ao_AhlmSwtfDRbO5hsvD|4IK(EuI!joVU z&(}c$N^y4kW6xsd*9sfrP;wy~W9Bx=$xeEb31|_XWQeqvxD_il4+&9x+9ew=646#j z#$j0?fp6$sN9O{NUNOx4_9DMz(VZ?+PaBU=}IqN2(VO410#tYtG~ zCktT$Ut&xlJJsG!=83 z(L04uPj~Lcl^HEUKAS)o${|i(|0+DEDn$7se|aK@p4jvuJ}$-43zl@|mlHN2!RTr(B+%wV<^CzR*yL$_b&D_s-j-ps6)(I5yvwUj zmPv1uF9AF|+|osWzs)slFj)-RXmN-yn(7vG+e_gha8IudE#{1nTF?@U^~gw0f3l;N zV-HRww_7QS-CAeVR&0tzpn>s>rXI22psoXlRclqB$gnFEmjze;u?7OFrn)V;xsP4; zWjV=$1pNlWqty+dnf#dNx7ClUO;DObPpmhPc0nxGv=bV$hTEK`^S&I8KuNR_(v~V1 zt4yL?Z1R+~DnHS?gnlzS|Am|Yf46Lbyt_?BAR+zfAp0=9wLLXI)6`v8+v>}m3A5Bf zyA~H>D>k@pOqkDbDXSG3U1!D`nV=?80b7~0f(BZsgKA_ZsLs@aeA)w+vFR+f*UuQ< zsdJ9ao|637r7McnwST~C2KX8cjHxyOM#w!Ocl#}Tu5fa`!|5pe7}Mt!e{xVK5EXxs zR>=rYxWa1@=NiQah<-g~!QP4^4h1Dn0C$3>*ysui>{oHxo8q z%Z5{1bgixf#pN_&hu`o#Yj*djfQGSR7@9fh@T_Hh7dF-wwcn5StGp+7>7Ey1*q|2A z%vFA-hNl+8E`;2*+%6t9SCx1T7pZOV`P#?$Vay({yf`NOx(_>Cu04!2InSS zz=a1Q*f83p0dQAY?Uh;@2YS~;b#P!Gj5K&v=Vvw2XfEh}Z8%!Ip@Ss&hXzM>IoN^& z<$O28Pgoa4;NUbrSOM$i7G5ZM3MhjpCTgLlPAsBpr?)3;@@r^;BV-tSvxZ7}^;Bi% zh9oCoTv&N&e;A1Wc0qP&fHg^%8Tb%x5yw_LXKP}xYhc)lJJTBlw>!o3ZAj8}w(^5v zK!cg55}YH42Y^&l7>?pNj$XivqzHl~k%hg;eu>yH;0K1pmJ00=d+>H7c!rFZ_Kn)G zk229N|3^z_fGfy$XR7dt{KJn3sf9uEVsf`~ekhHEe?S<(7=BZ;hm;73kcN#9#f=O( ze~$=}xEPY`SczxAA@k!|Zd7xn@ljkQktfMT1YnZUfRcRyUAIvvJT;H&k=*nE4Laa|x! zut08b_)EYSZ3$RE1;Q9QI2S$hfplY)fVqIVrV2Clkj5mKKu8Femwr>@j7KMuvd4(Y zB$;r=nM}EY%4m$sxQ2y+ni6GP%>ngK@wiTmKnVXkXE3MS-F_C z6jHKzC>L3oP1y#nkO0vbjCr|Y4kMaN>72%CRH3PV*MVojxdsCeNB0Plk@!-t;tIeQ zl!SJ6Ng$hY8K3ewp9Ys`H`jhf=0XJmb*@Pso|0TCfqZ@OW35(EzO)NH7zSLojw!cS zf05>$t&n{G;3$gYM`*#b3rkpzl*wFB2}J3lEj*V^fLJQp_XW%eG_b)VaJPAi*pTYS zi_4a2hB7tbnVmY7eiAwy2pU7D=NqzVptaQ(7qFu|dU|F+q(v$^sU?t%m_r20qMX(x zr88_#ni+4{Mi^QJ+xa%k7if25ahKJce>a+oDwCtT!T`{Bpjm1KQptXXSfeXSjK@f2 zQP-f%QKFYddlh)02?_>h(^Yj=eQZ;6C;BDHhbUUrkj_b;jM}JiDV0B_R=PEb!nuVc zNksm^Wg~MOp0S`(@|b$FB`T(uIfJGPQ7f4mq@a0B4iOuTsUb$LuM||(X(@fViIPxoNvMS+moZ18irs(H8}G@p7A+)8U#Ix4m*uyVqrPw;Pu+Ma$0 ztBxA7A{&JO`wE0qD+SdU&JrZ5h-gBiL)&5L~3im7BS)gh#6n)c_u60s5Jm72_Jb+5|Owf3!nl3=-f% zR@)K(exia?pp<1|MPa#IVlfGATY1XLh(h}wy!f^DBDQ2JwpR0P&0@Fx=CY4-t^Nl~ zJ{Y$Z*ljD~mW7*nX-WWw6&TzoWm96aG6FFd;6m(Dvs+f1IV-LQD^iC`v}q)^4JNi` z09R8Kd4fxA;sds;8cWFYe>JpQljXU#_Q_}&0JydSw-Gd_@(MM^ATGXImKle+n#*yw zt7tvA2SaL($dM4LQ?*x{wM-~J>oTE8z_CXVxiMy5!MnW>IjIVeV20Ip z!2bd4Zw#xc3@om);Th?xzNMK|Kc&GKyTAOq7r@C>_PUzZ>YZ4ZvU>r(!O^u8`>kbH zu_mQz>#H>;RySgKaIRsAVuY0ilXJ4sV{Y0e^98@7X~ImHv@OR*5bVKyCbginuE|2f zL$$)dyN-8a#gK=#e@^4XPt3#V#=ejSR3S{o_$!aRC&4P1Tv9cos+lO}8^>}CR+-?h z07%BoIwgeBR`DS<=9MhI0Ibr*hwF=7YS@Hc`@TAN5WfVmX6QUYb--xYhfkZsbml9g z3W9{Fp?zE^QN)O zh`>&(4)EB%-D5{e49q^O%e7_A+?BHj%**HX3NMJw*Ve_Z{L6#pd3Gz6(KN}WGR5g~ z8xXM1KBmYEe^3(N2gnuto)etJP%$JAn-7^h#}Yl!U-cKTdk`1R1s0vqVX(W?IZKRd zFxZgMR)7$|H@DlyuV+98+c2E~Y?mn;(swY@kNYTDtj>!;d?Dj;UVsoEtrSQ5(}`fw z5>V5m;L#d^jivk3F)ars&Cw((sBp5pKwZ>3E!0<_f74-bm!RlhLnYICgSz+9(*NhV z(SV@BlLf$7P0?)K)@}_4>*B(PFt-tjex_G}M}3xO>D8m~OWOO^Nfy_gP;itQ3xX|$ zhuseZd1Uy+|a#n>NuZ%kOkI#-PRr5+KnKC_}JThGIjjj;yvEvUEbz>-V+_K=)KwIkyOrtmZdTgNciFlQ4usAD)5Tq4x!OG{u4jG(%GQZFfQX7ZR0s@1@E_WqvQ0K0$Oq&UXFGl(oV_o!I`{ z>RsH>mVb`6|9Kpx!2JN%)+OxvtZQP!@`LMrV86MYb&c%=`HX_kJ5Ld2i)#|iGD4ma zOmd6Ht&2Sf4&VXY&g~z-(?!tj;x6txG49+>tvmlYuknDe?dI+Q4tDnBP7i92_7|k?;oj~P@$Tks^=Odws`3Q(J_QToZ`z=q z)xq!2DWixnzKaryj+?H~DfkGmk9!~UiVp@>rDPBv29A=aS$*ABQBP~xg+*J--xwT z%`H;^{QbiF-@@0wy3kb|URX;lhO_)bUx=?yky=yhfAl7AtR zD)dk_|IQBvfslFzSn-%#Hjf_w^@Kt^6aa{Gc|EtEGwQ>={EqVh4b%X~CI;;W4h}L1 z8yx{9^d2WED=o_$B*)bL0ut0BE*k{_D(fZ(IORM+Mave{7NSmFYi(~UQ`J^K0YY&D zbUS;0&q#rTRgs91g?U@aFgO7w9)JA`6eJ=H4+AVHz{4rv02HF9t6!%jsJ_L)$<1e{ zyB%T6=M#{VcbB1&{4lbWXb~k^bGVgp=Fb}Gm$KN7Oj!x1u_(wjn+JA zG9uJ9Gsnv3>PKzcw{hqGF@Ku(rmU%PEo4Q~%<5ahfggWOTy0NB+%ArMa38X(FM z{;1H8mZ>6pM1lz{Kw_yr^zaHa1EPUY!g_oo(7-VcXh6gW6&kQWq<^q@ki-e25m7`w z|NPj4AGp^0Fc4@EAg7a?#Cq&H<~;I|p!1L~aP=3kx(qNuYw#+7YoMZ(an^ z#_SphiOt5Kn+Qoh@P8zQ8UrAWE(#Y%6vKf?;b;KOOcw*xP%{%WgaJLhoK#b;0xb#B zrq+y9pfO>+gHPXv`R7s*IVGinPD3nU)KlloR8cG{Xn=w{EA+ze;~&PN46!+(H~*8Db9dxN2NQhNW{ z&;X0_$a4?K3lcT1SbPW27f=HRu;AS_!$9smRTTzAVj%q+N60&pOU}}*G}bts4o}?f z;_}D%(08GO3MskI=zS6L1DBnZ2(lF$(Jr{ zVNr}C8MaWp0QAP1sFKOxCbTi!CY%lqQ=Ep66HSAv0l_h*E~^u9v@I|NCocm7&CB3v z+4(M?hU}5zI(r_q0WZC+SnZJV&j+x)Qp+*`GYl`n#DDxUrrKfG>TolrqNkJA|8-P) z+mNPV0Olx|r$bX@NAm-~Y~cLMrf$Wfk&Yw1&e#PB_qF0NY!p z(y%c*kYayEqFm%qNR1$lj97z%+Y!wWxF8v?bHcmG)q>+gB_Z&5-r!;gn>dZ>g)x9c z6JHg>=e@e&&|~o9q14J38?!}l4IL~?36%z|gMZL)Cm)It{213GCQ7b*C~E)2ABXcj zyP*SAtO;ZxyWlq=iqI$cP@MMONXSdl>NAd;gTp9tAt?56d{Eip6y;+9`j9D(Vi4Vt zR@X{FmMwC2G-KT?Aien!Z+E%_lkLFp0AUW(PE{JF77)|BF!AmKyWAoYJ;w<>;p}D8#5-rw9mWUMW&#)VQXN3VKd?E>&7T8h@T8 zdSNnG&^4DEvtY5P(o&$lREBJMY}wXG7MM6jV_jU|JbMuaw%$Rs8S9QI)n^GQLS+wO zJ;x;9%AG^3Hj((cO==4%S(SB?u!3q{FFMa2Y!tAo81}zmT1B3sjjwnxf-8~4C z^0A8WO;4cjtD$K}Vx_A!WqOXH1bgscPXjHqke(&U%vzch=#;H`S!qXC6FR@}Z4eNc zq40?;tl{!8mg z|AW6r{%|SVv6wxk5GzI|z|TUAU*Rok%EQxZU?MQP$DOh+Q>pFW)Zsl6mu;_4KC_U3 z%UdP2nUg<4@|r_DWR%i4Fg9M^V>i5I5$+XoKXL_*MRAQz;in~0_ywO=XQwX5*pybH zFdX0lTyqW*k((UAr$HU+Pk#%~0?gHbrXK>-!Tv+kt#&K&+CvxH|Dxe9rear z8xoe4e56EMNe(2ImeSFTih>-#k~SAFkHpK!FqtqQCQO@<$X0fmnRw}_02eFOu(nmR zTwW^mvc2eCZ@K5&CG+}4-BB>YeR*>fHzl#6XLw3wr)Q*VJGsT>D}S(uIc!|2al5#c zSs5W9Ox(a?MnQ7$gTD|t#pz51rwGDLhfNEbOlBEMs~+zi7~YSE*A+pidoq`c3T^|| z`N=p%IGHshgCPH{EY4goOeUtTfs_Tk-j>{&SU@P34id@E0H!VLkaE@ z52ITqJ$3Xs5k*abw}0wALw)l4o#zY1LJ8;h8EVhM=dHx9RuPhv#n+=V|0 zzARjy?Va$3iGTKwiNrpv$|I~q+4vlQ31A)=?cCAxeXrZyCV!-H15fJ2_oMc!M?HDr z8>Ut4#noTJn->z(?)WNSO29*pxT1US-`^6(7Iyvh=_R~Ukv8CEBd0*OjQ!}sWb&Wq z*srVKqcAkwKdP0c_*>zJv#{vj83(b^(eu!z$L$a7*Vy`DV?xTW9`a6EXswR0PwJu} z^y)(KrpwB>&woG61Ixw3){}BJuFSn?w1ho!67;qn2 zYepR8^`dLLP>PnW>+<@I*G}f~*2kQ%0Ru_!z$UOCG%x`-=Is8=^x2w*EjE9Iw|}j`IfT z4by{h!te%#%NT6L^Ux1`W@?JOXX9=Q`{cmPR)<6+s0gX>sAg{vm`m{p@xYj43oQe@ zu&N&((dfi2zJO^CawnOZNxqb66G2hI(kplnKvC}K{!Wndu4obK#sS%``^L$*NX(9? zuCll%=YKY14`WgN+V2-_@rGK^BXFbsu1Dj3Fjl^y^-TZj5Jv9*g3Fb758QNd6+J7) zenQ8@M+Xzi{9KUoF2Wc&kC7;^4Xu$0$q*Z^2Mf~?q3{nEr4i+-%FA|+)=L0Y37dO#8Dg7=(Ymu9)C@+b(qMg7$U^@M*%y-D8T(-}EzvOL5d~i?2O%>r ze=rek5F7*3`;cXX_Ua}|b1%;^BMrw$Hh;cTHo=YkF0+tqGOG-0{}w0r zoYHiZh4$a0W}*zk-9p@a;PbwWos?|>#3(f%qA*68hgq>xqsbSN(&xyXPo*oq0L@_$G= z4;pOF?r07nEUU?e(Uf$pJy}ObMy5i;E%<0hOWgl*-9iydly8}W!7W1+R>(oXR1qT6 zZ}NU*`~2-M5e)pIk+|qA33o9uMUyi(vorA%*}PL@!h#fzu|IYzq5ecE>_mlnWm3~ zuFy*Nj&7dNlwR{71}t|7;D228Rp|x- z=Bb_%ATnw-R7sUU@8tUOl(?15`UTWM-?^-v<^5(;e~p```C zRJWX>Vi%__g<_{Fmf}h_OF=bMU+t;74CR&(Ww8J_FF{u`_A+`E1{dR4@$|r4uIqrN zSKki`a`soF^e4UXXi>pcTXwQ&lrQYl4vdiA@~gNua-eD!V=LiAV1KU7AN!Z@JSKeKZUhcXuO=&D8XE ze@JBwb{}TN5r+2{!>0nvqIZjHOPeCbwp7bfggo&ONiRWT5&&Afpv8V{Y|Du?W1>@< zihHAMG_SFHDQ^j}*Q%OTbH@?EZozu%p?>L6f1M6|2V%yiN`HiY26mI~4iuGamlrv? z6b;xHKaXx2RJ9f=6M^6N0Nbv7(nske|MEsPw(f33Q}csO1LkKP*MK2(IKmMp|LKK` z;Tk9a6$68LUigLs#BHH>hiLd3BZ6Q=ICc^Xp0dH%2304)^qVa3n+}rHkQICrbco{# z%hCvPO~L_MCVw*}q+PH$x}K0{X{B9C%U*PhO)!Ai8n}Y1>o~<2=4|+dr1u(`NCBTB%lkB2|vyzB0$Niif2!vjn_JmZAk{czbSxVjpch8xOL^h~w;6!!M4P$UN-Ei~1Q&=im6{zTI&ukD>lvL< zfr87dEq|i9fVp;;^ZCH=EFbUKWj6+lxvBt6xu+;6CyiJ_ffv%MQ;E+>lY6k857jk3 z+G%mnz~Grkr!truzz75jb3&69ac_oq8DIO>*$fJf7fX96+OAM|bSPO2TdK$Q=ipj^S%h0i0Qr>)| zPaW6~sG4PpcqJytb!RVoauaUI|2nOKuiQ2W-4cVn+G}+2dT;c4kQv$Wu7{-?O=6i) zsI{2cq>HEl8uzXu`aB4-3%H#|$jA^|d7>8@gF&*dVuV1`d)V`ajQL;}T6mk(HavTH zIDfky(#Wcr8h;FLM`xNcQhUkNOct>=k*xZ%LzZM?X{mpkt52>@UofOyVYL^fwS{|T zC3u8qdw?5yvR}LI$l(s9T5nCJy7jiL8N0OqQ;ietX+09SdHY(+=usIoYG2N~uZoHs zt8HDOHSnphVJo&ui@W)jZm=x1KbkBO+JBp+>1PgcvF%|%r@Eqf(0F9fi5;t65l5>H zJb$wzu1i_0NjSj)7xgXxfmHwZs%;{AsPug9i=}sUB|zMJMJ&Crat!c#Tb&1b-T- z9N^ONP-e)E;M2(OLC1Zyxknp5#%hP_t;&z*0kr&y4T?ibXjefD%75lT=po1hxSNlI zu(zogljnkbQGH7S$lplLo99{Jcj+ErzLm(a-JIwU-2nc34k~C^k)g@ioRK69fEC)# zf#HLJ&2#WPGD=Q?)x*EHMZP2aD1Vy=Y$08m7{jFf+>7R%(AztzvzQu&rO=B+2BExI z*IU!g;J)2^eSAH>`!<94{~Qwao4wtwnDIk!TUJ36In1S9fr~&lG>4X-DyEMP+dabz z9vu=&?M$?N+C@Y2oZ542d^Eg$+}DQN<8H-0#|O9l+bw37(KZ;4Ak4jh-G6tN-~0XC z$vt?YkJp34-B+TCr;^#hJ=%?Vn;AYDh}jZi+27Fs-l4DvnwAKP+2Oe$guy)95xyP5 zJ>WZI;?uq174+VnJLEUl;zc1%NuHFLSKTB2Ge$n0<=Y9U?fj;P;uYb5v z=#Bp9FA{%|e(8h$r+A)VcYpflE6BQ;zUr<1>ajlSwSMclzUyzCn7lshz5bV}UhK_2 zILV&pM`aO$8F+*KM2`RX?B#y$>Avpm{_gQU@AZD~tsc5^hVKC%Gyh)g@f+#irR)Pg z@fCmZ8Ncxz|M4L|@+E)rDgOsg&(zKm5gi{K>!k&Hwy!e{SF#{n@|$-T(dJ z|H(r&ogjrsB83mEJ%9i8-`Z^f2qFeUBoM$17se&C>3l+?QmBwSjItJpzRd7NRT_=P!m+Zu(uUQjjNe3mgGf>Nf zM+c+!{MN*1fsp@Z&!SDMb}iesZr{Ru-=R8|GVb6O${rdLrJq?=(Z%Oge}^KPsG^H9 z+Nh(C#^{E#K7f`vV?l%WAYIGltq<#mCiS*12=jaO9Kj&@;Asu*)nYO2~ZV8NHn zjY~w3lcX^_xx|sjzJVtaX+^5Gu;7BhDP_Teeun0yt>)zYU&rIRm&d=qngE4jEo38dX{lv2g5FMOR!1#TWpYf(6=3|Kx(6TuL{a*USvcFXt-xAStKJ6 z5j+}&_V+6tDJy|cd< z+2k5Y89F`e_(XKqVv{K&(b5Ra(^b@aXGMQ`yL7peMwZAWpY&Du2YTT=PbJxT4q+OM7y}pvRNd%=9MQ>{TAhM4 z@#w$f6s!&u&6+oIp?{2QHS|1JVIykDLs+@`^rC4Ss=b)%*vCRPvXYgoQ_~pLDQGf_ zO_(Z6D8Pn7lp+EGeI*p6XSdFfrE>7ABP;Qy#EON`q`x!_A<=3jjeemR$w1~f$y!

D?~+C&m5X2td5&aKl-*X5d%8~|z}qWlx9@lKn(o_KLew!Q8y)H=6Y$gcmt z)=k^{=Bvck31CVNATA+a)?mg-kN_~v5OeoeItUA?nL0gB>zG&81ZauoP-~K zGojzt#!>+pZ~&3H2jr__^tPs}u?{O4yEv4yy+*D8l9eo(2Q)clO#AXRh^v83TJOzq z7He_qfV`A-cq`drfHZ{sG1y)~0*Vfcq8*Gd3M})+Gk?bDnMIt26~{Q!n%*?0J8hO3 zSJ+a4Ij@devc|#z*fj|oSG=wF%>RbsU0X^RZg<7y$bo*p;3%Wdv+rw5pr zVaCNSD}Mz+ZmQI#E-s(h3&$f1jSa=twm1^D4O&JJtN%-Bt*3mG2SbV33DsFfISNxk zKP5#+Noc++<=SKQTT9OUHlGO|Z2fI=9A5P0MAcI|cM330*fy1eA24XK0Zrh+Y>xse z^&&Jt1KjA|InR6U^Pj_SGLMrt(Ra)|hYqySu73>7WO7PNL0Q1TYJoEy-ks#~2;J&g zrvwI?E?t9B9qUyO1p=bJYCRZXR~IJ*^V|*ex5GW|a-VxEq%8H2JUy~?y^a490h|hW z_n7X2A3Wg;Z}>YP59uJuJ7o7>n_LlrGMpntqg8wO%VR$CnveT|?vD4#C)M$^3AH%R zz9#w8qdxVjUp-yy5m%wcz??m0O#{Bj^w&h!x2~U>D_$CG$Yc#5 z4iUoIg#?@-*-j}%kVOF;$idiQRv#RKqUDr2ltBi*pK~~o26`X`$_NM^g6~z82)Y6Z zGKBv9s<1 zVMQbbhC#4J8g>L5Dg_*xms@!R0@U2ZA>f}iL%qF`q-dPbK!WF?fqx$|03afvy5xb4 z(b{ii4>XMl#+Ahs*xe*tBD;889%Q1MY+`bhiWYPtj1qts7Qb9S<3QHgF@W zRn9j~0#XhnYusNxo})AJT1gU`3sNKfJYy<=r4~2V#8sla7yzV6CM-3Mq`cd}Y{z7NP3%bKA}pd_ z;@U9%L+O!AMz*17{@N#+rD^63YKG`1L2(Xeb8<`v)FJ|afN}yT96W(|HIPGKXc>_a0o{sI;Ej(O+eILN zEcT>M(j-pGqAo_M6x8ApKqm(TlY4d7nW+h*&v_To+PZZ=xjs)ORoah>em5siGoqVeo5(!0m zYXM1sxnkP`hH6+sz+vUE;g+!{dCMtnA(SJzXikRn|u&N%GNwj(i z7F6qMu;fxoDv?p9v?h%kWvbdJv_IIzv{tz zhN;R#$;u``%Z6>IhNF?d38ro(Ch6&VJehh;1GZKsK)R&85L>@-Ox+gSnxa#;d4D9L zts~y@nEz#VEo-jaS*GU1Ipis-j7j>f;wIKq8r#I>Ei{p9Ben~KsVn37C*!cnPVE}x zs@He;r=-{qC4TKI0EIAY=@s;w6xdm0Bx*sbsBr+^kd7-DSpvLL6LXyuZPuxD%q}GD zqwF5mSmH_s!roQu9>ME|kRM*|2{LKM_M$9u z40Vod6M$@%YC!tFBj_Pyw~T>D+HJM)lCYKJCYCNyVkG{a0k*)$m<(lJU_iU9TjoBj zGA{3{02e#Bk^T8Es{m)1p=rdHX7K8#*D3>$&J6t)K-tX8;%e*Krc>L#)qf;vz@X(^ z;FTu-$#fp>Bn+gL3da!J0_-7r49&074Gp^{Zuu9=0t9SP4a%Smy8#J9eyR=gF2o3f z0tf@#5Y1v>%yWg!*fdt0c7aj2*2MitA*mbcG>y1MaUq0^o2m^F$B^sXlG*TX+%OH@ zJXgmAD(UXbfyGzCutRs2LVr)pm*^ahN7k-GvFk&PVQT<#;=02mEHSPvkMs=k6fE*_ zC_(cU7iCH^AwNMRBP7B410@@*BGcs{9~Rd%s_Ave^#X=AMHP}N(H~FbKB#i>%EHAq z>2jK{a-y&Ka>p(|r};JkFeYs(^f_)H%ASJAE|TT&y>r0JPZt&j$sHk0yVW++Ft2xLCfz=q`v5vj^h zml6evHz~3DQWblX8;s*@=CcV`1;!X6X-L8%kti_L9!y-^Zow^m-I87Mtq;Q* zpTQZf2|@-L@>3Mde1F#IZXWdX)+e7et;8}8PW>=PyTOdoA0lydC< zm6k&;?<744_AmQ#b)JkV)8(xZ(9O&=|Lo3gZV)6fptAw>W(c+Gj_2!A zb}K`-Ryv%HXiAqw0Z$jGAia-6lO+t{njVV+yzyD^?6u!5utWJVu1VboY9N9C_f(%T zJA8wIAGi}NF+z}$RyP+{*Xe*`GLKOvhC8(;D{mPcPJf5fvxPqahok20l7`j9Apds^ z2rtL&HAs^$eH}abH;>%eFzL1d$+$$&GWlvij|Tu@&!k}|wv`t7Lwsg4tlELHa(l+} zb4#{=DduJ0^p7slN!w{M?Ze9?(Pyi78f$>Z?f586Z8?>pDSBf-@JtjwpTW}+`_r#bdP=a(=+JM*wQX?FR&%|6nef%7BSqjnA|^Q^fER!9VvPs zsfSu?Hx3rVCE;gqHPWQ(4SsLyZ*A4grPw3;G<$dYq+c7tNu_sh`enKmYZKUEQPK%I zjjK4K7);5kVfGl|`skWU5d@DK?fP~s$v#N1=zluz*A=NFr}n;%B%*n869wV_SP^&> zsP%*Y?zM+HD1RhH5f;3SSBFZXSLn7NDZ-dPSeG;JFctf``-8ea1dwm+x*RrPf8fUE z)M4{DKrhRIVmMis`am!qx4(Ldu@S9zwjQMhA0$4@g+W=FxYcdx`_b{ZdI-gg| zC42LTTeheg7x1BW& zxV!V0!~N3$QXOD*baUj|7l>Z>!YM6&MbNt~bF83@FJVgozZ*FRRBtSl9he>buLnKX ziylSg#n(J+I6gYp8xv{$uO3|!w&BBG+f~;)N&Hg1DL})|^em30xvaFg64id{&wnf5 zLIeyoyjS9N>Epx6Z93BL+nk^A=gWL=NkO{8y4pm8e4ai5JNnj7ci_duP2I?jzdqtM zTI53m*n=CAKr%4P9LgKz^Me31JJnO&yeu+xeNEk4ZN;3kC94fU^^E*Ii%*d4y1_zQTFAql1 zIk{1x$8ap8MSvL-WlH<5k?8&>RCvVUdGp7lkNfdGLYFD}alccB9!I;+-oJO3_f#g5(@h%qS_ zidU5u1M=lX>ed3AhKFKsr8Mdj!bG6ql`ENU+`Dlppbf0p3{*G!#2|ix2A$hBSB7LU z4Apcpx6-x(mL|~I?bM6<>NOg8E#{p>gn_HZ*w=+>79RR0gT{G4V1HeagZoWV^cY~r zuL}nGJvn8Aw!B|gPOE&V+-16p*W=AGZSYdJ5Ah=x_AL6vi)zaWx;Ww!Vn4LNqK6%R z>Ul_=eBNo0K`}s32ZVMcJTNRjc#~?r*O1r@zg{%M>@J}s>dnK}GAeK-`lc}N7?vsm z;I>6j+6gt5U<@rofPZuv4kw*p9O5S3@wYi>B;{Tz!A^>4_4Zn9wJlaX53eFsK6RgEw?jqsYSq42O|$df zUI9CHS9tj~icDV;ybymvA^LGgVFB(LgTi&{g4p1H5^yoqY4OD@NH_ltl{2I&-_>|Y z7E`U2)q`d1urzrOy2LvEtRr$$i_I1Cqa!V%Gbol{eyiOd(N&|YkNZn0QeOv6lTTL- zI~pl8e!ID9tFOj7>;G=8OK3Z5O$H8?AF}f=;5r%!4?OAXOqqW>8SOCNi3*!;A(DM5 zbU;A~Ex6;~5I}XId&OA0Fy5jxRL`_aEWAv6k;k3 zjUM=+bklP^^dMPjeF8SF#rQhU5P?k36{t4%CH4+ypVsl3fI%~&CA2Fg-WDfo8SGGz z7x8YAj87H!k=1{!rue&+)XVJMd#iS!0^o=gRN5CU4r8Lc2R})z|Mzq-;mjXs*x`!V z_h;b>*AJzF+4|EQ&F>A>o@5jUqCOQz8KAO?$v$M5(7i4&sT+gHSmH92-GU(l5uPxh zRGW>3$$UuZ+<$yBhn@xFRk?ZsRci9Q>)|A7=1a-*IwF4=?e)u0476D=0{18A;m?OZ z1Y!`)APfc^zycA-0s_5P0SjQj0ZmX;8;a;eJ7p$XO{@q43&_MKcI1IZj8w)7rxQ;! z(E^sbpdB)xh!)~T0unHv8RzB|rqvEOmgwSDrs%{z6zx>*c^p(AfW>1;CJls4le@TR z0jfFfa^`;^BOo4dMl4Nd0J>wEf1LQnIKB~gQp6*w2H;6LHNgLq`&iKe2VgqWC14O$ zY!&75a=g`@@GZkwKrVAR3s55QXI0c?FsZgc=|$#MzU)OEFW>-Y*%Fcpfaa^9SvR%8 zjd&@9rXjOQ&Bw$_c`3r(8KWtMY2pZax1&QgrKx`aZqkTk;?!n2m$x}#a1jl9B0?9c zMF2k--~x0ipB{pl%NZV%M#$*rKb`4A5H$2b4F$m#<`<8K*#kpQc<2KjG|a2*YME#3 zr{{{;3{>5-iH2m7AqOdeEW+bB6j-B~>f*^xzHx+~a||S0c>q|h%tbIz$!tq zcmWLXF_Gs`jS%HJSGv{}16AaPt-ztEONu9e;yKd|0n{?&{HAbrLr&d*3XU?tXF7Dm zQ+_sufW<~jf!ui<3&D{dLnd}kp0$-7&B1@hy&g|^{ka!>qH-QRkro^gN#*gpC|TAK z2ZFS8UTy#L9qondI@DC{;JSIS-&znkr{y7U0cOp$!3I6lV_qk|*+11G$BtheP2W=W z-0CimyWqSfIKVXtc8bAm<7wV^2G@z^m=nD~j9>f^F;NUuG(sBy3B%%Np&y13Irx7p zpk-0_Uc`#mxUXePdW##|k_kbU$jMg(e}-7zxU(9A6D$8XOy%0ak}0kL;jm?Qc2l2y z$B&*9FeIyIw2uIDz{esiV^2|8^_{~`b;WUxb$qn}kY*9AG+hMnDww-+!!96`EK`e= zt*nxbR@O1>;~czLPjSedx%i(sXj^|;y_ITD3aFwM3E((Abcw;_d1QE_fsH36c?`~~ zVqgoyymG)1998BYw{EiK_I54IyXCG`Wm}glRzPXhoaJ`2tX16#*1CF)hP%`YUEwBo z5!CGQb%bUPGHZCb`#f^%#N#VHM|Yu=F7X( zaG?(!BQZ{xv=hJ;(u(*IJ9A?J=?)XCIGPmrkb+K1C}E^ZY=CWZYFz&y5pkD7VZx8C)yhkfiF4|wAoRxDspJyBUNdnmMZ?x3+f z?+@g5;TPZdJ}Uk3@t%Ktnj~@XsL!ykl|OyzSKs=GXMXK>kCf=s{`yvP+V{mje)5N@ z4P`I?T+g3=NV*fx?1z8+}{6 z$r~?WwdRS#v9mi(M8|ahR7Vl)zK>w94x_QRLbO_pj^Y}Ec5EZ_Lbw)EDR_a8ec;9x z%6}w!G)L(R$fFp@aN0+jI7qt758R5-TgRHT$(yV|4EiV-;*DN9sH-p{kZP_z8!dzS z8J#qQ%rO?^aL5!Br$KO?q(qurtgh#?9e<*n%9gB0UqeN$bT6v(N8FLFlLAE>8wHqf zCX8{VX3(bHTBe`eBD6fms=)w=%EpG0DEk@$YOD~5f+*A2C(?S?J6H3K1iE3jmu+tAw4b5{3{N2!Bgl z%0U92e1gp3!IJ}W8(`eUrR2&>d(DYdN!r{^SMW_zLB-8ci%K&uv`QiMah)PDvl{zM z6KXOH5}O(WB7_M^XPZV0k;a7KjeIystq~YH*qFt1J?{{j+l0B>!p!w#&-Nt0k5P*o zl0=|6h0F(lDg&7)wc>3=AlyP=a(`ZOq*fX5P*zPeB5fy6z4I|W6jP&iQf z!~;ISzhJCLkA63Pl6ZzYOI+EbylYu$=L#01HjCCx1dxNF0S7 z;=}~d9|!fR6zfn9Nz(iKrYvQmj~D<2m;n2HH}_=IHg!|fqnYekH7~_F53!CgHBHY^ zj(`i2)r7#W*v&fXk>If&N{i5;P|rI(RGg7buvAq1{7o$rl}D`;g@{RgA`eyRFholq zxZqP2RW#P*vG%!6XX8s7U4H_J`OY1+8rTpm+xjo#*vBR-uq!$+VPneC1T9?Dv@Ycm zP_0#YEV5n=g&{knH$~QDRaU)=BaWFf;Uo;=SyWpfxEQ;~<3hV~*iF6|)JC08Avhg0 zVT@@_o&qJ;=KtZGab%oxrBLed6KU-m-P8jw#8h($ol|oZE82;Le1DmHolEc|)%%Lk zQ*En)^*tKhABHK%F#)JeGY)kkCukBH=gK8vDJVCn*qbvQ2{lh0%beQDm#1Q>{ig$Ol}>TOS%oPdEU2^^;7R8_T&NzOo_c)Yp9~6h+tv z;Xt7|RnI#A9kZ;WAnV{ymT92dcpf5gRZu_!hsD{@72VMV6Mr(Qn_s;Q^Le?``;TH- zR5*OY=pkDTP+gCJ0Elfe*j2+!#ky`_TE+pScd6Fs@usSCT}Z8^^%&l*_0U4~oZ}@5 zK0N?5N+g$Ss|+>RmOBZ}P@xn#E!2I3+SLh%;NIW^SdtW2>$KbW!dvX5D1G>$t`waV zF)y!(PdNpdlYh0K0Z)>;0Tsrv7juk z;1YCNoLia=$4y{I>(vXcoPyclmO@e^DxJ+xEhiY?BYWW8nhg*}h_orXnES=4b`jX5|`3Zl+&TVre3Dx$HI6Pw^X*5f?} ziJ3(P%e4l!y`^?4m_vOv&jMsgu@}g*x*RHhVivxv}f2$z}Nd{qu*9^qOPmB4PjOv!l;O1 zI%b^G2x?AcW)=x6faYj@3I|?_OUnvC)aIPlY0)L&@UkT8yjSHpk6EMEKD%LBbJzJe zdl(!;b{-2);_6zT50B=!TvAw!ZYJWBm7j2oAYtrg`!t7z$v~Ky9c?p(!VN|t2 z7uJTB%m&@xbSHb}g3~6KV#(lzh_HG^RDy|KKd|h|2B3kFow!Bcj(%UbzEQb#YgCo1 z+C7<|+3NhoZV77FLHiF>fsJ4eV8Om_e+(+m*5n>tpav#Q$7b*LW>41v+<+SH#eWuM zZN-LWWrp4XOIwIkGG5`*-b$3lSMb_o|H(&Bj+Hj*@A{@}+NITk=pL4VIOFcx4LTnQ zr%otd?r3zF=+@3-rL3Ck!zQmdFl$by$aUOC!p@jZID)wg0YX zQG@DTFW2mv4Cf+h$USgZ3-<0Jc2(=^l-$&NEU)BT_TU=zO_g7#t(uX9U;5I^LjR|` zXOwIFq4sF8VcOCY&4RJcx_`D3MzE2Yv`$}%2lF&h7pw}Kv}^s24FjxM7x;mvb*}bD zU{kQd0&{avMp-4+e^_coCe(>%xMeRjW2W(oPc@4VI5Zcoh$l54leK&&_DW+$TLp-d zCyZ`Oc2i8DViY2C_egTTPDE!mXspg?+pKBRd12j0uxT@_gou8l_kRUL=J|L4af{_y ztfIa+w{$zNbvu-HiH4=*J{X=WiyQlM2zwS0 zJMH_6wm%E5d+?@P`!AHqnaldU=lj0*`}NGe#qg5fpzgmn{KH55#Gm!R?~~sDLJQnO zE8X*U#i#trxBSajR)5BaPRBoscJxBb2mR0&{n1ay^;?t+ZMywiSkh=6C+*hyLi7{^_Uw z*Mlk`um0@cx`WmJ?)QFMtoH90{{x|sLCW>>NB{I!|Mh48_J4Q(_lN)Zm;d>v|N6K8 z`^W$M*Z=+Je<1h?hs2`sh)gP%%%<}RjY_A~s`VNO47S|vAPWwQ$K-Sm2Wa7XlI7nDH=m3zI7?>4dU=Y#wxL~OF009xHm%z~3`TubEsEILI zY1Z&akfreGW`Ft$8!JoZ2q~F5n}yn-8o+AcN_Oy<8y4Z&NjbLL`x`73d0DLYgR`VuHF$E7Q zN-Cz}8Hf^l8DogHOva7m;`V`gEi6-=)G$C;Brvex!GsGNK8!fA;>C>r8xtXD_N?6i z67Y_>5P!L=(#g~qM6SU3E`X4sOBrO}SFb=#!>J70 z5O4~mZ@0$QGwRnev^8);z$Su9F}s!b&Sku5n9PYdqXu9Gb7Yh$!IvK3*(~VLAA^IP zj{6}<$MoylzmGq^{{8&>56q$n1p*EzAZNpo@qd6K6HwqyLF8FyS_O(!;D8-ft;g9y z2V~$|hkX1*Ms~R+^crb=9FWLNbcpCwasf!?p&17XXW3*d?&Knj4;^4)Leo)`<8rgy z2-#=^4(MHX2r9^+1t``Q#&;1;SfL|Jg{C2gdBJyFTJ!k_W|(4*N&jYT zqkkCUO=OH)<(XF2Oc-bxW1f1J0isf3Y1dJSgFLC?97O6CpCrV%NvU} zqQ>VMjWh*H2jXtC@M0+MylO+6?|V@%S zdg~DJU1XX_2>X)Ub!OJt3V?JFIlO0usf%YEzYaP+6K{}gqbAsCO#!|xQ|QS1n@d?C zc3fm;Zi$yw;*{BLkcotbZa&n762Sa~q5s)9Yi;ilvZ5-Z&;L>|={=|pMSsQbQnkyT zb#!Np@stOF&)Z1*2%tBEK!8#F;~LcH*CMJti!1l@)bF5Xmcl_sE7UO?8FE*&wSmud zqUxRfWY?AkR?ro|5#I&Vz#RqvuXtk^-e`EJi`j_=N~aLwc5I?71qDDlE~Fj|uh&8Y z1~G;=eBtXBz`87Iaf@8+qJJ0rQKaaIF&G_uQVM-&6AB#9B2O|28Zi_B1vJfMa#Vmr zup%<1$+0YTRKNwaw}7mr287Ep7bD)NMnzbpES4(+BG)JeG#1h`4&aKM%&4$H(xykG zbJ_uT7mP@xb$W{1w@G@O|#7Z`sUQbjDO|QjgYLO1x9DT zPvOsm$)n}W_~OG9daxN2N~Dn5__8;4O^yMiqa3eQ7L%#bGf0W!9Q%lrS9%hPN0e4o zCRjFO{sfsTM3e^ghc@dur<|?i*>WTqNMMc4h3Tw~vigR?LA5ggiWH+Z`guuPHnW!) zYbGQ6P)9!2@sA*+D1U+?>P9(Qw4s1YV*4bCGfIN60?t$vBi}dDl1@c}6*wnCX;-6( zZPIt11Z4x$$WT=7MJ_D)qECMc)SwD=i{YbU05|s&aEMcFQsbyYoJf%x6_ZIK#N}2L zAptOaN0xvbUmlj)$pu2JRAAj{SG$&nqt23uq~oM@;QyqBuzwAaslX&9Ap!_jJ&eVa z_A46iNEl49{W2%usG<6F>Aqd6sH|4xLk-QdrQUsqqEPMHbQs&zHa>N9kBZ$qNflN1 z1PpeAW$QZBriLj3mH?BrYjc1%0V`6^uP#Es|E|icR#? zO~C~w9ezXWR_Ybtfen1Fb&_k>Irt%o3;;14RPvPn^?%^yw&giwjb@ryt3p^sm|Uxg zWwefPbPy+SQWjEZldu}=_l}qHua`utu(}>unPFh@6wyV_9h#5Ft{tQXP>ki^=(NMQ zU9D}R+`Y`e@kjUNvW@dQ-cp4siUO|cnvZN?awRyuLjJH=qg?0lVpFOX?sIsT%V9L@ zS)e?tK!1D>jp#%xdeKxU(gPk1=|`87nF3T0CpaP8C)Fi@?E^4Gf3gk{z8S(R6=p-3 zyueFix>D{ks--VY-Ba`QQ^_ntd)zu$=P4y8s*ZJt_s|~Y4f9IV$ufnRLR%t==djFW zpJI2dYEbu0Aqc4Ub6yQ=K;e-zPoePfqMhkVaex1M$+IpPO8dIcV=qyv9h_>k(}Pa# zz4nM)Ew+|fO*R4K8`##?af%`h=}AM)qTlZIJ;iP1QB!ATp(b!7pXEIWquRmXW;Jb^ zmuiFSuiXNd^`GIqJZwvw5YS`*qfd_Vl&hS*EOg{@Zd-)RXyTSJZYvz1b8#=H`FqVi zbAJP;okRwvLOmp$>e@GlErXzApUwN0?OUy^coy{Q{t5uW{NV5Z1b8o z^no zai=rF$x)A<*yBE0g;Rt|g8&CvMM4&rzu zjljxZ5Bu25epW5_9WQ`G!Xg~NpwR&b+^y{CC_3EdL!NQwN5lJr9=~YH+I{lL<3p6< zUhlT%^R~~>{Nzh_>V~LE-sylB!B>`aUmxUPnXM|wJ6%QDe?Hn-qWw*0>^s3|KY#Ci zkJzy{-EC4deUe3=YkSv12%~*f23dgTDfM~?r^ z=!HXgWn`FueDi;pGeUNicx1s2Sonb(h=KZtgks268t6mlvV_LRb8wi1Qh%6#vzAw5 z;DdQYgt(@MQ{;)3&{I0-imwQZv6v4$xJ%@dP({dzmKS_Im~f@HZsa9rq1ZqhH3wAY zacEG5Nob2%h>D`;bi_D_rm%^_7I=n8P=mxf-lab^!EANGbcpzjuy6^N=5Jx>I}8AW z1BZEvV=V!_o3&SCcC25i;iIPijkN+n> zEZIH?fG5AlR&_`ba>bHDcw`&aKzWsnIr)-!LLu9rUqv%mCANna>3@PP>4M^w9!y3K zMfsD_NC*HE6V_M|<>wxg0*_NAF+YM6L1>IFd6bToWBHh--ZSZwJj_Q?N|cZqJKC{<6nmYXREB$<+}>6)*ZgGHiAvuSs0 zB{H;uj(1`u@%EV5l}2qKHg9qP74c9`hmIAZDw87tXrwclsXYyW0lNtq$7u&1wLs7* zow;~?BBL!5u$<@Oo!vww(TN(tfScH<4)G|Jn;?O6;E#d17k_rd7QF*3)k#howjtyb zgyNJ5Y;c{rnVzdzme&w$4bTQoB2o#YM5C3P0sz7dZhVzS62t#8HM2~p5WPP z=1EIFs-ARkez1wAX{x4+HeUuY6L{o|TCk%6#)gDwUCW`L2f<-wp$NzJSQv+tTQR2# zdX16MBeoS8>gl8q7N^j(5oy_QeK4p4xt`c(m>db1E`J&T7w4u5Y8E|`JN&v*_9bpHLKgGKmwSANH=Vk`U;v?FD-hFf_ZkwWr}Ek zn8g6B#%YePDnWH>c^q^cdAbfp>6?8znt-aE)G?`m!lwsusNJfbSo)$edZ+ZYsgV&3 z&Pu0(aDRqt3a{}huRhhLkvjiX8A^9BgGbj=6C8E{m>^s-Q$bI&aID0w4~CPw+Du); zsqn{h0yY(8M^pF;r$*EW{9}{(YLJx*2LV)@SXVR!K^mUnVU9WhB>0s%k&bfOJpEb* z|4OKY1UkSrpxhtNi5GLaF$xRqLDhDzj+>t&~U&3Sh9GMnzkpwlT}H>o9Q= zyK6qXL`91*4{NuYYA;I3s200K7z>$Mv9Z7LPxFeniL1CnC1MAvmtUxxH--@_Y7~xZ zYkyvf1~AE?=RvubySW^z{|8LuYbd&plu;p>`?-XmxssbF(TN9!u)2>6xu;vXuUiSO z3$=0(K%2KG45$XI3%aUnxz7=~vU_u#TL`i1xt^%JrqP|}*1Wo95bdzI)oZ=ii@n(^ zE0R>W!Rx)>3%bQgN{b4<c>wxcw4Bm2Ah5RwhDpArHibN+(^(M3g=)il(t^utF{q+xD3{6*z-tENTB%Ny z$Nj_`-Mc9VCeOr0T(1Ej6m{EQ=u*Y^veg0zQU}~K}-(fDkt1Q%aRyEcV(En7zfh4 zo&o5a*E|w_d2`W$(KN-;{3tqc3I`5tqW*NO-8WGGCtl(R(z(^nMq$qPJgvoAws1R# zwdyFTsDX1pw*sxwyt{@7ZPb6?yUS9rU8sS$;LZKHdsH3+KJ7;)EDSO`H~mt);RFMZUP&3#I(**1S%Lo*luv0ZXM zoehO#L)Jar&vNk9gBaFAJ<=WF(PyoK-aOEB9nMhr*(Tk$vrW>qJsJ5n)3969FV-3l z@UfJwjtex}M@qkg@YCBI(33r025HflP2K*o+1EY8yyIcM=@uQN-78{>e&9J#0y8aj zHIZa9h4#pC)j4%>E)RbLHnGgHs}0?nQaRc^VhW7j1z;_-FgbtMQp%JOgFTmW@lEE_ z*XT_zt2a=nK-Kbm(TOkwUIX75Yt6;?2yv@f04ta^DN?H;-UWrF^&R^s$6uH>#50E?s}!MV{H%jsN5>%wM^E zfMxX6-#vj*F0I-;UZD4jQY2>IyRt*n+N+ANaqD=HTC_*+Zo;Fr-3r=u-u=~ZijkLxl+^T*jezQ&bWJP?HlO4m;jgzO5Lw=ov#@hnMaA-Mzqnb}YqU^A+ zWpWueg2YL>-aN$wE*=|OGQOh!?F+X@8RbXm zJJ@dvSO;JP;#=+2mFWSmC!9|3BJ8Ofiyk#{KcZXOd;Xht7>RazidG0$BhlkiBSX;E<%V2|cu z)42+rpbAWMHjRHmKM&=fSc!rFr^#^jv+o;PZ~GK1=ezXl$4u##(9}?2^IMr>JSX2w zuhDIv8?#lZyDs(+_60ul{B;j;N+O6XMCSQMHvCy}Q%h~h-0~wre+!0<_=eUUqWVx1 z{hCp+uWL72Bslm8Qf*dk2sRyv`t-N^tPsC{nXi=|Kwt?h0DwmTnZy(iNhfkrd^#aT z#MF5xI-CtF7L3&v0gUh&omQ{eZTA}40159F9OgOA)!U>^h0gpM(f`Z6cZj2y++WM#52& zKo?+{N-9ZONg2!B30$?^tQmel9ZB10%5*y`AL(Hp{(lJoS4gfE{2~v)u`UOl`1{w4 zf;$KmB!C%^z<*&xRSYIpd=+aJ!7csJReAR$;6QHV(y=V{r``ZL^}-#9@DOKCojZB< z^qJFBP@zMK7BzYlX;P(2nKpIG6p4dVExrAVKn9AGRRAK4IWnc!FD$_XmLdjbUb1jM zd#beu$DlWjGQGS_((Q`Wwd1M=NQ-WYL%j(i6gF&_Eq@$@3X}Bmm_#qvDGK%lAjvqf zv$NRblACMU|DWT)do#z;NMTKsgw>v$et4A}Sqk`8I|N-8jOt=8huOX5yA49grHL0e zejItvr^}f)cm5oDbm`NnSD(ZVHPxJ}u8hH_twLB{yw`1pY(5p~+v1Yr>2(vXXZhYJ z55F55@PGZjw$7<9=YPHS-dOAj(fY%!waNmjKtMH8O0csCWg>7P-~_O(K?t*(qK{q@ zkm(-u?%=MLaAb)FpAE}H5G?ZaW6dnzV$y823~js-#~gXGj>jH-{1M0?g&dMdO~?Z9 zzrNtX$Q!a4NQfOIe-mp8*?__DKU(@@Pe(UkyMMs6`KtLWMP!P2heCd^`Y(YMxnxs2 zW)?_*PWb_BfwZy}*o5(a(;|v%UuOLxr=xJk{^o0M1>B zMSfCk1Jq`j5pKi54op|1GV<((+Bc#R7NE`I8uK7B>a}fMIgWf59!tZhC(|$-R@m4T z3rM0qDaLTo)Q49M6jEd!^9ofOPsJAHlz&xD?AMlEei`PNWu7?^G)OgZft+*B6WKYw zyTF2H|5jnpS$pd84Fd_3W-@4{-<_o}3-bJCmZqb?pxP~0&Q`=U242)z!X(Hz1CU4B zxGzkD?ghzz6(|hEU>lHHX#3oVS0~{F%78XIZ`K*`Ju-%1Z7kDpd#7BK)@W{}kAL|3 zGrcL`dlfq?Ea2@3reE>&bK)>-3OZw=sYXX`kr!9S@vqEgfC2}CW|x5o zl8#7A&dP4g)i=O7dF$ehKVA-+m0zCu=AD1uDKy%d9_wN2pl$ky^KG--RHtu;+>w;tYff)!nTde!y(-hblwv2bfD@uv?TUW4=gejWhKU&i(~laS~HZPPmj zwr2+JHTG_F}49m#-KDm8ow zc`=mX4ATHT8{QCyIn?0}^>DE>NRWDPij)FwcEI!CMlF~*p8y{dC_?40et*i~8Tvk_ zGLkT$iEPlwFUS-;NwuR{Y%>vWutyjXA)o;_3!em-q>2S-%3uD=$zsH)!6X6jD}Rz8 z|Ji8~Xq!Eg32$m0XBB&Sva)U!Gq7>N$qG*IqBalP}5y`;4L%O41 zk)ucO6v;0do)VQa3>hnxG(59L?nrA%u87sCCrk?>7C~?|ZP=g*6p??WgD6R&;&4F6c za9SiK9qOXQSnczn8NKB%HQG^+-eI9373oMxT2hmqbUGO2mObeiDr~9rqcKGTN@-eC zo8A?bJXCsU)Ip{Gez>Qb57RHr@_s!^5dRH<53t6mkWS=H)R zx!P5)eif`?73)~ZT7Oovo)xWWRqI;W+E%x|6|QlW>s;wtSG(R7uX)w$UisQrzyALf zuz?lqU}EOJSN!w{~TUz ze0kjCkj~e?9>`*l`HKVs6Ipf=5bzV~i;N@tcL3B;@C9GgQlZ9Ul1A(g2e)ZrkLpIp z-*l0RSLex|l$gqBupLOQd?~<;_#b$3R)f<3o9}Ha41bY;VVIBSV?Y17oj`8dlfzeE z#~s>yM?UnES)*hjGr7S16)-jhEM+zf-~b1JY>ODy!6Iy0Cp4jm1VB>Mj@by)n$9ek z`HTl9jb|@#KC_o&MBX-#S=P;v^Na1a2G}$JXc1`RaPt5O_O-frfL8XhUkPM5TA;pp zYVsM5Jbzn5^JB?QnD#fe&5sWdz|!ss=NcZolU0y6X;q>%vhToZcGKb2oEHBvi<^OF z;;EtBDSk7(q3L3#4M+jrBo&>D{RmjSJ7vsP_`-4MY;FHn(rBpm!ynDEyU2=uWX9Z;QhrXshWEaqYsUPDL)g-Eo1Uo z=o}@8WQDwdj%lH2$y3TZ}QDsnoEb0u%VQ8CQYDOx-A1mh*7Kt9Fw_wNR+K1 zqks0UR|xNBR>IQdu?&X#c}Iyq{p5$%om*Zq2r-@j+Sf9! zZPPiLzvc4uXCp4GLP+6++^7)(Wb{by^cv6seI@lUE&vSewkq(pUatZf4ck1x52oz_ z?5jucf#CS#8+2wfQY~W?Kn351d}@M|R>+M~httwb4OU_2vPA_eY6Z#eHUTwK5Q$n+2O6M=EJmRU^P^~h?FIiSOa;MC1@X)+ zCgKO*<j^msVjSpy5dfFs9H<^76&~l4JsIrVjIA43F?EaPAA`$am~-@p{7rq3BOm ztmc4l++xh%DuaM>rU-wi5A+7`gny6`Zlm`Wa8@2r6F0F)A~54TfHjB=;yy9R@+9^k z4HPZT0(yib(xnyEjRwVIEE1{0((fy-Xa?!-3?eM&2u}3wF1FYKM1;eR!UbdU2LVWh z@iHt)RHrWROf{nJXiP^vG^Yp21#d!$fcPO5r4K)%cv?! z4x|ANPtC)|(N(}fd-$aOTBx$}?HZ5h5^Jk|c7km9K^Y|mg^2MO{}ZATf2!9oF;+Oy zAs^B@JaGcEO%yNg$qr2QF76XI@G;D*o1lX~h=_ak%v!=A91HLa#(+z@;a%897ta9v zFlQFiY#>{RT6V1m50d%{5q}m>WeJ4=Cxe9=ZAm5B#SMQ0j_Tpw0Ff`A$v~0>&vq{k zBTMkkQKJ^A0P=|q00TMq0yH@zJ1#R(!t&FYGGA;BHmwWAE-f=H$TYQ3 z2_6v$C2ut6vJC8!R)6%;JkQf8_|o-QZwe+ZBfrh!WG@vlU=%G51fN4AmZl`evnMC> z2}y(?Tcyp2MFP(s^gvfjkC`*vq3*4OG;z25}=fmtjQR#96eC7{rn?^?&jFIJ8S1RBKG=?^1<9 zDU%IE%_hh*6VX#im()nIO#;~y72m}J>8k^0k3H|xIb?%2|JtPgx<)s5v(}_@J2vCs zAawT@G&J(TN52y_C$uD2=Ry-PK=H2|Y~nBsLsLqwcKFUNeDnAi<}%LIMAgg*iBzVd z!J>{6Mi*5^6MqyiaPvq15Fc4(_?X~M@w7)3#35epU50c(E#f+nw49ifR7;f-Jn;k9 z)Ahi>Ju&VuF^=|D6$!AkIezN9!hs3UBQnLbMpH66C$%RS$1~BQ=Jw1}^GH*XWLN)U zFBU{HSL#pk4;?GSd@vLyImS`jh2CKY-HA76*UhlOLJW1E%d&XVvuvlj8rP!wKK1E8CURgy|W5RX{gq zPU@r?N|Z+9#3rW|MCI@~+cZ5ou0nJ2K$gi*KF3+#&wLv8aIlq>>Y=pw%@9v?{p55v zNI_heXn$&0w)!jwMa+h`NF^W5gI#6Gx-7`~97zK(Ww>xs1ANwG=(S7m6>6iF5F!xB zQgI`xO;!sNK2sGwH?V8zQ&wrUISAJCJ?{{#~7Jp}FYG#Sk@@Z}nk-QAYp6C&?tQA}t zwM4`ra(l3Pe$8%&=7>}$GLlX(tkQ&HZVmh|C+dT5|FaKuBdG9Pwm+RVN2C^ab9WD_ zR%@MfB89AJf_D!TO=+suBLC9SG?LILjY^?|344%29fxra4TJU+)KpG)o(=}x_Hy91 zC4XpV&CZXdpeATc(O@#b0fH0}_oiqyS_|jiIrwG_kklgfMCZ0 z+Q=26Nz<@L@eTwyg)3|TSb+bJaPMGn3V)}UwsZw`W)CEXa$t;tXwY_%LwAEXYK>RF z$g3i)_9Fd@O1M^uos7s<5jsLhPX;1^RLF#Y=o0@IMisVq)5fxBymvGJ=wz_ZZep@H zL$`$7w}8}GflB0lxkUf?H$$a08PoXr)DM2F_=-PhaB0j<)3SUncY|A^g8_x8`hQpz za>>r7XCMkSkp;0Jd1)hH_>b23j`jEe(N7LY@`vkHh(Fm>d-uM&sXZ$aM3R`m0L+Av z*f@#!0}x<3*5#7MuQNBv4&hb30BSm=(nbHi$N?`ADNc*_>d!& zAi80t1fsjbF%{!Na0C}R)WBp zL?viq>UiuPvlPw`W~*KZ2C$z`Rtnu@+fF>kXstM}L*W0GnXT zq({0v9<-wegpyu5L;V?{e;TNRTBwJbsEhiVBFbz$_<5+4y7-tnM9-wg zni{LKTC2C3tGn8EVd@}ldPEv{V~o?Qw`QihTB>!LsvU%*&Kj=cTCV4suIu`tz%e(YUXtq!~y~hH(*PvHQ;{b{a!vd40X`7eKEabxL;~JY#gy*_AB71lpiFHta@Zu{a{k{KPtO zD$K}{^omXzV*{`!gq++knXLhkhrKKO|K`=2sAm(_!18z)%KssgY=i#}QQTq;G>Lrh zl6;PkJaHCrA!W=MP+ZRcOvP{f#RY)JpMb`bz|LDd$N6E$ZGXJS*?>B}6gj>;Gtk@* zyUd3>`Pk-9Q=FV95Ix2WL$D#;E7$VM1uA?$ZOa|Y&3%#5=f%?7X45s@%=51KFl^l_ zFVw++ROVdPdCW3Ez}8#b)=;(2+fsm3^RQSs+^-C*(b-t9_5D+}s}` z+tc9E(OBXk+kjFX+{H=UC85P!MbeE!-8sI)+Fju-V}FF=o#CfC$4m1nU~@e0?Z9H`OpP{W?B!yvDk*~L zGL*N3b(3E1!@6GXDh8K9jqDyHw)r1o!9JyHa!fD7Tbx~ zKA07l&40Q8*bXW1|CpP-zH#Z@iLyQpz8&!AWbZHnm?_NgF%R#1L4KTG4~(ly98X@> z9>Cr3;}>CG5I_H-9_k%mY#<*S|CK)Lc4ONaf9$Jn@ll=;9YP7=9wj^<_X{8F#3H`q z4(&~j=Quw%M#1fjfeXr=;8a8Ao8Pc#e&2DN#eZeT-+_J#dcNR)J?A;ZI`Wu)>~=>J ziHu{n2WxqK$s_pi7z6gY(I0n3FoTT(8IiA(rSr#;$H({RuPiM&w19vD09*pb<6sCt z7!$+D@t~Ye4@e00c{DDv%I(mwMTEDc49E*n+t(F7su(XyAKbR%_T)@53lrV<2XT$7evHUjB7 zd%OEPe7yWTeZBoXe!l)bf4~1fz<>e=5`Qdc@F2p33Ky0_!hu5vGY>f+n0UnE#fKO+ za(r;4!$VRV9%9W8K*q*E9)Xn(*a znbf>`_ww!QR}auSW_p&?g!g8#z+rm1omsP*%md+!p0V0W07yW$zZWdagNr7}%9z}c z!c?0^{i^_th0hwqIZI5Hv*%*382{0o5_lYFpNfU@9NR~8fC@6+*k&yQ*{HntOJZtXf*vujLN;R&N%qT9<8e zLx8@W02LEd0Ms~yH3!%eCn>lfgAF?PAcPT0I3a}}d*LnMJjkr5b$I1z~? z8S$YUADL(phVGb=jUHqi7mXv_g_WBkJvG4HPJBcc#e5HZW}X}wl%^LlJSFA8I);C6 z1=B9h1y>`Dz#&jUip1oRhKvC4MnE=`$i++qSt@rXnrW)p%#40{GNqSr_SPntRNf(2 zokI-LBWRfIX@`1zW&@>@d4aY6<(h?7HbDSJ$|j^>ffhO_Viv$@X<7x$sTp}Z3P8+_ zU49v+abD(=sB(cFwP>TgK)U61p*nw~NM?Ng6`r1`Dtf7sL3vswlo3eT$0J2(BygHIc^$Kv7Ms^^MaguPO}j9|mF5V3zA%i59e z7U6AG6$88KIx@+qO4gd6e7$)c6O6pVF@4_w+-j~yFe78iecBwJ8l!aX3i^By;bVL z2sHr|MKCqt=@QAucbZw%szzWAb#$5ThuFeWnGJN83CKRXYFFAtyR&Nh@;2w0k?k+m z!3*z~VqxdCG|Px#a{3@-L#nUMHEV9A?rO(AyX>lojlk$5Q#te`*JFR*3-U@A2l|WW zYtId=qfP(&m{t#us;ZfZ2|juqS8x1Yj|czy+r)>v^Q7c<*~=aOV#ciIQG$1EtJ~d( zFt`a)u!0u6AOoMezzo<+viSFL9+L*J0uF=ENw}L5qf^ ztCS5}s6RY0OfALR&$EAMK`<{c#dN%L8xOg|LeY&$O7nXn6xBe1-w;q`=A(=d!eXEF zg~dB5GZ?Eb12$XrtPvrLVqd;z8J7GZh+YVp%S2&_EMfwEG<<`MW*9SFY|&mA!yy{i zRKGzyLXCW+6V1pd0Nn+$hgkVx%*;5%EEJJ-QqdU2zO%>7RIz_nJD^q2cuKA(5;Ih1bfVkK*LVs=)9w6N?%;q-R83l1_(^Nn$XP#1%an zEdj!MCNx0>fdgFNEdRI2BBAzx$!0B46In`LBf~j7QB@0zSHwi7x>+2fRnnN#;}g!t zh_66Ev!3G2iy?ob*G78Q^O?$%qw+wb$Na@`hleDlI|(Mgd-7$Fl_}&JE%U-14m6Am zb>v~P!AySk6E7I}q%}Ep#N8n?k;k1P zx=V##w5+-UrklLcT zt0QlSS2pHPu5m^GtT3$FrmSA>X18GHB}dA&&`ou&YKodnLo3?RlD4#_4G2vSw<>t$ zbf+FvExmtI=+H5JH8;Q$?4}|H*QVa^P26$e+Z5K&(a@$cXN+tOv#77Gh7O6f73?~W z%S*^o*Dsw-t2wi~yZ|!Bjsdf1&vN!Yuu1o`v&)?Kh!#;@Xs?0V4d~1?u-o@VOg)@n zpI9_Grfj+i0{&g#|Ae_3!Hj~jmc;Eh^m{Ap1sH#!#f@HhbGbU@#;my{eXeoq>%Nrs zB^{^zFo;7e;t{7ZwdPvY14>k=5vGB0CiH1+Z`s(B{-|Gwk*;Ajg{Wopt0LoMo2YbyXCIQ54%aB2`>VuY;aKqwX$ zOIc2Y)v5mD9g!=M70dQEg_g@n?R^(E z*z_iM1egu~43HiBVYw{8OUeYQ27p`KMb^uku~z7XH+{UpcHxnPTu_b_PK)GAtePMLj+;<(^c$?u52=};etnrVNN!{jV zcY^)!Zku#G14Jidr`!~ls_JZn1);MKL>i>{-knz7kt zOkOyQvIF#~%4p-T)&^A;v~3D*Z)$&9N!dgwT0_ZZWnrPQQUWX3o^rC@yYW*NbYERWOq{Rm<7M6N> z?5E&Fwf{dnvkx?x`^Z`P&o{XdfXQ)p{j=4Q~^RZXKfKpUzbB={Oo1rImu-pH7n1a!|G{-IRBAs&C$O&mTTA_hYQ zSy&$yVvI~1SixJO_#q%BqBiwfC7OaA5@H^zfg?WRC#oFzJz(&LS<=qAlJcF6N>x?jkSt;yp!Sezji|rI{}l<1YT+C>oh(ErS8Pn?{ABI$jhfuA@7~NYvR| zrc_kpN#i?mqbuH{KJFtw_M<=kBS3vxBpedkUG61c#w7PV04w&TU=Ai>7Uumq40;)+VlE~>Du%JC zA!J6TWKL!~K*Hk$=J-J5)kJ`QjpJT$CIn=ne`yGaa$II$ex=bQU<9lmCt$$(i5Ey3 zTZb_KZPKP^2E%HeOCZYh0_3-97{@yq6|aNFyhrXir$$*eja9bw3l+^!+v^U zJfg{krqMO-MOPhwD(T96tO9b~(8y$wOy~pfO{jj^r#Rpz@xhtw@uzb>;UHSVfHqQr zUVwNC5^7K=GMWl~4k?iqsff9#>M4V;e+0&KLSYkH5kmQ>Vcn<@T~t_+B#h)zc~EF9 zKIkQ`CL$5pmd@y3SZJ7X$unjD=$ULNU#O{Gd}xTG;Ej-Ij|C3`q^TchU79Fpp5dL` zDJhsnDap9$UJ2@++GsFzNgJHz6J2S^@F|y0m61*=rB4X;r;yZ{h>3de+tCDn4~6fKpQi#A%|8 z=#%aOsXkE{=qZ{&YK!udrs@u_rU{`&UZ|GmvG#?jUO-N4Y9OuZ$S^A-dIyMFD!G=c zxmFNn?V22(0zX9SDY)ws<&oQUe`2F*Rz|j}mQoEA$!a-uYORhbtn!7K8mdPM54=LC zuhMIoa?r3w2c4D`8tj94+5f6z?cBOb9GOCCwceAw4w1qRkGDE0#XjD+o~y~8EXsOI zx`N8ZG9Y{;Km$C$Jv`L_42W(j0~2;eig?1aPC%$Wz_V5%pgdk>YvUJPvC)@>!i-pj`92QIF2G+@n2 z=ipi`;D&+7Va4j*A<|Ore}MKa(JGSX_ssRBWNk`sY{0L0t(NNkx9-=M>uF^u2>dyXVK`9ud0PC+)M2rki0j(6U0!Og& zA=Cf1Ug?Uc!?Hu_e<@Zh{7&u#!Z_BhJw%*Jjcj<02@hWA3k&cuHQzPCPXA_cF#zy1 z;NTPLFlc1&k0r1J>;K+7HSnE$@g#NdqFf+ufUEn;FCEvh9UDY5^_sTk;9=Q_V|+pB zGLKehm``kLkNll~v=e;P-`GkdeuS}a1WD~AV64=idfMt|UNV;j-91tQX7Us*h0{U@RUvXE2eF)rhM+#OQ?Z6P>(b$ovOKX! zJvea$p76ftfAJ-6*@Y4_@g8%1K=WUrXyzzJ0~~-MPm(zsi&ub!qJguC+QuhO)+E6zn1Cr`;4GOC8<%t5=!|7;+ zqC5-eY3mTRg~cdo=@3hu`c5S=8Ph`BR-AO77HF1qf61iWOtS0{*k0CrM9azjTsO|6 za<~dqcMSsFh>(>LEtj$Ho~ciBX)xei_}T8rA%K`UU*AiB#!frMRh(R(3QJALvXwx#mIzFbJPXF4F}3^!;)S$q&o*s? zLSh#~_w47?EdQuVKLMrPR^<5!7-^B14fcnY zv~Z_zb@laje)c# zgxiZ}W>tfCwPtyDk@0b$1#fMqxQfFsI{~Hya3+QBC-WFrZzm}iW#WuS)fhyle;rUm ze;T)by-ITDwT)oU-8hHm;to~EqqnY)1M&AVS|epY^?K}X*B;ehuJ0}%skwlVxT7I_&p+$#Ag=C^yLhb=drf8S4)^NO1jWNC6w<|4M` z{v3?YsElt|&3GWf$|8lAik;Vx?ew^Oe_Kw1eTvL72@zPJO<++vT)nQTAx7*vQw|XD*Ijk4Ex!ZV}7b**hFs^fJ*66B~b%}oz%n{$0 z7>m1zm;aQvD|^O1u^&)Vs$V?D)90#xje9LrI^DReCxY*cI|7FaNKqJXB^W&Qx+bOO zs5nAL*_=L8fUtNIzd!ukPK=`0f4evK0X^zPwCg+?40md~y8Iadwr3g<#Jp%;RJT*8 z+I;+2IeekILb)UC%4^2V*F1h7k$Ag1V!`|L==nkQ(u_{4IBmSwpQ+UE`+?E-EGHew z_vhUqGc|?Ok3(|Sf6kC3;F>W#&6HfGa`6csdnQ%X&ilD1B}m3MzT-#cf2wms&K!D_ z!d1vyMLITmNz;9FbojKVyuq{l$5^bD!6R0ig}uW0n=^3hpuI0L7nMU4+57o*F)8cc zvW}zw^AA*O+b3d<)4Ss1-+ZmQe%}e=r@p+;3E!Xog>8P9JD%9%6=9jV%0FP_s}1E# z$?zk;61((`!*{z66IT_tf8GbLVD>-%21nKK<8!8LIt%P(A#Q zag76kC4eXZ0Ea*_&@e`nPvyawc~*>rBopv>Qj86#(r^ubpG3eSiB6o00AWDU47<}% z#&m6L*P#+41-~~eF}f!+KgC7HM#o3Uy1ar&sKBJlfFds2|mz zi?BJ;%EgBST8P+KsXL{JOiKWUu#4UyJ|&Fe#atmY*u7tk#YAV$V_l_5jJj$hDCH{8 z%Krg~afrg(+c5xWMA*#Dq*uYxW_I9nv0A5lM~7iK|9|w72&2c$7&1kPUNJDY#FQ&N zp9*Q=G7n6hbnDm|f3QOhA+dmJCDQgKS*c*vO`JJ(?&R6i z=TD$Pg$^ZJ)aX&9NtG^T+SKV&s8OX(rCQbMRjfe!SsStn<}R5ujTA6v^QgA~TR{!v z(-47#c~m5h8aZUr#V{Gma7E+snaRHv+Cq8j%pTi_1SV1Ve?x$9*iYO*u8qlc=4H&6 z6a2m9uAQz4!`@^|`|*wBtrft!6l=LOXJc|>tu&H3*;sQB9wyn0>Iv<#G8Z?F+nTcf zVt)=CW8$0X!N*+353)o%sv#t1zHKwo%Z{68P78DI4$!;ez0d%+zvg84YiqpI$y%(( z`1f)G2z7Jye*$|5T*PDxXd+R>fy}zSIGWC{l;A-|F#rCeO9=zH8t%TwT$|7^(khE@ zrkb)6aYPbJH1R|fQ&e$97F%@j#jLhUKmi)lVQn%9E{I?ihkmg@f>*XEsyZuR>y3d3 zFaWXu1p^YW$U<^qfC42a;YvvfBU>bhE<&vRv}k zimDs%f0pbJ2sO4Ww-nZ~Lpup?EC_tC|FpIvq^;t8st5cv-3gO%K0HqJ3u+rk{XyXUTf>nOkiC5kkOd zH`AQW&8nl@`91l5er;#fPW5@#nPpl!<#+!C)7GSs-Z@?;hbFs`NN)`E?w_^RCCIn^ zf5?u!M!cPOP?Wo_19Hw@<~6Uo`vy!q&!x%NlL~!~kMW3f)rAd+h}PNXG*hSB?!a+( z6Y9{X#thC2Ocs84;)^%_c;u5;z9>DZo#24O2igy|S)NWp=Hse4Zf_rpo2%%wtEpSf z-lZKFB(>#JmTPLiay#2x&Xe9|vM(4%e{R7iSl^fNtM>mgEhr#*(fABE@*oeu!E1l3 z;X{8ecQ!ZCNO1wMAGLJXzH?}g5>#{G8*ml|1T?@(=c?ZB{15>v$)rC3GXD;pP)I*O z1x;`g#2e!jv_iw(f>P-Vl?MY?1p5GyUh;^C4_5|45#lcrHmVEec18>6C1ZN&e=Ffw zF6XrrrokLr`-I=PmoD!i2z=BMU(d?NMUcp203UINc2E^QV@wZTWrV^DVOGEUJ>-4* zlZ1wlwI2s8PmqHoWFZZCNJJ(QDUS%&k3_VFA1yEzZ;`+N|0g*vVU0pqazrDWhO9_l zQk0?k+QS0%fKVy|mGaZZk2Eq9e@e1)l(2MwEGPLaMtD+_pmgOubU91zC=r;r(8DT+ zdCYzMQWm(RWhIlDN@QZPmmq}ZGNS&MCj!Xv(Ccm8S$?XOzxrVW-?^}PB52ie=ZN@F!N^PsFKU)sBob} zM&b{57||GRu@V+tVrbk%#UwVt6COQ+-TH5hR;00#RWj%@*G8eBz9f)|3`td`dC7L3 z=iMZ%V^yU?zW2nlXs@=9S_iczqP+EXw*0MG?i#ZhYl=2SZDUoz>A=|G^Oiyd=+`s| zV#}^$tUo9ye^oys*XYr+ESl}-JnJIPk|T8`41Mm7Wmp93X7{=k9Rd=p+XNTJusJ|1 z?@7b^2_(2T0z8ai9^G36^Ug2{hPi1r^0^Yi{$H=*dE)~J=>M29(oumw=euR8+KLyj zxWdbOZG3L~vkuoG$RW${=pGwm<@O)SCA*d2F~!)Re>z9D1?>rE&m7JP_v7YFz8#x4 zLgcq_zyZQ$<8Qb5&zTsvbB!+XnV?(hFUs&D{@v&#OuEuZ0Pz$49RdxkBE#n3cL=sl zfUYay>zSq+!cF0ENVuG8BY@4CKGw__HdnE>+Qn@Qv<(c{Q z(TACMe_c1>k+CpyEQ0Rbr2jqKJNM7!w=MI_-$v;N&-}BQ&c>=uUG*!fx+1Rr1QDbi z?T~%~y$cb0c;iI&vd?MDc6F)1m<#~1v`}oqY3>pfLDvV^y5C}v$z91 z1L^w$>LVsN06+H|F!H;L3|s^ABEAJ^2=X%k1Yp2>AQdaYKLs-Y8o ze;eaI@m^+FX6u=NdBLhr; z2C$_Hx;`_jfChLV_^SgW8-OZgF1IK>S1>xWza!zl z0HMJ%ctAer6^tmq_G&~bF~J!T01BbQe^3)Q)ce9V6htsghyKw%PPx9-8^sc7JwJFo zCBQvQ<2u??f=OGStJ6K-o4r+Z#aSFBgi8mQP&i6SoAF>A&D$^4iJK=H9bc@(yU{Ps zk(#05G@;6(?14s>!y^9R5sWj&Q=^cmkqOhWBAlQ(rx~AK%*G**BVh`oeUcJ7fAbdW zL5%)EpJwD4!($veu^s#=of(rddc2^EBSv1_M-pT*c8r{wIY$05M_a&0HYyUEDHyP+ z1V9oh1k#e+5gVTgMvQWxvtS)aF~^5^qn+tL8Im*qZIDJ_vBW2^oIAwCJRC-!Go^7H z3_$EgQy744v@><&o0N1lF`+*je?msz7_XhM4QOk+O!0^JdC18C8&YgatWdXhTem_$ z#dkY9-kUwJ>%9<=q)Af+T6D2n6eWcFwUpp9OId(7LZAq!kp`j>L)6C~v^czgLmD~) zx2%h^OiQ4ImyWBUK#0RXK+AM+Jhws1H|QVat4m;01Q~IFqGQM=ilK5be@uTkLZj1- zKT!y8%n964qv_MjOhL=(sh^*dr@{;p#EeUCsR)D*uz z49M$)K--K>XT%X2Ig)ia&BN@Bwp@TbIFGf2um9wH%at&I+=PslQNzEOPP?R$CW1}b zWV0y&NylRZf_O)47^4~Kf6H}f&Qftpv+&BF(#4H*KbS!XhP+L1P>VH`Baxg2H`EY> zJ5S=|5H?#uu>nFyh=a2nrW2Kn-_XC%?i;j>>`%;Mt7 z{#>>stoJ2v2Y8JNjf4foM{nq74j)Pa!Z;ElAbu>xKO&RE2Y$^{PJ&$<$sYQ-{0JrbK1Dqk)u^iQKkT3ycg#QMD(Vf6f7hTvxP_}~YlmtA3=XzP_f?1fI zO^WTdNEsiye-oOCRoEI6x?!kTcU)P#D?GT2kDUz&K1Eaw@VJ~kS~g48n-j{QSk_3D zq~P=eqIFtcDMB8V%ZRYpyf0V3Mg?FBYU4Qt z5&T6x>_7nLWmepgr72rp3XoP43WMfdUwaZ?e{#rQ_}z;Jxmj^tQBcWXGT1a}!(GfR zVxus{I{3E{FoCjb#m_YXg2OO*^-)O!xF5huD9$%|#lSp*g}@ zR1M?R-~=IF;oh}_W#iq#`JNeG4gXhV%&?e*^MedEZs1eUUSEvfHy}f9zzM=x<2T;P zf1aJ=aNx*i07*0b-t7U0nCwUW{acT0M@gP2ePQIMEnrC{!IfcyZ{*45xtqw{-$#Jt zY#|%Sv&T|p4jz)yQ1(uqtmD?WV?xn`ww)Wssa9mos2zKwSw1sSo7`h5l8NdwP=S!< z0@@Is+YvtHV$`RFyf!E6WA=bya&%xCe@@s+R$NpS)*coJWIpF0zUHAaVs-`!Bn|_r z98yPXMcms;TeRoev*I8PfO<}0%1S!mfJZR~=CVZ`hO}f=7HAo2V?_p#wVjSbJ|Dn% z5}XrT1|D0d!9G3?3umqqK=z>j_WZ_IjcE1&Tu`>gRK|r3U1^ryP$!s_mX7H!e?!Mk z)}9=xIGKpfl5UA3NH(9w6l0!bnp0qAmL#GL>QUwcoH&4=PBvv}%%$om9s_XHX&P8OCU4mfOD}NudpE z0*xniKEG_{=s@6Rg#KgEqv$QAe-@@*OL4Aca&{=*h3mIYXI4|)cCKuncxNb}N)52R zd9K9(P-3-XG+E5beg5pLyrk4+4*8+#WAY)ak!bPTCPqkhDkhMhiV~M6|Pf%ds z8D7g6&k=5II%VE&o8Gq|S^tqL_V!=tdRx9X+JBf2UW-z)7gB zquyjV9tHp9;li%rTROt=-FFO z@9L41Tiu2zb!Opfb75&^2t7HXLOJj6(ONpnVZ4^+hI;H{-f-VYaLfL1oxp6bW3&-( z#jE6Oe!j}xbK=du*Z)ave`aP~mjK(fUXPqZZ;#dqeSmQd`0j^Ax-?7)^cDS|5%Zg9r4Hss`lui(TD1N+j)r0e4=hK`td9W;f%%%E??m0h>*oC+Ttc6 zge73!p7JBlMD?iffHiRcT4pGbSOo0uTFT=Ce_-<(zbxnGZ?+|ae=8SghHj&JNb|Z~ z^zBeiTENK5@VLLt^1YB$u$5NA5sxaDa4}Ng{`ioDwr;~Chk{-?bLQ~=#sVJyZV+#E zvBNN{Bk_F3=c@$m&$ZVYWkt_6Z5Ds=e`H2T70~fcCQXV++*xLftz3kgm!{KnO$~Cw z9P&bd5C&L<#L?wCf57O(fg7b&WXY&pGT+!Um?-`D0x1usj*JM}xCwO4cC?*tX-{?> zF35MJ_UkANxHRl(SGaaRc3e|9W4Cw0kd0p*Kl2spekBgK&5$^T4q?hRWp?)n!S`NX z_6$my>nQj?U~K^(Hvfb@T>lPvEC^^X*JDv>Xr3O{Zs%#oe?xXBz1l$u&P6@&9{Kjs z!1R>AJGWq=F*owr0rf7IObqv0*sehzPW7CTd8KxBSI;mge)^|}2F>R6RXlAJFS`>H zfhG>PUPp1Ulyqj)6N>2<<&Btx-^m5w5)h4@DRE4+=9P+(2DhUUN`Z+WsTNYPZ(;d# zVJVh)=Z#g^e^4vI_VwOBwj2wTF3@eAo3W=Eo<vgE$!TjLne@ z*c8X_nO=b=xX%FpkZhW46aCoF6x8PwwNXJwf%!-ve|<4&04~}6hvAhwIs5ARct3#b zoN0ahsrw9Yo1vNg!B+fLF%In4ecs1g>R%iy;*-(GtxjMIbeDL3<{Q!REDt<2^C<8O9;#)SBlVw|A2oBZ54rr zhlovf6Ix1k4*_R*k&t8o18o3m7f*CXmp~yR7=NZAxVgF^WhS^HfVl_+xFdkRAtOU0 zyT4(@$Iyw>)PI+iU6{j62AJA`3f^?pVG!a_f!CM}Vcq8#eCJgH+42tmVQ2D7l;cuk z0A-qd%0!Nd19@N4acXmqn>=`L7Gm0y$4$LXLjX*3Ck|p0iG&V?TUW58Ns$TtVH?0k zAAcZ5XfyyqFh?AOl4roE1SmxUNIx?{vcrim!ke1jZeHwYCZ$831uYHUSbA`$wj3{q`LT?TEy)!$ZO%%A( z5Gn77v!he)oErl-FASB{MYHjk9REbfUu8nQUo=v;9 z?c2C>>)y>2o+e~ zbT|`wUYW!QOf@=2$c#9yv%oftlsL$Z)jR+ncOHJnP=Xw0=9!DsAi(2wnt3B*7zcUv zqg$4l2Z$U3GH8aBNrX4znFA_N#vD#cHj&?)Li0Gc%aXrhpMd8cc4y2mGT zz13>#t+?i@>#n@^iW>sHno`gMbri^|B6U0f3$b)sqlXa1R>c#u$EJgon}5|N!mP1@ zY@00~(H=5@9p9D<7Xsm)hHf2=W;-ss<|3VCxVoE?vg8R9Q6i5v4{#cEaJNrpR_G*;Ntt%y8UY0;yxyu<(?(!rtI>| zFvl$O%rw_*^UXNt4Cl&-jDIw+yMN5_v(7{pZS>JdC#`g~>I}U!!=66+^wd;WP4jYlmbZ<;;-hB6cw1X%o zy|v$j7jF3Bh$r6g;EXZ(t=fYrF8Sn?SI%l5UZHLI=A3s9*BA^mD=@g(o|kU=>8Ph} z?x}{HvGC>a^;fd$wAXI?)7Qv;`|iB=E;H-C2QU2a#24@H>&BPS69OxjFn$Xrf6QA3 z9x%HEI`DxIjGzQ3NWluaEL5hkpawU{!47)xgYk<114cN)7yY464QP}C-s6$Fz2_iA!ZwDl| zHEjxQI@Xe26efs`#U?tc$TzY@f4VEBsak6Z!xaNC2O>3r5sR6k9Op>KI@ovW z8OWZ5CIi$wo1;oNG%f$Ntv}%j%_HBlNR4y}VGWwYfLd1=dZJ{TeLUs~dpXXAI`p9s zji~g>xs7vnDODz6CzmQye*~<=5t5voha zN%W>T&8bdzia3gb5?eLJC{eJa%s6(@k^c}XD;wvc1%RkP7({~tWcdV-00kyQisw!M ziaDt+38P~ef>Sq2C7I@OLqN5WHF?U`wz~DLaMhVKsnIs2z9~#1e{EfmMB|jU0Th%e zY!Gq$fK}}H^NaoX2Suc^5||ReuQB~Z$0qC1TE_LVn9ZzaH%pGWZUj+{R7}3G`NhDJ zGMltSgdXytPBTum{{kTTN=uZqOURkFs4-PnO%gBx(Q)>-zzwc&dFt7OApm*RVI~75 zAVRV(bvwgY&hUhYMJ*_MoCe}LK@|yR&=*47lXU5Dw4576k z?UHXd6p%5gwlUWgP+77WIAy-*AM-s?d`BiGHKg~z2u`qqKe%3*wU> zx4Po^Yf8m68pi%NNc5E_VwTk31)KQ9C{D5e8XU6+*JG8We^qPH?83xAQ~_O%6=Nc_ zE0>YDsgff8oI+Jho~gVDOpw-G?&^q*X(3qCo$+ z%73V=~=4GnZm}jiq zcDjc?)M4Gsf9OU#`q8HQssi+w<_UwARb6~-MpEmnQ(l3aRj9*AvPRMh)WHFTv8rU` zl&V0V$uJo}b!hG>>NZg3WT=F1NxBK?Ui74NqTaW$cqu>s>zz0t7=KX6L2QQbmCI&C2xx3&HkGRAqZpo-pm*N=DxW+d= zL5Xqv;~)>Y|Hwy9@{*hU@8E8Eb+!(u?H{i8bmf)_6b87F77*9e>X%CNytMFy|4+MKNb?#WPtE0kMpSK zC#FwdnbfDlhiM(r=y$j$*+W8!tXlo=TQ4q0A{TX-M;z>H@B61@dqi5|OsEAteK1km zP#z+8u^<2R2hET1Bo?S^Vzxr+u7CEef+0*HnRa7aDWJifRB)X^biIJ*e(eefgI2QYGi;32m(sue~iL+q4zR= zLNnr)VZHNJUeN%hXD$|iO4_4X45Cq1R4wpiS3Bknu15_nh-DjdRzt=-H~2?H)lL>u zW3EJlkz`IgSRFI9R#g-!yaOAnMSx(3e@Z7PWIw26Q3HP?LQ>WRYWWuy?AB@OM_1;j zh2BtU0_Y9)Mt+}>OBz^zMTmvuFl@fnhKojb3o(Z;^%iufEq4fpfB}A;!G)?ZWBC^V zWXNJK|0973xPS=xjRkfet2pUsyXN_;4}9e{0xd zivM(4P$PuXfK*{CHtCfN^K^*yzN?k?;32*?8ltBPkiw9Kz*oc0%MFHk`j$>C1-dBfz zU~wpug6H@TX>g8*v5wPLDpXh_fA%W~I6sf(zyMdSF241V#csamWAEw4!<^YwP(^atqB8g@)cd>7xM3wKxj2NQ;4AK%aB9}#? zDQ*N4LD-KaL6>~Bc}HjxM6}X6x$N`bK0g0f1QgD(SfQdTuABnbB zKhpf4x<2 zQC3EGVVH8DPL>%`^$CBIr;y@8pA>c!1p1h<*Cz`qRr=VU(*&W^FrfZv4GdZ%4ib$H z<2E$~Lw$&0hlQVKK@n|3qR}Qes@a+=82~XFqky226S$hNSv11Q6*AP4G6Z7<#ajTg zPcg)x#?mL_I03qee?k)4eJn&(TY#0(Csi?|pu=Kk2{Ue65Mf9v0k9=i4QPEW!2kpG zj9U67?O*_E@TJ=rrafT*V_K&E&;UAeDOUQXajGLbs%L7nLQn8Ra0jJS8hB%c25A2( zZtvlvw$}wgYJwK?9^=BM*ylOQ>1;$9A51zY&6NPUR-}JAe`iyg0Hziw;peDQuumN$ zod$8HZlaxt+N2)yoqgJ<*aD?OdO~XIrSz#`cv=N=DyDkiCaBhWwu+SmKmoC3YSw3} ztD0!Y$_b*{Lh5-M*g34}}VD=yAvj>7o2u{f97DAU*>#pII>WtOkA?GHnN{M zlbSc$nzV@@GkUd#V57FF0W^v;ij|n3@fDWvQVKO{Nr4|ucxipkM)5QlcRHBx66C%8AVr>dAInR8LbC`g0BY=fw{Sx4C>fx`kT>g^0GZn>C4~!)ZY(~`)zzjUNO0aI@3kXTOvqQmHZtJ)x z(_Pa0UDpA^#fgzGDv}3iwK*!IkjTOupfFfqk}doP7O0HuseM)nk*^hvNwolls<~<_ zf5ZigS{cj{zO_PMm5yp*#IpvkB#4x)C{11ULy~4jN-(cX0!BwC6SsVEjf`8Y^2?rlCPM5ENZFfw616QUsEf&+ z%ezE&_{=qhTtPg<+VRBkc@e#QXlN`@=7G%#3Cre)%VotW+C0vywozS$ADir0e*rpG z*?h`0*};bRTBiihY&*#zoD>z%4eiU8d1~)uNc6fEP9pD&>QL&0SwYvgIy#|c>({stIWu{sp7{6 zT?sEup%+=TE6fBBn6*3|!#^#Fe~sePVL;SSryy53n4!GRT=-X`1`))G78x`WhAF`H zK^3g#kJ}J~IX#s3C>bEE9U1hYs5N%*)m5zpgkw#rWTk6_YeH9M*4?^G7wcGa{8Oje zs!a4}?ILarf}DNXERY4u?eb}!LvKRs28+C&Hlm+2h6Y;=T9_QV_vg+f9?cG(f6>zgpHY0cRLf&TCFpeS=DHo{Z~hnO5IS={&4}P2#9`!BEQ4(B z>5Mlnd#|;`{%2px*-sZ5ISBG@#PND1kA-R!T;PQnk80}vg4d90!MESDo z@%`W8a$MX3?F=r`*5QWM9_;B`m%}R$MTJ2r^x?^E>j@EJe^(~%%I>0E+u{M>(_8DB z$p^zTjKecdG@<%^gRbBX?CJN*SI>lIg65|DAjjD7vtw4|DXi%oqRxSGlNS(PNi}*k z(GU(lXv^$+RZhnd-!Y?jX;-{^>byeVkwaVIVPY7{@SWvD|6V#Oo4?c`7eFEN!!5s{ zKIDe}=odxte>{wE)c!cHwDR?K@qY#J5)a9vw@X5g>e}o8{gU&x?DSQW=u}b$iw-Nf z1L$(DGC$wjlWz0IzVy31B-M`eNv{-QkLiXg^>Y5)QD64pzVjkaYOs~`H-hVAD}xN* z?*=0l$0F1HwM8_a$;8$+9-*@z-xh*TR6{U3Ox?Elf5rE}Jo$yW>{`$3+lLm{?%Su{ zS0T;$o#lpx-|T@6Vc&iZ03TwI!>fX!Yl{z15$&t3k-|2^;;ktYEFSNOVAM>&`$mH< z96@=2?Z-x2Uo`^lqe1*P?%di`AYnqqX~_C8%bC=*@l5|quYza~^2QetX(YyC{Znfg zV5SE`fBbzYJnF47)c{XGu)nllQ-+}Yo$l(LbFo~kYXA%&G@s@j1{8SD*b)W=0bvCI z7zmMpLlKh{LW)soG2*mdv03dlNhwmaM1aHzH42N9B%-)TE~W*=5owM`t4ij(NDr{5 zCM=wm#`w;J0Hp-E8XX@SF}?`<^v=A_2GX3wnkWq+Lw`lNq6otFlFaA|$&keS6r&iC zEbgQjgjf$@3jznbP=_iLdl!F++bS5M-0E!c5)+;ukcuNGtpL@M9NL^VN3p~JDh~3( z8z;blWlaODow})XdS#PW?BVQNdMtn5`)43B)E5vSp|2r z)@6D4r+*^FH2WUaBR4T0NGls1iJXYyiS%bCA#4$nRNutejSvCFV) z4S)Xi;>DB1I(AGcq`*q{n(I7EP6N=mWfnZ76=x8kPdnB8OD(#H;@j*f>@K{onEbBW zk2nlRTuhs!V1qBd@C;yvp$HIqseo$+q$i^dCj+fGk&baNwlw^>4wc4mF)T;bo*~hZ zx1iz3vETd(Wuw=cERsi3y|Z6OmiGZ_<#OE#HoGPRB5vB(N2 zLOZD)h#IPHNh3i)(#9$41HdIA*$OMGw8To}Dzmskf~+h+xC#WV8buVqV#1@)JO|3K zODSaROi;orVg&3%6Ct95CA6sX4aX!kA~e<<)zfed2meyl@YOAHRdWDdokUH!41fMh zgxJMi0~NPlp4+039tGs>Rt3`O@;YZdJyp|h!SxcI=CDPrnH?1yFjZJLL~K?5K4JB* z2E%2m&Qs2Vuq$Il6Lwi&tBe<3CooU|LclPYuuv_jGuXX)6P49KOAgFr$91<07-C2& zEANWC@)Z?C`;sX5V6>vu!a|a1aep|Ngar$05S#5mm&t%aN zFoADv>QqTPEy?rNKkI-%>Zzk(00NJ>kibbOoyLOGm^Qj#>ak^k;G$c*_FCJqsV>55 ztQSZ??nBv@y6UU1KuI;Z<-W7-yRj}ai(cWZweTnZ{&pL0^spoE3OpZwxPRx%v?h8( z4Y{VUMU6L3=}}B0^=hk31(+0zO0inQ^v3JZN)p>ry>V5EJjFhKZ6Ut6c)t6N#RY|YTSCb7^*T}&K*#~o`7@( z!QkaFT{rp=_0|^(MS*U74;WqON=LdYY^76Xxl|&vRskvc$qJpgLgfnJ2b&qm4>j`A z?`UJ50Wt_))rlf*I)C^ix3TL1<>?p?FOxjg2n~_0)Di+%rOQO{vOAqJ1GR|RJY4oH zmOOFC5ch^hSy?c9pM2vey@g3_KEie58qoU+6+GN+h%X`u-o2j2FmxK`m1~d}BtUsa z@jys}&P?ZZm?%sQY%+$vqz9{JxXURXW1aH<0F2TmI0`H=ZGVFjo5{p5aRhUUuZT`` zL_EJ$j3Wx*0w}xYVgfqMfl{cM6AI}cVrR-N-BYABloBEjslZ>FNKi()3?>p#Bw&hh zkBk%N*K)^1su&SbP|D2$kc!lE5QHJUy2!zj8dV%t(=B+2zz?u$NGUDg0uB&c6zX|V z1&mcj3J8*Dpnp?6ELdQyAUn)h&zjBdKy8h2WGh+Q09Rhhvy*G~dt!0ht zyw0ad3seSuap`F>3~&KVP_ZLzor95@`bMYZb+TdIrWHUCT1bT!1V>n10MxR&(^_G) z4}jEEKg+eQvK6ufWB@}fATP$|)~x`QMgMM7g-9_`Ab$f!?UMwMTS4R|gf1a6LjwG9 zux4^WB)7Fd1c=Z}W@NwtuIrjGYjL#xVf5#AaYv_q<4&uz^JASj9_)V$HBdQN!Oqk9r2RayN6IQix=2j z`#@m<2*wgGzChw3%fZMce#AmIh}_*QcOVb7vczc2%PGGLt5eFhF!K`cD^`P!>8d0Cepo=KqgoW_PM^fXo7#Q7H zB!8KW)IRc(&|b7zY4$`VNCQDY9%~=`CR3V9x$aYl7M@7U4UZ zcUUiu7vm>>KP?WE5x8aYD@Hln0$TMh^&tk1o2n^k3Jgu3w=vGRXLHG2;4DnWia%TXPjhhfS{77EGrcqF0va zGu9399bGicnlf}zW?rn5+QH|+MmH-XOm&!#dv#Wjulg?6wWFQje)r4YQ-9rZ z^Az4Z^y0AFzTAk*%i(M(B6-W{UQxhjoKezV%WAic?F}>nQfnbSh8!Nq{u~UZf6#h8 z8JMCV?S*hcEtB0PxUjw71WKN5!~j~Jn{T%m!}=CcAP(>O$llobwwFG=jLIPu5spZT zFOvJ$&2DO zaHzb-=1Fw!XZejc`PWW=+1H%dcWq-szaPSs1 z$W%lFFbuFEhOPtYA^Ad&5bQ?nEI}6dZ?i0}XjJO6xC^$_rwg-S#fBpO$gm96XILC9 zQF1E;MF9+dXbsI!n|3M=RYMG=C>+r64q3^+?$A`=5MrQ&niMIw^iWwOzzZXR%EE*Y zS1@Z7F$~l24IKaj5b>hMkbnQn{%{d9@l2MB4$Cm)@a{)8F&idP6WOpT7||0Gp%WQ{ z75nEAA#oHH$qqLTm_E&&Qn6_E#0>oq)>P3EDX|r0aTaqi7OyZQXb}=`u?~yz6^C&E zFrX9@@erqi4=ZshlJ6RSaT~d@8@=%x!7&`U5o8K60_#OfT&Enxaep1zu^q*%2Hi0p zA95lo za@Nwy9xbXOHF6_4F&H`WBSA7GMRFtyGK&zhsO*j;RdOX+vL#)zui7aNPx2*cvLfs`Q^e`Aw6KG655qpRBDx`r))9ITNfCy&4dc0!>9 z{gb*{lnS3{CsHXY$H_&FV@GW?!bmU>Ky)^R@Bwdf^N0pTPt-)w!AHxCU~md7hjdD* zv`Ve?O0hIcwRB6lv`fA82da?dG>$ERqh2a4@P>g$oel;eaWgXVAZzqVOENWbe-tX6 zG)1d1PE!;{g#-aOBMq)p0%EVlTr&IEZcM47Oz}`p)kXnb^GhK$QYCd#DYgGnE%j0{ zHB+&wF*roZdV&8G6&u+!27%^IA%;&!;Z1XfQ32#NGHmIX(p1GmRzK+gOTt#B%!0gmt~8n07BkofKE1LO@cC@Hdt9SO@B0Ev{p`)b|pILVQWJgq7Xh! z<|d|U9fI=!Cc*-q6G$?Ne`l=#tB8wfp-VfR_G&$gS3Jyu?xAj%;ckoQX%z?eP_{p+ zmOb=#eCQ`<9`+*=R%RvuYBdRQ6*gkmz-9FTX1jLSwpA+)HgrXIbV;{#P4{$>Qw*+% z+~S}&S@#x7CiY@-6!a$v!y}J|PUObU{nD=K_(kS;%8eo}W*Nspe{rp5TMYT+E=+gP z5@HVnVpHq>Lr{4R*;><3IZdCichurEM1O=_#ch@3M61s2779^qfwTWKDBw9ki3_%O z|3paomTv@6tw+XWe(6GcQ}X+MNKUw}245F7Mf46}lV5wrC#Mp16?lOexPcw`fi1PO zo~>o^>aE7gD0q{Ce*vql%41i7HeZj|YjJ}xMrC_?Zym+~sqEmLAL=_eHqx;}V> zdqxn|7ac(6Ra;D9Z547%45_xJ+yE=sP?l}k>!=WId=|lF53MEQrilTr!<={-U}cxUf>V8;GhK)>3H1TWkRUb{f1rRx2m;!Qiiwy4#sPU` zfr;5AALbZ}t8cS%!;b0rkor!8HHw4dVkrHgG*G6GEm#3Mn2%>T|AZI^i=oM1AvlvY zd6PN0lRbGkNlhW|Zf<+CXUwB(ZV3VFQI-rLRR)12o`s}jIo2R>tBPljRQIX2mJ4ne zQT!xGE&w)je>qm%SaNDgnO5--LgO`4c}e*&LWTVotOjtNacv?@Q82kv8;;b-@;3-)ETC-9b5(WU}iuNlX zI<3`uf34ZNt-Ul6iqJHY^^7VSQPuc=pf(g#@Srcjqy1Wh;UQ&$2A^}xsJ#TQ^BNDU z5^sfMI?QN)K7@F1rV95AO(O!YnF6L71MKqn7WJvKvDw>v`og|h?T9LPhib8t+V}?h zI(~;pRRpwW?XvkMN&%3byPG{?TJ?S_pdO8G)X%zls2)ru+*eK*P zQrZkknjx2tHdE*lc)UXhdwNCfG+ubI#5Df=yW{@52Z0=)<1eJc zwY?!jw{=jinW;mB%6r^Sx{Ruv4!bGKg~tC~PD*A@=Fgoct1;2S@fqIy zMbqOj%Hb!}#T(HLoAlZj(hVbc%=-`ig^6ffr-7HcJ^gosoD^rBrZxN%sHM&2f2q+E zb(a$u&xL*1iM`khmcm{KCWI46Tbt5=U1emP(2r<^EPbSDoxDZpv7d-<@U&Qg9jKIP z(&rk6k~_)8HK&1sj8drF4{~hyJ0?KgTtq#GZAaVTo!d2K%k=yZ@EFrEoKSp73s#+? zhytdt{KQ>winPS1Ap(4Oy?kP*e>f`R-H+1PE&k#$KI0{ot@ue>JShq4`s1glq(WQt z5)ax59fUwhlx+GK+^U!;L`|l8l3VN4Skc48O(~{48YLgVg)_gNw`zN z*?A*C%ic)7=!CcnKpmB$L)vR&vnf9z1XkjoUFKE>us0)i_9D<45s`U|3ykFP7cSY*RuAG~TG zzwYh5)NAZxWyhpH#b)2&qM!8lKJ{g9!TwPEq00ZZaEnzipUgHtgy}x--T(dJKmLnz zdv#voy5~2&M1Yys%T*Z&0Ez&yXgnSd001GNWIC4vqNK3AE-S|bf3|C^cCQO$0Aa;C ziq9~>LVjzr)AV{?M18_#G#I%&2i=KLiT@bah#v zZQMt10SuNYxrA4)aw6S%0>D5*lUo$nMJdn(8x$&ru*^ZiN6gS9SP~dRG_C>2HZ707 zR5ujB1$mqXG$;q_+?5HS&LJbRfY3E%-hv*HV0LBHb>g0>Dl@g~uS7?a3Y(jyE-s!j zt=8$rhNhLEg^B2YLgY$_;B>K=UU4jHYE{5=unJ~?_L^X?M_4_A_CRklzD34{jKJ(I zkzsiSmqy}OCf?Sh4e<5YRLsb2D*u9`3z}q8mXg-WY)fkZPY9NuLyr!aBlYUmuVc@y zeLMH=-oJwnFMj+&1Q;w>2+L_@WA*`$+CLWvy)KLIDCl~-b! zrIuSFamECHT&mL{m}8PzrkP`6fQ1%kvMFMeZ^9X;oO9Ayr=54=nP+()w%Mnje*)@Y zWPu_fCZUHSnkbqlD%xlrdO{khq?1xwsil`o;HX#5nyaq6^4hDfzXBVqu)`7zTdc9iBAcwT%QD;lmwO=@O@9LE z7|OyALmaWh6H{Dq!BasX866gL+_A?<5-@aF9H+_H)&tBfH83w&I2 zu_3!$^2sT$+)2(P?;P_j6U-cB1O^zOnp{X9k>M3P9$~Z8Q&X)GX@dzxR-zVMpmfuu zJe_q<>Z~+m)o0&%wJ&08&?whl_kThPhyfJkPT4@BhKU1rKjNuV>!BUE;DZOGb{BKk zt>^?eeGN7Mh--}t-k}AxgB5#9o_Llo?kyk>Bqkz`|`M72mB(=PdeY* zTlms9zDLs5flp241tsgZ~-a4;oQt#wm1ePpaCF);AXJW0Hq-S zX;V=l(02^2_uL?6%s{-cX;6zod^dSvIU3gyM`En2$H1TA&3?j zVsfT1zyN~bfE!C9ANx43CB`BQZ8L)7^n-`HJc3GSz=z6Q13pTOaes~55aeUnpfbMs zr7~i%WT8&62=e(cl>PwZI4DU-uo-eUE6I%_Bg4qhsN#@eFh^R*2p232avN8> zH!*aQFDHfxwmZbI{$_YmhA&;M!8bEb2kZy;wh->|~m8A6_%SpwV^(@k!|jh@MY3^9XY z4Ch3WmdOk#O=~JGb&?@*s{x;LViFYKsf=?Mzz0nbbBc+=5`URQ=pT%18Me$B`Ypi+wjQWD1y0B?9b&>=FFT$Br zvPRN@o}*q}$X$DS7k?494evDXYhJ4^_P6v1E_-X~ z-kiesCtqEx9O`>t{OWVR)IAD+`|IHko9e%%4R9(190_BP!k%tr?LvQGfKiUvf5q)? zm+V@~atI&}q$nwZaRK7`iCCv49Cya-C*9Wt=oq@rzj$ffqf4&2v z2T182e}C-dFH0)OHoh!)c^ZK;qZ!RA)^R};{Jt3jxW+n}@{f%0lP#wi&HoYAEx@ci zF-x<|Mb2uT)4XOoFaM#U9VQ+_ zOhlU#e}ZI?Rs6y}oE%y^2${unHcx6ZWSWg$`hN|cwjZb|tGfXUw$bN6HRDz-iB{XV zy{3+_j$g|R2GBa!w&nz%Q4~P1?mFArW>T+D`D;O6TeYyHrLnJpY|=V-*|9Dymnl0> z>5fFd)Xuf8x1GFhGvnK%PQ`Q!yINU1+XxXjx3hH%>ttuB-KTu_D$kKoTx+@=dF-&g zD}QeB@Mx3{u_p7rm5f}s;=vw^VGVQ(fsfH9S=k3CZB-M{8}lr@5YTvOgkY}ETRZIH zXUjMf#|&;&+*v~ZH3@k=MlSQ#KKJB@Ca$n)Tv(U)E#|BR70p*vSe*OFw42sB*SlUF zp7+f@)tu2m^-bh7Wg$IW>*vvtA_0>M!hfC_nM93+=?u-C4|acoX7c{(J51j1 zF{+{9Zz9sYq6P66P<;5R?T*^O_VK#ky+jO72C%uo@hE_;lX{k&! zbwx_misS7c$AFLjJ)8Fh;0T&l0e|k(0Vbeq+(iTGhWbSwYkA*mAkt3N!Ue(x9NnBe zAYhL*RtNgv5AKhZ^hhkY2#nlEpM1!KEeDHC2M~G;mJH!I6rqej4VNS#rZJ%ac|p!O zVHbMg7lL6IVhoo3Qy7}z8KPktX4@5Vp&Gj38^U26%HbT+VIA7x9pYgg>X(~t0}Gd> z!V@ZgUWyTTVknB@D3T&d|3pnGq9VU6RneG<$@mP8xFX9G9GIkHl<*G-;o{sp&<-g8 z(qJ9`@S-nX#mlLP$lOXSHeo0^+2b3O+;g1QEdbn^tmL6|BtdFqDMnNBM<*t21qKINZQl*pk#tIN=`yYo5AEkMgmcumOjG6P13?nwqkA_ zO06g*DH1?ex&uKdgJNA}X`$r@_RKr1B}a%tQ(o0mD&$C#MM(yd*36}>g^F7OP}3=x zLx3a!Ay=?bBvT^fWk{Ks$lGE5WfA0mB_+0HGc4l-Je&j2QF5@P=6Oj4{DDAB8-g6+ zw6RuU+T~rs!)6Y|?>LYSO~C`83`oq(FY@Ir`DMGo%n7xFR0?J=trl!nCKVU}Z-S;? z6+;imsZoJ} zz^58~5PQav0SFNh|3w8^F3oiM+fwM~c@igc;-@zG&=qBoHMYib(&s&0zyzI!0pOi= zIu~3f|6=}F7B+l9B zFvaL1f~ayiO*+7jMZFMURY3E+g)&-|Ij)0o+$4h<0|>t8JoKqQ@PxvD8QTXPDh1f6 zF8=0%1}2c&C`dC<5z!-!!KK<$H+@rKtpq>)4Ou!A#Bmkil~aWg-=~;VIfhYP zN-2S$n1t>rg-t*&=9YMW6_nQ5#AIqJNIgxZA|i-_iqW;k0UY3RCY)yez%K;E#5F}4 zK!b!KnTSnl8Pe-M%;(1eU3Y5hb^kZ$_S$I+Qa zrlk_^aIW34M?~F<_beEQe*H!8SeV1%>fDGDktM)8U)PV?Qqk7g{9VImh6ExmC1shf(W1E z24Q(Z+35f91X>Jl6&@!~WI#v-!Uv6%s{SX$xgZiCu4}TbnK~VRs;I-NQ>q2rdhuJT zx`X$61XGk(Gfb}_@^0f;ll)y8lr|g@2!sW>LIPZ>hD>e~2rcwR@7s3pK2+6v0FwoA zMf3$z-u4N9@|G+Ck5<|u+Vc(DcFrIIPo_RWo3DW%2Ma{YP9y}AuxHND@hmS%C5A3I z!%Pk_cG|A^{iP2hapyQD_Ql!3cJbg=rMg#_%cDF~gpMU+{uUokiDwpz01g%1>wv15YpywWG&Tn#e9) zC6%A)|MX)dY1;fc@#9u0T;MV8y=f@(sK!jB6lBFvV1fdtDJBQg7A7vdMo!)0t#P5T z>rTTca~~TIAE-L-=&nJlP)TyvaA`4*GdZ7sG$Vb&2eELjO|k{UgEx&=<+hLQf+bc~ zah3nTW*pOkU>0rbj`7_#@u;zEK({pIx-?X_@ECWGGgm7}KQAr|wK<86!bNOpovu4q zw0n-*FhALxDXsK55}o!27Y8xAIh@$)Qv>X@9)jp0-%ZjIUtQRWCI4|pFrT5`vf(0s za!x1qU(c#az3kLxnxu;HJ5cO~0Pa%vm+_CNTrY^on(MOld<*#6>#;vu>Y5Z>hG9#oiUrb;0(iROU6K zIc;>m(O>7`pB_L4+$_qbT?SxaT^PcD0;pXyVd>+7EFPc&L?`QBK@&&4_blEDcDEHU z|2Z>7k{$(|M^i|ucy-MsA1=272=LsWl!9jT2>2wJZw6q%1t@MUBwm9rp2X7RfzqAU z5H=~}T}MJlRhO7+)1?AbntOBigUcLw3y68wLV-^okB$uop$FVicsxU`R>Q%6Pc)Q( z8@JPymfOkrTr-_#I?bv|QeC5%0+hHd%|#vf_n8r&emekv)At?zX*h$ikt&%Xo3Qcr z=%C>1RW*SuZL-@=d1B=gNQ_S*yYjQ*>5U6`JmTriTDegkP9pWeC^K}Hmmh(T^pSm^ z0E!y08s1>34PR)fX^l1NIJew?L6s}#xdWScqB~fmnRZ*7AIMf^J^J}E2OBaKx}5*o z!K_w^Dyd1C*P;DJkRR(4tP&=2XvQE7L`Dm9R}Zl@XG0>J`g)QDYH+L~Rb%+c29*%A z-oANsr1cCThjWd_4dNUI-qVa*=~0xBxLU5Clc4S-Mw{8jz^?l780cAlKrBdCWTd7= z3R1FDL*E}9J17@X{#JVA>>z#Jl6+?;Xr^u|*LAnX2B_PCgI}NDtP(5aIv%p-Yq6$+ z)`)>95oFKiz%xX{M6Yx+`QM>lhvUZ)!i0^0V*&RJ8xmm_0y$tD{Dw$8lMislWBguA zPT}4&$Op)PIDE{@e6RF>Oi(9s*fKoCRcKnmB#HL6@rdOkq}$9BebM7f$DfCM|06xZ z=lsm_u%8rszk8+bA8vpOVfjW*f+hLW4V@)`YC&T+N(Xeh<)3; zz1yB=H(ckK{042T{oUhz-bacyk_q^}{oezA;0ylX6Mo?v{^28+ng0e6e^Y+tTmI!^ ze&%cb=5v1Md;aHxe&~z-=#zfwoBrvee(J0K>a%|9yZ-CLe(cNs?9+bj+y3q2e(vl3 z?(=@{`~L3(fA9zbNoMVAMYh)kH7i1`q^< zLt@c*EH(@cf>5!KKdN`Hws$jpz~lDzi_o}a^9&wDm{8$Dh7BD)gcwocM2ZzH zu4?tK;3)?Y!ek4je=AqGMH5I)LI6+F50))G>Z0Z<|Kmj>9Y21{(vCtVn=tzT1X*cY zziUDH?b?LEV}yM~+P&L&>8TKPQH3-`mC|a>rUXw8F$ut59iTXiF!)MS?OL{N-M)nz zSMFT8b?x4pc|_;314ccGj0Cu3T1b1v`Nd0kZC|r^T0YLie>kR)p<;_RMp;&%mIH}C zVRd4!Y65nmRbI_E?=%sD7l=TZCBaD8u}3N+xV-tb;=8?l{{|jh_;BLIjUR79FRz{g zypw~HJWBAR>2$&hZC+pir|3CBv+XW3^|;@v6K%cM7sH zXxbVrt1k~gf8+)vus{P3L@+@G7j#Go3M8litpxw#&?CZRDyYh{BN(HQkP29uu#5(V zc@GLIpvhoElf0pL`*aE1Wf`ECCpJWnU1hYfJ8mZkg$U7kZ8}et*Shf5%=aB0-c+J z)WX7K43N`B*g%}IO&}MTG=K)cv>;X?Uj1(hL{rrPOQCU}Ay02#>o5NH{mck8ZaVho*Fv1P9cusu4$toJ!(E#=PPxH!u_+1XbVl&U zf2D0(U-~e=dBOuC&b;oy!^UEAK%GID)VTk%tKjrBqiy&r|@nQwpxPc6zO$#Ss z=@8gn=aJyKN`YWv;KZt>!C%SYOd48JP2xwc13borc^csm3aZVcx_t#mMRJru%Yy!Rbsv<`+9T%iOlQXLJfBZ105e}vi9u!^@0FjQ*YG0P$)`cAn!u|3bth7|IKaYY>(QY{hRMRcReQCcrdGoGoYj z17sitIY>el@_z0cf&o2qHudRZhVKClBT1M!o1G~+{UR8`W+p{6G?9|&YC>h6lfYl? z!IY;AB_hedw<~z^C<5abR%GXle=c%uXkT*TzBISK+-b*$yUW5X<5x>Lna)>0%oh@Q zNgri^sAc2RNG>@^5h}`KC{E0X^gg*O0*9W{0bi1=Z+$>vy9(x z*20b^i2-%0D%Nl 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 literal 2543753 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