From b1dbad56add98d50e1910747e25f8f41f83eed4a Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Fri, 26 May 2023 17:07:50 +0200 Subject: [PATCH] chore: improve tests and docs of persisted types (#833) Co-authored-by: Morgan --- gnovm/docs/go-gno-compatibility.md | 80 +++++++++++------ gnovm/pkg/gnolang/uverse.go | 12 +-- gnovm/tests/challenges/persist_map.gno | 18 ++++ gnovm/tests/files/zpersist_valids.gno | 114 +++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 33 deletions(-) create mode 100644 gnovm/tests/challenges/persist_map.gno create mode 100644 gnovm/tests/files/zpersist_valids.gno diff --git a/gnovm/docs/go-gno-compatibility.md b/gnovm/docs/go-gno-compatibility.md index a579a96b6cc..317d10d97ce 100644 --- a/gnovm/docs/go-gno-compatibility.md +++ b/gnovm/docs/go-gno-compatibility.md @@ -6,33 +6,59 @@ Legend: full, partial, missing, TBD. -| keyword | status | -|-------------|--------| -| break | TBD | -| case | TBD | -| chan | TBD | -| const | TBD | -| continue | TBD | -| default | TBD | -| defer | TBD | -| else | TBD | -| fallthrough | TBD | -| for | TBD | -| func | TBD | -| go | TBD | -| goto | TBD | -| if | TBD | -| import | TBD | -| interface | TBD | -| map | TBD | -| package | TBD | -| range | TBD | -| return | TBD | -| select | TBD | -| struct | TBD | -| switch | TBD | -| type | TBD | -| var | TBD | +| keyword | support | +|-------------|------------------------| +| break | full | +| case | full | +| const | full | +| continue | full | +| default | full | +| defer | full | +| else | full | +| fallthrough | full | +| for | full | +| func | full | +| go | missing (after launch) | +| goto | full | +| if | full | +| import | full | +| interface | full | +| package | full | +| range | full | +| return | full | +| select | missing (after launch) | +| struct | full | +| switch | full | +| type | full | +| var | full | + +## Native types + +| type | usage | persistency | +|-----------------------------------------------|------------------------|------------------------------------------------------------| +| `bool` | full | full | +| `byte` | full | full | +| `float32`, `float64` | full | full | +| `int`, `int8`, `int16`, `int32`, `int64` | full | full | +| `uint`, `uint8`, `uint16`, `uint32`, `uint64` | full | full | +| `string` | full | full | +| `rune` | full | full | +| `interface{}` | full | full | +| `[]T` (slices) | full | full* | +| `map[T1]T2` | full | missing (in progress, will be for launch) | +| `func (T1...) T2...` | full | full (needs more tests) | +| `*T` (pointers) | full | full* | +| `chan T` (channels) | missing (after launch) | missing (after launch) | + +**\*:** depends on `T` + +Additional native types: + +| type | comment | +|----------|--------------------------------------------------------------------------------------------| +| `bigint` | Based on `math/big.Int` | +| `bigdec` | Based on https://github.com/cockroachdb/apd, (see https://github.com/gnolang/gno/pull/306) | + ## Stdlibs diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index a0987b50392..80f8a751e57 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -95,23 +95,23 @@ func UverseNode() *PackageNode { def("._", undefined) // special, path is zero. def("iota", undefined) // special def("nil", undefined) + def("bigint", asValue(BigintType)) def("bool", asValue(BoolType)) - def("string", asValue(StringType)) + def("byte", asValue(Uint8Type)) + def("float32", asValue(Float32Type)) + def("float64", asValue(Float64Type)) def("int", asValue(IntType)) def("int8", asValue(Int8Type)) def("int16", asValue(Int16Type)) - def("rune", asValue(Int32Type)) def("int32", asValue(Int32Type)) def("int64", asValue(Int64Type)) + def("rune", asValue(Int32Type)) + def("string", asValue(StringType)) def("uint", asValue(UintType)) - def("byte", asValue(Uint8Type)) def("uint8", asValue(Uint8Type)) def("uint16", asValue(Uint16Type)) def("uint32", asValue(Uint32Type)) def("uint64", asValue(Uint64Type)) - def("bigint", asValue(BigintType)) - def("float32", asValue(Float32Type)) - def("float64", asValue(Float64Type)) // NOTE on 'typeval': We can't call the type of a TypeValue a // "type", even though we want to, because it conflicts with // the pre-existing syntax for type-switching, `switch diff --git a/gnovm/tests/challenges/persist_map.gno b/gnovm/tests/challenges/persist_map.gno new file mode 100644 index 00000000000..886e306f52d --- /dev/null +++ b/gnovm/tests/challenges/persist_map.gno @@ -0,0 +1,18 @@ +// PKGPATH: gno.land/r/demo/tests_test +package tests_test + +var amap map[string]string = map[string]string{"a": "1"} + +func init() { + println("preinit", amap) + amap["b"] = "2" + println("postinit", amap) +} + +func main() { + println("premain", amap) + amap["b"] = "2" + println("postmain", amap) +} + +// Current behavior: panics diff --git a/gnovm/tests/files/zpersist_valids.gno b/gnovm/tests/files/zpersist_valids.gno new file mode 100644 index 00000000000..33280b54e57 --- /dev/null +++ b/gnovm/tests/files/zpersist_valids.gno @@ -0,0 +1,114 @@ +// PKGPATH: gno.land/r/demo/tests_test +package tests_test + +type myStruct struct { + A int + B string +} + +var ( + // Native types + abigint bigint = 16 + abool bool = true + abyte byte = 0x16 + afloat32 float32 = 16.16 + afloat64 float64 = 16.16 + aint int = 16 + aint8 int8 = 16 + aint16 int16 = 16 + aint32 int32 = 16 + aint64 int64 = 16 + arune rune = 'a' + astring string = "hello" + astringslice []string = []string{"A"} + astruct myStruct = myStruct{16, "A"} + auint uint = 16 + auint8 uint8 = 16 + auint16 uint16 = 16 + auint32 uint32 = 16 + auint64 uint64 = 16 + ainterface interface{} = struct{ a float32 }{16.0} + afunc func() string = func() string { return "A" } + + // TODO: + // amap map[string]string = map[string]string{"a": "1"} + // more slices + // slice/map containing unsupported types + + // Not supported: + // error +) + +func init() { + printVars("preinit ") + mutateVars("B") + printVars("postinit") +} + +func main() { + printVars("premain ") + mutateVars("C") + printVars("postmain") +} + +func mutateVars(stringModifier string) { + abigint *= 2 + abool = !abool + abyte *= 2 + afloat32 *= 2 + afloat64 *= 2 + aint *= 2 + aint8 *= 2 + aint16 *= 2 + aint32 *= 2 + aint64 *= 2 + arune = rune(stringModifier[0]) + astring += stringModifier + astringslice = append(astringslice, stringModifier) + auint *= 2 + auint8 *= 2 + auint16 *= 2 + auint32 *= 2 + auint64 *= 2 + astruct.A *= 2 + astruct.B = stringModifier + ainterface = struct{ a string }{stringModifier} + afunc = func() string { return stringModifier } + + // TODO: + // amap["c"] = "3" +} + +func printVars(phase string) { + println(phase, + // variables + abigint, + abool, + abyte, + afloat32, + afloat64, + aint, + aint8, + aint16, + aint32, + aint64, + arune, + astring, + astringslice, + astringslice[0], + astruct, + auint, + auint8, + auint16, + auint32, + auint64, + ainterface, + afunc(), + ) +} + +// Output: +// preinit 16 true 22 16.16 16.16 16 16 16 16 16 97 hello slice[("A" string)] A struct{(16 int),("A" string)} 16 16 16 16 16 struct{(16 float32)} A +// postinit 32 false 44 32.32 32.32 32 32 32 32 32 66 helloB slice[("A" string),("B" string)] A struct{(32 int),("B" string)} 32 32 32 32 32 struct{("B" string)} B +// premain 32 false 44 32.32 32.32 32 32 32 32 32 66 helloB slice[("A" string),("B" string)] A struct{(32 int),("B" string)} 32 32 32 32 32 struct{("B" string)} B +// postmain 64 true 88 64.64 64.64 64 64 64 64 64 67 helloBC slice[("A" string),("B" string),("C" string)] A struct{(64 int),("C" string)} 64 64 64 64 64 struct{("C" string)} C