diff --git a/examples/gno.land/p/demo/memeland/memeland_test.gno b/examples/gno.land/p/demo/memeland/memeland_test.gno index 76c44327993..fbfcfec8ae3 100644 --- a/examples/gno.land/p/demo/memeland/memeland_test.gno +++ b/examples/gno.land/p/demo/memeland/memeland_test.gno @@ -6,6 +6,7 @@ import ( "testing" "time" + "gno.land/p/demo/seqid" "gno.land/p/demo/testutils" "gno.land/p/demo/ufmt" ) @@ -97,7 +98,7 @@ func TestGetPostsInRangeByTimestamp(t *testing.T) { // Count the number of posts returned in the JSON string as a rudimentary check for correct pagination/filtering postCount := strings.Count(jsonStr, `"id":"`) - if postCount != m.MemeCounter { + if seqid.ID(postCount) != m.MemeCounter { t.Errorf("Expected %d posts in the JSON string, but found %d", m.MemeCounter, postCount) } @@ -157,7 +158,7 @@ func TestGetPostsInRangeByUpvote(t *testing.T) { // Count the number of posts returned in the JSON string as a rudimentary check for correct pagination/filtering postCount := strings.Count(jsonStr, `"id":"`) - if postCount != m.MemeCounter { + if seqid.ID(postCount) != m.MemeCounter { t.Errorf("Expected %d posts in the JSON string, but found %d", m.MemeCounter, postCount) } diff --git a/gno.land/pkg/sdk/vm/vm.proto b/gno.land/pkg/sdk/vm/vm.proto index b99be0a85ff..aa0be4f6e14 100644 --- a/gno.land/pkg/sdk/vm/vm.proto +++ b/gno.land/pkg/sdk/vm/vm.proto @@ -15,6 +15,12 @@ message m_call { repeated string args = 5; } +message m_run { + string caller = 1; + string send = 2; + std.MemPackage package = 3; +} + message m_addpkg { string creator = 1; std.MemPackage package = 2; @@ -28,4 +34,8 @@ message InvalidStmtError { } message InvalidExprError { +} + +message TypeCheckError { + repeated string errors = 1 [json_name = "Errors"]; } \ No newline at end of file diff --git a/gnovm/Makefile b/gnovm/Makefile index ff3f07158c5..452b2dcc81a 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -81,6 +81,9 @@ _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) ######################################## # Code gen diff --git a/gnovm/pkg/gnolang/debugger_test.go b/gnovm/pkg/gnolang/debugger_test.go index 1b5a72a183a..3f2f58b9709 100644 --- a/gnovm/pkg/gnolang/debugger_test.go +++ b/gnovm/pkg/gnolang/debugger_test.go @@ -31,9 +31,9 @@ func evalTest(debugAddr, in, file string) (out, err string) { stdout := writeNopCloser{bout} stderr := writeNopCloser{berr} debug := in != "" || debugAddr != "" - mode := tests.ImportModeNativePreferred - if strings.HasSuffix(file, "_stdlibs.gno") { - mode = tests.ImportModeStdlibsPreferred + mode := tests.ImportModeStdlibsPreferred + if strings.HasSuffix(file, "_native.gno") { + mode = tests.ImportModeNativePreferred } defer func() { @@ -196,7 +196,8 @@ func TestRemoteDebug(t *testing.T) { func TestRemoteError(t *testing.T) { _, err := evalTest(":xxx", "", debugTarget) t.Log("err:", err) - if !strings.Contains(err, "tcp/xxx: unknown port") { + if !strings.Contains(err, "tcp/xxx: unknown port") && + !strings.Contains(err, "tcp/xxx: nodename nor servname provided, or not known") { t.Error(err) } } diff --git a/gnovm/pkg/gnolang/gnolang.proto b/gnovm/pkg/gnolang/gnolang.proto index f7eaa907ec5..9904e26078f 100644 --- a/gnovm/pkg/gnolang/gnolang.proto +++ b/gnovm/pkg/gnolang/gnolang.proto @@ -58,6 +58,8 @@ message FuncValue { google.protobuf.Any closure = 5 [json_name = "Closure"]; string file_name = 6 [json_name = "FileName"]; string pkg_path = 7 [json_name = "PkgPath"]; + string native_pkg = 8 [json_name = "NativePkg"]; + string native_name = 9 [json_name = "NativeName"]; } message MapValue { diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index f73a5c58962..6127fa42b07 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -890,7 +890,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 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/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index 0cc30861355..eb67ffcc351 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -50,7 +50,7 @@ func (m *Machine) doOpAddAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -73,7 +73,7 @@ func (m *Machine) doOpSubAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -96,7 +96,7 @@ func (m *Machine) doOpMulAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -119,7 +119,7 @@ func (m *Machine) doOpQuoAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -142,7 +142,7 @@ func (m *Machine) doOpRemAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -165,7 +165,7 @@ func (m *Machine) doOpBandAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -188,7 +188,7 @@ func (m *Machine) doOpBandnAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -211,7 +211,7 @@ func (m *Machine) doOpBorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) @@ -234,7 +234,7 @@ func (m *Machine) doOpXorAssign() { rv := m.PopValue() // only one. lv := m.PopAsPointer(s.Lhs[0]) if debug { - assertSameTypes(lv.TV.T, rv.T) + debugAssertSameTypes(lv.TV.T, rv.T) } // XXX HACK (until value persistence impl'd) diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index 99b56c18a06..a1861ed3aaa 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -45,7 +45,7 @@ func (m *Machine) doOpLor() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // set result in lv. @@ -60,7 +60,7 @@ func (m *Machine) doOpLand() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // set result in lv. @@ -77,7 +77,7 @@ func (m *Machine) doOpEql() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertEqualityTypes(lv.T, rv.T) + debugAssertEqualityTypes(lv.T, rv.T) } // set result in lv. @@ -94,7 +94,7 @@ func (m *Machine) doOpNeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertEqualityTypes(lv.T, rv.T) + debugAssertEqualityTypes(lv.T, rv.T) } // set result in lv. @@ -111,7 +111,7 @@ func (m *Machine) doOpLss() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // set the result in lv. @@ -128,7 +128,7 @@ func (m *Machine) doOpLeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // set the result in lv. @@ -145,7 +145,7 @@ func (m *Machine) doOpGtr() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // set the result in lv. @@ -162,7 +162,7 @@ func (m *Machine) doOpGeq() { rv := m.PopValue() lv := m.PeekValue(1) // also the result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // set the result in lv. @@ -179,7 +179,7 @@ func (m *Machine) doOpAdd() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // add rv to lv. @@ -193,7 +193,7 @@ func (m *Machine) doOpSub() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // sub rv from lv. @@ -207,7 +207,7 @@ func (m *Machine) doOpBor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv | rv @@ -221,7 +221,7 @@ func (m *Machine) doOpXor() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv ^ rv @@ -235,7 +235,7 @@ func (m *Machine) doOpMul() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv * rv @@ -249,7 +249,7 @@ func (m *Machine) doOpQuo() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv / rv @@ -263,7 +263,7 @@ func (m *Machine) doOpRem() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv % rv @@ -309,7 +309,7 @@ func (m *Machine) doOpBand() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv & rv @@ -323,7 +323,7 @@ func (m *Machine) doOpBandn() { rv := m.PopValue() lv := m.PeekValue(1) // also result if debug { - assertSameTypes(lv.T, rv.T) + debugAssertSameTypes(lv.T, rv.T) } // lv &^ rv diff --git a/gnovm/pkg/gnolang/op_exec.go b/gnovm/pkg/gnolang/op_exec.go index 12e0f9e26e3..c7e8ffd600c 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) + debugAssertEqualityTypes(cv.T, tv.T) } match := isEql(m.Store, cv, tv) if match { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 88c5c2f1da4..8aca0058dcd 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -753,66 +753,75 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *BinaryExpr: 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 && 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 + + 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)) } - // Left and right hand expressions must evaluate to a boolean typed value if - // the operation is a logical AND or OR. - if (n.Op == LAND || n.Op == LOR) && (lt.Kind() != BoolKind || rt.Kind() != BoolKind) { - panic("operands of boolean operators must evaluate to boolean typed values") + // Special (recursive) case if shift and right isn't uint. + isShift := n.Op == SHL || n.Op == SHR + if isShift { + // check LHS type compatibility + n.checkShiftLhs(lt) + // checkOrConvert RHS + if 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 + } + // Then, evaluate the expression. + if lic && ric { + cx := evalConst(store, last, n) + return cx, TRANS_CONTINUE + } + return n, TRANS_CONTINUE } + // general cases + n.AssertCompatible(lt, rt) // check compatibility against binaryExprs other than shift expr // General case. - lcx, lic := n.Left.(*ConstExpr) - rcx, ric := n.Right.(*ConstExpr) if lic { if ric { // Left const, Right const ---------------------- // Replace with *ConstExpr if const operands. // First, convert untyped as necessary. - if !isShift { - cmp := cmpSpecificity(lcx.T, rcx.T) - if cmp < 0 { - // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rcx.T, false) - } else if 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 { - // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lcx.T, false) - } + 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 ---------------- - if rnt, ok := rt.(*NativeType); ok { - if isShift { + 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 := 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) - // 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) @@ -822,100 +831,127 @@ 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) return resn, TRANS_CONTINUE // NOTE: binary operations are always computed in // gno, never with reflect. } else { - 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 { - // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, false) - } + // convert n.Left to right type. + checkOrConvertType(store, last, &n.Left, rt, false) } - } else if lcx.T == nil { + } else if lcx.T == nil { // LHS is nil. // convert n.Left to typed-nil type. 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 { - if baseOf(rt) != UintType { - // convert n.Right to (gno) uint type. - checkOrConvertType(store, last, &n.Right, UintType, false) - } else { - // leave n.Left as is and baseOf(n.Right) as UintType. + if lnt, ok := lt.(*NativeType); ok { + // get concrete native base type. + pt, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) + if !ok { + panic(fmt.Sprintf( + "unexpected type pair: cannot use %s as %s", + rt.String(), + lnt.String())) } - } else { - if lnt, ok := lt.(*NativeType); ok { - // 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 type, - checkOrConvertType(store, last, &n.Right, pt, false) - // and convert result back. - tx := constType(n, lnt) - // reset/create n2 to preprocess left child. - n2 := &BinaryExpr{ - Left: ln, - Op: n.Op, - Right: n.Right, - } - 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 { - // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lt, false) + // 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) + // and convert result back. + tx := constType(n, lnt) + // reset/create n2 to preprocess left child. + n2 := &BinaryExpr{ + Left: ln, + Op: n.Op, + Right: n.Right, } + 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 { + // convert n.Right to left type. + checkOrConvertType(store, last, &n.Right, lt, false) } - } else if rcx.T == nil { - // convert n.Right to typed-nil type. + } else if rcx.T == nil { // RHS is nil + // refer to tests/files/types/eql_0f20.gno checkOrConvertType(store, last, &n.Right, lt, false) } } else { // Left not const, Right not const ------------------ - if n.Op == EQL || n.Op == NEQ { - // If == or !=, no conversions. - } else if lnt, ok := lt.(*NativeType); ok && isNative(rt) { - if debug { - if !isShift { - assertSameTypes(lt, rt) - } - } - // If left and right are native type, and same type + if lnt, ok := lt.(*NativeType); ok { + // If left and right are native type, // convert left and right to gno, then // convert result back to native. - // - // get concrete native base type. - if lt.TypeID() != rt.TypeID() { + // get native base type. + lpt, ok := go2GnoBaseType(lnt.Type).(PrimitiveType) + if !ok { panic(fmt.Sprintf( - "incompatible types in binary expression: %v %v %v", + "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 + // e.g. native: time.Second + time.Second, convert both(or it will be converted recursively) + // see tests/files/types/time_native.gno + if rnt, ok := rt.(*NativeType); ok { + 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 + assertAssignableTo(lpt, rpt, false) // both primitive types + rn = Expr(Call(rpt.String(), n.Right)) + } else { // rt not native + panic(fmt.Sprintf( + "incompatible operands in binary expression: %s %s %s", lt.TypeID(), n.Op, rt.TypeID())) } - pt := go2GnoBaseType(lnt.Type).(PrimitiveType) + + // 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 + 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, - ln := Expr(Call(pt.String(), n.Left)) + rn := Expr(Call(pt.String(), n.Right)) // convert n.Right to pt or uint type, - rn := n.Right + ln := n.Left if isShift { - if baseOf(rt) != UintType { - rn = Expr(Call("uint", n.Right)) - } + panic("should not happen") } else { - rn = Expr(Call(pt.String(), n.Right)) + checkOrConvertType(store, last, &n.Left, pt, false) } // and convert result back. - tx := constType(n, lnt) + tx := constType(n, rnt) // reset/create n2 to preprocess // children. n2 := &BinaryExpr{ @@ -929,8 +965,6 @@ 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 { // non-shift non-const binary operator. liu, riu := isUntyped(lt), isUntyped(rt) @@ -941,24 +975,20 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { "incompatible types in binary expression: %v %v %v", lt.TypeID(), n.Op, rt.TypeID())) } - } else { + } else { // left untyped, right typed checkOrConvertType(store, last, &n.Left, rt, false) } - } else { - if riu { - checkOrConvertType(store, last, &n.Right, lt, false) + } else if riu { // left typed, right untyped + checkOrConvertType(store, last, &n.Right, lt, false) + } else { // both typed, refer to 0a1g.gno + if !shouldSwapOnSpecificity(lt, rt) { + checkOrConvertType(store, last, &n.Left, rt, false) } else { - // left is untyped, right is not. - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf( - "incompatible types in binary expression: %v %v %v", - lt.TypeID(), n.Op, rt.TypeID())) - } + checkOrConvertType(store, last, &n.Right, lt, false) } } } } - // TRANS_LEAVE ----------------------- case *CallExpr: // Func type evaluation. @@ -1177,12 +1207,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) + assertAssignableTo(tv.T, spts[len(spts)-1].Type.Elem(), true) } else { - checkType(tv.T, spts[i].Type, true) + assertAssignableTo(tv.T, spts[i].Type, true) } } else { - checkType(tv.T, spts[i].Type, true) + assertAssignableTo(tv.T, spts[i].Type, true) } } } else { @@ -1278,6 +1308,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_LEAVE ----------------------- case *UnaryExpr: xt := evalStaticTypeOf(store, last, n.X) + n.AssertCompatible(xt) if xnt, ok := xt.(*NativeType); ok { // get concrete native base type. pt := go2GnoBaseType(xnt.Type).(PrimitiveType) @@ -1325,12 +1356,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, false) + convertType(store, last, &n.Elts[i].Key, IntType) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *SliceType: for i := 0; i < len(n.Elts); i++ { - checkOrConvertType(store, last, &n.Elts[i].Key, IntType, false) + convertType(store, last, &n.Elts[i].Key, IntType) checkOrConvertType(store, last, &n.Elts[i].Value, cclt.Elt, false) } case *MapType: @@ -1571,6 +1602,7 @@ 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 { // Rhs consts become default *ConstExprs. @@ -1578,22 +1610,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: does nothing if rx is "nil". convertIfConst(store, last, rx) } + 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] @@ -1601,11 +1624,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 tt := evalStaticType(store, last, cx.Type) @@ -1613,11 +1631,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 @@ -1649,56 +1662,27 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } } } else { // ASSIGN, or assignment operation (+=, -=, <<=, etc.) - // If this is an assignment operation, ensure there's only 1 - // expr on lhs/rhs. - if n.Op != ASSIGN && - (len(n.Lhs) != 1 || len(n.Rhs) != 1) { - panic("assignment operator " + n.Op.TokenString() + - " requires only one expression on lhs and rhs") - } - // NOTE: Keep in sync with DEFINE above. - if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { - // Special case if shift assign <<= or >>=. - checkOrConvertType(store, last, &n.Rhs[0], UintType, false) - } else 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) { - 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 { + if len(n.Lhs) > len(n.Rhs) { + // check is done in assertCompatible + } 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") } - cx.HasOK = true - case *IndexExpr: - // Index case: v, ok := x[k], x is map. - if len(n.Lhs) != 2 { - panic("should not happen") + // Special case if shift assign <<= or >>=. + convertType(store, last, &n.Rhs[0], UintType) + } 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, + lt := evalStaticTypeOf(store, last, n.Lhs[0]) + 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) } - cx.HasOK = true - default: - panic("should not happen") - } - } else { - // 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) } } } @@ -1737,6 +1721,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } + case *IncDecStmt: + xt := evalStaticTypeOf(store, last, n.X) + n.AssertCompatible(xt) + // TRANS_LEAVE ----------------------- case *ForStmt: // Cond consts become bool *ConstExprs. @@ -1750,6 +1738,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: @@ -2438,47 +2427,25 @@ func isConstType(x Expr) bool { return ok } -func cmpSpecificity(t1, t2 Type) int { - 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 - } -} - -// 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() +// 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) + 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. + // "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 { - // check type xt := evalStaticTypeOf(store, last, *x) if t != nil { - checkType(xt, t, autoNative) + assertAssignableTo(xt, t, autoNative) } - // convert type - if isUntyped(xt) { // convert if x is untyped literal - if t == nil { - t = defaultTypeOf(xt, nil) - } + if isUntyped(xt) { // Push type into expr if qualifying binary expr. if bx, ok := (*x).(*BinaryExpr); ok { switch bx.Op { @@ -2496,20 +2463,47 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative // default: } } + } + } + // convert recursively + convertType(store, last, x, 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() +func convertType(store Store, last BlockNode, x *Expr, t Type) { + if debug { + debug.Printf("convertType, *x: %v:, t:%v \n", *x, t) + } + if cx, ok := (*x).(*ConstExpr); ok { + convertConst(store, last, cx, t) + } else if *x != nil { + xt := evalStaticTypeOf(store, last, *x) + if isUntyped(xt) { + if t == nil { + t = defaultTypeOf(xt) + } + if debug { + debug.Printf("default type of t: %v \n", t) + } // convert x to destination type t - convertType(store, last, x, t) + doConvertType(store, last, x, t) } else { // if one side is declared name type and the other side is unnamed type if isNamedConversion(xt, t) { // covert right (xt) to the type of the left (t) - convertType(store, last, x, t) + doConvertType(store, last, x, t) } } } } // convert x to destination type t -func convertType(store Store, last BlockNode, x *Expr, t Type) { +func doConvertType(store Store, last BlockNode, x *Expr, t Type) { cx := Expr(Call(constType(nil, t), *x)) cx = Preprocess(store, last, cx).(Expr) *x = cx @@ -2563,7 +2557,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 { - checkType(cx.T, t, false) + assertAssignableTo(cx.T, t, false) } t = nil // signifies to convert to default type. } @@ -2577,232 +2571,6 @@ 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) { - 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.PointerTo(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") - } - } - // 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(to) gonative{*x} - //nolint:misspell - if enxt, ok := pxt.Elt.(*NativeType); ok { - xt = &NativeType{ - Type: reflect.PointerTo(enxt.Type), - } - } - } - if pdt, ok := dt.(*PointerType); ok { - // *gonative{x} is gonative{*x} - if endt, ok := pdt.Elt.(*NativeType); ok { - dt = &NativeType{ - Type: reflect.PointerTo(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 - } - } - } 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 { - 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, 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 { - 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())) -} - // 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/preprocess_test.go b/gnovm/pkg/gnolang/preprocess_test.go index 2419a385e14..49e6d53fd3d 100644 --- a/gnovm/pkg/gnolang/preprocess_test.go +++ b/gnovm/pkg/gnolang/preprocess_test.go @@ -29,7 +29,7 @@ func main() { defer func() { err := recover() - assert.Contains(t, fmt.Sprint(err), "incompatible types in binary expression") + assert.Contains(t, fmt.Sprint(err), "incompatible operands in binary expression") }() Preprocess(store, pn, n) } @@ -54,7 +54,7 @@ func main() { defer func() { err := recover() - assert.Contains(t, fmt.Sprint(err), "incompatible types in binary expression") + assert.Contains(t, fmt.Sprint(err), "incompatible operands in binary expression") }() Preprocess(store, pn, n) } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go new file mode 100644 index 00000000000..870eb10b690 --- /dev/null +++ b/gnovm/pkg/gnolang/type_check.go @@ -0,0 +1,926 @@ +package gnolang + +import ( + "fmt" + "reflect" + + "github.com/gnolang/gno/tm2/pkg/errors" +) + +// 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 assertCompatible()s. +var ( + binaryChecker = map[Word]func(t Type) bool{ + ADD: isNumericOrString, + SUB: isNumeric, + MUL: isNumeric, + QUO: isNumeric, + REM: isIntNum, + SHL: isIntNum, + 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, + } + // TODO: star, addressable + unaryChecker = map[Word]func(t Type) bool{ + ADD: isNumeric, + SUB: isNumeric, + XOR: isIntNum, + NOT: isBoolean, + } + IncDecStmtChecker = map[Word]func(t Type) bool{ + 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 ( + IsBoolean category = 1 << iota + IsInteger + IsFloat + IsString + IsBigInt + IsBigDec + + IsNumeric = IsInteger | IsFloat | IsBigInt | IsBigDec + IsOrdered = IsNumeric | IsString +) + +func (pt PrimitiveType) category() category { + switch pt.Kind() { + case BoolKind: + return IsBoolean + case StringKind: + return IsString + 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 BigintKind: + return IsBigInt + case BigdecKind: + return IsBigDec + default: + panic(fmt.Sprintf("unexpected primitive type %v", pt)) + } +} + +func isOrdered(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + return t.category()&IsOrdered != 0 + default: + return false + } +} + +func isBoolean(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + return t.category()&IsBoolean != 0 + default: + return false + } +} + +// rune can be numeric and string +func isNumeric(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + return t.category()&IsNumeric != 0 + default: + return false + } +} + +func isIntNum(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + return t.category()&IsInteger != 0 || t.category()&IsBigInt != 0 + default: + return false + } +} + +func isNumericOrString(t Type) bool { + switch t := baseOf(t).(type) { + case PrimitiveType: + return t.category()&IsNumeric != 0 || t.category()&IsString != 0 + default: + return false + } +} + +// =========================================================== +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 +func assertComparable2(dt Type) { + if debug { + 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, *ChanType: + assertComparable2(cdt.Elem()) + default: + panic(fmt.Sprintf("%v is not comparable", dt)) + } + case *StructType: + for _, f := range cdt.Fields { + switch cft := baseOf(f.Type).(type) { + case PrimitiveType, *PointerType, *InterfaceType, *NativeType, *ArrayType, *StructType: + assertComparable2(cft) + default: + panic(fmt.Sprintf("%v is not comparable", dt)) + } + } + case *PointerType: // &a == &b + case *InterfaceType: + case *SliceType, *FuncType, *MapType: + case *NativeType: + if !cdt.Type.Comparable() { + panic(fmt.Sprintf("%v is not comparable", dt)) + } + default: + panic(fmt.Sprintf("%v is not comparable", dt)) + } +} + +func maybeNil(t Type) bool { + switch cxt := baseOf(t).(type) { + case *SliceType, *FuncType, *MapType, *InterfaceType, *PointerType, *ChanType: // 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 + } + default: + return false + } +} + +func checkSame(at, bt Type, msg string) error { + if debug { + debug.Printf("checkSame, at: %v bt: %v \n", at, bt) + } + if at.TypeID() != bt.TypeID() { + return errors.New("incompatible types %v and %v %s", + at.TypeID(), bt.TypeID(), msg) + } + return nil +} + +func assertAssignableTo(xt, dt Type, autoNative bool) { + err := checkAssignableTo(xt, dt, autoNative) + if err != nil { + panic(err.Error()) + } +} + +// 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 checkAssignableTo(xt, dt Type, autoNative bool) error { + if debug { + debug.Printf("checkAssignableTo, xt: %v dt: %v \n", xt, dt) + } + // case0 + if xt == nil { // see test/files/types/eql_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 + if dt.Kind() == InterfaceKind { // note native interface + 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 nil // ok + } else if idt.IsImplementedBy(xt) { + // if dt implements idt, ok. + return nil // ok + } else { + return errors.New( + "%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 nil // ok + } else if nxt, ok := baseOf(xt).(*NativeType); ok { + // if xt has native base, do the naive native. + if nxt.Type.AssignableTo(nidt) { + return nil // ok + } else { + return errors.New( + "cannot use %s as %s", + nxt.String(), + nidt.String()) + } + } else if pxt, ok := baseOf(xt).(*PointerType); ok { + nxt, ok := pxt.Elt.(*NativeType) + if !ok { + return errors.New( + "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 nil // ok + } else { + return errors.New( + "cannot use %s as %s", + pxt.String(), + nidt.String()) + } + } else if xdt, ok := xt.(*DeclaredType); ok { + if gno2GoTypeMatches(baseOf(xdt), ndt.Type) { + return nil + } // not check against native interface + } else { + return errors.New( + "unexpected type pair: cannot use %s as %s", + xt.String(), + dt.String()) + } + } else { + return errors.New("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 nil // ok + } else if dxt.TypeID() == ddt.TypeID() { + return nil // ok + } else { + return errors.New( + "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 { + return errors.New( + "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 + } + } + } 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) { + return errors.New( + "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 + } + } + + // 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 nil // ok + } else { + return errors.New( + "cannot use untyped bool as %s", + dt.Kind()) + } + case UntypedStringType: + if dt.Kind() == StringKind { + return nil // ok + } else { + return errors.New( + "cannot use untyped string as %s", + dt.Kind()) + } + // 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 after const evaluated. + // assignable does not guarantee convertible. + case UntypedBigdecType: + switch dt.Kind() { + case IntKind, Int8Kind, Int16Kind, Int32Kind, + Int64Kind, UintKind, Uint8Kind, Uint16Kind, + Uint32Kind, Uint64Kind, BigdecKind, Float32Kind, Float64Kind: + return nil // 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: // see 0d0 + return nil // ok + default: + return errors.New( + "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 nil // ok + default: + return errors.New( + "cannot use untyped rune as %s", + dt.Kind()) + } + + default: + if isUntyped(xt) { + panic("unexpected untyped type") + } + if xt.TypeID() == cdt.TypeID() { + return nil // ok + } + } + case *PointerType: // case 4 from here on + if pt, ok := xt.(*PointerType); ok { + return checkAssignableTo(pt.Elt, cdt.Elt, false) + } + case *ArrayType: + if at, ok := xt.(*ArrayType); ok { + if at.Len != cdt.Len { + return errors.New( + "cannot use %s as %s", + at.String(), + cdt.String()) + } + err := checkSame(at.Elt, cdt.Elt, "") + if err != nil { + return errors.New( + "cannot use %s as %s", + at.String(), + cdt.String()) + } + return nil + } + case *SliceType: + if st, ok := xt.(*SliceType); ok { + if cdt.Vrd { + return checkAssignableTo(st.Elt, cdt.Elt, false) + } else { + err := checkSame(st.Elt, cdt.Elt, "") + if err != nil { + return errors.New( + "cannot use %s as %s", + st.String(), + cdt.String()) + } + return nil + } + } + case *MapType: + if mt, ok := xt.(*MapType); ok { + err := checkSame(mt.Key, cdt.Key, "") + if err != nil { + return errors.New( + "cannot use %s as %s", + mt.String(), + cdt.String()).Stacktrace() + } + return nil + } + case *InterfaceType: + return errors.New("should not happen") + case *DeclaredType: + panic("should not happen") + case *FuncType, *StructType, *PackageType, *ChanType, *TypeType: + if xt.TypeID() == cdt.TypeID() { + return nil // 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 nil // 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 nil // ok + } + } + default: + return errors.New( + "unexpected type %s", + dt.String()) + } + return errors.New( + "cannot use %s as %s", + xt.String(), + dt.String()).Stacktrace() +} + +// =========================================================== +func (x *BinaryExpr) checkShiftLhs(dt Type) { + if checker, ok := binaryChecker[x.Op]; ok { + if !checker(dt) { + 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)) + } +} + +// AssertCompatible works as a pre-check prior to checkOrConvertType. +// 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. +func (x *BinaryExpr) AssertCompatible(lt, rt Type) { + // native type will be converted to gno in latter logic, + // this check logic will be conduct again from trans_leave *BinaryExpr. + lnt, lin := lt.(*NativeType) + rnt, rin := rt.(*NativeType) + if lin && rin { + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf( + "incompatible operands in binary expression: %s %s %s", + lt.TypeID(), x.Op, rt.TypeID())) + } + } + if lin { + if _, ok := go2GnoBaseType(lnt.Type).(PrimitiveType); ok { + return + } + } + if rin { + if _, ok := go2GnoBaseType(rnt.Type).(PrimitiveType); ok { + return + } + } + + xt, dt := lt, rt + if shouldSwapOnSpecificity(lt, rt) { + xt, dt = dt, xt + } + + if isComparison(x.Op) { + switch x.Op { + case EQL, NEQ: + assertComparable(xt, dt) + if !isUntyped(xt) && !isUntyped(dt) { + assertAssignableTo(xt, dt, false) + } + case LSS, LEQ, GTR, GEQ: + if checker, ok := binaryChecker[x.Op]; ok { + x.checkCompatibility(xt, dt, checker, x.Op.TokenString()) + } else { + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) + } + default: + panic("invalid comparison operator") + } + } else { + if checker, ok := binaryChecker[x.Op]; ok { + x.checkCompatibility(xt, dt, checker, x.Op.TokenString()) + } else { + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) + } + + switch x.Op { + case QUO, REM: + // special case of zero divisor + if isQuoOrRem(x.Op) { + if rcx, ok := x.Right.(*ConstExpr); ok { + if rcx.TypedValue.isZero() { + panic("invalid operation: division by zero") + } + } + } + default: + // do nothing + } + } +} + +// Check compatibility of the destination type (dt) with the operator. +// If both source type (xt) and destination type (dt) are typed: +// Verify that xt is assignable to dt. +// If xt is untyped: +// The function checkOrConvertType will be invoked after this check. +// NOTE: dt is established based on a specificity check between xt and dt, +// confirming dt as the appropriate destination type for this context. +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))) + } + + // if both typed + if !isUntyped(xt) && !isUntyped(dt) { + err := checkAssignableTo(xt, dt, false) + if err != nil { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", xt, dt)) + } + } +} + +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[x.Op]; ok { + if !checker(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", x.Op)) + } +} + +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[x.Op]; ok { + if !checker(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", x.Op)) + } +} + +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 + } + if isBlankIdentifier(x.Key) && isBlankIdentifier(x.Value) { + // both "_" + return + } + assertValidAssignLhs(store, last, x.Key) + // if is valid left value + + kt := evalStaticTypeOf(store, last, x.Key) + 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) + if vt != nil { + assertAssignableTo(cxt.Value, vt, false) + } + case *SliceType: + assertIndexTypeIsInt(kt) + if vt != nil { + assertAssignableTo(cxt.Elt, vt, false) + } + case *ArrayType: + assertIndexTypeIsInt(kt) + if vt != nil { + 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 { + if vt.Kind() != Int32Kind { // rune + panic(fmt.Sprintf("value type should be int32, but got %v", kt)) + } + } + } + } +} + +func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { + if x.Op == ASSIGN || x.Op == DEFINE { + if len(x.Lhs) > len(x.Rhs) { + if len(x.Rhs) != 1 { + panic(fmt.Sprintf("assignment mismatch: %d variables but %d values", len(x.Lhs), len(x.Rhs))) + } + 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(x.Lhs) != len(cft.Results) { + panic(fmt.Sprintf( + "assignment mismatch: "+ + "%d variables but %s returns %d values", + len(x.Lhs), cx.Func.String(), len(cft.Results))) + } + if x.Op == ASSIGN { + // check assignable + for i, lx := range x.Lhs { + if !isBlankIdentifier(lx) { + assertValidAssignLhs(store, last, lx) + lxt := evalStaticTypeOf(store, last, lx) + assertAssignableTo(cft.Results[i].Type, lxt, false) + } + } + } + case *TypeAssertExpr: + // Type-assert case: a, ok := x.(type) + if len(x.Lhs) != 2 { + panic("should not happen") + } + if x.Op == ASSIGN { + // check assignable to first value + if !isBlankIdentifier(x.Lhs[0]) { // see composite3.gno + 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 + 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)) + } + } + } + cx.HasOK = true + case *IndexExpr: // must be with map type when len(Lhs) > len(Rhs) + if len(x.Lhs) != 2 { + panic("should not happen") + } + if x.Op == ASSIGN { + if !isBlankIdentifier(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) + if mt, ok := rt.(*MapType); ok { + assertAssignableTo(mt.Value, lt, false) + } + } else if _, ok := cx.X.(*CompositeLitExpr); ok { + cpt := evalStaticTypeOf(store, last, cx.X) + if mt, ok := cpt.(*MapType); ok { + assertAssignableTo(mt.Value, lt, false) + } else { + panic("should not happen") + } + } + } + if !isBlankIdentifier(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)) + } + } + } + cx.HasOK = true + default: + panic(fmt.Sprintf("RHS should not be %v when len(Lhs) > len(Rhs)", cx)) + } + } else { // len(Lhs) == len(Rhs) + if x.Op == ASSIGN { + // assert valid left value + for _, lx := range x.Lhs { + assertValidAssignLhs(store, last, lx) + } + } + } + } else { // Ops other than assign and define + // If this is an assignment operation, ensure there's only 1 + // expr on lhs/rhs. + 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 x.Lhs { + lt := evalStaticTypeOf(store, last, lx) + rt := evalStaticTypeOf(store, last, x.Rhs[i]) + + if checker, ok := AssignStmtChecker[x.Op]; ok { + if !checker(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: + // 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 { + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", lt, rt)) + } + } + } + default: + // do nothing + } + } else { + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) + } + } + } +} + +// misc +func assertValidAssignLhs(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() + } + return "nil" +} + +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 + } +} + +// 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 + return false // also with both nil + } else if t2 == nil { + return true + } + + // check interface + if it1, ok := baseOf(t1).(*InterfaceType); ok { + if it1.IsEmptyInterface() { + return true // left empty interface + } else { + if _, ok := baseOf(t2).(*InterfaceType); ok { + return false + } else { + return true // right not interface + } + } + } else if _, ok := t2.(*InterfaceType); ok { + return false // left not interface, right is interface + } + + // primitive types + 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 true + } else { + return false + } +} + +func isBlankIdentifier(x Expr) bool { + if nx, ok := x.(*NameExpr); ok { + return nx.Name == "_" + } + return false +} diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index 86b3d588eda..ab8e9effdc8 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -1203,8 +1203,8 @@ func (ft *FuncType) Specify(store Store, argTVs []TypedValue, isVarg bool) *Func continue } else if vargt == nil { vargt = varg.T - } else if isUntyped(varg.T) && vargt.TypeID() == defaultTypeOf(varg.T, varg.V).TypeID() { - vargt = defaultTypeOf(varg.T, varg.V) + } else if isUntyped(varg.T) && vargt.TypeID() == defaultTypeOf(varg.T).TypeID() { + vargt = defaultTypeOf(varg.T) } else if vargt.TypeID() != varg.T.TypeID() { panic(fmt.Sprintf( "incompatible varg types: expected %v, got %s", @@ -2203,11 +2203,11 @@ func KindOf(t Type) Kind { // ---------------------------------------- // main type-assertion functions. -// TODO: document what class of problems its for. +// Only for runtime debugging. // 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) { +// usage: if debug { debugAssertSameTypes() } +func debugAssertSameTypes(lt, rt Type) { if lt == nil && rt == nil { // both are nil. } else if lt == nil || rt == nil { @@ -2232,8 +2232,10 @@ func assertSameTypes(lt, rt Type) { } } -// Like assertSameTypes(), but more relaxed, for == and !=. -func assertEqualityTypes(lt, rt Type) { +// Only for runtime debugging. +// Like debugAssertSameTypes(), but more relaxed, for == and !=. +// usage: if debug { debugAssertEqualityTypes() } +func debugAssertEqualityTypes(lt, rt Type) { if lt == nil && rt == nil { // both are nil. } else if lt == nil || rt == nil { @@ -2281,23 +2283,14 @@ func isDataByte(t Type) bool { // TODO move untyped const stuff to preprocess.go. // TODO associate with ConvertTo() in documentation. -func defaultTypeOf(t Type, v Value) Type { +func defaultTypeOf(t Type) Type { switch t { case UntypedBoolType: return BoolType case UntypedRuneType: return Int32Type case UntypedBigintType: - typeVal := IntType - if bigintValue, ok := v.(BigintValue); ok { - if bigintValue.V != nil && bigintValue.V.Sign() == 1 && !bigintValue.V.IsInt64() { - // Use an unsigned type if the value is positive and we know - // it won't fit in an int64. - typeVal = Uint64Type - } - } - - return typeVal + return IntType case UntypedBigdecType: return Float64Type case UntypedStringType: @@ -2371,6 +2364,7 @@ func fillEmbeddedName(ft *FieldType) { ft.Embedded = true } +// TODO: empty interface? refer to assertAssignableTo func IsImplementedBy(it Type, ot Type) bool { switch cbt := baseOf(it).(type) { case *InterfaceType: @@ -2505,7 +2499,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) + assertAssignableTo(spec, match.Elem(), false) return // ok } else { // Panic here, because we don't know whether T @@ -2519,11 +2513,11 @@ 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) + assertAssignableTo(spec, match, false) return // ok } else { if isUntyped(spec) { - spec = defaultTypeOf(spec, nil) + spec = defaultTypeOf(spec) } lookup[ct.Generic] = spec return // ok diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index d8d4bc58bc3..344977a849c 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -1494,6 +1494,88 @@ func (tv *TypedValue) GetBigDec() *apd.Decimal { return tv.V.(BigdecValue).V } +// 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 true + } + case Int8Kind: + v := tv.GetInt8() + if v == 0 { + return true + } + case Int16Kind: + v := tv.GetInt16() + if v == 0 { + return true + } + case Int32Kind: + v := tv.GetInt32() + if v == 0 { + return true + } + case Int64Kind: + v := tv.GetInt64() + if v == 0 { + return true + } + case UintKind: + v := tv.GetUint() + if v == 0 { + return true + } + case Uint8Kind: + v := tv.GetUint8() + if v == 0 { + return true + } + case Uint16Kind: + v := tv.GetUint16() + if v == 0 { + return true + } + case Uint32Kind: + v := tv.GetUint32() + if v == 0 { + return true + } + case Uint64Kind: + v := tv.GetUint64() + if v == 0 { + return true + } + case Float32Kind: + v := tv.GetFloat32() + if v == 0 { + return true + } + case Float64Kind: + v := tv.GetFloat64() + if v == 0 { + return true + } + case BigintKind: + v := tv.GetBigInt() + if v.Sign() == 0 { + return true + } + case BigdecKind: + v := tv.GetBigDec() + if v.Sign() == 0 { + return true + } + default: + panic("not numeric") + } + return false +} + func (tv *TypedValue) ComputeMapKey(store Store, omitType bool) MapKey { // Special case when nil: has no separator. if tv.T == nil { @@ -1594,7 +1676,7 @@ func (tv *TypedValue) Assign(alloc *Allocator, tv2 TypedValue, cu bool) { } *tv = tv2.Copy(alloc) if cu && isUntyped(tv.T) { - ConvertUntypedTo(tv, defaultTypeOf(tv.T, tv.V)) + ConvertUntypedTo(tv, defaultTypeOf(tv.T)) } } diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index edaa8883819..c5ddc232fcb 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -881,6 +881,11 @@ GNO_CASE: // Panics if conversion is illegal. // TODO: method on TypedValue? func ConvertUntypedTo(tv *TypedValue, t Type) { + if debug { + defer func() { + debug.Printf("ConvertUntypedTo done, tv: %v \n", tv) + }() + } if debug { if !isUntyped(tv.T) { panic(fmt.Sprintf( @@ -926,7 +931,7 @@ func ConvertUntypedTo(tv *TypedValue, t Type) { } // general case if t == nil { - t = defaultTypeOf(tv.T, tv.V) + t = defaultTypeOf(tv.T) } switch tv.T { case UntypedBoolType: diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 852bb74d198..8ab60145bd5 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -263,8 +263,18 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { 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] + } if errstr != errWanted { - panic(fmt.Sprintf("fail on %s: got %q, want: %q", path, errstr, errWanted)) + if f.syncWanted { + // write error to file + replaceWantedInPlace(path, "Error", errstr) + } else { + panic(fmt.Sprintf("fail on %s: got %q, want: %q", path, errstr, errWanted)) + } } // NOTE: ignores any gno.GetDebugErrors(). @@ -279,12 +289,16 @@ 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 := 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 ***" + // write error to file replaceWantedInPlace(path, "Error", ctl) panic(fmt.Sprintf("fail on %s: err recorded, check the message and run test again", path)) } diff --git a/gnovm/tests/files/access0.gno b/gnovm/tests/files/access0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/access0.gno rename to gnovm/tests/files/access0_stdlibs.gno diff --git a/gnovm/tests/files/access1.gno b/gnovm/tests/files/access1_stdlibs.gno similarity index 53% rename from gnovm/tests/files/access1.gno rename to gnovm/tests/files/access1_stdlibs.gno index d9bb9f46203..7a2f2cf3817 100644 --- a/gnovm/tests/files/access1.gno +++ b/gnovm/tests/files/access1_stdlibs.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/access1.gno:8: cannot access gno.land/p/demo/testutils.testVar2 from main +// main/files/access1_stdlibs.gno:8: cannot access gno.land/p/demo/testutils.testVar2 from main diff --git a/gnovm/tests/files/access2.gno b/gnovm/tests/files/access2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/access2.gno rename to gnovm/tests/files/access2_stdlibs.gno diff --git a/gnovm/tests/files/access3.gno b/gnovm/tests/files/access3_stdlibs.gno similarity index 100% rename from gnovm/tests/files/access3.gno rename to gnovm/tests/files/access3_stdlibs.gno diff --git a/gnovm/tests/files/access4.gno b/gnovm/tests/files/access4_stdlibs.gno similarity index 57% rename from gnovm/tests/files/access4.gno rename to gnovm/tests/files/access4_stdlibs.gno index bb2dcc340f0..6f092efb61c 100644 --- a/gnovm/tests/files/access4.gno +++ b/gnovm/tests/files/access4_stdlibs.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/access4.gno:9: cannot access gno.land/p/demo/testutils.TestAccessStruct.privateField from main +// main/files/access4_stdlibs.gno:9: cannot access gno.land/p/demo/testutils.TestAccessStruct.privateField from main diff --git a/gnovm/tests/files/access5.gno b/gnovm/tests/files/access5_stdlibs.gno similarity index 100% rename from gnovm/tests/files/access5.gno rename to gnovm/tests/files/access5_stdlibs.gno diff --git a/gnovm/tests/files/access6.gno b/gnovm/tests/files/access6_stdlibs.gno similarity index 67% rename from gnovm/tests/files/access6.gno rename to gnovm/tests/files/access6_stdlibs.gno index 991b4a5457a..b9e019525a7 100644 --- a/gnovm/tests/files/access6.gno +++ b/gnovm/tests/files/access6_stdlibs.gno @@ -16,4 +16,4 @@ func main() { } // Error: -// main/files/access6.gno:15: main.mystruct does not implement gno.land/p/demo/testutils.PrivateInterface +// main/files/access6_stdlibs.gno:15: main.mystruct does not implement gno.land/p/demo/testutils.PrivateInterface diff --git a/gnovm/tests/files/access7.gno b/gnovm/tests/files/access7_stdlibs.gno similarity index 72% rename from gnovm/tests/files/access7.gno rename to gnovm/tests/files/access7_stdlibs.gno index 2b4c32ab818..ab63b3b9639 100644 --- a/gnovm/tests/files/access7.gno +++ b/gnovm/tests/files/access7_stdlibs.gno @@ -20,4 +20,4 @@ func main() { } // Error: -// main/files/access7.gno:19: main.PrivateInterface2 does not implement gno.land/p/demo/testutils.PrivateInterface +// main/files/access7_stdlibs.gno:19: main.PrivateInterface2 does not implement gno.land/p/demo/testutils.PrivateInterface diff --git a/gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno b/gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno index 5d994352f35..ba40fb8caa3 100644 --- a/gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/method/declaredType6_filetest.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/assign_unnamed_type/method/declaredType6_filetest.gno:15: cannot use main.c as main.word without explicit conversion +// main/files/assign_unnamed_type/method/declaredType6_filetest.gno:15: cannot use []main.c as []main.word diff --git a/gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno index 88b3203a805..9e46c884252 100644 --- a/gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/method/declaredType6b_filetest.gno @@ -17,4 +17,4 @@ func main() { } // Error: -// main/files/assign_unnamed_type/method/declaredType6b_filetest.gno:15: cannot use uint as main.word without explicit conversion +// main/files/assign_unnamed_type/method/declaredType6b_filetest.gno:15: cannot use []uint as []main.word diff --git a/gnovm/tests/files/assign_unnamed_type/more/cross_realm_compositelit_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/cross_realm_compositelit_filetest_stdlibs.gno similarity index 100% rename from gnovm/tests/files/assign_unnamed_type/more/cross_realm_compositelit_filetest.gno rename to gnovm/tests/files/assign_unnamed_type/more/cross_realm_compositelit_filetest_stdlibs.gno diff --git a/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno index cc1d54cfa2a..8f1eb5399b2 100644 --- a/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/unnamedtype0b_filetest.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/assign_unnamed_type/unnamedtype0b_filetest.gno:11: cannot use main.word as int without explicit conversion +// main/files/assign_unnamed_type/unnamedtype0b_filetest.gno:11: cannot use []main.word as []int diff --git a/gnovm/tests/files/bigint1.gno b/gnovm/tests/files/bigint1.gno deleted file mode 100644 index 01032e27b3f..00000000000 --- a/gnovm/tests/files/bigint1.gno +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "math" -) - -func main() { - println(float64(math.MaxUint32)) - println(float64(math.MaxUint64)) -} - -// Output: -// 4.294967295e+09 -// 1.8446744073709552e+19 diff --git a/gnovm/tests/files/bool6.gno b/gnovm/tests/files/bool6.gno index ad4d832036c..3ad789dda32 100644 --- a/gnovm/tests/files/bool6.gno +++ b/gnovm/tests/files/bool6.gno @@ -9,4 +9,4 @@ func X() string { } // Error: -// main/files/bool6.gno:8: operands of boolean operators must evaluate to boolean typed values +// main/files/bool6.gno:8: operator || not defined on: StringKind diff --git a/gnovm/tests/files/comp4.gno b/gnovm/tests/files/comp4.gno new file mode 100644 index 00000000000..501cffeb871 --- /dev/null +++ b/gnovm/tests/files/comp4.gno @@ -0,0 +1,32 @@ +package main + +type S struct { +} + +func main() { + x := (*S)(nil) + println("x == x", x == x) + println("x == nil", x == nil) + println("nil == x", nil == x) + + var y interface{} = (*S)(nil) + println("y == y", y == y) + println("y == nil", y == nil) + println("nil == y", nil == y) + + y = nil + println("y == y", y == y) + println("y == nil", y == nil) + println("nil == y", nil == y) +} + +// Output: +// x == x true +// x == nil true +// nil == x true +// y == y true +// y == nil false +// nil == y false +// y == y true +// y == nil true +// nil == y true diff --git a/gnovm/tests/files/comp5.gno b/gnovm/tests/files/comp5.gno new file mode 100644 index 00000000000..827800f2a67 --- /dev/null +++ b/gnovm/tests/files/comp5.gno @@ -0,0 +1,23 @@ +package main + +type S struct { +} + +func main() { + x := (*S)(nil) + var y interface{} = (*S)(nil) + var znil interface{} = nil + + println("y == znil", y == znil) + println("znil == y", znil == y) + + y = nil + println("y == znil", y == znil) + println("znil == y", znil == y) +} + +// Output: +// y == znil false +// znil == y false +// y == znil true +// znil == y true diff --git a/gnovm/tests/files/fun24.gno b/gnovm/tests/files/fun24.gno index 42468ff087e..100d3c26ded 100644 --- a/gnovm/tests/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/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 diff --git a/gnovm/tests/files/math_native.gno b/gnovm/tests/files/math_native.gno new file mode 100644 index 00000000000..54bddcde1f3 --- /dev/null +++ b/gnovm/tests/files/math_native.gno @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "math" +) + +func main() { + var a float64 = 2.0 + fmt.Println(math.Pi * a) +} + +// Output: +// 6.283185307179586 diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files/op7.gno index 7167171035b..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: incompatible types in binary expression: .uverse.error GTR main.T +// main/files/op7.gno:11: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/std0.gno b/gnovm/tests/files/std0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std0.gno rename to gnovm/tests/files/std0_stdlibs.gno diff --git a/gnovm/tests/files/std10.gno b/gnovm/tests/files/std10_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std10.gno rename to gnovm/tests/files/std10_stdlibs.gno diff --git a/gnovm/tests/files/std11.gno b/gnovm/tests/files/std11_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std11.gno rename to gnovm/tests/files/std11_stdlibs.gno diff --git a/gnovm/tests/files/std2.gno b/gnovm/tests/files/std2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std2.gno rename to gnovm/tests/files/std2_stdlibs.gno diff --git a/gnovm/tests/files/std3.gno b/gnovm/tests/files/std3_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std3.gno rename to gnovm/tests/files/std3_stdlibs.gno diff --git a/gnovm/tests/files/std4.gno b/gnovm/tests/files/std4_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std4.gno rename to gnovm/tests/files/std4_stdlibs.gno diff --git a/gnovm/tests/files/std5.gno b/gnovm/tests/files/std5_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std5.gno rename to gnovm/tests/files/std5_stdlibs.gno diff --git a/gnovm/tests/files/std6.gno b/gnovm/tests/files/std6_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std6.gno rename to gnovm/tests/files/std6_stdlibs.gno diff --git a/gnovm/tests/files/std7.gno b/gnovm/tests/files/std7_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std7.gno rename to gnovm/tests/files/std7_stdlibs.gno diff --git a/gnovm/tests/files/std8.gno b/gnovm/tests/files/std8_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std8.gno rename to gnovm/tests/files/std8_stdlibs.gno diff --git a/gnovm/tests/files/std9.gno b/gnovm/tests/files/std9_stdlibs.gno similarity index 100% rename from gnovm/tests/files/std9.gno rename to gnovm/tests/files/std9_stdlibs.gno diff --git a/gnovm/tests/files/time16_native.gno b/gnovm/tests/files/time16_native.gno index 1789fcbef4f..03eca47172f 100644 --- a/gnovm/tests/files/time16_native.gno +++ b/gnovm/tests/files/time16_native.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/time16_native.gno:10: incompatible types in binary expression: go:time.Duration MUL int64 +// main/files/time16_native.gno:10: incompatible operands in binary expression: go:time.Duration MUL int64 diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index a613c67525c..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: incompatible types in binary expression: string ADD main.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 bc943d90186..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: incompatible types in binary expression: string ADD main.S +// main/files/type32.gno:9#1: invalid operation: mismatched types string and main.S diff --git a/gnovm/tests/files/types/add_a0.gno b/gnovm/tests/files/types/add_a0.gno new file mode 100644 index 00000000000..9b8e08718b7 --- /dev/null +++ b/gnovm/tests/files/types/add_a0.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) + int8(1)) +} + +// Error: +// main/files/types/add_a0.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/add_a1.gno b/gnovm/tests/files/types/add_a1.gno new file mode 100644 index 00000000000..f5bcec883b2 --- /dev/null +++ b/gnovm/tests/files/types/add_a1.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/add_a1.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/add_assign_a0.gno b/gnovm/tests/files/types/add_assign_a0.gno new file mode 100644 index 00000000000..181941d1ea9 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_a0.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + int(0) += int8(1) +} + +// Error: +// main/files/types/add_assign_a0.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/add_assign_a1.gno b/gnovm/tests/files/types/add_assign_a1.gno new file mode 100644 index 00000000000..f169e58d5b1 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_a1.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/add_assign_a1.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/add_assign_a_01.gno b/gnovm/tests/files/types/add_assign_a_01.gno new file mode 100644 index 00000000000..f09c7ed7344 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_a_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/add_assign_a_01.gno:6: assignment operator += requires only one expression on lhs and rhs diff --git a/gnovm/tests/files/types/add_assign_b0.gno b/gnovm/tests/files/types/add_assign_b0.gno new file mode 100644 index 00000000000..28b6af83d3a --- /dev/null +++ b/gnovm/tests/files/types/add_assign_b0.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/add_assign_b0.gno:8: invalid operation: mismatched types int and main.Error diff --git a/gnovm/tests/files/types/add_assign_b1.gno b/gnovm/tests/files/types/add_assign_b1.gno new file mode 100644 index 00000000000..2e702256f29 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_b1.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/add_assign_b2.gno b/gnovm/tests/files/types/add_assign_b2.gno new file mode 100644 index 00000000000..87b09754046 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_b2.gno @@ -0,0 +1,10 @@ +package main + +func main() { + r := 1 + r += 'a' + println(r) +} + +// Output: +// 98 diff --git a/gnovm/tests/files/types/add_assign_d0.gno b/gnovm/tests/files/types/add_assign_d0.gno new file mode 100644 index 00000000000..f3da2497a84 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_d0.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/add_assign_e.gno b/gnovm/tests/files/types/add_assign_e.gno new file mode 100644 index 00000000000..3a72f9711be --- /dev/null +++ b/gnovm/tests/files/types/add_assign_e.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/add_assign_e0.gno b/gnovm/tests/files/types/add_assign_e0.gno new file mode 100644 index 00000000000..d71bedab118 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_e0.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/add_assign_e0.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/add_assign_e1.gno b/gnovm/tests/files/types/add_assign_e1.gno new file mode 100644 index 00000000000..3657cf2872d --- /dev/null +++ b/gnovm/tests/files/types/add_assign_e1.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/add_assign_f0_stdlibs.gno b/gnovm/tests/files/types/add_assign_f0_stdlibs.gno new file mode 100644 index 00000000000..b91fa58c30d --- /dev/null +++ b/gnovm/tests/files/types/add_assign_f0_stdlibs.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/add_assign_f0_stdlibs.gno:20: invalid operation: mismatched types int and .uverse.error diff --git a/gnovm/tests/files/types/add_assign_f1_stdlibs.gno b/gnovm/tests/files/types/add_assign_f1_stdlibs.gno new file mode 100644 index 00000000000..090f8f51f89 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_f1_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") + +// 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 // 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: +// main/files/types/add_assign_f1_stdlibs.gno:21: invalid operation: mismatched types main.Error and .uverse.error diff --git a/gnovm/tests/files/types/add_assign_f2_stdlibs.gno b/gnovm/tests/files/types/add_assign_f2_stdlibs.gno new file mode 100644 index 00000000000..5cfd351f574 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_f2_stdlibs.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/add_assign_f2_stdlibs.gno:20: operator += not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/add_assign_f3.gno b/gnovm/tests/files/types/add_assign_f3.gno new file mode 100644 index 00000000000..7a48c584dff --- /dev/null +++ b/gnovm/tests/files/types/add_assign_f3.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/add_assign_f3.gno:27: operator += not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/add_assign_f4.gno b/gnovm/tests/files/types/add_assign_f4.gno new file mode 100644 index 00000000000..bb4083e8935 --- /dev/null +++ b/gnovm/tests/files/types/add_assign_f4.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a += int(1) + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/add_b0.gno b/gnovm/tests/files/types/add_b0.gno new file mode 100644 index 00000000000..3790f9d7134 --- /dev/null +++ b/gnovm/tests/files/types/add_b0.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/add_b1.gno b/gnovm/tests/files/types/add_b1.gno new file mode 100644 index 00000000000..854ecaa9770 --- /dev/null +++ b/gnovm/tests/files/types/add_b1.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/add_b2.gno b/gnovm/tests/files/types/add_b2.gno new file mode 100644 index 00000000000..b6463134da4 --- /dev/null +++ b/gnovm/tests/files/types/add_b2.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 + "a") +} + +// Error: +// main/files/types/add_b2.gno:5: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/files/types/add_b3.gno b/gnovm/tests/files/types/add_b3.gno new file mode 100644 index 00000000000..c8a94c5b6ab --- /dev/null +++ b/gnovm/tests/files/types/add_b3.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/add_d0.gno b/gnovm/tests/files/types/add_d0.gno new file mode 100644 index 00000000000..3f0d9548fff --- /dev/null +++ b/gnovm/tests/files/types/add_d0.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +// untyped bigint to untyped bigdec +// TODO: dec value representation +func main() { + println(1.0 + 1) + println(1.0 + 0) +} + +// Output: +// 2 +// 1 diff --git a/gnovm/tests/files/types/add_d1.gno b/gnovm/tests/files/types/add_d1.gno new file mode 100644 index 00000000000..7bf7c26565a --- /dev/null +++ b/gnovm/tests/files/types/add_d1.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/add_d2.gno b/gnovm/tests/files/types/add_d2.gno new file mode 100644 index 00000000000..7ea4924a594 --- /dev/null +++ b/gnovm/tests/files/types/add_d2.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/add_d3.gno b/gnovm/tests/files/types/add_d3.gno new file mode 100644 index 00000000000..b130fc98b66 --- /dev/null +++ b/gnovm/tests/files/types/add_d3.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/add_d4.gno b/gnovm/tests/files/types/add_d4.gno new file mode 100644 index 00000000000..bdfca69ea88 --- /dev/null +++ b/gnovm/tests/files/types/add_d4.gno @@ -0,0 +1,11 @@ +package main + +var a int +var b interface{} + +func main() { + println(b + a) +} + +// Error: +// main/files/types/add_d4.gno:7: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/add_e0.gno b/gnovm/tests/files/types/add_e0.gno new file mode 100644 index 00000000000..b7fc8e395be --- /dev/null +++ b/gnovm/tests/files/types/add_e0.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/add_e0.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/add_f0_stdlibs.gno b/gnovm/tests/files/types/add_f0_stdlibs.gno new file mode 100644 index 00000000000..cf16d0ff084 --- /dev/null +++ b/gnovm/tests/files/types/add_f0_stdlibs.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/add_f0_stdlibs.gno:19: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/add_f1_stdlibs.gno b/gnovm/tests/files/types/add_f1_stdlibs.gno new file mode 100644 index 00000000000..6bf1f814ac5 --- /dev/null +++ b/gnovm/tests/files/types/add_f1_stdlibs.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/add_f1_stdlibs.gno:19: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/add_f2.gno b/gnovm/tests/files/types/add_f2.gno new file mode 100644 index 00000000000..7adfcfdaca6 --- /dev/null +++ b/gnovm/tests/files/types/add_f2.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/add_f2.gno:27: operator + not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/and_a0.gno b/gnovm/tests/files/types/and_a0.gno new file mode 100644 index 00000000000..b1d23b23c91 --- /dev/null +++ b/gnovm/tests/files/types/and_a0.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(0) & int8(1)) +} + +// Error: +// main/files/types/and_a0.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/and_a1.gno b/gnovm/tests/files/types/and_a1.gno new file mode 100644 index 00000000000..d2fceec80ef --- /dev/null +++ b/gnovm/tests/files/types/and_a1.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/and_a1.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/and_b0.gno b/gnovm/tests/files/types/and_b0.gno new file mode 100644 index 00000000000..525796320e6 --- /dev/null +++ b/gnovm/tests/files/types/and_b0.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/and_b1.gno b/gnovm/tests/files/types/and_b1.gno new file mode 100644 index 00000000000..dc21fc3956b --- /dev/null +++ b/gnovm/tests/files/types/and_b1.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/and_b2.gno b/gnovm/tests/files/types/and_b2.gno new file mode 100644 index 00000000000..8ff36aaa26b --- /dev/null +++ b/gnovm/tests/files/types/and_b2.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 & "a") +} + +// Error: +// main/files/types/and_b2.gno:5: operator & not defined on: StringKind diff --git a/gnovm/tests/files/types/and_b3.gno b/gnovm/tests/files/types/and_b3.gno new file mode 100644 index 00000000000..69be88d2dc9 --- /dev/null +++ b/gnovm/tests/files/types/and_b3.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" & "a") +} + +// Error: +// main/files/types/and_b3.gno:5: operator & not defined on: StringKind diff --git a/gnovm/tests/files/types/and_b4.gno b/gnovm/tests/files/types/and_b4.gno new file mode 100644 index 00000000000..725714eeafd --- /dev/null +++ b/gnovm/tests/files/types/and_b4.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/and_d0.gno b/gnovm/tests/files/types/and_d0.gno new file mode 100644 index 00000000000..90646e97bc9 --- /dev/null +++ b/gnovm/tests/files/types/and_d0.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/and_d0.gno:6: operator & not defined on: BigdecKind diff --git a/gnovm/tests/files/types/and_d1.gno b/gnovm/tests/files/types/and_d1.gno new file mode 100644 index 00000000000..232fff4d385 --- /dev/null +++ b/gnovm/tests/files/types/and_d1.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/and_d2.gno b/gnovm/tests/files/types/and_d2.gno new file mode 100644 index 00000000000..f5c2660bafc --- /dev/null +++ b/gnovm/tests/files/types/and_d2.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/and_d3.gno b/gnovm/tests/files/types/and_d3.gno new file mode 100644 index 00000000000..f5cb8075f24 --- /dev/null +++ b/gnovm/tests/files/types/and_d3.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/and_d4.gno b/gnovm/tests/files/types/and_d4.gno new file mode 100644 index 00000000000..b4f8a70ad3c --- /dev/null +++ b/gnovm/tests/files/types/and_d4.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 & 0) +} + +// Error: +// main/files/types/and_d4.gno:6: operator & not defined on: BigdecKind diff --git a/gnovm/tests/files/types/and_e0.gno b/gnovm/tests/files/types/and_e0.gno new file mode 100644 index 00000000000..28d58acf42b --- /dev/null +++ b/gnovm/tests/files/types/and_e0.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/and_e0.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/and_f0_stdlibs.gno b/gnovm/tests/files/types/and_f0_stdlibs.gno new file mode 100644 index 00000000000..6b56a8e59c4 --- /dev/null +++ b/gnovm/tests/files/types/and_f0_stdlibs.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/and_f0_stdlibs.gno:19: operator & not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/and_f1_stdlibs.gno b/gnovm/tests/files/types/and_f1_stdlibs.gno new file mode 100644 index 00000000000..f1d7589e2f6 --- /dev/null +++ b/gnovm/tests/files/types/and_f1_stdlibs.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/and_f1_stdlibs.gno:19: operator & not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/and_f2.gno b/gnovm/tests/files/types/and_f2.gno new file mode 100644 index 00000000000..24368256822 --- /dev/null +++ b/gnovm/tests/files/types/and_f2.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/and_f2.gno:27: operator & not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/assign_call.gno b/gnovm/tests/files/types/assign_call.gno new file mode 100644 index 00000000000..a94b4a0b126 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_call.gno:9: cannot use int as string diff --git a/gnovm/tests/files/types/assign_index.gno b/gnovm/tests/files/types/assign_index.gno new file mode 100644 index 00000000000..93f4cf0a3c1 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_index.gno:8: cannot use int as string diff --git a/gnovm/tests/files/types/assign_index_a.gno b/gnovm/tests/files/types/assign_index_a.gno new file mode 100644 index 00000000000..dd92220b1fe --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_index_a.gno:6: cannot use int as string 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_c.gno b/gnovm/tests/files/types/assign_index_c.gno new file mode 100644 index 00000000000..592191189a2 --- /dev/null +++ b/gnovm/tests/files/types/assign_index_c.gno @@ -0,0 +1,12 @@ +package main + +func main() { + s := []int{1, 2, 3} + + var s1 string + s1 = s[0] + println(s) +} + +// Error: +// main/files/types/assign_index_c.gno:7: 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/files/types/assign_literal10.gno b/gnovm/tests/files/types/assign_literal10.gno new file mode 100644 index 00000000000..d7b29f91aec --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal10a.gno b/gnovm/tests/files/types/assign_literal10a.gno new file mode 100644 index 00000000000..f6963d926ee --- /dev/null +++ b/gnovm/tests/files/types/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/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/files/types/assign_literal7.gno b/gnovm/tests/files/types/assign_literal7.gno new file mode 100644 index 00000000000..56308cdbbfc --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal7a.gno b/gnovm/tests/files/types/assign_literal7a.gno new file mode 100644 index 00000000000..8be126c49de --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal7b.gno b/gnovm/tests/files/types/assign_literal7b.gno new file mode 100644 index 00000000000..dc61467e07c --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal7c.gno b/gnovm/tests/files/types/assign_literal7c.gno new file mode 100644 index 00000000000..989dcca6699 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal7c.gno:7: cannot assign to str[(const (0 int))] diff --git a/gnovm/tests/files/types/assign_literal7d.gno b/gnovm/tests/files/types/assign_literal7d.gno new file mode 100644 index 00000000000..f56c304b3d3 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal8.gno b/gnovm/tests/files/types/assign_literal8.gno new file mode 100644 index 00000000000..d652efc0874 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_literal9.gno b/gnovm/tests/files/types/assign_literal9.gno new file mode 100644 index 00000000000..1d672ae46ce --- /dev/null +++ b/gnovm/tests/files/types/assign_literal9.gno @@ -0,0 +1,14 @@ +package main + +type foo struct { + a int +} + +func main() { + s := &foo{} + s.a = 1 + println(s.a) +} + +// Output: +// 1 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/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.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_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)) 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_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 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..6903cb0b7bc --- /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, value = 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_rune.gno b/gnovm/tests/files/types/assign_rune.gno new file mode 100644 index 00000000000..7c1e8742fd4 --- /dev/null +++ b/gnovm/tests/files/types/assign_rune.gno @@ -0,0 +1,18 @@ +package main + +var r rune + +// TODO: print right dec, float +func main() { + r = 'a' + println(r) + println(float32(r)) + println(float64(r)) + println(string(r)) +} + +// Output: +// 97 +// 97 +// 97 +// a diff --git a/gnovm/tests/files/types/assign_rune_a.gno b/gnovm/tests/files/types/assign_rune_a.gno new file mode 100644 index 00000000000..13321fd8b08 --- /dev/null +++ b/gnovm/tests/files/types/assign_rune_a.gno @@ -0,0 +1,12 @@ +package main + +var r rune + +// assign +func main() { + r = "a" + println(r) +} + +// Error: +// main/files/types/assign_rune_a.gno:7: cannot use untyped string as Int32Kind diff --git a/gnovm/tests/files/types/assign_type_assertion.gno b/gnovm/tests/files/types/assign_type_assertion.gno new file mode 100644 index 00000000000..6bc2b4b26c8 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_type_assertion.gno:13: cannot use string as int diff --git a/gnovm/tests/files/types/assign_type_assertion_a.gno b/gnovm/tests/files/types/assign_type_assertion_a.gno new file mode 100644 index 00000000000..1b28408d309 --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/assign_type_assertion_b.gno b/gnovm/tests/files/types/assign_type_assertion_b.gno new file mode 100644 index 00000000000..4f68751667d --- /dev/null +++ b/gnovm/tests/files/types/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/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 new file mode 100644 index 00000000000..044154dadfd --- /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: 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..bc2907eb8af --- /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 assign to (const (1 bigint)) 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 diff --git a/gnovm/tests/files/types/bigdec.gno b/gnovm/tests/files/types/bigdec.gno new file mode 100644 index 00000000000..baa3d4d6309 --- /dev/null +++ b/gnovm/tests/files/types/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/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 diff --git a/gnovm/tests/files/types/bigdec3.gno b/gnovm/tests/files/types/bigdec3.gno new file mode 100644 index 00000000000..0e0effa7cbb --- /dev/null +++ b/gnovm/tests/files/types/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/files/types/bigdec4.gno b/gnovm/tests/files/types/bigdec4.gno new file mode 100644 index 00000000000..88cbe894020 --- /dev/null +++ b/gnovm/tests/files/types/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/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 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 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..490a3424965 --- /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 is not comparable 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..f23ef6c9a78 --- /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 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_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_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/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..5e8add9f1d6 --- /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 is not comparable 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..f767fec16d5 --- /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: 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 new file mode 100644 index 00000000000..4894e32d0e5 --- /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.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 new file mode 100644 index 00000000000..4c2f6eb848f --- /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.bar is not comparable 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..4640c0e4252 --- /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 is not comparable 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 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 diff --git a/gnovm/tests/files/types/eql_0a0.gno b/gnovm/tests/files/types/eql_0a0.gno new file mode 100644 index 00000000000..32e5473b34f --- /dev/null +++ b/gnovm/tests/files/types/eql_0a0.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) == int8(1)) +} + +// Error: +// main/files/types/eql_0a0.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/eql_0a01.gno b/gnovm/tests/files/types/eql_0a01.gno new file mode 100644 index 00000000000..e5cdeff4b63 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a01.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(nil == nil) // xt: , dt: +} + +// Error: +// main/files/types/eql_0a01.gno:4: is not comparable diff --git a/gnovm/tests/files/types/eql_0a02.gno b/gnovm/tests/files/types/eql_0a02.gno new file mode 100644 index 00000000000..67116da6cc8 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a02.gno @@ -0,0 +1,11 @@ +package main + +func main() { + intPtr := new(int) + *intPtr = 5 + s := "hello" + println(intPtr == s) +} + +// Error: +// main/files/types/eql_0a02.gno:7: cannot use *int as string diff --git a/gnovm/tests/files/types/eql_0a03.gno b/gnovm/tests/files/types/eql_0a03.gno new file mode 100644 index 00000000000..677493a9af6 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a03.gno @@ -0,0 +1,12 @@ +package main + +func main() { + intPtr := new(int8) + *intPtr = 5 + + i := 0 + println(intPtr == &i) +} + +// Error: +// main/files/types/eql_0a03.gno:8: cannot use int8 as int diff --git a/gnovm/tests/files/types/eql_0a1.gno b/gnovm/tests/files/types/eql_0a1.gno new file mode 100644 index 00000000000..9641e67c90a --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) != int8(1)) +} + +// Error: +// main/files/types/eql_0a1.gno:5: cannot use int as int8 diff --git a/gnovm/tests/files/types/eql_0a1a.gno b/gnovm/tests/files/types/eql_0a1a.gno new file mode 100644 index 00000000000..deb369511fd --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1a.gno @@ -0,0 +1,11 @@ +package main + +// left typed, right untyped +func main() { + println(int(1) == 1) + println(int(1) != 1) +} + +// Output: +// true +// false diff --git a/gnovm/tests/files/types/eql_0a1a0.gno b/gnovm/tests/files/types/eql_0a1a0.gno new file mode 100644 index 00000000000..e251174adef --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1a0.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := uint(1) + println(uint64(1) == a) +} + +// Error: +// main/files/types/eql_0a1a0.gno:5: cannot use uint64 as uint diff --git a/gnovm/tests/files/types/eql_0a1a1.gno b/gnovm/tests/files/types/eql_0a1a1.gno new file mode 100644 index 00000000000..0af8aa45943 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1a1.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := uint(1) + println(a == uint64(1)) +} + +// Error: +// main/files/types/eql_0a1a1.gno:5: cannot use uint as uint64 diff --git a/gnovm/tests/files/types/eql_0a1b.gno b/gnovm/tests/files/types/eql_0a1b.gno new file mode 100644 index 00000000000..1db537a4d8c --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1b.gno @@ -0,0 +1,20 @@ +package main + +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 + } + + a := "hello" + + println(a == s.expected) + +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0a1c.gno b/gnovm/tests/files/types/eql_0a1c.gno new file mode 100644 index 00000000000..76f2db8d7d8 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1c.gno @@ -0,0 +1,10 @@ +package main + +func main() { + expected := `hello`[:] + a := "hello" + println(a == expected) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0a1d.gno b/gnovm/tests/files/types/eql_0a1d.gno new file mode 100644 index 00000000000..018d53fa81a --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1d.gno @@ -0,0 +1,14 @@ +package main + +type S struct { + expected string +} + +func main() { + println("hello" == S{ + expected: `hello`[:], + }.expected) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0a1e.gno b/gnovm/tests/files/types/eql_0a1e.gno new file mode 100644 index 00000000000..2795d618e91 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1e.gno @@ -0,0 +1,16 @@ +package main + +type S struct { + expected string +} + +func main() { + var s = S{ + expected: `hello`[:], + } + a := "hello" + println(a == s.expected) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0a1f.gno b/gnovm/tests/files/types/eql_0a1f.gno new file mode 100644 index 00000000000..fda84dcdff8 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a1f.gno @@ -0,0 +1,10 @@ +package main + +func main() { + expected := `hello`[:] + a := 1 + println(a == expected) // both typed +} + +// Error: +// main/files/types/eql_0a1f.gno:6: cannot use int as string diff --git a/gnovm/tests/files/types/eql_0a1g.gno b/gnovm/tests/files/types/eql_0a1g.gno new file mode 100644 index 00000000000..d80b6e0c9ac --- /dev/null +++ b/gnovm/tests/files/types/eql_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/eql_0a1g.gno:6: cannot use int as float32 diff --git a/gnovm/tests/files/types/eql_0a2.gno b/gnovm/tests/files/types/eql_0a2.gno new file mode 100644 index 00000000000..281a61e50eb --- /dev/null +++ b/gnovm/tests/files/types/eql_0a2.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/eql_0a2.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/eql_0a3.gno b/gnovm/tests/files/types/eql_0a3.gno new file mode 100644 index 00000000000..198a65b0827 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a3.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/eql_0a3.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/eql_0a4.gno b/gnovm/tests/files/types/eql_0a4.gno new file mode 100644 index 00000000000..d2c859edd09 --- /dev/null +++ b/gnovm/tests/files/types/eql_0a4.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/eql_0a4.gno:21: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/eql_0b0.gno b/gnovm/tests/files/types/eql_0b0.gno new file mode 100644 index 00000000000..2c968b5158f --- /dev/null +++ b/gnovm/tests/files/types/eql_0b0.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 +// left is assignable to right +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/eql_0b1.gno b/gnovm/tests/files/types/eql_0b1.gno new file mode 100644 index 00000000000..a7bdf5275da --- /dev/null +++ b/gnovm/tests/files/types/eql_0b1.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 untyped const, right is typed const +func main() { + if 1 != Error(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/eql_0b2.gno b/gnovm/tests/files/types/eql_0b2.gno new file mode 100644 index 00000000000..51981348a6e --- /dev/null +++ b/gnovm/tests/files/types/eql_0b2.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 +// 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?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/eql_0b2.gno:14: cannot use untyped Bigint as StringKind diff --git a/gnovm/tests/files/types/eql_0b3.gno b/gnovm/tests/files/types/eql_0b3.gno new file mode 100644 index 00000000000..34c8a24cba2 --- /dev/null +++ b/gnovm/tests/files/types/eql_0b3.gno @@ -0,0 +1,15 @@ +package main + +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/eql_0b4_native.gno b/gnovm/tests/files/types/eql_0b4_native.gno new file mode 100644 index 00000000000..b78d5f9be73 --- /dev/null +++ b/gnovm/tests/files/types/eql_0b4_native.gno @@ -0,0 +1,13 @@ +package main + +import ( + "errors" +) + +func main() { + errCmp := errors.New("xxx") + println(5 == errCmp) +} + +// Error: +// main/files/types/eql_0b4_native.gno:9: unexpected type pair: cannot use bigint as gonative{error} diff --git a/gnovm/tests/files/types/eql_0b4_stdlibs.gno b/gnovm/tests/files/types/eql_0b4_stdlibs.gno new file mode 100644 index 00000000000..de36f025f34 --- /dev/null +++ b/gnovm/tests/files/types/eql_0b4_stdlibs.gno @@ -0,0 +1,13 @@ +package main + +import ( + "errors" +) + +func main() { + errCmp := errors.New("xxx") + println(5 == errCmp) +} + +// Error: +// main/files/types/eql_0b4_stdlibs.gno:9: bigint does not implement .uverse.error diff --git a/gnovm/tests/files/types/eql_0c2.gno b/gnovm/tests/files/types/eql_0c2.gno new file mode 100644 index 00000000000..6ac4a2799ab --- /dev/null +++ b/gnovm/tests/files/types/eql_0c2.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/files/types/eql_0c2.gno:16: bigint overflows target kind diff --git a/gnovm/tests/files/types/eql_0d0.gno b/gnovm/tests/files/types/eql_0d0.gno new file mode 100644 index 00000000000..6890d450bab --- /dev/null +++ b/gnovm/tests/files/types/eql_0d0.gno @@ -0,0 +1,13 @@ +package main + +// both untyped const +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/eql_0e0.gno b/gnovm/tests/files/types/eql_0e0.gno new file mode 100644 index 00000000000..a1ab28d1932 --- /dev/null +++ b/gnovm/tests/files/types/eql_0e0.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/eql_0e0.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/eql_0e1.gno b/gnovm/tests/files/types/eql_0e1.gno new file mode 100644 index 00000000000..798d4f04777 --- /dev/null +++ b/gnovm/tests/files/types/eql_0e1.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/eql_0e1.gno:23: cannot use main.Error1 as main.Error2 without explicit conversion diff --git a/gnovm/tests/files/types/eql_0f0_native.gno b/gnovm/tests/files/types/eql_0f0_native.gno new file mode 100644 index 00000000000..7db72819774 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f0_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") + +// 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/eql_0f0_native.gno:19: unexpected type pair: cannot use bigint as gonative{error} diff --git a/gnovm/tests/files/types/eql_0f0_stdlibs.gno b/gnovm/tests/files/types/eql_0f0_stdlibs.gno new file mode 100644 index 00000000000..39a7ac68490 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f0_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") + +// 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/eql_0f0_stdlibs.gno:19: bigint does not implement .uverse.error diff --git a/gnovm/tests/files/types/eql_0f12.gno b/gnovm/tests/files/types/eql_0f12.gno new file mode 100644 index 00000000000..751852d0b70 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f12.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/eql_0f14.gno b/gnovm/tests/files/types/eql_0f14.gno new file mode 100644 index 00000000000..500157d7303 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f14.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/eql_0f14.gno:10: cannot use [2]string as [2]int diff --git a/gnovm/tests/files/types/eql_0f15.gno b/gnovm/tests/files/types/eql_0f15.gno new file mode 100644 index 00000000000..36077127332 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f15.gno @@ -0,0 +1,17 @@ +package main + +var a [2]interface{} +var c [2]interface{} + +func gen() interface{} { + return 1 +} + +func main() { + a = [2]interface{}{gen(), gen()} + c = [2]interface{}{gen(), gen()} + println(a == c) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0f16.gno b/gnovm/tests/files/types/eql_0f16.gno new file mode 100644 index 00000000000..ae0d8f45ab6 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f16.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: consider log desc +func main() { + a = [2]word{gen(), gen()} + c = [2]word{gen(), gen()} + println(a == c) +} + +// Error: +// main/files/types/eql_0f16.gno:16: [2]main.word is not comparable diff --git a/gnovm/tests/files/types/eql_0f17.gno b/gnovm/tests/files/types/eql_0f17.gno new file mode 100644 index 00000000000..d60d474f668 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f17.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: +// main/files/types/eql_0f17.gno:9: main.f can only be compared to nil diff --git a/gnovm/tests/files/types/eql_0f18.gno b/gnovm/tests/files/types/eql_0f18.gno new file mode 100644 index 00000000000..ad534066fd1 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f18.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/eql_0f19.gno b/gnovm/tests/files/types/eql_0f19.gno new file mode 100644 index 00000000000..8b08d616a06 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f19.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/eql_0f1_stdlibs.gno b/gnovm/tests/files/types/eql_0f1_stdlibs.gno new file mode 100644 index 00000000000..e0b8ec5c753 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f1_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 int64(1) == errCmp { + //if errCmp == 1 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/eql_0f1_stdlibs.gno:19: int64 does not implement .uverse.error diff --git a/gnovm/tests/files/types/eql_0f20.gno b/gnovm/tests/files/types/eql_0f20.gno new file mode 100644 index 00000000000..f0e2e93ffc9 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f20.gno @@ -0,0 +1,13 @@ +package main + +type f func() bool + +// slice would be comparable +var a [2]f + +func main() { + println(a == nil) // rcx.T == nil +} + +// Error: +// main/files/types/eql_0f20.gno:9: [2]main.f is not comparable diff --git a/gnovm/tests/files/types/eql_0f21.gno b/gnovm/tests/files/types/eql_0f21.gno new file mode 100644 index 00000000000..20b52988a8d --- /dev/null +++ b/gnovm/tests/files/types/eql_0f21.gno @@ -0,0 +1,13 @@ +package main + +type f func() bool + +var a [2]f +var b [2]f + +func main() { + println(a == b) +} + +// Error: +// main/files/types/eql_0f21.gno:9: [2]main.f is not comparable diff --git a/gnovm/tests/files/types/eql_0f21a.gno b/gnovm/tests/files/types/eql_0f21a.gno new file mode 100644 index 00000000000..075149d264f --- /dev/null +++ b/gnovm/tests/files/types/eql_0f21a.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/eql_0f22.gno b/gnovm/tests/files/types/eql_0f22.gno new file mode 100644 index 00000000000..75891def307 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f22.gno @@ -0,0 +1,11 @@ +package main + +var a int = 0 +var b int = 1 + +func main() { + println(&a == &b) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/eql_0f23.gno b/gnovm/tests/files/types/eql_0f23.gno new file mode 100644 index 00000000000..55f2ab5189d --- /dev/null +++ b/gnovm/tests/files/types/eql_0f23.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/eql_0f24.gno b/gnovm/tests/files/types/eql_0f24.gno new file mode 100644 index 00000000000..d01a9d4a14a --- /dev/null +++ b/gnovm/tests/files/types/eql_0f24.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/eql_0f25.gno b/gnovm/tests/files/types/eql_0f25.gno new file mode 100644 index 00000000000..8a3343146b0 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f25.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/eql_0f27_stdlibs.gno b/gnovm/tests/files/types/eql_0f27_stdlibs.gno new file mode 100644 index 00000000000..2bee791279a --- /dev/null +++ b/gnovm/tests/files/types/eql_0f27_stdlibs.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/eql_0f27_stdlibs.gno:13: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f28.gno b/gnovm/tests/files/types/eql_0f28.gno new file mode 100644 index 00000000000..64f973cdde0 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f28.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/eql_0f28.gno:27: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f29.gno b/gnovm/tests/files/types/eql_0f29.gno new file mode 100644 index 00000000000..b5d1e897b89 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f29.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/eql_0f29.gno:16: operator > not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f2b_native.gno b/gnovm/tests/files/types/eql_0f2b_native.gno new file mode 100644 index 00000000000..fe961441328 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f2b_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") + +// special 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/eql_0f2b_native.gno:19: operator <= not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f2b_stdlibs.gno b/gnovm/tests/files/types/eql_0f2b_stdlibs.gno new file mode 100644 index 00000000000..20de4b5b104 --- /dev/null +++ b/gnovm/tests/files/types/eql_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") + +// special 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/eql_0f2b_stdlibs.gno:19: operator <= not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f2c_native.gno b/gnovm/tests/files/types/eql_0f2c_native.gno new file mode 100644 index 00000000000..c17c757b760 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f2c_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") + +// special 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/eql_0f2c_native.gno:19: operator < not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f2c_stdlibs.gno b/gnovm/tests/files/types/eql_0f2c_stdlibs.gno new file mode 100644 index 00000000000..f8da518f4a9 --- /dev/null +++ b/gnovm/tests/files/types/eql_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") + +// special 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/eql_0f2c_stdlibs.gno:19: operator < not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/eql_0f2d.gno b/gnovm/tests/files/types/eql_0f2d.gno new file mode 100644 index 00000000000..5ad121f515b --- /dev/null +++ b/gnovm/tests/files/types/eql_0f2d.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)) +} + +// special case: +// one is interface +func main() { + var e0 E + e0 = Error(0) + fmt.Printf("%T \n", e0) + if e0 == Error(0) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// int64 +// what the firetruck? diff --git a/gnovm/tests/files/types/eql_0f2e.gno b/gnovm/tests/files/types/eql_0f2e.gno new file mode 100644 index 00000000000..ea03028f5e1 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f2e.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)) +} + +// special case: +// one is interface +func main() { + var e0 E + e0 = Error(0) + fmt.Printf("%T \n", e0) + if Error(0) == e0 { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// int64 +// what the firetruck? diff --git a/gnovm/tests/files/types/eql_0f30.gno b/gnovm/tests/files/types/eql_0f30.gno new file mode 100644 index 00000000000..0a9a61a96cf --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30.gno @@ -0,0 +1,9 @@ +package main + +// both not const, and both interface +func main() { + println([]byte("a") == []byte("b")) +} + +// Error: +// main/files/types/eql_0f30.gno:5: []uint8 can only be compared to nil diff --git a/gnovm/tests/files/types/eql_0f30a.gno b/gnovm/tests/files/types/eql_0f30a.gno new file mode 100644 index 00000000000..2dadbd9d6d3 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(map[string]int{"a": 1} == map[string]int{"b": 2}) +} + +// Error: +// main/files/types/eql_0f30a.gno:4: map[string]int can only be compared to nil diff --git a/gnovm/tests/files/types/eql_0f30b.gno b/gnovm/tests/files/types/eql_0f30b.gno new file mode 100644 index 00000000000..2e7a463fddd --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30b.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/eql_0f30b.gno:9: main.f can only be compared to nil diff --git a/gnovm/tests/files/types/eql_0f30c.gno b/gnovm/tests/files/types/eql_0f30c.gno new file mode 100644 index 00000000000..ffa8c7c96e7 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30c.gno @@ -0,0 +1,10 @@ +package main + +var f1 func() + +func main() { + println(f1 == nil) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0f30d.gno b/gnovm/tests/files/types/eql_0f30d.gno new file mode 100644 index 00000000000..8b0612f011b --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30d.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println([]int{1} == []int{1}) +} + +// Error: +// main/files/types/eql_0f30d.gno:4: []int can only be compared to nil diff --git a/gnovm/tests/files/types/eql_0f30e.gno b/gnovm/tests/files/types/eql_0f30e.gno new file mode 100644 index 00000000000..002910072c3 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30e.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println([]int{1} == nil) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/eql_0f30f.gno b/gnovm/tests/files/types/eql_0f30f.gno new file mode 100644 index 00000000000..880b081b6cd --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30f.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/eql_0f30f.gno:7: cannot use [2]int as [3]int diff --git a/gnovm/tests/files/types/eql_0f30g.gno b/gnovm/tests/files/types/eql_0f30g.gno new file mode 100644 index 00000000000..66135a83b62 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f30g.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/eql_0f30g.gno:7: []int can only be compared to nil diff --git a/gnovm/tests/files/types/eql_0f31.gno b/gnovm/tests/files/types/eql_0f31.gno new file mode 100644 index 00000000000..bcb62dc76c3 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f31.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/eql_0f32.gno b/gnovm/tests/files/types/eql_0f32.gno new file mode 100644 index 00000000000..321824566cb --- /dev/null +++ b/gnovm/tests/files/types/eql_0f32.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println([]byte("a") == nil) // lx: (const (slice[0x61] []uint8)), rx: (const (undefined)), cmp = 0 +} + +// Output: +// false diff --git a/gnovm/tests/files/types/eql_0f33.gno b/gnovm/tests/files/types/eql_0f33.gno new file mode 100644 index 00000000000..e7aac0cf069 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f33.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/eql_0f34.gno b/gnovm/tests/files/types/eql_0f34.gno new file mode 100644 index 00000000000..8b5d3830091 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f34.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 +// ---- diff --git a/gnovm/tests/files/types/eql_0f35.gno b/gnovm/tests/files/types/eql_0f35.gno new file mode 100644 index 00000000000..c57d3e9d375 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f35.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/eql_0f37.gno b/gnovm/tests/files/types/eql_0f37.gno new file mode 100644 index 00000000000..7fb051961ee --- /dev/null +++ b/gnovm/tests/files/types/eql_0f37.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/eql_0f40_stdlibs.gno b/gnovm/tests/files/types/eql_0f40_stdlibs.gno new file mode 100644 index 00000000000..d826bdbd155 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f40_stdlibs.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/eql_0f41_stdlibs.gno b/gnovm/tests/files/types/eql_0f41_stdlibs.gno new file mode 100644 index 00000000000..679cb1f9295 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f41_stdlibs.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/eql_0f41_stdlibs.gno:27: main.animal does not implement .uverse.error diff --git a/gnovm/tests/files/types/eql_0f42.gno b/gnovm/tests/files/types/eql_0f42.gno new file mode 100644 index 00000000000..efb63d40b97 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f42.gno @@ -0,0 +1,10 @@ +package main + +var m map[string]int + +func main() { + println(m == nil) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0f43_hasNil.gno b/gnovm/tests/files/types/eql_0f43_hasNil.gno new file mode 100644 index 00000000000..c336aa92ef6 --- /dev/null +++ b/gnovm/tests/files/types/eql_0f43_hasNil.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/eql_0f44.gno b/gnovm/tests/files/types/eql_0f44.gno new file mode 100644 index 00000000000..e23e6c07aba --- /dev/null +++ b/gnovm/tests/files/types/eql_0f44.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/eql_0f45.gno b/gnovm/tests/files/types/eql_0f45.gno new file mode 100644 index 00000000000..7707136b82e --- /dev/null +++ b/gnovm/tests/files/types/eql_0f45.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/eql_0f46.gno b/gnovm/tests/files/types/eql_0f46.gno new file mode 100644 index 00000000000..3a65bd18b3b --- /dev/null +++ b/gnovm/tests/files/types/eql_0f46.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/eql_0f46a.gno b/gnovm/tests/files/types/eql_0f46a.gno new file mode 100644 index 00000000000..9476b1f22ef --- /dev/null +++ b/gnovm/tests/files/types/eql_0f46a.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/eql_0f48.gno b/gnovm/tests/files/types/eql_0f48.gno new file mode 100644 index 00000000000..fbf4f164c9d --- /dev/null +++ b/gnovm/tests/files/types/eql_0f48.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() { // about untyped nil to (interface{})typed-nil, no support for native for now. + r := gen() + testEql(r, error(nil)) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/eql_0f8_stdlibs.gno b/gnovm/tests/files/types/eql_0f8_stdlibs.gno new file mode 100644 index 00000000000..400ce3c6d1e --- /dev/null +++ b/gnovm/tests/files/types/eql_0f8_stdlibs.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 errCmp == int64(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/eql_0f8_stdlibs.gno:19: int64 does not implement .uverse.error diff --git a/gnovm/tests/files/types/eql_iface.gno b/gnovm/tests/files/types/eql_iface.gno new file mode 100644 index 00000000000..d3d41348a62 --- /dev/null +++ b/gnovm/tests/files/types/eql_iface.gno @@ -0,0 +1,13 @@ +package main + +type Foo struct { + n int +} + +func main() { + var l interface{} = 1 + println(1 == l) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/incdec_a0.gno b/gnovm/tests/files/types/incdec_a0.gno new file mode 100644 index 00000000000..8f3f97caaee --- /dev/null +++ b/gnovm/tests/files/types/incdec_a0.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a++ + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/incdec_a1.gno b/gnovm/tests/files/types/incdec_a1.gno new file mode 100644 index 00000000000..ee9d2b18c7e --- /dev/null +++ b/gnovm/tests/files/types/incdec_a1.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + a++ + println(a) +} + +// Error: +// main/files/types/incdec_a1.gno:5: operator ++ not defined on: StringKind diff --git a/gnovm/tests/files/types/incdec_a2.gno b/gnovm/tests/files/types/incdec_a2.gno new file mode 100644 index 00000000000..a91080a0d95 --- /dev/null +++ b/gnovm/tests/files/types/incdec_a2.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/incdec_a3.gno b/gnovm/tests/files/types/incdec_a3.gno new file mode 100644 index 00000000000..f257b822f8e --- /dev/null +++ b/gnovm/tests/files/types/incdec_a3.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/incdec_a4.gno b/gnovm/tests/files/types/incdec_a4.gno new file mode 100644 index 00000000000..5f87eb5c09c --- /dev/null +++ b/gnovm/tests/files/types/incdec_a4.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/incdec_a4.gno:12: cannot use int8 as main.Int without explicit conversion 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 diff --git a/gnovm/tests/files/types/or_a0.gno b/gnovm/tests/files/types/or_a0.gno new file mode 100644 index 00000000000..b2f14c73785 --- /dev/null +++ b/gnovm/tests/files/types/or_a0.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(0) | int8(1)) +} + +// Error: +// main/files/types/or_a0.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/or_a1.gno b/gnovm/tests/files/types/or_a1.gno new file mode 100644 index 00000000000..c2e7bff0d5d --- /dev/null +++ b/gnovm/tests/files/types/or_a1.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/or_a1.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/or_b0.gno b/gnovm/tests/files/types/or_b0.gno new file mode 100644 index 00000000000..655121ee2f2 --- /dev/null +++ b/gnovm/tests/files/types/or_b0.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/or_b1.gno b/gnovm/tests/files/types/or_b1.gno new file mode 100644 index 00000000000..1616c4db687 --- /dev/null +++ b/gnovm/tests/files/types/or_b1.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/or_b2.gno b/gnovm/tests/files/types/or_b2.gno new file mode 100644 index 00000000000..0bdf3e0a73a --- /dev/null +++ b/gnovm/tests/files/types/or_b2.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println(1 | "a") +} + +// Error: +// main/files/types/or_b2.gno:5: operator | not defined on: StringKind diff --git a/gnovm/tests/files/types/or_b3.gno b/gnovm/tests/files/types/or_b3.gno new file mode 100644 index 00000000000..4b6f20530cd --- /dev/null +++ b/gnovm/tests/files/types/or_b3.gno @@ -0,0 +1,9 @@ +package main + +// one untyped const, one typed const +func main() { + println("b" | "a") +} + +// Error: +// main/files/types/or_b3.gno:5: operator | not defined on: StringKind diff --git a/gnovm/tests/files/types/or_b4.gno b/gnovm/tests/files/types/or_b4.gno new file mode 100644 index 00000000000..54c50033ad1 --- /dev/null +++ b/gnovm/tests/files/types/or_b4.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/or_d0.gno b/gnovm/tests/files/types/or_d0.gno new file mode 100644 index 00000000000..827e29a8fba --- /dev/null +++ b/gnovm/tests/files/types/or_d0.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/or_d0.gno:6: operator | not defined on: BigdecKind diff --git a/gnovm/tests/files/types/or_d1.gno b/gnovm/tests/files/types/or_d1.gno new file mode 100644 index 00000000000..ac2458a96a2 --- /dev/null +++ b/gnovm/tests/files/types/or_d1.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/or_d2.gno b/gnovm/tests/files/types/or_d2.gno new file mode 100644 index 00000000000..0812ff926e7 --- /dev/null +++ b/gnovm/tests/files/types/or_d2.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/or_d3.gno b/gnovm/tests/files/types/or_d3.gno new file mode 100644 index 00000000000..226c9423da5 --- /dev/null +++ b/gnovm/tests/files/types/or_d3.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/or_d4.gno b/gnovm/tests/files/types/or_d4.gno new file mode 100644 index 00000000000..f1240f32c71 --- /dev/null +++ b/gnovm/tests/files/types/or_d4.gno @@ -0,0 +1,10 @@ +package main + +// both untyped const +// TODO: dec value representation +func main() { + println(1.0 | 0) +} + +// Error: +// main/files/types/or_d4.gno:6: operator | not defined on: BigdecKind diff --git a/gnovm/tests/files/types/or_e0.gno b/gnovm/tests/files/types/or_e0.gno new file mode 100644 index 00000000000..555ee5ad37b --- /dev/null +++ b/gnovm/tests/files/types/or_e0.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/or_e0.gno:23: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/or_f0_stdlibs.gno b/gnovm/tests/files/types/or_f0_stdlibs.gno new file mode 100644 index 00000000000..d2a080e0bab --- /dev/null +++ b/gnovm/tests/files/types/or_f0_stdlibs.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/or_f0_stdlibs.gno:19: operator | not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/or_f1_stdlibs.gno b/gnovm/tests/files/types/or_f1_stdlibs.gno new file mode 100644 index 00000000000..9cc9eb5157b --- /dev/null +++ b/gnovm/tests/files/types/or_f1_stdlibs.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/or_f1_stdlibs.gno:19: operator | not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/or_f2.gno b/gnovm/tests/files/types/or_f2.gno new file mode 100644 index 00000000000..284078f41d4 --- /dev/null +++ b/gnovm/tests/files/types/or_f2.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/or_f2.gno:27: operator | not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/overflow_a0.gno b/gnovm/tests/files/types/overflow_a0.gno new file mode 100644 index 00000000000..e3ecefd621f --- /dev/null +++ b/gnovm/tests/files/types/overflow_a0.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/overflow_a1.gno b/gnovm/tests/files/types/overflow_a1.gno new file mode 100644 index 00000000000..bd893312cf2 --- /dev/null +++ b/gnovm/tests/files/types/overflow_a1.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/rem_a0.gno b/gnovm/tests/files/types/rem_a0.gno new file mode 100644 index 00000000000..7ba0f66f533 --- /dev/null +++ b/gnovm/tests/files/types/rem_a0.gno @@ -0,0 +1,9 @@ +package main + +// both typed(different) const +func main() { + println(int(1) % int8(1)) +} + +// Error: +// main/files/types/rem_a0.gno:5: invalid operation: mismatched types int and int8 diff --git a/gnovm/tests/files/types/rem_a1.gno b/gnovm/tests/files/types/rem_a1.gno new file mode 100644 index 00000000000..edea73382ce --- /dev/null +++ b/gnovm/tests/files/types/rem_a1.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/rem_a1.gno:21: invalid operation: mismatched types main.Error1 and main.Error2 diff --git a/gnovm/tests/files/types/rem_a2.gno b/gnovm/tests/files/types/rem_a2.gno new file mode 100644 index 00000000000..3ebba194c0a --- /dev/null +++ b/gnovm/tests/files/types/rem_a2.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 % 0) +} + +// Error: +// main/files/types/rem_a2.gno:4: invalid operation: division by zero diff --git a/gnovm/tests/files/types/rem_b0.gno b/gnovm/tests/files/types/rem_b0.gno new file mode 100644 index 00000000000..9b5f82fb3b7 --- /dev/null +++ b/gnovm/tests/files/types/rem_b0.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/rem_f3.gno b/gnovm/tests/files/types/rem_f3.gno new file mode 100644 index 00000000000..e34dfab9ae0 --- /dev/null +++ b/gnovm/tests/files/types/rem_f3.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := 1 + println(a % 0) +} + +// Error: +// main/files/types/rem_f3.gno:5: invalid operation: division by zero diff --git a/gnovm/tests/files/types/runtime_a0.gno b/gnovm/tests/files/types/runtime_a0.gno new file mode 100644 index 00000000000..7d6312e5b9c --- /dev/null +++ b/gnovm/tests/files/types/runtime_a0.gno @@ -0,0 +1,9 @@ +package main + +func main() { + m := map[string]bool{"foo": true} + m["foo"]++ +} + +// Error: +// main/files/types/runtime_a0.gno:5: operator ++ not defined on: BoolKind diff --git a/gnovm/tests/files/types/runtime_a0a.gno b/gnovm/tests/files/types/runtime_a0a.gno new file mode 100644 index 00000000000..fecce01817e --- /dev/null +++ b/gnovm/tests/files/types/runtime_a0a.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/runtime_a2.gno b/gnovm/tests/files/types/runtime_a2.gno new file mode 100644 index 00000000000..d53c9c4d970 --- /dev/null +++ b/gnovm/tests/files/types/runtime_a2.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func gen() interface{} { + return false +} + +func main() { + r := gen() + fmt.Printf("%T \n", r) +} + +// Output: +// bool diff --git a/gnovm/tests/files/types/runtime_a3.gno b/gnovm/tests/files/types/runtime_a3.gno new file mode 100644 index 00000000000..d46a83a1c35 --- /dev/null +++ b/gnovm/tests/files/types/runtime_a3.gno @@ -0,0 +1,12 @@ +package main + +func gen() interface{} { + return false +} + +func main() { + gen()++ +} + +// Error: +// main/files/types/runtime_a3.gno:8: operator ++ not defined on: InterfaceKind diff --git a/gnovm/tests/files/types/shift_a0.gno b/gnovm/tests/files/types/shift_a0.gno new file mode 100644 index 00000000000..a31e7bd8f82 --- /dev/null +++ b/gnovm/tests/files/types/shift_a0.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/shift_a1.gno b/gnovm/tests/files/types/shift_a1.gno new file mode 100644 index 00000000000..ba92bf0f7d2 --- /dev/null +++ b/gnovm/tests/files/types/shift_a1.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/shift_a10.gno b/gnovm/tests/files/types/shift_a10.gno new file mode 100644 index 00000000000..0eba81f4a9c --- /dev/null +++ b/gnovm/tests/files/types/shift_a10.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/shift_a11.gno b/gnovm/tests/files/types/shift_a11.gno new file mode 100644 index 00000000000..2d3c935e97d --- /dev/null +++ b/gnovm/tests/files/types/shift_a11.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/shift_a11.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types/shift_a12.gno b/gnovm/tests/files/types/shift_a12.gno new file mode 100644 index 00000000000..5735854d684 --- /dev/null +++ b/gnovm/tests/files/types/shift_a12.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/shift_a13.gno b/gnovm/tests/files/types/shift_a13.gno new file mode 100644 index 00000000000..7d70cc3589a --- /dev/null +++ b/gnovm/tests/files/types/shift_a13.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/shift_a14.gno b/gnovm/tests/files/types/shift_a14.gno new file mode 100644 index 00000000000..f879da5f3f9 --- /dev/null +++ b/gnovm/tests/files/types/shift_a14.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := "hello" + r := a << 1 + println(r) +} + +// Error: +// main/files/types/shift_a14.gno:5: operator << not defined on: StringKind diff --git a/gnovm/tests/files/types/shift_a15.gno b/gnovm/tests/files/types/shift_a15.gno new file mode 100644 index 00000000000..b86445f3e75 --- /dev/null +++ b/gnovm/tests/files/types/shift_a15.gno @@ -0,0 +1,10 @@ +package main + +// TODO: fix in assignment +func main() { + a := "hello" + a <<= 1 +} + +// Error: +// main/files/types/shift_a15.gno:6: operator <<= not defined on: StringKind diff --git a/gnovm/tests/files/types/shift_a16.gno b/gnovm/tests/files/types/shift_a16.gno new file mode 100644 index 00000000000..ed41f35f20d --- /dev/null +++ b/gnovm/tests/files/types/shift_a16.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := "hello" << 1 + println(r) +} + +// Error: +// main/files/types/shift_a16.gno:4: operator << not defined on: StringKind diff --git a/gnovm/tests/files/types/shift_a2.gno b/gnovm/tests/files/types/shift_a2.gno new file mode 100644 index 00000000000..91072929306 --- /dev/null +++ b/gnovm/tests/files/types/shift_a2.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/shift_a3.gno b/gnovm/tests/files/types/shift_a3.gno new file mode 100644 index 00000000000..79d5c566f1d --- /dev/null +++ b/gnovm/tests/files/types/shift_a3.gno @@ -0,0 +1,10 @@ +package main + +// both typed(different) const +func main() { + println(1 << 'a') + println(1 >> 'a') +} + +// Error: +// main/files/types/shift_a3.gno:5: bigint overflows target kind diff --git a/gnovm/tests/files/types/shift_a4.gno b/gnovm/tests/files/types/shift_a4.gno new file mode 100644 index 00000000000..3561929b672 --- /dev/null +++ b/gnovm/tests/files/types/shift_a4.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/shift_a5.gno b/gnovm/tests/files/types/shift_a5.gno new file mode 100644 index 00000000000..0394f8a2f3f --- /dev/null +++ b/gnovm/tests/files/types/shift_a5.gno @@ -0,0 +1,10 @@ +package main + +// TODO: support this? +func main() { + println(1.0 << 1) + println(1.0 >> 1) +} + +// Error: +// main/files/types/shift_a5.gno:5: operator << not defined on: BigdecKind diff --git a/gnovm/tests/files/types/shift_a6.gno b/gnovm/tests/files/types/shift_a6.gno new file mode 100644 index 00000000000..03ad4c0bcea --- /dev/null +++ b/gnovm/tests/files/types/shift_a6.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/shift_a7.gno b/gnovm/tests/files/types/shift_a7.gno new file mode 100644 index 00000000000..5cad6897a21 --- /dev/null +++ b/gnovm/tests/files/types/shift_a7.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := int(1) + println(r << "a") +} + +// Error: +// main/files/types/shift_a7.gno:3: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types/shift_a8.gno b/gnovm/tests/files/types/shift_a8.gno new file mode 100644 index 00000000000..a7a3e1f07d9 --- /dev/null +++ b/gnovm/tests/files/types/shift_a8.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/shift_a9.gno b/gnovm/tests/files/types/shift_a9.gno new file mode 100644 index 00000000000..f998381ef1c --- /dev/null +++ b/gnovm/tests/files/types/shift_a9.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a <<= 1 + println(a) +} + +// Output: +// 2 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 diff --git a/gnovm/tests/files/types/unary_a0.gno b/gnovm/tests/files/types/unary_a0.gno new file mode 100644 index 00000000000..2e5a1d289c9 --- /dev/null +++ b/gnovm/tests/files/types/unary_a0.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/unary_a0a.gno b/gnovm/tests/files/types/unary_a0a.gno new file mode 100644 index 00000000000..3556bcf2bf6 --- /dev/null +++ b/gnovm/tests/files/types/unary_a0a.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/unary_a0b.gno b/gnovm/tests/files/types/unary_a0b.gno new file mode 100644 index 00000000000..ff4e863e10e --- /dev/null +++ b/gnovm/tests/files/types/unary_a0b.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/unary_a0c.gno b/gnovm/tests/files/types/unary_a0c.gno new file mode 100644 index 00000000000..9f1fa057357 --- /dev/null +++ b/gnovm/tests/files/types/unary_a0c.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + x := "hello" + y := +x + fmt.Println(y) +} + +// Error: +// main/files/types/unary_a0c.gno:7: operator + not defined on: StringKind diff --git a/gnovm/tests/files/types/unary_a1.gno b/gnovm/tests/files/types/unary_a1.gno new file mode 100644 index 00000000000..c3c96d6724e --- /dev/null +++ b/gnovm/tests/files/types/unary_a1.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/unary_a2.gno b/gnovm/tests/files/types/unary_a2.gno new file mode 100644 index 00000000000..1b9edf1b712 --- /dev/null +++ b/gnovm/tests/files/types/unary_a2.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/unary_a2a.gno b/gnovm/tests/files/types/unary_a2a.gno new file mode 100644 index 00000000000..9081ad64ebf --- /dev/null +++ b/gnovm/tests/files/types/unary_a2a.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + a := 1 + b := !a + fmt.Println(b) // Output: false + +} + +// Error: +// main/files/types/unary_a2a.gno:7: operator ! not defined on: IntKind diff --git a/gnovm/tests/files/types/unary_a3.gno b/gnovm/tests/files/types/unary_a3.gno new file mode 100644 index 00000000000..3f216ccb1c1 --- /dev/null +++ b/gnovm/tests/files/types/unary_a3.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/unary_a4.gno b/gnovm/tests/files/types/unary_a4.gno new file mode 100644 index 00000000000..caaf1ed0438 --- /dev/null +++ b/gnovm/tests/files/types/unary_a4.gno @@ -0,0 +1,10 @@ +package main + +func main() { + v := 42 + p := &v + println(v == *p) +} + +// Output: +// true diff --git a/gnovm/tests/files/types/unary_a5.gno b/gnovm/tests/files/types/unary_a5.gno new file mode 100644 index 00000000000..bb956f85673 --- /dev/null +++ b/gnovm/tests/files/types/unary_a5.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/unary_a6.gno b/gnovm/tests/files/types/unary_a6.gno new file mode 100644 index 00000000000..99e87b66683 --- /dev/null +++ b/gnovm/tests/files/types/unary_a6.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/unary_a6.gno:7: operator ^ not defined on: Float64Kind diff --git a/gnovm/tests/files/var18.gno b/gnovm/tests/files/var18.gno index 9fc0cba3053..f2f97f62b15 100644 --- a/gnovm/tests/files/var18.gno +++ b/gnovm/tests/files/var18.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/var18.gno:4: should not happen +// main/files/var18.gno:4: assignment mismatch: 3 variables but 2 values diff --git a/gnovm/tests/files/zrealm12.gno b/gnovm/tests/files/zrealm12_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm12.gno rename to gnovm/tests/files/zrealm12_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_const.gno b/gnovm/tests/files/zrealm_const_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_const.gno rename to gnovm/tests/files/zrealm_const_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm0.gno b/gnovm/tests/files/zrealm_crossrealm0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm0.gno rename to gnovm/tests/files/zrealm_crossrealm0_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm10.gno b/gnovm/tests/files/zrealm_crossrealm10_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm10.gno rename to gnovm/tests/files/zrealm_crossrealm10_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11_stdlibs.gno similarity index 99% rename from gnovm/tests/files/zrealm_crossrealm11.gno rename to gnovm/tests/files/zrealm_crossrealm11_stdlibs.gno index b250b07bbac..e6f33c50654 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11_stdlibs.gno @@ -2,13 +2,10 @@ package crossrealm_test 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/zrealm_crossrealm12.gno b/gnovm/tests/files/zrealm_crossrealm12_stdlibs.gno similarity index 86% rename from gnovm/tests/files/zrealm_crossrealm12.gno rename to gnovm/tests/files/zrealm_crossrealm12_stdlibs.gno index ef8ea141ac5..f2f229cd5de 100644 --- a/gnovm/tests/files/zrealm_crossrealm12.gno +++ b/gnovm/tests/files/zrealm_crossrealm12_stdlibs.gno @@ -2,22 +2,22 @@ package crossrealm_test 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/zrealm_crossrealm13.gno b/gnovm/tests/files/zrealm_crossrealm13_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm13.gno rename to gnovm/tests/files/zrealm_crossrealm13_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm13a.gno b/gnovm/tests/files/zrealm_crossrealm13a_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm13a.gno rename to gnovm/tests/files/zrealm_crossrealm13a_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm1.gno b/gnovm/tests/files/zrealm_crossrealm1_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm1.gno rename to gnovm/tests/files/zrealm_crossrealm1_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm2.gno b/gnovm/tests/files/zrealm_crossrealm2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm2.gno rename to gnovm/tests/files/zrealm_crossrealm2_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm3.gno b/gnovm/tests/files/zrealm_crossrealm3_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm3.gno rename to gnovm/tests/files/zrealm_crossrealm3_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm4.gno b/gnovm/tests/files/zrealm_crossrealm4_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm4.gno rename to gnovm/tests/files/zrealm_crossrealm4_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm5.gno b/gnovm/tests/files/zrealm_crossrealm5_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm5.gno rename to gnovm/tests/files/zrealm_crossrealm5_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm6.gno b/gnovm/tests/files/zrealm_crossrealm6_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm6.gno rename to gnovm/tests/files/zrealm_crossrealm6_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm7.gno b/gnovm/tests/files/zrealm_crossrealm7_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm7.gno rename to gnovm/tests/files/zrealm_crossrealm7_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm8.gno b/gnovm/tests/files/zrealm_crossrealm8_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm8.gno rename to gnovm/tests/files/zrealm_crossrealm8_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_crossrealm9.gno b/gnovm/tests/files/zrealm_crossrealm9_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_crossrealm9.gno rename to gnovm/tests/files/zrealm_crossrealm9_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_initctx.gno b/gnovm/tests/files/zrealm_initctx_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_initctx.gno rename to gnovm/tests/files/zrealm_initctx_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_natbind0.gno b/gnovm/tests/files/zrealm_natbind0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_natbind0.gno rename to gnovm/tests/files/zrealm_natbind0_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std0.gno b/gnovm/tests/files/zrealm_std0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_std0.gno rename to gnovm/tests/files/zrealm_std0_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std1.gno b/gnovm/tests/files/zrealm_std1_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_std1.gno rename to gnovm/tests/files/zrealm_std1_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std2.gno b/gnovm/tests/files/zrealm_std2_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_std2.gno rename to gnovm/tests/files/zrealm_std2_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std3.gno b/gnovm/tests/files/zrealm_std3_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_std3.gno rename to gnovm/tests/files/zrealm_std3_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std4.gno b/gnovm/tests/files/zrealm_std4_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_std4.gno rename to gnovm/tests/files/zrealm_std4_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std5.gno b/gnovm/tests/files/zrealm_std5_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_std5.gno rename to gnovm/tests/files/zrealm_std5_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_std6.gno b/gnovm/tests/files/zrealm_std6_stdlibs.gno similarity index 56% rename from gnovm/tests/files/zrealm_std6.gno rename to gnovm/tests/files/zrealm_std6_stdlibs.gno index fb9e0f825a2..17a79c1d43b 100644 --- a/gnovm/tests/files/zrealm_std6.gno +++ b/gnovm/tests/files/zrealm_std6_stdlibs.gno @@ -1,5 +1,5 @@ -// PKGPATH: gno.land/r/test -package test +// 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_tests0.gno b/gnovm/tests/files/zrealm_tests0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_tests0.gno rename to gnovm/tests/files/zrealm_tests0_stdlibs.gno diff --git a/gnovm/tests/files/zrealm_testutils0.gno b/gnovm/tests/files/zrealm_testutils0_stdlibs.gno similarity index 100% rename from gnovm/tests/files/zrealm_testutils0.gno rename to gnovm/tests/files/zrealm_testutils0_stdlibs.gno diff --git a/gnovm/tests/package_test.go b/gnovm/tests/package_test.go index ded5bedce5f..8e497941c7f 100644 --- a/gnovm/tests/package_test.go +++ b/gnovm/tests/package_test.go @@ -18,7 +18,7 @@ import ( func TestStdlibs(t *testing.T) { // NOTE: this test only works using _test.gno files; // filetests are not meant to be used for testing standard libraries. - // The examples directory is tested directly using `gno test`. + // The examples directory is tested directly using `gno test`u // find all packages with *_test.gno files. rootDirs := []string{ 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...) } diff --git a/tm2/pkg/sdk/sdk.proto b/tm2/pkg/sdk/sdk.proto index 828b17950cf..62fbfc19758 100644 --- a/tm2/pkg/sdk/sdk.proto +++ b/tm2/pkg/sdk/sdk.proto @@ -12,4 +12,4 @@ message Result { abci.ResponseBase response_base = 1 [json_name = "ResponseBase"]; sint64 gas_wanted = 2 [json_name = "GasWanted"]; sint64 gas_used = 3 [json_name = "GasUsed"]; -} +} \ No newline at end of file