From 3d5030ae7afd3d1c2bdfcd2a1b1f0acb9dc9a3a6 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Sat, 21 Sep 2024 16:08:23 +0200 Subject: [PATCH 01/10] feat(gnovm): align Gno constant handling with Go specifications --- .../r/demo/keystore/keystore_test.gno | 2 +- .../r/demo/microblog/microblog_test.gno | 2 +- gnovm/pkg/gnolang/preprocess.go | 18 +++ gnovm/pkg/gnolang/type_check.go | 109 ++++++++++++++++++ gnovm/tests/files/const23.gno | 11 ++ gnovm/tests/files/const24.gno | 76 ++++++++++++ gnovm/tests/files/const25.gno | 11 ++ gnovm/tests/files/const26.gno | 15 +++ gnovm/tests/files/const27.gno | 16 +++ gnovm/tests/files/const28.gno | 12 ++ gnovm/tests/files/const29.gno | 12 ++ gnovm/tests/files/const30.gno | 15 +++ gnovm/tests/files/const31.gno | 15 +++ gnovm/tests/files/const32.gno | 11 ++ 14 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 gnovm/tests/files/const23.gno create mode 100644 gnovm/tests/files/const24.gno create mode 100644 gnovm/tests/files/const25.gno create mode 100644 gnovm/tests/files/const26.gno create mode 100644 gnovm/tests/files/const27.gno create mode 100644 gnovm/tests/files/const28.gno create mode 100644 gnovm/tests/files/const29.gno create mode 100644 gnovm/tests/files/const30.gno create mode 100644 gnovm/tests/files/const31.gno create mode 100644 gnovm/tests/files/const32.gno diff --git a/examples/gno.land/r/demo/keystore/keystore_test.gno b/examples/gno.land/r/demo/keystore/keystore_test.gno index ffd8e60936f..9b5fafa2f95 100644 --- a/examples/gno.land/r/demo/keystore/keystore_test.gno +++ b/examples/gno.land/r/demo/keystore/keystore_test.gno @@ -11,7 +11,7 @@ import ( ) func TestRender(t *testing.T) { - const ( + var ( author1 std.Address = testutils.TestAddress("author1") author2 std.Address = testutils.TestAddress("author2") ) diff --git a/examples/gno.land/r/demo/microblog/microblog_test.gno b/examples/gno.land/r/demo/microblog/microblog_test.gno index a3c8f04ee7f..9ad98d3cbfe 100644 --- a/examples/gno.land/r/demo/microblog/microblog_test.gno +++ b/examples/gno.land/r/demo/microblog/microblog_test.gno @@ -10,7 +10,7 @@ import ( ) func TestMicroblog(t *testing.T) { - const ( + var ( author1 std.Address = testutils.TestAddress("author1") author2 std.Address = testutils.TestAddress("author2") ) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9168fc6f7c1..8a3ad82d9f6 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2188,6 +2188,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: may or may not be a *ConstExpr, // but if not, make one now. for i, vx := range n.Values { + checkConstantExpr(store, last, vx) n.Values[i] = evalConst(store, last, vx) } } else { @@ -2268,6 +2269,16 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if n.Type != nil { // only a single type can be specified. nt := evalStaticType(store, last, n.Type) + if n.Const { + if xnt, ok := nt.(*NativeType); ok { + nt = go2GnoBaseType(xnt.Type) + } + + if _, ok := baseOf(nt).(PrimitiveType); !ok { + panic(fmt.Sprintf("invalid constant type %s", nt.String())) + } + } + for i := 0; i < numNames; i++ { sts[i] = nt } @@ -2279,6 +2290,13 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // derive static type from values. for i, vx := range n.Values { vt := evalStaticTypeOf(store, last, vx) + if xnt, ok := vt.(*NativeType); ok { + vt = go2GnoBaseType(xnt.Type) + } + + if _, ok := baseOf(vt).(PrimitiveType); !ok { + panic(fmt.Sprintf("invalid constant type %s", vt.String())) + } sts[i] = vt } } else { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 31025fef152..8b2ea344d74 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -215,6 +215,115 @@ func assertAssignableTo(xt, dt Type, autoNative bool) { } } +func checkConstantExpr(store Store, last BlockNode, vx Expr) { +Main: + switch vx := vx.(type) { + case *NameExpr: + t := evalStaticTypeOf(store, last, vx) + if _, ok := t.(*ArrayType); ok { + break Main + } + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.Name, t)) + case *TypeAssertExpr: + panic(fmt.Sprintf("%s (comma, ok expression of type %s) is not constant", vx.String(), vx.Type)) + case *IndexExpr: + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), vx.X)) + case *CallExpr: + ift := evalStaticTypeOf(store, last, vx.Func) + switch baseOf(ift).(type) { + case *FuncType: + tup := evalStaticTypeOfRaw(store, last, vx).(*tupleType) + + // check for built-in functions + if cx, ok := vx.Func.(*ConstExpr); ok { + if fv, ok := cx.V.(*FuncValue); ok { + if fv.PkgPath == uversePkgPath { + // TODO: should support min, max + switch { + case fv.Name == "len": + checkConstantExpr(store, last, vx.Args[0]) + break Main + case fv.Name == "cap": + checkConstantExpr(store, last, vx.Args[0]) + break Main + } + } + } + } + + switch { + case len(tup.Elts) == 0: + panic(fmt.Sprintf("%s (no value) used as value", vx.String())) + case len(tup.Elts) == 1: + panic(fmt.Sprintf("%s (value of type %s) is not constant", vx.String(), tup.Elts[0])) + default: + panic(fmt.Sprintf("multiple-value %s (value of type %s) in single-value context", vx.String(), tup.Elts)) + } + case *TypeType: + for _, arg := range vx.Args { + checkConstantExpr(store, last, arg) + } + case *NativeType: + panic("NativeType\n") + default: + panic(fmt.Sprintf( + "unexpected func type %v (%v)", + ift, reflect.TypeOf(ift))) + } + case *BinaryExpr: + checkConstantExpr(store, last, vx.Left) + checkConstantExpr(store, last, vx.Right) + case *SelectorExpr: + xt := evalStaticTypeOf(store, last, vx.X) + switch xt := xt.(type) { + case *PackageType: + // Todo: check if the package is const after the fix of https://github.com/gnolang/gno/issues/2836 + // var pv *PackageValue + // if cx, ok := vx.X.(*ConstExpr); ok { + // // NOTE: *Machine.TestMemPackage() needs this + // // to pass in an imported package as *ConstEzpr. + // pv = cx.V.(*PackageValue) + // } else { + // // otherwise, packages can only be referred to by + // // *NameExprs, and cannot be copied. + // pvc := evalConst(store, last, vx.X) + // pv_, ok := pvc.V.(*PackageValue) + // if !ok { + // panic(fmt.Sprintf( + // "missing package in selector expr %s", + // vx.String())) + // } + // pv = pv_ + // } + // if pv.GetBlock(store).Source.GetIsConst(store, vx.Sel) { + // break Main + // } + // panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt)) + case *PointerType, *DeclaredType, *StructType, *InterfaceType: + ty := evalStaticTypeOf(store, last, vx.X) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) + case *TypeType: + ty := evalStaticType(store, last, vx.X) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) + case *NativeType: + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt)) + default: + panic(fmt.Sprintf( + "unexpected selector expression type %v", + reflect.TypeOf(xt))) + } + + case *ArrayTypeExpr: + case *ConstExpr: + case *BasicLitExpr: + case *CompositeLitExpr: + checkConstantExpr(store, last, vx.Type) + default: + ift := evalStaticTypeOf(store, last, vx) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ift)) + } +} + // checkValDefineMismatch checks for mismatch between the number of variables and values in a ValueDecl or AssignStmt. func checkValDefineMismatch(n Node) { var ( diff --git a/gnovm/tests/files/const23.gno b/gnovm/tests/files/const23.gno new file mode 100644 index 00000000000..bb6464fd88a --- /dev/null +++ b/gnovm/tests/files/const23.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const t []string = []string{} + fmt.Println(t) +} + +// Error: +// main/files/const23.gno:6:8: [](const-type string){} (variable of type []string) is not constant diff --git a/gnovm/tests/files/const24.gno b/gnovm/tests/files/const24.gno new file mode 100644 index 00000000000..58901fe301b --- /dev/null +++ b/gnovm/tests/files/const24.gno @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + const a int = 1_000_000 + const b byte = byte(1) + const c float64 = 1_000_000.000 + const d string = "Hello, World!" + const e rune = 'a' + const g bool = true + const h uint = 1_000 + const i int8 = 1 + const j int16 = 1 + const k int32 = 1 + const l int64 = 1 + const m uint8 = 1 + const n uint16 = 1 + const o uint32 = 1 + const p uint64 = 1 + const r float32 = 1_000_000.000 + const s = r + const t = len("s") + const u = 1 + len("s") + 3 + ars := [10]string{} + const v = len(ars) + const w = cap(ars) + + fmt.Println(a) + fmt.Println(b) + fmt.Println(c) + fmt.Println(d) + fmt.Println(e) + fmt.Println(g) + fmt.Println(h) + fmt.Println(i) + fmt.Println(j) + fmt.Println(k) + fmt.Println(l) + fmt.Println(m) + fmt.Println(n) + fmt.Println(o) + fmt.Println(p) + fmt.Println(r) + fmt.Println(s) + fmt.Println(t) + fmt.Println(u) + fmt.Println(v) + fmt.Println(w) +} + +// Output: +// 1000000 +// 1 +// 1e+06 +// Hello, World! +// 97 +// true +// 1000 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1e+06 +// 1e+06 +// 1 +// 5 +// 10 +// 10 diff --git a/gnovm/tests/files/const25.gno b/gnovm/tests/files/const25.gno new file mode 100644 index 00000000000..64e0358bdef --- /dev/null +++ b/gnovm/tests/files/const25.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const t = []string{"1"} + fmt.Println(t) +} + +// Error: +// main/files/const25.gno:6:8: [](const-type string){(const ("1" string))} (variable of type []string) is not constant diff --git a/gnovm/tests/files/const26.gno b/gnovm/tests/files/const26.gno new file mode 100644 index 00000000000..a1533e98c57 --- /dev/null +++ b/gnovm/tests/files/const26.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func v() string { + return "" +} + +func main() { + const t = v() + fmt.Println(t) +} + +// Error: +// main/files/const26.gno:10:8: v() (value of type string) is not constant diff --git a/gnovm/tests/files/const27.gno b/gnovm/tests/files/const27.gno new file mode 100644 index 00000000000..4be731e16a7 --- /dev/null +++ b/gnovm/tests/files/const27.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func v() string { + return "" +} + +func main() { + var i interface{} = 1 + const t, ok = i.(int) + fmt.Println(t, ok) +} + +// Error: +// main/files/const27.gno:11:8: i.((const-type int)) (comma, ok expression of type (const-type int)) is not constant diff --git a/gnovm/tests/files/const28.gno b/gnovm/tests/files/const28.gno new file mode 100644 index 00000000000..7b6b5648bf1 --- /dev/null +++ b/gnovm/tests/files/const28.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + var s []string = []string{"1"} + const t, ok = s[0] + fmt.Println(t, ok) +} + +// Error: +// main/files/const28.gno:7:8: s[(const (0 int))] (variable of type s) is not constant diff --git a/gnovm/tests/files/const29.gno b/gnovm/tests/files/const29.gno new file mode 100644 index 00000000000..0ebd8bcab6c --- /dev/null +++ b/gnovm/tests/files/const29.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + s := "1" + const t = s + fmt.Println(t) +} + +// Error: +// main/files/const29.gno:7:8: s (variable of type string) is not constant diff --git a/gnovm/tests/files/const30.gno b/gnovm/tests/files/const30.gno new file mode 100644 index 00000000000..3908ee26ee3 --- /dev/null +++ b/gnovm/tests/files/const30.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func v() { + return +} + +func main() { + const t = v() + fmt.Println(t) +} + +// Error: +// main/files/const30.gno:10:8: v() (no value) used as value diff --git a/gnovm/tests/files/const31.gno b/gnovm/tests/files/const31.gno new file mode 100644 index 00000000000..a192bd8ab86 --- /dev/null +++ b/gnovm/tests/files/const31.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func v() (string, string) { + return "", "" +} + +func main() { + const t, v = v() + fmt.Println(t) +} + +// Error: +// main/files/const31.gno:10:8: multiple-value (const (v func()( string, string)))() (value of type [string string]) in single-value context diff --git a/gnovm/tests/files/const32.gno b/gnovm/tests/files/const32.gno new file mode 100644 index 00000000000..83d3ae5e73c --- /dev/null +++ b/gnovm/tests/files/const32.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const t = 1 + 2 + len([]string{}) + fmt.Println(t) +} + +// Error: +// main/files/const32.gno:6:8: [](const-type string){} (variable of type []string) is not constant From bb2d9fd4799e845acdaa46214bbb8f9a0c1c8cc2 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Sat, 19 Oct 2024 00:53:24 +0200 Subject: [PATCH 02/10] feat: correct test --- gnovm/pkg/gnolang/type_check.go | 2 +- gnovm/tests/files/const23.gno | 2 +- gnovm/tests/files/const25.gno | 2 +- gnovm/tests/files/const32.gno | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index bd34070ae95..22445a720e7 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -319,7 +319,7 @@ Main: case *CompositeLitExpr: checkConstantExpr(store, last, vx.Type) default: - ift := evalStaticTypeOf(store, last, vx) + ift := evalStaticType(store, last, vx) panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ift)) } } diff --git a/gnovm/tests/files/const23.gno b/gnovm/tests/files/const23.gno index bb6464fd88a..7282c959b02 100644 --- a/gnovm/tests/files/const23.gno +++ b/gnovm/tests/files/const23.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/const23.gno:6:8: [](const-type string){} (variable of type []string) is not constant +// main/files/const23.gno:6:8: [](const-type string) (variable of type []string) is not constant diff --git a/gnovm/tests/files/const25.gno b/gnovm/tests/files/const25.gno index 64e0358bdef..c83495a4d20 100644 --- a/gnovm/tests/files/const25.gno +++ b/gnovm/tests/files/const25.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/const25.gno:6:8: [](const-type string){(const ("1" string))} (variable of type []string) is not constant +// main/files/const25.gno:6:8: [](const-type string) (variable of type []string) is not constant diff --git a/gnovm/tests/files/const32.gno b/gnovm/tests/files/const32.gno index 83d3ae5e73c..75acf5fb446 100644 --- a/gnovm/tests/files/const32.gno +++ b/gnovm/tests/files/const32.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/const32.gno:6:8: [](const-type string){} (variable of type []string) is not constant +// main/files/const32.gno:6:8: [](const-type string) (variable of type []string) is not constant From b80a890e4641dce6846370b8c26c87a80958a69e Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Wed, 23 Oct 2024 20:55:18 +0200 Subject: [PATCH 03/10] feat: add a todo for native type conversion --- gnovm/pkg/gnolang/type_check.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index cac86ea0d51..243cfed6ef3 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -264,7 +264,9 @@ Main: checkConstantExpr(store, last, arg) } case *NativeType: - panic("NativeType\n") + // Todo: should add a test after the fix of https://github.com/gnolang/gno/issues/3006 + ty := evalStaticType(store, last, vx.Func) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) default: panic(fmt.Sprintf( "unexpected func type %v (%v)", From ff74523155566b0f3c6dc364ac03818afd0a920a Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Wed, 23 Oct 2024 20:59:25 +0200 Subject: [PATCH 04/10] feat: uncomment package branch --- gnovm/pkg/gnolang/type_check.go | 43 ++++++++++++++++----------------- gnovm/tests/files/const24.gno | 3 +++ 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 243cfed6ef3..f2cd7d73c67 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -279,28 +279,27 @@ Main: xt := evalStaticTypeOf(store, last, vx.X) switch xt := xt.(type) { case *PackageType: - // Todo: check if the package is const after the fix of https://github.com/gnolang/gno/issues/2836 - // var pv *PackageValue - // if cx, ok := vx.X.(*ConstExpr); ok { - // // NOTE: *Machine.TestMemPackage() needs this - // // to pass in an imported package as *ConstEzpr. - // pv = cx.V.(*PackageValue) - // } else { - // // otherwise, packages can only be referred to by - // // *NameExprs, and cannot be copied. - // pvc := evalConst(store, last, vx.X) - // pv_, ok := pvc.V.(*PackageValue) - // if !ok { - // panic(fmt.Sprintf( - // "missing package in selector expr %s", - // vx.String())) - // } - // pv = pv_ - // } - // if pv.GetBlock(store).Source.GetIsConst(store, vx.Sel) { - // break Main - // } - // panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt)) + var pv *PackageValue + if cx, ok := vx.X.(*ConstExpr); ok { + // NOTE: *Machine.TestMemPackage() needs this + // to pass in an imported package as *ConstEzpr. + pv = cx.V.(*PackageValue) + } else { + // otherwise, packages can only be referred to by + // *NameExprs, and cannot be copied. + pvc := evalConst(store, last, vx.X) + pv_, ok := pvc.V.(*PackageValue) + if !ok { + panic(fmt.Sprintf( + "missing package in selector expr %s", + vx.String())) + } + pv = pv_ + } + if pv.GetBlock(store).Source.GetIsConst(store, vx.Sel) { + break Main + } + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt)) case *PointerType, *DeclaredType, *StructType, *InterfaceType: ty := evalStaticTypeOf(store, last, vx.X) panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) diff --git a/gnovm/tests/files/const24.gno b/gnovm/tests/files/const24.gno index 58901fe301b..cc2187b9ac4 100644 --- a/gnovm/tests/files/const24.gno +++ b/gnovm/tests/files/const24.gno @@ -28,6 +28,7 @@ func main() { ars := [10]string{} const v = len(ars) const w = cap(ars) + const x = time.Second fmt.Println(a) fmt.Println(b) @@ -50,6 +51,7 @@ func main() { fmt.Println(u) fmt.Println(v) fmt.Println(w) + fmt.Println(x) } // Output: @@ -74,3 +76,4 @@ func main() { // 5 // 10 // 10 +// 1s From 761ef1afa7ba27ff1d94acf3ba82156217cd2ad5 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Wed, 23 Oct 2024 21:09:44 +0200 Subject: [PATCH 05/10] feat: use println --- gnovm/tests/files/const24.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/tests/files/const24.gno b/gnovm/tests/files/const24.gno index cc2187b9ac4..c9cb14ef369 100644 --- a/gnovm/tests/files/const24.gno +++ b/gnovm/tests/files/const24.gno @@ -51,7 +51,7 @@ func main() { fmt.Println(u) fmt.Println(v) fmt.Println(w) - fmt.Println(x) + println(x) } // Output: From 5fa41e9284dbe2d5490b23aae7caf8b35b237f8d Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Wed, 23 Oct 2024 22:13:45 +0200 Subject: [PATCH 06/10] feat: add test --- gnovm/tests/files/const33.gno | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 gnovm/tests/files/const33.gno diff --git a/gnovm/tests/files/const33.gno b/gnovm/tests/files/const33.gno new file mode 100644 index 00000000000..989fe7dda5b --- /dev/null +++ b/gnovm/tests/files/const33.gno @@ -0,0 +1,12 @@ +package main + +var x = 1 +var y = 1 + +const b = x == y + +func main() { + println("ok") +} +// Error: +// main/files/const33.gno:6:7: x (variable of type int) is not constant From 90c8c5bdb4b1eee893f32c77ccff627b63fe050f Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Wed, 23 Oct 2024 22:21:33 +0200 Subject: [PATCH 07/10] fix: use evalStaticType only for type --- gnovm/pkg/gnolang/type_check.go | 5 ++++- gnovm/tests/files/const34.gno | 10 ++++++++++ gnovm/tests/files/const35.gno | 12 ++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 gnovm/tests/files/const34.gno create mode 100644 gnovm/tests/files/const35.gno diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index f2cd7d73c67..0763e7ae3ee 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -320,7 +320,10 @@ Main: case *CompositeLitExpr: checkConstantExpr(store, last, vx.Type) default: - ift := evalStaticType(store, last, vx) + ift := evalStaticTypeOf(store, last, vx) + if _, ok := ift.(*TypeType); ok { + ift = evalStaticType(store, last, vx) + } panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ift)) } } diff --git a/gnovm/tests/files/const34.gno b/gnovm/tests/files/const34.gno new file mode 100644 index 00000000000..9c79cf86b88 --- /dev/null +++ b/gnovm/tests/files/const34.gno @@ -0,0 +1,10 @@ +package main + +const a = func() { println("hey") } + +func main() { + println("ok") +} + +// Error: +// main/files/const34.gno:3:7: func func(){ (const (println func(xs ...interface{})()))((const ("hey" string))) } (variable of type func()()) is not constant diff --git a/gnovm/tests/files/const35.gno b/gnovm/tests/files/const35.gno new file mode 100644 index 00000000000..e684edb7263 --- /dev/null +++ b/gnovm/tests/files/const35.gno @@ -0,0 +1,12 @@ +package main + +var x = 1 + +const ff = +(1 << x) + +func main() { + println("ok") +} + +// Error: +// main/files/const35.gno:5:7: +(const (1 bigint)) << (const-type uint)(x) (variable of type bigint) is not constant From e74e6e99bd3137e644efa8ca5a36f88874797708 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Thu, 24 Oct 2024 00:50:48 +0200 Subject: [PATCH 08/10] feat: add more test --- gnovm/pkg/gnolang/preprocess.go | 2 +- gnovm/pkg/gnolang/type_check.go | 7 +++++-- gnovm/tests/files/const36.gno | 13 +++++++++++++ gnovm/tests/files/const37_native.gno | 10 ++++++++++ gnovm/tests/files/const37_stdlibs.gno | 10 ++++++++++ gnovm/tests/files/const38.gno | 11 +++++++++++ gnovm/tests/files/const39.gno | 14 ++++++++++++++ gnovm/tests/files/const40.gno | 8 ++++++++ gnovm/tests/files/const41.gno | 8 ++++++++ 9 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 gnovm/tests/files/const36.gno create mode 100644 gnovm/tests/files/const37_native.gno create mode 100644 gnovm/tests/files/const37_stdlibs.gno create mode 100644 gnovm/tests/files/const38.gno create mode 100644 gnovm/tests/files/const39.gno create mode 100644 gnovm/tests/files/const40.gno create mode 100644 gnovm/tests/files/const41.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 21d562bb8d5..1b06dd3b489 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2404,7 +2404,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { } if _, ok := baseOf(vt).(PrimitiveType); !ok { - panic(fmt.Sprintf("invalid constant type %s", vt.String())) + panic(fmt.Sprintf("%s (value of type %s) is not constant", vx.String(), vt.String())) } sts[i] = vt } diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 0763e7ae3ee..d4ed40ab03b 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -299,7 +299,9 @@ Main: if pv.GetBlock(store).Source.GetIsConst(store, vx.Sel) { break Main } - panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt)) + + tt := pv.GetBlock(store).Source.GetStaticTypeOf(store, vx.Sel) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), tt)) case *PointerType, *DeclaredType, *StructType, *InterfaceType: ty := evalStaticTypeOf(store, last, vx.X) panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) @@ -307,7 +309,8 @@ Main: ty := evalStaticType(store, last, vx.X) panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) case *NativeType: - panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt)) + ty := evalStaticTypeOf(store, last, vx.X) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), ty)) default: panic(fmt.Sprintf( "unexpected selector expression type %v", diff --git a/gnovm/tests/files/const36.gno b/gnovm/tests/files/const36.gno new file mode 100644 index 00000000000..c6cf82c6f6b --- /dev/null +++ b/gnovm/tests/files/const36.gno @@ -0,0 +1,13 @@ +package main + +type s struct { + x int +} + +func main() { + s := s{1} + const v = s.x +} + +// Error: +// main/files/const36.gno:9:8: s.x (variable of type main.s) is not constant diff --git a/gnovm/tests/files/const37_native.gno b/gnovm/tests/files/const37_native.gno new file mode 100644 index 00000000000..413fa011151 --- /dev/null +++ b/gnovm/tests/files/const37_native.gno @@ -0,0 +1,10 @@ +package main + +import "time" + +func main() { + const v = time.UTC +} + +// Error: +// main/files/const37_native.gno:6:8: time.UTC (variable of type gonative{*time.Location}) is not constant \ No newline at end of file diff --git a/gnovm/tests/files/const37_stdlibs.gno b/gnovm/tests/files/const37_stdlibs.gno new file mode 100644 index 00000000000..9ec614f2538 --- /dev/null +++ b/gnovm/tests/files/const37_stdlibs.gno @@ -0,0 +1,10 @@ +package main + +import "time" + +func main() { + const v = time.UTC +} + +// Error: +// main/files/const37_stdlibs.gno:6:8: time.UTC (variable of type *time.Location) is not constant \ No newline at end of file diff --git a/gnovm/tests/files/const38.gno b/gnovm/tests/files/const38.gno new file mode 100644 index 00000000000..1aee945d434 --- /dev/null +++ b/gnovm/tests/files/const38.gno @@ -0,0 +1,11 @@ +package main + +import "net" + +func main() { + v := net.TCPAddr{} + const c = v.IP +} + +// Error: +// main/files/const38.gno:7:8: v.IP (variable of type gonative{net.TCPAddr}) is not constant \ No newline at end of file diff --git a/gnovm/tests/files/const39.gno b/gnovm/tests/files/const39.gno new file mode 100644 index 00000000000..fa3cdb5f517 --- /dev/null +++ b/gnovm/tests/files/const39.gno @@ -0,0 +1,14 @@ +package main + +type T struct { + a int +} + +func (tv T) Mv(a int) int { return 0 } + +func main() { + const t = T.Mv +} + +// Error: +// main/files/const39.gno:10:8: T.Mv (variable of type main.T) is not constant \ No newline at end of file diff --git a/gnovm/tests/files/const40.gno b/gnovm/tests/files/const40.gno new file mode 100644 index 00000000000..f0eeedeaeb9 --- /dev/null +++ b/gnovm/tests/files/const40.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const t = [0]string{} +} + +// Error: +// main/files/const40.gno:4:8: (const (array[] [0]string)) (value of type [0]string) is not constant \ No newline at end of file diff --git a/gnovm/tests/files/const41.gno b/gnovm/tests/files/const41.gno new file mode 100644 index 00000000000..b4424dcef94 --- /dev/null +++ b/gnovm/tests/files/const41.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const t [0]string = [0]string{} +} + +// Error: +// main/files/const41.gno:4:8: invalid constant type [0]string \ No newline at end of file From 3a52e1452130155342ba43090b9eb833b66b23ee Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Thu, 24 Oct 2024 23:12:51 +0200 Subject: [PATCH 09/10] feat: add missing init expr --- gnovm/pkg/gnolang/preprocess.go | 4 ++++ gnovm/tests/files/const42.gno | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 gnovm/tests/files/const42.gno diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 1b06dd3b489..0cec8e25475 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2379,6 +2379,10 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // only a single type can be specified. nt := evalStaticType(store, last, n.Type) if n.Const { + if len(n.Values) == 0 { + panic(fmt.Sprintf("missing init expr for %s", n.NameExprs[0].Name)) + } + if xnt, ok := nt.(*NativeType); ok { nt = go2GnoBaseType(xnt.Type) } diff --git a/gnovm/tests/files/const42.gno b/gnovm/tests/files/const42.gno new file mode 100644 index 00000000000..5763a2fc121 --- /dev/null +++ b/gnovm/tests/files/const42.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const t int +} + +// Error: +// main/files/const42.gno:4:8: missing init expr for t \ No newline at end of file From f53a19f5a9c243c0828c1fb2be4ddb0820308ba9 Mon Sep 17 00:00:00 2001 From: Omar Sy Date: Thu, 7 Nov 2024 22:07:58 +0100 Subject: [PATCH 10/10] feat: add real and imag on todo --- gnovm/pkg/gnolang/type_check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index d4ed40ab03b..4b0a2490a0b 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -238,7 +238,7 @@ Main: if cx, ok := vx.Func.(*ConstExpr); ok { if fv, ok := cx.V.(*FuncValue); ok { if fv.PkgPath == uversePkgPath { - // TODO: should support min, max + // TODO: should support min, max, real, imag switch { case fv.Name == "len": checkConstantExpr(store, last, vx.Args[0])